Diff
Not logged in

Differences From:

File src/zip.c part of check-in [9b780d220b] - Add a ZIP archive generator. by drh on 2007-07-31 19:18:53. [view]

To:

File src/zip.c part of check-in [dead090c0b] - Update the ZIP archiver to include date information. Provide a function that constructs a ZIP archive from manifest. by drh on 2007-07-31 20:20:40. [view]

@@ -47,8 +47,10 @@
 */
 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.
 */
@@ -55,8 +57,36 @@
 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.
@@ -63,9 +93,9 @@
 **
 ** 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;
@@ -84,10 +114,10 @@
   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.
@@ -155,10 +185,10 @@
   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);
@@ -176,9 +206,9 @@
 
 /*
 ** 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];
 
@@ -223,5 +253,66 @@
     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]);
 }