Fossil

Check-in [4619361d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fill islink field in vfile table when adding files. Support symlinks in export. Make manifest_file_perm() return 2 for symlinks. Add file_perm() function, and use it instead of file_isexe() when we need both isexe and islink properties.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | symlinks
Files: files | file ages | folders
SHA1:4619361d585c8c52a827eb8a470c8e0cbe28f3e2
User & Date: dmitry 2011-08-23 17:44:23
Context
2011-08-24
19:12
Support symlinks in ZIP files. check-in: 16da26c5 user: dmitry tags: symlinks
2011-08-23
17:44
Fill islink field in vfile table when adding files. Support symlinks in export. Make manifest_file_perm() return 2 for symlinks. Add file_perm() function, and use it instead of file_isexe() when we need both isexe and islink properties. check-in: 4619361d user: dmitry tags: symlinks
16:50
Avoid using invalid SQL when checking to see if the vfile table needs to have the islink column added. check-in: 2de9e876 user: drh tags: symlinks
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/add.c.

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
  if( db_exists("SELECT 1 FROM vfile"
                " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){
    db_multi_exec("UPDATE vfile SET deleted=0"
                  " WHERE pathname=%Q COLLATE %s", zPath, zCollate);
  }else{
    char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
    db_multi_exec(
      "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
      "VALUES(%d,0,0,0,%Q,%d)",
      vid, zPath, file_isexe(zFullname));
    fossil_free(zFullname);
  }
  if( db_changes() ){
    fossil_print("ADDED  %s\n", zPath);
    return 1;
  }else{
    fossil_print("SKIP   %s\n", zPath);







|
|
|







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
  if( db_exists("SELECT 1 FROM vfile"
                " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){
    db_multi_exec("UPDATE vfile SET deleted=0"
                  " WHERE pathname=%Q COLLATE %s", zPath, zCollate);
  }else{
    char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
    db_multi_exec(
      "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink)"
      "VALUES(%d,0,0,0,%Q,%d,%d)",
      vid, zPath, file_isexe(zFullname), file_islink(zFullname));
    fossil_free(zFullname);
  }
  if( db_changes() ){
    fossil_print("ADDED  %s\n", zPath);
    return 1;
  }else{
    fossil_print("SKIP   %s\n", zPath);

Changes to src/export.c.

267
268
269
270
271
272
273
274







275

276
277
278
279
280
281
282
    );
    while( db_step(&q4)==SQLITE_ROW ){
      const char *zName = db_column_text(&q4,0);
      int zNew = db_column_int(&q4,1);
      int mPerm = db_column_int(&q4,2);
      if( zNew==0)
        printf("D %s\n", zName);
      else if( bag_find(&blobs, zNew) )







        printf("M %s :%d %s\n", mPerm ? "100755" : "100644", BLOBMARK(zNew), zName);

    }
    db_finalize(&q4);
    db_finalize(&q3);
    printf("\n");
  }
  db_finalize(&q2);
  db_finalize(&q);







|
>
>
>
>
>
>
>
|
>







267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
    );
    while( db_step(&q4)==SQLITE_ROW ){
      const char *zName = db_column_text(&q4,0);
      int zNew = db_column_int(&q4,1);
      int mPerm = db_column_int(&q4,2);
      if( zNew==0)
        printf("D %s\n", zName);
      else if( bag_find(&blobs, zNew) ) {
        const char *zPerm;
        if( mPerm==1 )
          zPerm = "100755";
        else if( mPerm==2 )
          zPerm = "120000";
        else
          zPerm = "100644";
        printf("M %s :%d %s\n", zPerm, BLOBMARK(zNew), zName);
      }
    }
    db_finalize(&q4);
    db_finalize(&q3);
    printf("\n");
  }
  db_finalize(&q2);
  db_finalize(&q);

Changes to src/file.c.

195
196
197
198
199
200
201















202
203
204
205
206
207
208
#  endif
  return ((S_IXUSR)&fileStat.st_mode)!=0;
#else
  return ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0;
#endif
}

















