Add Dirk Luetjen's ssphys libraries and command-line tool
[vss2svn.git] / ssphys / SSPhysLib / SSItemInfoObject.cpp
bloba69260d168470945747719b19ff1f43c0963d180
1 // SSItemInfoObject.cpp: implementation of the SSItems class.
2 //
3 //////////////////////////////////////////////////////////////////////
5 #include "stdafx.h"
6 #include "SSFiles.h"
7 #include "SSName.h"
8 #include "SSItemInfoObject.h"
9 #include "SSParentFolderObject.h"
10 #include "SSBranchFileObject.h"
12 //---------------------------------------------------------------------------
13 #include "LeakWatcher.h"
15 #ifdef _DEBUG
16 #define new DEBUG_NEW
17 #undef THIS_FILE
18 static char THIS_FILE[] = __FILE__;
19 #endif
21 //////////////////////////////////////////////////////////////////////
22 // Construction/Destruction
23 //////////////////////////////////////////////////////////////////////
25 SSItemInfoObject::SSItemInfoObject (SSRecordPtr pRecord)
26 : SSObject (pRecord, eItemRecord)
28 if (pRecord->GetLen() < sizeof (DH))
29 throw SSRecordException ("not enough data for info object");
31 memcpy (&m_InfoItem, pRecord->GetBuffer(), sizeof (DH));
34 SSItemInfoObject::~SSItemInfoObject ()
38 SSItemInfoObject* SSItemInfoObject::MakeItemInfo (SSRecordPtr pRecord)
40 if (pRecord->GetLen () < sizeof (DH))
41 throw SSException ("not enough bytes for DH Header in record");
43 const DH* pDh = reinterpret_cast<const DH*> (pRecord->GetBuffer ());
44 if (pDh->Type == 1)
45 return new SSProjectItem (pRecord);
46 else if (pDh->Type == 2)
47 return new SSFileItem (pRecord);
48 else
49 throw SSException ("unsupported item type");
51 return (SSItemInfoObject*) NULL;
56 SSVersionObject SSItemInfoObject::GetVersion (int i)
58 SSFileImpPtr filePtr = GetFile ();
60 // TODO: Cache versions
61 SSVersionObject version (filePtr->GetRecord (GetHistoryOffsetLast ()));
63 while (version && version.GetVersionNumber () != i)
65 version = version.GetPreviousObject();
68 return version;
72 bool SSItemInfoObject::Get (int ver, const char* dest)
74 // SSFileImpPtr filePtr = GetFile ();
76 // std::string lastVersion = filePtr->GetFileName () + GetLatestExt ();
77 // char tmrFile[2][255];
78 // char* ptr[2] = {tmrFile[0], (char*)dest};
79 // ptr[0] = tmpnam (ptr[0]);
80 //
81 // CopyFile (lastVersion.c_str(), ptr[0]);
83 // SSVersionObject version (filePtr->GetRecord (GetHistoryOffsetLast ()));
84 //
85 // while (version && version.GetVersionNumber() > ver)
86 // {
87 // if (version.GetActionId() == Checked_in)
88 // {
89 // SSCheckedInAction* pAction = dynamic_cast <SSCheckedInAction*> (version.GetAction());
90 // SSRecordPtr pRecord = pAction->GetFileDelta();
91 // ReverseDelta (ptr[0], pRecord->GetBuffer(), pRecord->GetLen(), ptr[1]);
92 // std::swap (ptr[0], ptr[1]);
93 // }
95 // version = version.GetPrevious ();
96 // }
98 // if (0 != strcmp (ptr[0], dest))
99 // {
100 // CopyFile (ptr[0], dest);
101 // _unlink (ptr[0]);
102 // }
103 // else
104 // {
105 // _unlink (ptr[1]);
106 // }
107 return false;
110 bool SSItemInfoObject::Validate()
112 SSFileImpPtr filePtr = GetFile ();
114 bool retval = true;
115 retval &= warn_if (GetLatestExt() != ".A" && GetLatestExt() != ".B");
116 retval &= warn_if (GetHistoryOffsetEnd() != filePtr->Size());
117 retval &= warn_if (filePtr->GetRecord (GetHistoryOffsetLast ())->GetType() != eHistoryRecord);
118 retval &= warn_if (filePtr->GetRecord (GetHistoryOffsetBegin ())->GetType() != eHistoryRecord);
119 retval &= warn_if (filePtr->GetRecord (GetHistoryOffsetBegin ())->GetType() != eHistoryRecord);
121 int nCount = 0;
122 long offset = GetHistoryOffsetLast ();
123 do {
124 SSRecordPtr pRecord = filePtr->GetRecord (offset);
125 retval &= warn_if (pRecord->GetType() != eHistoryRecord);
127 std::auto_ptr <SSObject> objectPtr (SSObject::MakeObject(pRecord));
128 SSVersionObject* pVersion = dynamic_cast<SSVersionObject*> (objectPtr.get ());
129 if (pVersion)
131 SSVersionObject previous (pVersion->GetPreviousObject ());
132 offset = previous ? previous.GetOffset() : NULL;
134 else
135 offset = NULL;
137 ++nCount;
138 } while (offset != NULL /*GetHistoryOffsetBegin ()*/);
140 retval &= warn_if (nCount != GetNumberOfActions ());
141 return retval;
144 void SSItemInfoObject::ToXml (XMLNode* pParent) const
146 XMLElement type (pParent, "Type", GetType());
147 XMLElement data (pParent, "DataFileName", GetDataFileName ());
148 XMLElement ext (pParent, "LatestExt", GetLatestExt());
149 GetSSName().ToXml (pParent);
150 XMLElement noActions (pParent, "NumberOfActions", GetNumberOfActions());
153 void SSItemInfoObject::Dump (std::ostream& os) const
155 SSObject::Dump (os);
157 SSFileImpPtr filePtr = GetFile ();
159 os << "Item Type: ";
161 switch (m_InfoItem.Type)
163 case 1: os << "Project" << std::endl; break;
164 case 2: os << "File" << std::endl; break;
165 default: os << "Unknown (" << m_InfoItem.Type << ")" << std::endl; break;
168 SSName ssName (GetSSName ());
169 os << "Last Name: " << ssName << std::endl;
170 // os << "Number Of Records: " << GetNumberOfRecords () << std::endl;
171 os << "LatestExt of last version: " << m_InfoItem.LatestExt[0] << m_InfoItem.LatestExt[1] << std::endl;
172 os << "Offset to first History record: 0x" << std::hex << GetHistoryOffsetBegin()<< std::dec << std::endl;
173 os << "Offset to last History record: 0x" << std::hex << GetHistoryOffsetLast() << std::dec << std::endl;
174 os << "Offset to the end of the file: 0x" << std::hex << GetHistoryOffsetEnd() << std::dec << std::endl;
175 os << "Size of the file: 0x" << std::hex << filePtr->Size() << std::dec << std::endl;
182 //---------------------------------------------------------------------------
183 SSProjectItem::SSProjectItem (SSRecordPtr pRecord)
184 : SSItemInfoObject (pRecord)
186 if (pRecord->GetLen() < sizeof (DH_PROJECT))
187 throw SSRecordException ("not enough data for project info object");
190 std::string SSProjectItem::GetName () const
192 return ("ProjectItem");
194 void SSProjectItem::ToXml (XMLNode* pParent) const
196 SSItemInfoObject::ToXml (pParent);
197 XMLElement spec (pParent, "ParentSpec", GetParentSpec ());
198 XMLElement phys (pParent, "ParentPhys", GetParentPhys ());
199 XMLElement noitems (pParent, "NumberOfItems", GetNumberOfItems ());
200 XMLElement noProjects (pParent, "NumberOfProjects", GetNumberOfProjects ());
203 void SSProjectItem::Dump (std::ostream& os) const
205 SSItemInfoObject::Dump (os);
207 // Hexdump (oss, dummy4, 20);
208 os << "last parent spec: " << GetParentSpec () << std::endl;
209 os << "parentPhys: " << GetParentPhys () << std::endl;
210 os << "Number of Items: " << GetNumberOfItems () << std::endl;
211 os << "Number of Projects: " << GetNumberOfProjects () << std::endl;
217 //---------------------------------------------------------------------------
218 SSFileItem::SSFileItem (SSRecordPtr pRecord)
219 : SSItemInfoObject (pRecord)
221 if (pRecord->GetLen() < sizeof (DH_FILE))
222 throw SSRecordException ("not enough data for file info object");
225 bool SSFileItem::Validate()
227 SSItemInfoObject::Validate ();
229 const DH_FILE* pFileInfoItem = GetData();
231 bool retval = true;
232 retval &= warn_if (pFileInfoItem->NumberOfItems > 0);
233 retval &= warn_if (pFileInfoItem->NumberOfProjects > 0);
235 byte knownFlags[] =
237 0x00, 0x02, 0x04, 0x41, 0x42, 0x20, 0x22
239 for (int i = 0; i < countof (knownFlags); i++)
240 if (pFileInfoItem->Flag == knownFlags[i])
241 break;
242 retval &= warn_if (i == countof (knownFlags));
244 return retval;
247 eFileType SSFileItem::GetFileType () const
249 if ((GetFlag () & 0x02) == 0x02)
250 return eFileTypeBinary;
252 return eFileTypeText;
255 bool SSFileItem::GetStoreOnlyLatestRev () const
257 if ((GetFlag () & 0x04) == 0x04)
258 return true;
260 return false;
263 bool SSFileItem::GetCheckedOut () const
265 if ((GetFlag () & 0x41) == 0x41)
266 return true;
268 return false;
271 bool SSFileItem::GetShared () const
273 if ((GetFlag () & 0x20) == 0x20)
274 return true;
276 return false;
279 SSParentFolderObject* SSFileItem::GetFirstParentFolder ()
281 SSRecordPtr pRecord = GetFile()->GetRecord(GetOffsetPFRecord ());
282 return new SSParentFolderObject (pRecord);
285 SSBranchFileObject* SSFileItem::GetFirstBranchFile ()
287 SSRecordPtr pRecord = GetFile()->GetRecord(GetOffsetBFRecord ());
288 return new SSBranchFileObject (pRecord);
291 std::string SSFileItem::GetName () const
293 return ("FileItem");
295 void SSFileItem::ToXml (XMLNode* pParent) const
297 SSItemInfoObject::ToXml (pParent);
298 XMLElement binary (pParent, "Binary", GetFileType () == eFileTypeBinary ? true : false);
299 XMLElement store (pParent, "StoreOnlyLatestRev", GetStoreOnlyLatestRev ());
300 XMLElement checkedOut (pParent, "CheckedOut", GetCheckedOut ());
301 XMLElement shared (pParent, "Shared", GetShared ());
302 XMLElement sharedSrc (pParent, "ShareSrc", GetShareSrcPhys());
303 XMLElement ref (pParent, "NumberOfReferences", GetNumberOfReferences());
304 XMLElement branch (pParent, "NumberOfBranches", GetNumberOfBranches ());
307 void SSFileItem::Dump (std::ostream& os) const
309 SSItemInfoObject::Dump (os);
311 // Hexdump (oss, dummy4, 20);
313 const DH_FILE* pFileInfoItem = GetData ();
314 os << "Status: 0x" << std::hex << pFileInfoItem->Flag << std::dec << " ";
315 if (pFileInfoItem->Flag == 0x00)
316 os << "normal";
317 else if (pFileInfoItem->Flag == 0x02)
318 os << "binary";
319 else if (pFileInfoItem->Flag == 0x04)
320 os << "store only latest revision";
321 else if (pFileInfoItem->Flag == 0x41)
322 os << "checked out, locked";
323 else if (pFileInfoItem->Flag == 0x43)
324 os << "binary, checked out, locked";
325 else if (pFileInfoItem->Flag == 0x20)
326 os << "shared";
327 else if (pFileInfoItem->Flag == 0x22)
328 os << "binary, shared";
329 else
330 os << "unknown";
331 os << std::endl;
333 os << "Share source physical file: " << pFileInfoItem->ShareSrcSpec << std::endl;
335 os << "Offset to first parent record: 0x" << std::hex << pFileInfoItem->OffsetPFRecord << std::dec << std::endl;
336 os << "Reference count: " << pFileInfoItem->NumberOfReferences << std::endl;
337 os << "Offset to 1st checkout record: 0x" << std::hex << pFileInfoItem->OffsetCFRecord1 << std::dec << std::endl;
338 os << "Offset to 2nd checkout record: 0x" << std::hex << pFileInfoItem->OffsetCFRecord2 << std::dec << std::endl;
340 os << "Number of Items: " << std::hex << pFileInfoItem->NumberOfItems << std::dec << std::endl;
341 os << "Number of Projects: " << std::hex << pFileInfoItem->NumberOfProjects << std::dec << std::endl;