فهرست منبع

non-destructive mode

David Rose 16 سال پیش
والد
کامیت
c5082a543e
2فایلهای تغییر یافته به همراه79 افزوده شده و 41 حذف شده
  1. 72 40
      panda/src/express/patchfile.cxx
  2. 7 1
      panda/src/express/patchfile.h

+ 72 - 40
panda/src/express/patchfile.cxx

@@ -100,7 +100,6 @@ const PN_uint32 Patchfile::_HASH_MASK = (PN_uint32(1) << Patchfile::_HASH_BITS)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 Patchfile::
 Patchfile::
 Patchfile() {
 Patchfile() {
-  _hash_table = NULL;
   PT(Buffer) buffer = new Buffer(patchfile_buffer_size);
   PT(Buffer) buffer = new Buffer(patchfile_buffer_size);
   init(buffer);
   init(buffer);
 }
 }
@@ -112,7 +111,6 @@ Patchfile() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 Patchfile::
 Patchfile::
 Patchfile(PT(Buffer) buffer) {
 Patchfile(PT(Buffer) buffer) {
-  _hash_table = NULL;
   init(buffer);
   init(buffer);
 }
 }
 
 
@@ -123,6 +121,9 @@ Patchfile(PT(Buffer) buffer) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void Patchfile::
 void Patchfile::
 init(PT(Buffer) buffer) {
 init(PT(Buffer) buffer) {
+  _rename_output_to_orig = false;
+  _delete_patchfile = false;
+  _hash_table = NULL;
   _initiated = false;
   _initiated = false;
   nassertv(!buffer.is_null());
   nassertv(!buffer.is_null());
   _buffer = buffer;
   _buffer = buffer;
@@ -143,8 +144,9 @@ Patchfile::
     PANDA_FREE_ARRAY(_hash_table);
     PANDA_FREE_ARRAY(_hash_table);
   }
   }
 
 