/*
** Return 1 if zFilename is a directory.  Return 0 if zFilename
** does not exist.  Return 2 if zFilename exists but is something
** other than a directory.
*/
int file_isdir(const char *zFilename){







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#  endif
  return ((S_IXUSR)&fileStat.st_mode)!=0;
#else
  return ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0;
#endif
}


/*
** Return file "permissions":
** 0: normal
** 1: exec
** 2: symlink
*/
int file_perm(const char *zFilename){
  //TODO(dchest): optimize by calling stat once.
  if( file_isexe(zFilename) )
    return 1;
  if( file_islink(zFilename) )
    return 2;
  return 0;
}

/*
** Return 1 if zFilename is a directory.  Return 0 if zFilename
** does not exist.  Return 2 if zFilename exists but is something
** other than a directory.
*/
int file_isdir(const char *zFilename){

Changes to src/info.c.

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
...
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
*/
static void append_file_change_line(
  const char *zName,    /* Name of the file that has changed */
  const char *zOld,     /* blob.uuid before change.  NULL for added files */
  const char *zNew,     /* blob.uuid after change.  NULL for deletes */
  const char *zOldName, /* Prior name.  NULL if no name change. */
  int showDiff,         /* Show edit diffs if true */
  int mperm             /* EXE permission for zNew */
){
  if( !g.okHistory ){
    if( zNew==0 ){
      @ <p>Deleted %h(zName)</p>
    }else if( zOld==0 ){
      @ <p>Added %h(zName)</p>
    }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
      @ <p>Name change from %h(zOldName) to %h(zName)
    }else if( fossil_strcmp(zNew, zOld)==0 ){
      @ <p>Execute permission %s(mperm?"set":"cleared") for %h(zName)</p>
    }else{
      @ <p>Changes to %h(zName)</p>
    }
    if( showDiff ){
      @ <blockquote><pre>
      append_diff(zOld, zNew);
      @ </pre></blockquote>
................................................................................
        @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
        @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>
      }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
        @ <p>Name change from
        @ from <a href="%s(g.zTop)/finfo?name=%T(zOldName)">%h(zOldName)</a>
        @ to <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>.
      }else{
        @ <p>Execute permission %s(mperm?"set":"cleared") for
        @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      }
    }else if( zOld ){
      @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
    }else{
      @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>







|









|







 







|







280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
...
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
*/
static void append_file_change_line(
  const char *zName,    /* Name of the file that has changed */
  const char *zOld,     /* blob.uuid before change.  NULL for added files */
  const char *zNew,     /* blob.uuid after change.  NULL for deletes */
  const char *zOldName, /* Prior name.  NULL if no name change. */
  int showDiff,         /* Show edit diffs if true */
  int mperm             /* executable or symlink permission for zNew */
){
  if( !g.okHistory ){
    if( zNew==0 ){
      @ <p>Deleted %h(zName)</p>
    }else if( zOld==0 ){
      @ <p>Added %h(zName)</p>
    }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
      @ <p>Name change from %h(zOldName) to %h(zName)
    }else if( fossil_strcmp(zNew, zOld)==0 ){
      @ <p>Execute permission %s(( mperm==1 )?"set":"cleared") for %h(zName)</p>
    }else{
      @ <p>Changes to %h(zName)</p>
    }
    if( showDiff ){
      @ <blockquote><pre>
      append_diff(zOld, zNew);
      @ </pre></blockquote>
................................................................................
        @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
        @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>
      }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
        @ <p>Name change from
        @ from <a href="%s(g.zTop)/finfo?name=%T(zOldName)">%h(zOldName)</a>
        @ to <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>.
      }else{
        @ <p>Execute permission %s(( mperm==1 )?"set":"cleared") for
        @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      }
    }else if( zOld ){
      @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
    }else{
      @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>

Changes to src/manifest.c.

1084
1085
1086
1087
1088
1089
1090

1091
1092


1093
1094
1095
1096
1097
1098
1099
....
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115

/*
** Compute an appropriate mlink.mperm integer for the permission string
** of a file.
*/
int manifest_file_mperm(ManifestFile *pFile){
  int mperm = 0;

  if( pFile && pFile->zPerm && strstr(pFile->zPerm,"x")!=0 ){
    mperm = 1;


  }
  return mperm;
}

/*
** Add a single entry to the mlink table.  Also add the filename to
** the filename table if it is not there already.
................................................................................
static void add_one_mlink(
  int mid,                  /* The record ID of the manifest */
  const char *zFromUuid,    /* UUID for the mlink.pid. "" to add file */
  const char *zToUuid,      /* UUID for the mlink.fid. "" to delele */
  const char *zFilename,    /* Filename */
  const char *zPrior,       /* Previous filename. NULL if unchanged */
  int isPublic,             /* True if mid is not a private manifest */
  int mperm                 /* 1: exec */
){
  int fnid, pfnid, pid, fid;
  static Stmt s1;

  fnid = filename_to_fnid(zFilename);
  if( zPrior==0 ){
    pfnid = 0;







>
|
|
>
>







 







|







1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
....
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118

/*
** Compute an appropriate mlink.mperm integer for the permission string
** of a file.
*/
int manifest_file_mperm(ManifestFile *pFile){
  int mperm = 0;
  if( pFile && pFile->zPerm){
    if( strstr(pFile->zPerm,"x")!=0 )
      mperm = 1;
    else if( strstr(pFile->zPerm,"l")!=0 )
      mperm = 2;
  }
  return mperm;
}

/*
** Add a single entry to the mlink table.  Also add the filename to
** the filename table if it is not there already.
................................................................................
static void add_one_mlink(
  int mid,                  /* The record ID of the manifest */
  const char *zFromUuid,    /* UUID for the mlink.pid. "" to add file */
  const char *zToUuid,      /* UUID for the mlink.fid. "" to delele */
  const char *zFilename,    /* Filename */
  const char *zPrior,       /* Previous filename. NULL if unchanged */
  int isPublic,             /* True if mid is not a private manifest */
  int mperm                 /* 1: exec, 2: symlink */
){
  int fnid, pfnid, pid, fid;
  static Stmt s1;

  fnid = filename_to_fnid(zFilename);
  if( zPrior==0 ){
    pfnid = 0;

Changes to src/update.c.

566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
  }
  pManifest = manifest_get(rid, CFTYPE_MANIFEST);
  
  if( pManifest ){
    pFile = manifest_file_seek(pManifest, file);
    if( pFile ){
      rid = uuid_to_rid(pFile->zUuid, 0);
      if( pIsExe ) *pIsExe = manifest_file_mperm(pFile);
      if( pIsLink ){
	//TODO(dchest): figure out how to fit manifest_file_mperm.
	*pIsLink = pFile->zPerm && strstr(pFile->zPerm, "l") ? 1 : 0;
      }
      manifest_destroy(pManifest);
      return content_get(rid, content);
    }
    manifest_destroy(pManifest);
    if( errCode<=0 ){
      fossil_fatal("file %s does not exist in checkin: %s", file, revision);
    }







|
|
<
<
<







566
567
568
569
570
571
572
573
574



575
576
577
578
579
580
581
  }
  pManifest = manifest_get(rid, CFTYPE_MANIFEST);
  
  if( pManifest ){
    pFile = manifest_file_seek(pManifest, file);
    if( pFile ){
      rid = uuid_to_rid(pFile->zUuid, 0);
      if( pIsExe ) *pIsExe = ( manifest_file_mperm(pFile)==1 );
      if( pIsLink ) *pIsLink = ( manifest_file_mperm(pFile)==2 );



      manifest_destroy(pManifest);
      return content_get(rid, content);
    }
    manifest_destroy(pManifest);
    if( errCode<=0 ){
      fossil_fatal("file %s does not exist in checkin: %s", file, revision);
    }

Changes to src/vfile.c.

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
      size = 0;
    }
    db_reset(&ridq);
    if( rid==0 || size<0 ){
      fossil_warning("content missing for %s", pFile->zName);
      continue;
    }
    db_bind_int(&ins, ":isexe", manifest_file_mperm(pFile));
    db_bind_int(&ins, ":id", rid);
    db_bind_text(&ins, ":name", pFile->zName);
    //TODO(dchest) figure out how to fit manifest_file_mperm here:
    db_bind_int(&ins, ":islink", pFile->zPerm && strstr(pFile->zPerm, "l"));
    db_step(&ins);
    db_reset(&ins);
  }
  db_finalize(&ridq);
  db_finalize(&ins);
  manifest_destroy(p);
  db_end_transaction(0);







|


<
|







108
109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
      size = 0;
    }
    db_reset(&ridq);
    if( rid==0 || size<0 ){
      fossil_warning("content missing for %s", pFile->zName);
      continue;
    }
    db_bind_int(&ins, ":isexe", ( manifest_file_mperm(pFile)==1 ));
    db_bind_int(&ins, ":id", rid);
    db_bind_text(&ins, ":name", pFile->zName);

    db_bind_int(&ins, ":islink", ( manifest_file_mperm(pFile)==2 ));
    db_step(&ins);
    db_reset(&ins);
  }
  db_finalize(&ridq);
  db_finalize(&ins);
  manifest_destroy(p);
  db_end_transaction(0);

