Check-in [dead090c0b]
Not logged in
Overview

SHA1 Hash:dead090c0bd601124619cbde91215e9a873972bc
Date: 2007-07-31 20:20:40
User: drh
Comment:Update the ZIP archiver to include date information. Provide a function that constructs a ZIP archive from manifest.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified src/zip.c from [967d1ecc36] to [8d50d34cbb].

@@ -46,27 +46,57 @@
 ** Variables in which to accumulate a growing ZIP archive.
 */
 static Blob body;    /* The body of the ZIP archive */
 static Blob toc;     /* The table of contents */
 static int nEntry;   /* Number of files */
+static int dosTime;  /* DOS-format time */
+static int dosDate;  /* DOS-format date */
 
 /*
 ** Initialize a new ZIP archive.
 */
 void zip_open(void){
   blob_zero(&body);
   blob_zero(&toc);
   nEntry = 0;
+  dosTime = 0;
+  dosDate = 0;
+}
+
+/*
+** Set the date and time values from an ISO8601 date string.
+*/
+void zip_set_timedate_from_str(const char *zDate){
+  int y, m, d;
+  int H, M, S;
+
+  y = atoi(zDate);
+  m = atoi(&zDate[5]);
+  d = atoi(&zDate[8]);
+  H = atoi(&zDate[11]);
+  M = atoi(&zDate[14]);
+  S = atoi(&zDate[17]);
+  dosTime = (H<<11) + (M<<5) + S;
+  dosDate = ((y-1980)<<9) + (m<<5) + d;
+}
+
+/*
+** Set the date and time from a julian day number.
+*/
+void zip_set_timedate(double rDate){
+  char *zDate = db_text(0, "SELECT datetime(%.17g)", rDate);
+  zip_set_timedate_from_str(zDate);
+  free(zDate);
 }
 
 /*
 ** Append a single file to a growing ZIP archive.
 **
 ** pFile is the file to be appended.  zName is the name
 ** that the file should be saved as.
 */
-int zip_add_file(const char *zName, const Blob *pFile){
+void zip_add_file(const char *zName, const Blob *pFile){
   z_stream stream;
   int nameLen;
   int skip;
   int toOut;
   int iStart;
@@ -83,12 +113,12 @@
   nameLen = strlen(zName);
   put32(&zHdr[0], 0x04034b50);
   put16(&zHdr[4], 0x0014);
   put16(&zHdr[6], 0);
   put16(&zHdr[8], 8);
-  put16(&zHdr[10], 0);
-  put16(&zHdr[12], 0);
+  put16(&zHdr[10], dosTime);
+  put16(&zHdr[12], dosDate);
   put16(&zHdr[26], nameLen);
   put16(&zHdr[28], 0);
 
   /* Write the header and filename.
   */
@@ -154,12 +184,12 @@
   put32(&zBuf[0], 0x02014b50);
   put16(&zBuf[4], 0x0317);
   put16(&zBuf[6], 0x0014);
   put16(&zBuf[8], 0);
   put16(&zBuf[10], 0x0008);
-  put16(&zBuf[12], 0);
-  put16(&zBuf[14], 0);
+  put16(&zBuf[12], dosTime);
+  put16(&zBuf[14], dosDate);
   put32(&zBuf[16], iCRC);
   put32(&zBuf[20], nByteCompr);
   put32(&zBuf[24], nByte);
   put16(&zBuf[28], nameLen);
   put16(&zBuf[30], 0);
@@ -175,11 +205,11 @@
 
 
 /*
 ** Write the ZIP archive into the given BLOB.
 */
-int zip_close(Blob *pZip){
+void zip_close(Blob *pZip){
   int iTocStart;
   int iTocEnd;
   char zBuf[30];
 
   iTocStart = blob_size(&body);
@@ -222,6 +252,67 @@
     zip_add_file(g.argv[i], &file);
     blob_reset(&file);
   }
   zip_close(&zip);
   blob_write_to_file(&zip, g.argv[2]);
+}
+
+/*
+** Given the RID for a manifest, construct a ZIP archive containing
+** all files in the corresponding baseline.
+**
+** If RID is for an object that is not a real manifest, then the
+** resulting ZIP archive contains a single file which is the RID
+** object.
+**
+** If the RID object does not exist in the repository, then
+** pZip is zeroed.
+*/
+void zip_of_baseline(int rid, Blob *pZip){
+  int i;
+  Blob mfile, file;
+  Manifest m;
+
+  content_get(rid, &mfile);
+  if( blob_size(&mfile)==0 ){
+    blob_zero(pZip);
+    return;
+  }
+  blob_zero(&file);
+  blob_copy(&file, &mfile);
+  zip_open();
+  if( manifest_parse(&m, &mfile) ){
+    zip_set_timedate(m.rDate);
+    zip_add_file("manifest", &file);
+    blob_reset(&file);
+    for(i=0; i<m.nFile; i++){
+      int fid = uuid_to_rid(m.aFile[i].zUuid, 0);
+      if( fid ){
+        content_get(fid, &file);
+        zip_add_file(m.aFile[i].zName, &file);
+        blob_reset(&file);
+      }
+    }
+    manifest_clear(&m);
+  }else{
+    blob_reset(&mfile);
+    blob_reset(&file);
+  }
+  zip_close(pZip);
+}
+
+/*
+** COMMAND: test-baseline-zip
+**
+** Generate a ZIP archive for a specified baseline.
+*/
+void baseline_zip_cmd(void){
+  int rid;
+  Blob zip;
+  if( g.argc!=4 ){
+    usage("UUID ZIPFILE");
+  }
+  db_must_be_within_tree();
+  rid = name_to_rid(g.argv[2]);
+  zip_of_baseline(rid, &zip);
+  blob_write_to_file(&zip, g.argv[3]);
 }

Modified todo.txt from [9ee026f875] to [f69075047f].

@@ -60,24 +60,21 @@
         Information available in the mlink table.  Hyperlinks to
         the finfo page for each file.
      +  Hyperlinks to diff all files in this version against any
         of the named decendents or ancestors.  The unified_diff()
         function will compute a unified diff given to file blobs.
+     +  Add a link that will download a ZIP archive containing the
+        complete baseline.  Use zip_of_baseline() function in
+        zip.c to construct the ZIP archive.
 
  *  A new webpage: "finfo"  Information about a particular file
     given its name.
 
      +  All historical changes to this file with version number,
         user, and comment, and hyperlink to the vinfo page for
         the version.  Information available from the minfo table.
      +  Hyperlinks for diffing consecutive versions of the file.
-
- *  Given any version uuid, construct a ZIP archive that contains
-    the complete content for that version.  Feature should be
-    callable from the command-line or from the www interface.
-    Perhaps a hyperlink on the vinfo page to download the ZIP archive
-    for any version.
 
  *  Timeline enhanced so that you can specify a range of dates.
 
  *  The /xfer handler (for push, pull, and clone) does not do
     delta compression.  This results in excess bandwidth usage.