1 // GetCommand.cpp: implementation of the GetCommand class.
3 //////////////////////////////////////////////////////////////////////
6 #include "GetCommand.h"
7 #include <SSPhysLib\SSFiles.h>
8 #include <SSPhysLib\SSItemInfoObject.h>
9 #include <SSPhysLib\SSVersionObject.h>
10 #include <SSPhysLib\FileName.h>
11 #include <SSPhysLib\SSProjectObject.h>
18 //////////////////////////////////////////////////////////////////////
19 // Construction/Destruction
20 //////////////////////////////////////////////////////////////////////
21 bool fexists (const char* file
)
23 FILE* pFile
= fopen (file
, "r");
32 //---------------------------------------------------------------------------
33 CGetCommand::CGetCommand ()
36 m_bForceOverwrite (false),
41 COptionInfoList
CGetCommand::GetOptionsInfo () const
43 COptionInfoList options
= CCommand::GetOptionsInfo();
44 options
.push_back (COptionInfo ('v', 'v', "version", "version to get", COptionInfo::requiredArgument
));
45 options
.push_back (COptionInfo ('f', 'f', "force-overwrite", "overwrite target file", COptionInfo::noArgument
));
46 options
.push_back (COptionInfo ('b', 'b', "bulk", "bulk operation: get all intermediate files with the same name as the source name", COptionInfo::noArgument
));
50 bool CGetCommand::SetOption (const COption
& option
)
55 m_Version
= atoi ((const char*) option
.value
);
58 m_bForceOverwrite
= true;
69 bool CGetCommand::SetArguments (CArguments
& args
)
72 throw SSException ("no argument");
74 m_PhysFile
= args
.front ();
78 throw SSException ("missing argument");
80 m_DestFile
= args
.front ();
88 class CActionVisitor
: public ISSActionVisitor
91 virtual ~CActionVisitor () {}
93 virtual bool Apply (const SSLabeledAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
94 // virtual bool Apply (const SSSingleFileAction& rAction) { return Apply ((const SSAction&) rAction); }
95 virtual bool Apply (const SSCreatedProjectAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
96 virtual bool Apply (const SSCreatedFileAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
97 virtual bool Apply (const SSAddedProjectAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
98 virtual bool Apply (const SSAddedFileAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
99 virtual bool Apply (const SSDeletedProjectAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
100 virtual bool Apply (const SSDeletedFileAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
101 virtual bool Apply (const SSRecoveredProjectAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
102 virtual bool Apply (const SSRecoveredFileAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
103 virtual bool Apply (const SSRollbackAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
105 virtual bool Apply (const SSDestroyedProjectAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
106 virtual bool Apply (const SSDestroyedFileAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
107 virtual bool Apply (const SSRenamedProjectAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
108 virtual bool Apply (const SSRenamedFileAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
109 virtual bool Apply (const SSCheckedInAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
110 virtual bool Apply (const SSSharedAction
& rAction
) { return Apply ((const SSAction
&) rAction
); }
113 virtual bool Apply (const SSAction
& rAction
)
120 std::string
CreateTempFile ( const char* pzPrefix
= NULL
, const char* pzPath
= NULL
)
122 return tempnam( pzPath
, pzPrefix
);
125 // std::string cPath = tempnam( pzPath, pzPrefix );
126 // if (Open (cPath, O_RDWR | O_CREAT | O_EXCL ) < 0)
128 // if ( errno == EEXIST )
134 //// throw errno_exception( "Failed to create file" );
148 CAutoFile (std::string name
, bool bDelete
= true)
150 m_bDeleteFile (bDelete
)
154 CAutoFile (CAutoFile
const & r
)
155 : m_bDeleteFile (r
.m_bDeleteFile
),
156 m_FileName (r
.Detatch ())
160 CAutoFile
& operator= (CAutoFile
const & r
)
164 if (m_FileName
!= r
.GetPath())
168 m_bDeleteFile
= r
.m_bDeleteFile
;
170 else if (r
.m_bDeleteFile
)
171 m_bDeleteFile
= r
.m_bDeleteFile
;
172 m_FileName
= r
.Detatch();
183 std::string
GetPath () const { return m_FileName
; }
185 std::string
Detatch() const;
190 std::string m_FileName
;
191 mutable bool m_bDeleteFile
;
194 std::string
CAutoFile::Detatch() const
196 m_bDeleteFile
= false;
200 int CAutoFile::Unlink()
204 m_bDeleteFile
= false;
205 return( unlink( m_FileName
.c_str () ) );
218 CReverseDelta (const char* buffer
, size_t length
)
219 : m_pBuffer (buffer
), m_length (length
)
223 bool operator () (std::istream
& input
, std::ostream
& output
) const
225 for (long i
= 0; i
< m_length
; )
227 const FD
* pfd
= (const FD
*) (m_pBuffer
+i
);
229 // printf ("fd: %d, start %d, len %d\n", pfd->command, pfd->start, pfd->end);
231 switch (pfd
->command
)
239 long size
= pfd
->end
;
240 input
.seekg(pfd
->start
);
242 throw SSException ("reverse delta: invalid seek beyond file size");
246 long s
= __min (size
, sizeof (b
));
254 output
.write (m_pBuffer
+i
, pfd
->end
);
259 msg
<< "unknown reverse delta command " << pfd
->command
;
260 throw SSException (msg
.str());
268 const char* m_pBuffer
;
273 class CHistoryHandler
: public CActionVisitor
276 CHistoryHandler (std::string src
)
277 : m_File (src
, false)
281 std::string
GetPath ()
283 return m_File
.GetPath();
286 virtual bool SaveAs (std::string name
, bool overwrite
= false) = 0;
293 class CReverseHistoryHandler
: public CHistoryHandler
296 CReverseHistoryHandler (std::string src
)
297 : CHistoryHandler (src
)
301 virtual bool Apply (const SSCheckedInAction
& rAction
)
303 SSRecordPtr pRecord
= rAction
.GetFileDelta();
304 CAutoFile
targetFile (CreateTempFile());
306 std::ifstream
input (m_File
.GetPath().c_str(), std::ios::in
|std::ios::binary
);
307 if (!input
.is_open())
309 std::ofstream
output (targetFile
.GetPath().c_str(), std::ios::out
|std::ios::binary
);
310 if (!output
.is_open())
313 CReverseDelta
revDelta ((const char*)pRecord
->GetBuffer(), pRecord
->GetLen());
314 bool ret
= revDelta (input
, output
);
326 virtual bool SaveAs (std::string name
, bool overwrite
= false)
328 return ::CopyFile (GetPath ().c_str(), name
.c_str(), !overwrite
) != 0;
331 virtual bool Apply (const SSAction
& rAction
)
333 throw SSException ("unsuported action in CReverseHistoryHandler");
338 class CProjectHistoryHandler
: public CHistoryHandler
341 CProjectHistoryHandler (std::string src
)
342 : CHistoryHandler (src
)
344 SSProjectFile
projectFile (GetPath ());
345 BuildList (projectFile
);
348 virtual bool SaveAs (std::string name
, bool overwrite
= false)
353 virtual bool Apply (const SSLabeledAction
& rAction
) { /* nothing to do */ return true; }
354 //// virtual bool Apply (const SSSingleFileAction& rAction) { return Apply ((const SSAction&) rAction); }
355 virtual bool Apply (const SSCreatedProjectAction
& rAction
) { /* nothing to do */ return true; }
356 virtual bool Apply (const SSCreatedFileAction
& rAction
) { /* nothing to do */ return true; }
357 virtual bool Apply (const SSAddedProjectAction
& rAction
);
358 virtual bool Apply (const SSAddedFileAction
& rAction
);
359 virtual bool Apply (const SSDeletedProjectAction
& rAction
);
360 virtual bool Apply (const SSDeletedFileAction
& rAction
);
361 virtual bool Apply (const SSRecoveredProjectAction
& rAction
);
362 virtual bool Apply (const SSRecoveredFileAction
& rAction
);
364 virtual bool Apply (const SSDestroyedProjectAction
& rAction
);
365 virtual bool Apply (const SSDestroyedFileAction
& rAction
);
366 virtual bool Apply (const SSRenamedProjectAction
& rAction
);
367 virtual bool Apply (const SSRenamedFileAction
& rAction
);
368 // virtual bool Apply (const SSCheckedInAction& rAction) { return Apply ((const SSAction&) rAction); }
370 // virtual bool Apply (const SSSharedFileAction& rAction) { return Apply ((const SSAction&) rAction); }
373 virtual bool Apply (const SSAction
& rAction
)
375 throw SSException ("unsuported action in CProjectHistoryHandler");
378 typedef std::vector
<SSProjectObject
>::iterator iterator
;
379 std::vector
<SSProjectObject
> m_Items
;
381 void BuildList (SSProjectFile
& rFile
);
382 iterator
FindItem (std::string physFile
);
383 iterator
InsertItem (SSProjectObject object
);
388 void CProjectHistoryHandler::BuildList (SSProjectFile
& rFile
)
390 // iterate all records and add them to the collection
391 SSRecordPtr recordPtr
= rFile
.GetFirstRecord ();
394 if (recordPtr
->GetType() == eProjectEntry
)
396 SSProjectObject
projectObject (recordPtr
);
397 m_Items
.push_back (projectObject
);
400 recordPtr
= rFile
.GetNextRecord (recordPtr
);
404 CProjectHistoryHandler::iterator
CProjectHistoryHandler::FindItem (std::string physFile
)
407 iterator end
= m_Items
.end();
408 iterator found
= end
;
410 for (itor
= m_Items
.begin(); itor
!= end
; ++itor
)
412 SSProjectObject
& po
= *itor
;
413 // std::cout << itemPtr->GetPhysical () << std::endl;
414 if (physFile
== po
.GetPhysFile())
417 throw SSException ("duplicate entry");
426 CProjectHistoryHandler::iterator
CProjectHistoryHandler::InsertItem (SSProjectObject object
)
428 m_Items
.push_back (object
);
429 iterator last
= m_Items
.end();
433 bool CProjectHistoryHandler::Apply (const SSAddedFileAction
& rAction
)
435 iterator itor
= FindItem (rAction
.GetPhysical());
436 if (itor
!= m_Items
.end())
439 throw SSException ("item not found");
444 bool CProjectHistoryHandler::Apply (const SSAddedProjectAction
& rAction
)
446 iterator itor
= FindItem (rAction
.GetPhysical());
447 if (itor
!= m_Items
.end())
450 throw SSException ("item not found");
455 bool CProjectHistoryHandler::Apply (const SSDeletedFileAction
& rAction
)
457 iterator itor
= FindItem (rAction
.GetPhysical());
458 if (itor
!= m_Items
.end ())
460 SSProjectObject
& po
= *itor
;
464 throw SSException ("item not found");
468 bool CProjectHistoryHandler::Apply (const SSDeletedProjectAction
& rAction
)
470 iterator itor
= FindItem (rAction
.GetPhysical());
471 if (itor
!= m_Items
.end ())
473 SSProjectObject
& po
= *itor
;
477 throw SSException ("item not found");
481 bool CProjectHistoryHandler::Apply (const SSRecoveredFileAction
& rAction
)
483 iterator itor
= FindItem (rAction
.GetPhysical());
484 if (itor
!= m_Items
.end ())
486 SSProjectObject
& po
= *itor
;
490 throw SSException ("item not found");
494 bool CProjectHistoryHandler::Apply (const SSRecoveredProjectAction
& rAction
)
496 iterator itor
= FindItem (rAction
.GetPhysical());
497 if (itor
!= m_Items
.end ())
499 SSProjectObject
& po
= *itor
;
503 throw SSException ("item not found");
508 bool CProjectHistoryHandler::Apply (const SSDestroyedProjectAction
& rAction
)
510 if (FindItem (rAction
.GetPhysical ()) != m_Items
.end ())
511 throw SSException ("adding already existing item");
515 pe
.name
= rAction
.GetSSName ();
516 strncpy (pe
.phys
, rAction
.GetPhysical().c_str(), 8);
518 pe
.pinnedToVersion
= 0;
520 SSProjectObject
pr (pe
);
526 bool CProjectHistoryHandler::Apply (const SSDestroyedFileAction
& rAction
)
528 // durch map wahrscheinlich besser zu lösen
529 if (FindItem (rAction
.GetPhysical()) != m_Items
.end ())
530 throw SSException ("adding already existing item");
534 pe
.name
= rAction
.GetSSName ();
535 strncpy (pe
.phys
, rAction
.GetPhysical().c_str(), 8);
537 pe
.pinnedToVersion
= 0;
539 SSProjectObject
pr (pe
);
545 bool CProjectHistoryHandler::Apply (const SSRenamedProjectAction
& rAction
)
547 iterator itor
= FindItem (rAction
.GetPhysical());
548 if (itor
== m_Items
.end ())
549 throw SSException ("item not found");
551 SSProjectObject
& po
= *itor
;
552 po
.Rename (rAction
.GetNewSSName (), rAction
.GetSSName());
556 bool CProjectHistoryHandler::Apply (const SSRenamedFileAction
& rAction
)
558 iterator itor
= FindItem (rAction
.GetPhysical());
559 if (itor
== m_Items
.end ())
560 throw SSException ("item not found");
562 SSProjectObject
& po
= *itor
;
563 po
.Rename (rAction
.GetNewSSName (), rAction
.GetSSName());
572 void CGetCommand::Execute ()
574 if (m_DestFile
.empty ())
575 throw SSException ("please specify a destination file for the get operation");
577 if (fexists (m_DestFile
.c_str ()) && !m_bForceOverwrite
)
578 throw SSException ("destination file exists. Please use overwrite flag");
580 SSHistoryFile
file(m_PhysFile
);
581 std::auto_ptr
<SSItemInfoObject
> pItem (file
.GetItemInfo());
583 throw SSException ("no information object found");
585 std::auto_ptr
<CHistoryHandler
> pVisitor
;
586 std::string lastDataFileName
= pItem
->GetDataFileName ();
588 if (pItem
->GetType() == SSITEM_FILE
)
589 pVisitor
= std::auto_ptr
<CHistoryHandler
> (new CReverseHistoryHandler (lastDataFileName
));
591 pVisitor
= std::auto_ptr
<CHistoryHandler
> (new CProjectHistoryHandler (lastDataFileName
));
594 SSVersionObject
version (pItem
->GetHistoryLast ());
595 while (version
&& version
.GetVersionNumber() > m_Version
)
597 if (version
.GetAction())
599 version
.GetAction ()->Accept (*pVisitor
.get());
603 CFileName
fname (m_PhysFile
.c_str ());
604 fname
.SetExt (itoa (version
.GetVersionNumber (), buffer
, 10));
606 if (!pVisitor
->SaveAs (fname
.GetFileName ().c_str(), false))
607 throw SSException ("failed to create target file" + fname
.GetFileName ());
611 version
= version
.GetPreviousObject ();
614 if (!pVisitor
->SaveAs (m_DestFile
.c_str(), m_bForceOverwrite
))
615 throw SSException ("failed to create target file");