Changes to src/zip.c.

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

/*
** 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.
*/
void zip_add_file(const char *zName, const Blob *pFile, int isExe){
  z_stream stream;
  int nameLen;
  int toOut = 0;
  int iStart;
  int iCRC = 0;
  int nByte = 0;
  int nByteCompr = 0;
................................................................................
  char zOutBuf[100000];

  /* Fill in as much of the header as we know.
  */
  nBlob = pFile ? blob_size(pFile) : 0;
  if( nBlob>0 ){
    iMethod = 8;
    iMode =  isExe ? 0100755 : 0100644;
  }else{
    iMethod = 0;
    iMode = 040755;
  }
  nameLen = strlen(zName);
  memset(zHdr, 0, sizeof(zHdr));
  put32(&zHdr[0], 0x04034b50);
................................................................................
  if( g.argc<3 ){
    usage("ARCHIVE FILE....");
  }
  zip_open();
  for(i=3; i<g.argc; i++){
    blob_zero(&file);
    blob_read_from_file(&file, g.argv[i]);
    zip_add_file(g.argv[i], &file, file_isexe(g.argv[i]));
    blob_reset(&file);
  }
  zip_close(&zip);
  blob_write_to_file(&zip, g.argv[2]);
}

/*







|







 







|







 







|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

/*
** 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.
*/
void zip_add_file(const char *zName, const Blob *pFile, int mPerm){
  z_stream stream;
  int nameLen;
  int toOut = 0;
  int iStart;
  int iCRC = 0;
  int nByte = 0;
  int nByteCompr = 0;
................................................................................
  char zOutBuf[100000];

  /* Fill in as much of the header as we know.
  */
  nBlob = pFile ? blob_size(pFile) : 0;
  if( nBlob>0 ){
    iMethod = 8;
    iMode = ( mPerm == 1 ) ? 0100755 : 0100644; //TODO(dchest): handle links
  }else{
    iMethod = 0;
    iMode = 040755;
  }
  nameLen = strlen(zName);
  memset(zHdr, 0, sizeof(zHdr));
  put32(&zHdr[0], 0x04034b50);
................................................................................
  if( g.argc<3 ){
    usage("ARCHIVE FILE....");
  }
  zip_open();
  for(i=3; i<g.argc; i++){
    blob_zero(&file);
    blob_read_from_file(&file, g.argv[i]);
    zip_add_file(g.argv[i], &file, file_perm(g.argv[i]));
    blob_reset(&file);
  }
  zip_close(&zip);
  blob_write_to_file(&zip, g.argv[2]);
}

/*