1 // SSVersionObject.cpp: implementation of the SSVersionObject class.
3 //////////////////////////////////////////////////////////////////////
6 #include "SSVersionObject.h"
10 //---------------------------------------------------------------------------
11 #include "LeakWatcher.h"
16 static char THIS_FILE
[] = __FILE__
;
20 //////////////////////////////////////////////////////////////////////
21 // Construction/Destruction
22 //////////////////////////////////////////////////////////////////////
23 SSVersionObject::SSVersionObject (SSRecordPtr pRecord
)
24 : SSObject (pRecord
, eHistoryRecord
),
29 if (pRecord
->GetLen() < sizeof (VERSION_RECORD
))
30 throw SSRecordException ("not enough data for version object");
32 m_pAction
= SSAction::MakeAction (pRecord
);
36 SSVersionObject::~SSVersionObject ()
41 SSVersionObject::SSVersionObject (SSVersionObject
& object
)
45 m_pAction
= SSAction::MakeAction (GetRecord());
48 SSVersionObject
& SSVersionObject::operator= (SSVersionObject
const & object
)
52 *(SSObject
*)this = object
;
53 m_pAction
= SSAction::MakeAction (GetRecord());
58 std::string
SSVersionObject::GetComment () const
60 if (GetOffsetToNextRecordOrComment() && GetLengthComment())
62 SSCommentObject
comment (GetFile ()->GetRecord (GetOffsetToNextRecordOrComment()));
63 return comment
.GetComment();
68 //std::string SSVersionObject::GetLabel () const
70 // const SSLabeledAction* pLabeledAction = dynamic_cast<const SSLabeledAction*> (m_pAction);
71 // return pLabeledAction ? pLabeledAction->GetLabel () : "";
73 std::string
SSVersionObject::GetLabelComment () const
75 const SSLabeledAction
* pLabeledAction
= dynamic_cast<const SSLabeledAction
*> (m_pAction
);
76 return pLabeledAction
? pLabeledAction
->GetLabelComment () : "";
79 SSVersionObject
SSVersionObject::GetPreviousObject () const
81 if (GetPrevious () == 0)
82 return SSVersionObject (SSRecordPtr());
84 return SSVersionObject (GetFile ()->GetRecord (GetPrevious ()));
87 bool SSVersionObject::Validate ()
91 SSRecordPtr pLabelCommentRecord
;
93 SSRecordPtr pPrevious
;
95 const VERSION_RECORD
* pVersion
= GetData ();
96 if (pVersion
->OffsetToLabelComment
)
97 pLabelCommentRecord
= GetFile ()->GetRecord (pVersion
->OffsetToLabelComment
);
98 if (pVersion
->OffsetToNextRecordOrComment
)
99 pNext
= GetFile ()->GetRecord (pVersion
->OffsetToNextRecordOrComment
);
100 if (pVersion
->Previous
)
101 pPrevious
= GetFile ()->GetRecord (pVersion
->Previous
);
103 if ( (pVersion
->LengthLabelComment
== 0 && pVersion
->OffsetToLabelComment
!= 0)
104 || (pVersion
->LengthLabelComment
!= 0 && pVersion
->OffsetToLabelComment
== 0) )
106 Warning ("invalid length and offset combination");
110 if (pVersion
->LengthLabelComment
)
112 retval
&= warn_with_msg_if (!pLabelCommentRecord
, "the expected comment record is invalid")
114 retval
&= warn_with_msg_if (pLabelCommentRecord
->GetType () != eCommentRecord
,
115 "the record pointed to by offsetToLabelComment is expected to be a comment record");
119 if (pVersion
->LengthComment
)
121 retval
&= warn_with_msg_if (!pNext
, "the expected comment record is invalid");
123 retval
&= warn_with_msg_if (pNext
->GetType () != eCommentRecord
,
124 "the record pointed to by offsetToNextRecordOrComment is expected to be a comment record");
127 if (pVersion
->Previous
&& !pPrevious
)
129 Warning ("a previous record is specified, but the record could not be read");
135 retval
= warn_with_msg_if (pPrevious
->GetType () != eHistoryRecord
,
136 "the record pointed to by previous is expected to be a history record");
141 // ---------------------------------------------------------------
142 class ActionNode
: public XMLNode
145 ActionNode (XMLNode
* pParent
, eAction actionid
)
146 : XMLNode (pParent
, "Action", ToAttribMap(actionid
))
150 static AttribMap
ToAttribMap (eAction actionid
)
152 std::string actionString
= CAction::ActionToString (actionid
);
153 actionString
.erase (std::remove (actionString
.begin (), actionString
.end (), ' '));
155 return ToAttribMap (actionString
);
157 static AttribMap
ToAttribMap (std::string actionString
)
160 map
["ActionId"] = actionString
;
166 void SSVersionObject::ToXml (XMLNode
* pParent
) const
168 XMLElement
versionNumber (pParent
, "VersionNumber", GetVersionNumber());
169 XMLElement
useName (pParent
, "UserName", GetUsername());
170 XMLElement
date (pParent
, "Date", GetDate());
171 if (!GetComment ().empty ())
173 XMLElement
date (pParent
, "Comment", GetComment());
178 SSAction
* pAction
= GetAction ();
179 ActionNode
node (pParent
, pAction
->GetActionID());
181 pAction
->ToXml (&node
);
185 void SSVersionObject::Dump (std::ostream
& os
) const
187 SSRecordPtr pLabelCommentRecord
;
189 const VERSION_RECORD
* pVersion
= GetData ();
191 if (pVersion
->OffsetToLabelComment
)
192 pLabelCommentRecord
= GetFile ()->GetRecord (pVersion
->OffsetToLabelComment
);
193 if (pVersion
->OffsetToNextRecordOrComment
)
194 pNext
= GetFile ()->GetRecord (pVersion
->OffsetToNextRecordOrComment
);
196 // dump basic information
199 SSVersionObject previous
= GetPreviousObject ();
203 os
<< "Type " << SSRecord::TypeToString (previous
.GetType ()) << ", ";
204 os
<< "Offset 0x" << std::hex
<< previous
.GetOffset () << std::dec
;
208 os
<< "NULL" << std::endl
;
210 os
<< "Action " << GetActionID() << " : " << CAction::ActionToString (GetActionID()) << std::endl
;
211 os
<< "ActionStr: " << GetActionString () << std::endl
;
212 os
<< "Version: " << GetVersionNumber () << std::endl
;
213 // os << "Date" << std::endl;
214 os
<< "User: " << GetUsername () << std::endl
;
215 os
<< "Comment: " << GetComment () << std::endl
;
217 os
<< "Comment Offset 0x" << std::hex
<< pVersion
->OffsetToNextRecordOrComment
<< std::dec
<< ", Length " << pVersion
->LengthComment
;
219 os
<< ", Type " << pNext
->GetRecordType ();
222 os
<< "LabelComment Offset 0x" << std::hex
<< pVersion
->OffsetToLabelComment
<< std::dec
<< ", Length " << pVersion
->LengthLabelComment
;
223 if (pLabelCommentRecord
)
224 os
<< ", Type " << pLabelCommentRecord
->GetRecordType ();
227 SSAction
* pAction
= GetAction ();
232 //---------------------------------------------------------------------------
233 SSAction::SSAction (SSRecordPtr pRecord
)
235 const VERSION_RECORD
* pVersion
= GetHistoryRecordPtr (pRecord
);
237 m_ActionId
= static_cast <eAction
> (pVersion
->ActionID
);
240 SSAction::~SSAction ()
244 SSAction
* SSAction::MakeAction (SSRecordPtr pRecord
)
249 if (pRecord
->GetLen () < sizeof (VERSION_RECORD
))
250 throw SSException ("not enough bytes for Version Header in record");
252 const VERSION_RECORD
* pVersion
= reinterpret_cast<const VERSION_RECORD
*> (pRecord
->GetBuffer ());
254 if (pVersion
->ActionID
== Labeled
)
255 return new SSLabeledAction (pRecord
);
256 else if (pVersion
->ActionID
== Created_Project
)
257 return new SSCreatedProjectAction (pRecord
);
258 else if (pVersion
->ActionID
== Added_Project
)
259 return new SSAddedProjectAction (pRecord
);
260 else if (pVersion
->ActionID
== Added_File
)
261 return new SSAddedFileAction (pRecord
);
262 else if (pVersion
->ActionID
== Destroyed_Project
)
263 return new SSDestroyedProjectAction(pRecord
);
264 else if (pVersion
->ActionID
== Destroyed_File
)
265 return new SSDestroyedFileAction (pRecord
);
266 else if (pVersion
->ActionID
== Deleted_Project
)
267 return new SSDeletedProjectAction (pRecord
);
268 else if (pVersion
->ActionID
== Deleted_File
)
269 return new SSDeletedFileAction (pRecord
);
270 else if (pVersion
->ActionID
== Recovered_Project
)
271 return new SSRecoveredProjectAction (pRecord
);
272 else if (pVersion
->ActionID
== Recovered_File
)
273 return new SSRecoveredFileAction (pRecord
);
274 else if (pVersion
->ActionID
== Renamed_Project
)
275 return new SSRenamedProjectAction (pRecord
);
276 else if (pVersion
->ActionID
== Renamed_File
)
277 return new SSRenamedFileAction (pRecord
);
278 // else if (pVersion->ActionID == missing action 12)
279 // return new SSVersionObject (pRecord);
280 // else if (pVersion->ActionID == missing action 13)
281 // return new SSVersionObject (pRecord);
282 else if (pVersion
->ActionID
== Shared_File
)
283 return new SSSharedAction (pRecord
);
284 else if (pVersion
->ActionID
== Branch_File
)
285 return new SSRollbackAction (pRecord
);
286 else if (pVersion
->ActionID
== Created_File
)
287 return new SSCreatedFileAction (pRecord
);
288 else if (pVersion
->ActionID
== Checked_in
)
289 return new SSCheckedInAction (pRecord
);
290 // else if (pVersion->ActionID == // missing action 18)
291 // return new SSVersionObject (pRecord);
292 else if (pVersion
->ActionID
== RollBack
)
293 return new SSRollbackAction (pRecord
);
295 throw SSUnknownActionException (pVersion
->ActionID
, pRecord
);
300 const VERSION_RECORD
* SSAction::GetHistoryRecordPtr (SSRecordPtr pRecord
) const
302 assert (pRecord
->GetBuffer ());
303 return reinterpret_cast<const VERSION_RECORD
*> (pRecord
->GetBuffer ());
306 void SSAction::Dump (std::ostream
& os
) const
310 //---------------------------------------------------------------------------
311 SSLabeledAction::SSLabeledAction (SSRecordPtr pRecord
)
312 : SSActionEx
<SSLabeledAction
> (pRecord
)
314 const VERSION_RECORD
* pVersion
= GetHistoryRecordPtr (pRecord
);
316 m_Label
= std::string (pVersion
->Label
);
318 if (pVersion
->OffsetToLabelComment
&& pVersion
->LengthLabelComment
> 0)
321 SSCommentObject
commentObject (pRecord
->GetFileImp ()->GetRecord (pVersion
->OffsetToLabelComment
));
322 m_LabelComment
= commentObject
.GetComment();
324 catch (SSRecordException
&)
330 SSLabeledAction::~SSLabeledAction ()
334 std::string
SSLabeledAction::FormatActionString ()
336 return "Labeled " + m_Label
;
339 void SSLabeledAction::ToXml (XMLNode
* pParent
) const
341 XMLElement
label (pParent
, "Label", GetLabel());
342 XMLElement
comment (pParent
, "LabelComment", GetLabelComment());
346 void SSLabeledAction::Dump (std::ostream
& os
) const
348 SSActionEx
<SSLabeledAction
>::Dump (os
);
351 //---------------------------------------------------------------------------
352 template <class ACTION
, class STRUCT
>
353 SSItemAction
<ACTION
, STRUCT
>::SSItemAction (SSRecordPtr pRecord
, std::string actionString
)
354 : SSActionEx
<ACTION
> (pRecord
),
355 m_ActionString (actionString
)
357 memcpy (&m_Action
, pRecord
->GetBuffer()+sizeof(VERSION_RECORD
), sizeof(STRUCT
));
360 template <class T
, class ACTION
>
361 std::string SSItemAction
<T
, ACTION
>::FormatActionString ()
363 return m_ActionString
+ GetName ();
366 template <class T
, class ACTION
>
367 void SSItemAction
<T
, ACTION
>::ToXml (XMLNode
* pParent
) const
369 XMLElement
physical (pParent
, "Physical", GetPhysical());
370 GetSSName().ToXml (pParent
);
373 template <class T
, class ACTION
>
374 void SSItemAction
<T
, ACTION
>::Dump (std::ostream
& os
) const
376 SSActionEx
<T
>::Dump (os
);
379 //---------------------------------------------------------------------------
380 template <class ACTION
>
381 SSDestroyedAction
<ACTION
>::SSDestroyedAction (SSRecordPtr pRecord
, std::string prefix
)
382 : SSItemAction
<ACTION
, DESTROYED_ACTION
> (pRecord
, ""),
387 template <class ACTION
>
388 std::string SSDestroyedAction
<ACTION
>::FormatActionString ()
390 std::string
action (m_Prefix
);
391 action
+= GetName () + " Destroyed";
395 //---------------------------------------------------------------------------
396 template <class ACTION
>
397 SSRenamedAction
<ACTION
>::SSRenamedAction (SSRecordPtr pRecord
, std::string prefix
)
398 : SSItemAction
<ACTION
, RENAMED_ACTION
> (pRecord
, ""),
403 template <class ACTION
>
404 std::string SSRenamedAction
<ACTION
>::FormatActionString ()
406 SSName
ssOldName (GetSSName ());
407 SSName
ssNewName (m_Action
.newName
);
408 std::string
action (m_Prefix
);
409 action
+= ssOldName
.GetFullName ();
410 action
+= " renamedto " + m_Prefix
;
411 action
+= ssNewName
.GetFullName ();
415 template <class ACTION
>
416 void SSRenamedAction
<ACTION
>::ToXml (XMLNode
* pParent
) const
418 SSItemAction
<ACTION
,RENAMED_ACTION
>::ToXml (pParent
);
420 GetNewSSName().ToXml (pParent
, "NewSSName");
423 template <class ACTION
>
424 void SSRenamedAction
<ACTION
>::Dump (std::ostream
& os
) const
426 SSItemAction
<ACTION
, RENAMED_ACTION
>::Dump (os
);
429 //---------------------------------------------------------------------------
430 SSCheckedInAction::SSCheckedInAction (SSRecordPtr pRecord
)
431 : SSActionEx
<SSCheckedInAction
> (pRecord
),
432 m_FilePtr (pRecord
->GetFileImp ())
434 memcpy (&m_Action
, pRecord
->GetBuffer()+sizeof(VERSION_RECORD
), sizeof(CHECKED_IN_ACTION
));
437 SSCheckedInAction::~SSCheckedInAction ()
441 std::string
SSCheckedInAction::FormatActionString ()
443 std::string action
= "Checked In ";
444 action
+= std::string (m_Action
.checkInSpec
);
448 SSRecordPtr
SSCheckedInAction::GetFileDelta () const
450 if (!m_pFileDelta
&& m_Action
.offsetFileDelta
)
452 m_pFileDelta
= m_FilePtr
->GetRecord (m_Action
.offsetFileDelta
);
458 void SSCheckedInAction::ToXml (XMLNode
* pParent
) const
460 XMLElement
checkInNode (pParent
, "CheckInSpec", GetFileSepc());
461 XMLElement
offsetNode (pParent
, "Offset", GetOffset());
464 void SSCheckedInAction::Dump (std::ostream
& os
) const
466 SSActionEx
<SSCheckedInAction
>::Dump (os
);
469 //---------------------------------------------------------------------------
470 SSSharedAction::SSSharedAction (SSRecordPtr pRecord
)
471 : SSItemAction
<SSSharedAction
, SHARED_FILE_ACTION
> (pRecord
, "")
475 SSSharedAction::~SSSharedAction ()
479 std::string
SSSharedAction::FormatActionString ()
481 std::ostringstream str
;
482 SSName
name (m_Action
.name
);
483 if (m_Action
.pinnedToVersion
== -1)
484 str
<< m_Action
.srcPathSpec
<< "/" << name
.GetFullName() << ";" << m_Action
.version
<< " shared";
485 else if (m_Action
.pinnedToVersion
== 0)
486 str
<< m_Action
.srcPathSpec
<< "/" << name
.GetFullName() << " pinned to version " << m_Action
.version
;
487 else if (m_Action
.version
== 0)
488 str
<< m_Action
.srcPathSpec
<< "/" << name
.GetFullName() << " unpinned";
490 throw SSException ("bad share/pin/unpin action: version should be 0");
496 void SSSharedAction::ToXml (XMLNode
* pParent
) const
498 SSItemAction
<SSSharedAction
, SHARED_FILE_ACTION
>::ToXml(pParent
);
500 XMLElement
srcPathNode (pParent
, "SrcPath", GetSrcPathSpec ());
501 XMLElement
pinnedNode (pParent
, "PinnedToVersion", GetPinnedToVersion ());
502 XMLElement
versionNode (pParent
, "Version", GetVersion ());
505 void SSSharedAction::Dump (std::ostream
& os
) const
507 SSItemAction
<SSSharedAction
, SHARED_FILE_ACTION
>::Dump(os
);
510 //---------------------------------------------------------------------------
511 void SSRollbackAction::ToXml (XMLNode
* pParent
) const
513 SSItemAction
<SSRollbackAction
, ROLLBACK_ACTION
>::ToXml (pParent
);
515 XMLElement
parentNode (pParent
, "Parent", GetParent());
518 void SSRollbackAction::Dump (std::ostream
& os
) const
520 SSItemAction
<SSRollbackAction
, ROLLBACK_ACTION
>::Dump (os
);