-  if (true == _initiated)
+  if (_initiated) {
     cleanup();
     cleanup();
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -154,7 +156,7 @@ Patchfile::
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void Patchfile::
 void Patchfile::
 cleanup() {
 cleanup() {
-  if (false == _initiated) {
+  if (!_initiated) {
     express_cat.error()
     express_cat.error()
       << "Patchfile::cleanup() - Patching has not been initiated"
       << "Patchfile::cleanup() - Patching has not been initiated"
       << endl;
       << endl;
@@ -189,6 +191,22 @@ cleanup() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int Patchfile::
 int Patchfile::
 initiate(const Filename &patch_file, const Filename &file) {
 initiate(const Filename &patch_file, const Filename &file) {
+  int result = initiate(patch_file, file, Filename::temporary("", "patch_"));
+  _rename_output_to_orig = true;
+  _delete_patchfile = !keep_temporary_files;
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Patchfile::initiate
+//       Access: Published
+//  Description: Set up to apply the patch to the file.  In this form,
+//               neither the original file nor the patch file are
+//               destroyed.
+////////////////////////////////////////////////////////////////////
+int Patchfile::
+initiate(const Filename &patch_file, const Filename &orig_file,
+         const Filename &target_file) {
   if (_initiated) {
   if (_initiated) {
     express_cat.error()
     express_cat.error()
       << "Patchfile::initiate() - Patching has already been initiated"
       << "Patchfile::initiate() - Patching has already been initiated"
@@ -196,8 +214,10 @@ initiate(const Filename &patch_file, const Filename &file) {
     return EU_error_abort;
     return EU_error_abort;
   }
   }
 
 
+  nassertr(orig_file != target_file, EU_error_abort);
+
   // Open the original file for read
   // Open the original file for read
-  _orig_file = file;
+  _orig_file = orig_file;
   _orig_file.set_binary();
   _orig_file.set_binary();
   if (!_orig_file.open_read(_origfile_stream)) {
   if (!_orig_file.open_read(_origfile_stream)) {
     express_cat.error()
     express_cat.error()
@@ -206,32 +226,20 @@ initiate(const Filename &patch_file, const Filename &file) {
   }
   }
 
 
   // Open the temp file for write
   // Open the temp file for write
-  {
-    char *tempfilename = tempnam(".", "pf");
-    if (NULL == tempfilename) {
-      express_cat.error()
-        << "Patchfile::initiate() - Failed to create temp file name, using default" << endl;
-      _temp_file = "patcher_temp_file";
-    } else {
-      _temp_file = Filename::from_os_specific(tempfilename);
-      free(tempfilename);
-    }
-  }
-
-  _temp_file.set_binary();
-  if (!_temp_file.open_write(_write_stream)) {
+  _output_file = target_file;
+  _output_file.set_binary();
+  if (!_output_file.open_write(_write_stream)) {
     express_cat.error()
     express_cat.error()
-      << "Patchfile::initiate() - Failed to open file: " << _temp_file << endl;
+      << "Patchfile::initiate() - Failed to open file: " << _output_file << endl;
     return get_write_error();
     return get_write_error();
   }
   }
 
 
   if (express_cat.is_debug()) {
   if (express_cat.is_debug()) {
     express_cat.debug()
     express_cat.debug()
-      << "Using temporary file " << _temp_file << "\n";
+      << "Patchfile using output file " << _output_file << "\n";
   }
   }
 
 
   int result = internal_read_header(patch_file);
   int result = internal_read_header(patch_file);
-
   _total_bytes_processed = 0;
   _total_bytes_processed = 0;
 
 
   _initiated = true;
   _initiated = true;
@@ -410,7 +418,7 @@ run() {
       // check the MD5 from the patch file against the newly patched file
       // check the MD5 from the patch file against the newly patched file
       {
       {
         HashVal MD5_actual;
         HashVal MD5_actual;
-        MD5_actual.hash_file(_temp_file);
+        MD5_actual.hash_file(_output_file);
         if (_MD5_ofResult != MD5_actual) {
         if (_MD5_ofResult != MD5_actual) {
           // Whoops, patching screwed up somehow.
           // Whoops, patching screwed up somehow.
           _origfile_stream.close();
           _origfile_stream.close();
@@ -447,8 +455,10 @@ run() {
           }
           }
 
 
           // delete the temp file and the patch file
           // delete the temp file and the patch file
-          if (!keep_temporary_files) {
-            _temp_file.unlink();
+          if (_rename_output_to_orig) {
+            _output_file.unlink();
+          }
+          if (_delete_patchfile) {
             _patch_file.unlink();
             _patch_file.unlink();
           }
           }
           // return "invalid checksum"
           // return "invalid checksum"
@@ -456,25 +466,20 @@ run() {
         }
         }
       }
       }
 
 
-      // delete the patch file and the original file
-      if (!keep_temporary_files) {
+      // delete the patch file
+      if (_delete_patchfile) {
         _patch_file.unlink();
         _patch_file.unlink();
-        _orig_file.unlink();
-
-      } else {
-        // If we're keeping temporary files, rename the orig file to a
-        // backup.
-        Filename orig_backup = _orig_file.get_fullpath() + ".orig";
-        orig_backup.unlink();
-        _orig_file.rename_to(orig_backup);
       }
       }
 
 
       // rename the temp file to the original file name
       // rename the temp file to the original file name
-      if (!_temp_file.rename_to(_orig_file)) {
-        express_cat.error()
-          << "Patchfile::run() failed to rename temp file to: " << _orig_file
-          << endl;
-        return EU_error_write_file_rename;
+      if (_rename_output_to_orig) {
+        _orig_file.unlink();
+        if (!_output_file.rename_to(_orig_file)) {
+          express_cat.error()
+            << "Patchfile::run() failed to rename temp file to: " << _orig_file
+            << endl;
+          return EU_error_write_file_rename;
+        }
       }
       }
 
 
       return EU_success;
       return EU_success;
@@ -489,6 +494,9 @@ run() {
 //       Access: Public
 //       Access: Public
 //  Description: Patches the entire file in one call
 //  Description: Patches the entire file in one call
 //               returns true on success and false on error
 //               returns true on success and false on error
+//
+//               This version will delete the patch file and overwrite
+//               the original file.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool Patchfile::
 bool Patchfile::
 apply(Filename &patch_file, Filename &file) {
 apply(Filename &patch_file, Filename &file) {
@@ -505,6 +513,30 @@ apply(Filename &patch_file, Filename &file) {
   return false;
   return false;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: Patchfile::apply
+//       Access: Public
+//  Description: Patches the entire file in one call
+//               returns true on success and false on error
+//
+//               This version will not delete any files.
+////////////////////////////////////////////////////////////////////
+bool Patchfile::
+apply(Filename &patch_file, Filename &orig_file, const Filename &target_file) {
+  int ret = initiate(patch_file, orig_file, target_file);
+  if (ret < 0)
+    return false;
+  for (;;) {
+    ret = run();
+    if (ret == EU_success)
+      return true;
+    if (ret < 0)
+      return false;
+  }
+  return false;
+}
+
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Patchfile::internal_read_header
 //     Function: Patchfile::internal_read_header
 //       Access: Private
 //       Access: Private

+ 7 - 1
panda/src/express/patchfile.h

@@ -48,9 +48,13 @@ PUBLISHED:
   int read_header(const Filename &patch_file);
   int read_header(const Filename &patch_file);
 
 
   int initiate(const Filename &patch_file, const Filename &file);
   int initiate(const Filename &patch_file, const Filename &file);
+  int initiate(const Filename &patch_file, const Filename &orig_file,
+               const Filename &target_file);
   int run();
   int run();
 
 
   bool apply(Filename &patch_file, Filename &file);
   bool apply(Filename &patch_file, Filename &file);
+  bool apply(Filename &patch_file, Filename &orig_file, 
+             const Filename &target_file);
 
 
   INLINE float get_progress() const;
   INLINE float get_progress() const;
 
 
@@ -182,7 +186,9 @@ protected:
 
 
   Filename _patch_file;
   Filename _patch_file;
   Filename _orig_file;
   Filename _orig_file;
-  Filename _temp_file;
+  Filename _output_file;
+  bool _rename_output_to_orig;
+  bool _delete_patchfile;
 
 
   static const PN_uint32 _v0_magic_number;
   static const PN_uint32 _v0_magic_number;
   static const PN_uint32 _magic_number;
   static const PN_uint32 _magic_number;