Fossil

Check-in [ae092ec605]
Login

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

Overview
Comment:Add the --setmtime command-line option to "fossil update". When this option is used, the mtime of all unmodified managed files is set to the time when that file was originally checked in.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ae092ec605eed11fc5790718aff2b110b156c97d
User & Date: drh 2012-10-11 19:22:18.554
References
2012-10-11
19:45
Cherrypick changes [0c37874941c8972], [9ba8a393fcc569b], and [ae092ec605eed11] in order to backport the --setmtime option of "fossil update" and the --age and -t options of "fossil ls" to version 1.19. check-in: 773c6c5f2c user: drh tags: branch-1.19
Context
2012-10-11
20:58
Tweaks to the "fileages" user interface. check-in: da2fe1be82 user: drh tags: trunk
19:22
Add the --setmtime command-line option to "fossil update". When this option is used, the mtime of all unmodified managed files is set to the time when that file was originally checked in. check-in: ae092ec605 user: drh tags: trunk
18:33
Back out the undo/redo logic changes of [0c37874941c89] that caused the mtime to be restored on files. Playing games with mtimes is bad policy. Consider a scenario: "fossil merge; make; fossil undo; make". If the mtimes are reset by undo, then the second "make" above will not work correctly. This is not a complete backout of [0c37874941c89] as the underlying infrastructure used to compute the age of files is retained. check-in: 5c0843a8f1 user: drh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/checkin.c.
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  int showHdr = find_option("header",0,0)!=0;
  int verbose = find_option("verbose","v",0)!=0;
  int cwdRelative = 0;
  db_must_be_within_tree();
  cwdRelative = determine_cwd_relative_option();
  blob_zero(&report);
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, 0, useSha1sum);
  status_report(&report, "", 0, cwdRelative);
  if( verbose && blob_size(&report)==0 ){
    blob_append(&report, "  (none)\n", -1);
  }
  if( showHdr && blob_size(&report)>0 ){
    fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
                 g.zLocalRoot);







|







158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  int showHdr = find_option("header",0,0)!=0;
  int verbose = find_option("verbose","v",0)!=0;
  int cwdRelative = 0;
  db_must_be_within_tree();
  cwdRelative = determine_cwd_relative_option();
  blob_zero(&report);
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
  status_report(&report, "", 0, cwdRelative);
  if( verbose && blob_size(&report)==0 ){
    blob_append(&report, "  (none)\n", -1);
  }
  if( showHdr && blob_size(&report)>0 ){
    fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
                 g.zLocalRoot);
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
    if( showAge ){
      zOrderBy = mprintf("checkin_mtime(%d,rid) DESC", vid);
    }else{
      zOrderBy = "mtime DESC";
    }
  }
  verify_all_options();
  vfile_check_signature(vid, 0, 0);
  if( showAge ){
    db_prepare(&q,
       "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0),"
       "       datetime(checkin_mtime(%d,rid),'unixepoch','localtime')"
       "  FROM vfile"
       " ORDER BY %s", vid, zOrderBy
    );







|







242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
    if( showAge ){
      zOrderBy = mprintf("checkin_mtime(%d,rid) DESC", vid);
    }else{
      zOrderBy = "mtime DESC";
    }
  }
  verify_all_options();
  vfile_check_signature(vid, 0);
  if( showAge ){
    db_prepare(&q,
       "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0),"
       "       datetime(checkin_mtime(%d,rid),'unixepoch','localtime')"
       "  FROM vfile"
       " ORDER BY %s", vid, zOrderBy
    );
Changes to src/checkout.c.
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
**     2:   There is no existing checkout
*/
int unsaved_changes(void){
  int vid;
  db_must_be_within_tree();
  vid = db_lget_int("checkout",0);
  if( vid==0 ) return 2;
  vfile_check_signature(vid, 1, 0);
  return db_exists("SELECT 1 FROM vfile WHERE chnged"
                   " OR coalesce(origname!=pathname,0)");
}

/*
** Undo the current check-out.  Unlink all files from the disk.
** Clear the VFILE table.







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
**     2:   There is no existing checkout
*/
int unsaved_changes(void){
  int vid;
  db_must_be_within_tree();
  vid = db_lget_int("checkout",0);
  if( vid==0 ) return 2;
  vfile_check_signature(vid, CKSIG_ENOTFILE);
  return db_exists("SELECT 1 FROM vfile WHERE chnged"
                   " OR coalesce(origname!=pathname,0)");
}

/*
** Undo the current check-out.  Unlink all files from the disk.
** Clear the VFILE table.
Changes to src/diffcmd.c.
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  int vid;
  Blob sql;
  Stmt q;
  int asNewFile;            /* Treat non-existant files as empty files */

  asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, 1, 0);
  blob_zero(&sql);
  db_begin_transaction();
  if( zFrom ){
    int rid = name_to_typed_rid(zFrom, "ci");
    if( !is_a_version(rid) ){
      fossil_fatal("no such check-in: %s", zFrom);
    }







|







320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  int vid;
  Blob sql;
  Stmt q;
  int asNewFile;            /* Treat non-existant files as empty files */

  asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, CKSIG_ENOTFILE);
  blob_zero(&sql);
  db_begin_transaction();
  if( zFrom ){
    int rid = name_to_typed_rid(zFrom, "ci");
    if( !is_a_version(rid) ){
      fossil_fatal("no such check-in: %s", zFrom);
    }
Changes to src/finfo.c.
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
    int vid;

    if( g.argc!=3 ) usage("-s|--status FILENAME");
    vid = db_lget_int("checkout", 0);
    if( vid==0 ){
      fossil_panic("no checkout to finfo files in");
    }
    vfile_check_signature(vid, 1, 0);
    file_tree_name(g.argv[2], &fname, 1);
    db_prepare(&q,
        "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
        "  FROM vfile WHERE vfile.pathname=%B %s",
        &fname, filename_collation());
    blob_zero(&line);
    if ( db_step(&q)==SQLITE_ROW ) {







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
    int vid;

    if( g.argc!=3 ) usage("-s|--status FILENAME");
    vid = db_lget_int("checkout", 0);
    if( vid==0 ){
      fossil_panic("no checkout to finfo files in");
    }
    vfile_check_signature(vid, CKSIG_ENOTFILE);
    file_tree_name(g.argv[2], &fname, 1);
    db_prepare(&q,
        "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
        "  FROM vfile WHERE vfile.pathname=%B %s",
        &fname, filename_collation());
    blob_zero(&line);
    if ( db_step(&q)==SQLITE_ROW ) {
Changes to src/merge.c.
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
                 " Use --force to override.\n");
    return;
  }
  if( detailFlag ){
    print_checkin_description(mid, 12, "merge-from:");
    print_checkin_description(pid, 12, "baseline:");
  }
  vfile_check_signature(vid, 1, 0);
  db_begin_transaction();
  if( !nochangeFlag ) undo_begin();
  load_vfile_from_rid(mid);
  load_vfile_from_rid(pid);
  if( debugFlag ){
    char *z;
    z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid);







|







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
                 " Use --force to override.\n");
    return;
  }
  if( detailFlag ){
    print_checkin_description(mid, 12, "merge-from:");
    print_checkin_description(pid, 12, "baseline:");
  }
  vfile_check_signature(vid, CKSIG_ENOTFILE);
  db_begin_transaction();
  if( !nochangeFlag ) undo_begin();
  load_vfile_from_rid(mid);
  load_vfile_from_rid(pid);
  if( debugFlag ){
    char *z;
    z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid);
Changes to src/stash.c.
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
    prompt_for_user_comment(&comment, &prompt);
    blob_reset(&prompt);
    zComment = blob_str(&comment);
  }
  stashid = db_lget_int("stash-next", 1);
  db_lset_int("stash-next", stashid+1);
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, 0, 0);
  db_multi_exec(
    "INSERT INTO stash(stashid,vid,comment,ctime)"
    "VALUES(%d,%d,%Q,julianday('now'))",
    stashid, vid, zComment
  );
  if( g.argc>3 ){
    int i;







|







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
    prompt_for_user_comment(&comment, &prompt);
    blob_reset(&prompt);
    zComment = blob_str(&comment);
  }
  stashid = db_lget_int("stash-next", 1);
  db_lset_int("stash-next", stashid+1);
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, 0);
  db_multi_exec(
    "INSERT INTO stash(stashid,vid,comment,ctime)"
    "VALUES(%d,%d,%Q,julianday('now'))",
    stashid, vid, zComment
  );
  if( g.argc>3 ){
    int i;
Changes to src/update.c.
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
  int vid;              /* Current version */
  int tid=0;            /* Target version - version we are changing to */
  Stmt q;
  int latestFlag;       /* --latest.  Pick the latest version if true */
  int nochangeFlag;     /* -n or --nochange.  Do a dry run */
  int verboseFlag;      /* -v or --verbose.  Output extra information */
  int debugFlag;        /* --debug option */

  int nChng;            /* Number of file renames */
  int *aChng;           /* Array of file renames */
  int i;                /* Loop counter */
  int nConflict = 0;    /* Number of merge conflicts */
  int nOverwrite = 0;   /* Number of unmanaged files overwritten */
  int nUpdate = 0;      /* Number of chagnes of any kind */
  Stmt mtimeXfer;       /* Statment to transfer mtimes */

  if( !internalUpdate ){
    undo_capture_command_line();
    url_proxy_options();
  }
  latestFlag = find_option("latest",0, 0)!=0;
  nochangeFlag = find_option("nochange","n",0)!=0;
  verboseFlag = find_option("verbose","v",0)!=0;
  debugFlag = find_option("debug",0,0)!=0;

  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("cannot find current version");
  }
  if( !nochangeFlag && !internalUpdate ) autosync(AUTOSYNC_PULL);
  







>
















>







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  int vid;              /* Current version */
  int tid=0;            /* Target version - version we are changing to */
  Stmt q;
  int latestFlag;       /* --latest.  Pick the latest version if true */
  int nochangeFlag;     /* -n or --nochange.  Do a dry run */
  int verboseFlag;      /* -v or --verbose.  Output extra information */
  int debugFlag;        /* --debug option */
  int setmtimeFlag;     /* --setmtime.  Set mtimes on files */
  int nChng;            /* Number of file renames */
  int *aChng;           /* Array of file renames */
  int i;                /* Loop counter */
  int nConflict = 0;    /* Number of merge conflicts */
  int nOverwrite = 0;   /* Number of unmanaged files overwritten */
  int nUpdate = 0;      /* Number of chagnes of any kind */
  Stmt mtimeXfer;       /* Statment to transfer mtimes */

  if( !internalUpdate ){
    undo_capture_command_line();
    url_proxy_options();
  }
  latestFlag = find_option("latest",0, 0)!=0;
  nochangeFlag = find_option("nochange","n",0)!=0;
  verboseFlag = find_option("verbose","v",0)!=0;
  debugFlag = find_option("debug",0,0)!=0;
  setmtimeFlag = find_option("setmtime",0,0)!=0;
  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("cannot find current version");
  }
  if( !nochangeFlag && !internalUpdate ) autosync(AUTOSYNC_PULL);
  
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  }

  if( tid==0 ){
    fossil_panic("Internal Error: unable to find a version to update to.");
  }

  db_begin_transaction();
  vfile_check_signature(vid, 1, 0);
  if( !nochangeFlag && !internalUpdate ) undo_begin();
  load_vfile_from_rid(tid);

  /*
  ** The record.fn field is used to match files against each other.  The
  ** FV table contains one row for each each unique filename in
  ** in the current checkout, the pivot, and the version being merged.







|







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  }

  if( tid==0 ){
    fossil_panic("Internal Error: unable to find a version to update to.");
  }

  db_begin_transaction();
  vfile_check_signature(vid, CKSIG_ENOTFILE);
  if( !nochangeFlag && !internalUpdate ) undo_begin();
  load_vfile_from_rid(tid);

  /*
  ** The record.fn field is used to match files against each other.  The
  ** FV table contains one row for each each unique filename in
  ** in the current checkout, the pivot, and the version being merged.
527
528
529
530
531
532
533

534
535
536
537
538
539
540
      db_lset_int("checkout", tid);
    }else{
      /* A subset of files have been checked out.  Keep the current
      ** checkout unchanged. */
      db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
    }
    if( !internalUpdate ) undo_finish();

    db_end_transaction(0);
  }
}

/*
** Make sure empty directories are created
*/







>







529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
      db_lset_int("checkout", tid);
    }else{
      /* A subset of files have been checked out.  Keep the current
      ** checkout unchanged. */
      db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
    }
    if( !internalUpdate ) undo_finish();
    if( setmtimeFlag ) vfile_check_signature(vid, CKSIG_SETMTIME);
    db_end_transaction(0);
  }
}

/*
** Make sure empty directories are created
*/
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
      file_tree_name(zFile, &fname, 1);
      db_multi_exec("REPLACE INTO torevert VALUES(%B)", &fname);
      blob_reset(&fname);
    }
  }else{
    int vid;
    vid = db_lget_int("checkout", 0);
    vfile_check_signature(vid, 0, 0);
    db_multi_exec(
      "DELETE FROM vmerge;"
      "INSERT INTO torevert "
      "SELECT pathname"
      "  FROM vfile "
      " WHERE chnged OR deleted OR rid=0 OR pathname!=origname;"
    );







|







697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
      file_tree_name(zFile, &fname, 1);
      db_multi_exec("REPLACE INTO torevert VALUES(%B)", &fname);
      blob_reset(&fname);
    }
  }else{
    int vid;
    vid = db_lget_int("checkout", 0);
    vfile_check_signature(vid, 0);
    db_multi_exec(
      "DELETE FROM vmerge;"
      "INSERT INTO torevert "
      "SELECT pathname"
      "  FROM vfile "
      " WHERE chnged OR deleted OR rid=0 OR pathname!=origname;"
    );
Changes to src/vfile.c.
116
117
118
119
120
121
122

123










124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
  }
  db_finalize(&ridq);
  db_finalize(&ins);
  manifest_destroy(p);
  db_end_transaction(0);
}


/*










** Look at every VFILE entry with the given vid and  set update
** VFILE.CHNGED field on every file according to whether or not
** the file has changes.  0 means no change.  1 means edited.  2 means
** the file has changed due to a merge.  3 means the file was added
** by a merge.
**
** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was
** either removed from managemented via "fossil rm" or added via
** "fossil add", respectively, and in both cases we always know that 
** the file has changed without having the check the size, mtime,
** or on-disk content.
**
** If the size of the file has changed, then we always know that the file
** changed without having to look at the mtime or on-disk content.
**
** The mtime of the file is only a factor if the mtime-changes setting
** is false and the useSha1sum flag is false.  If the mtime-changes
** setting is true (or undefined - it defaults to true) or if useSha1sum
** is true, then we do not trust the mtime and will examine the on-disk
** content to determine if a file really is the same.
**
** If the mtime is used, it is used only to determine if files are the same.
** If the mtime of a file has changed, we still examine the on-disk content
** to see whether or not the edit was a null-edit.
*/
void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){
  int nErr = 0;
  Stmt q;
  Blob fileCksum, origCksum;

  int useMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1);

  db_begin_transaction();
  db_prepare(&q, "SELECT id, %Q || pathname,"
                 "       vfile.mrid, deleted, chnged, uuid, size, mtime"
                 "  FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
                 " WHERE vid=%d ", g.zLocalRoot, vid);
  while( db_step(&q)==SQLITE_ROW ){







>

>
>
>
>
>
>
>
>
>
>
|
|
|



|
|

















|



>
|







116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  }
  db_finalize(&ridq);
  db_finalize(&ins);
  manifest_destroy(p);
  db_end_transaction(0);
}

#if INTERFACE
/*
** The cksigFlags parameter to vfile_check_signature() is an OR-ed
** combination of the following bits:
*/
#define CKSIG_ENOTFILE  0x001   /* non-file FS objects throw an error */
#define CKSIG_SHA1      0x002   /* Verify file content using sha1sum */
#define CKSIG_SETMTIME  0x004   /* Set mtime to last check-out time */

#endif /* INTERFACE */

/*
** Look at every VFILE entry with the given vid and update
** VFILE.CHNGED field according to whether or not
** the file has changed.  0 means no change.  1 means edited.  2 means
** the file has changed due to a merge.  3 means the file was added
** by a merge.
**
** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either
** removed from configuration management via "fossil rm" or added via
** "fossil add", respectively, and in both cases we always know that 
** the file has changed without having the check the size, mtime,
** or on-disk content.
**
** If the size of the file has changed, then we always know that the file
** changed without having to look at the mtime or on-disk content.
**
** The mtime of the file is only a factor if the mtime-changes setting
** is false and the useSha1sum flag is false.  If the mtime-changes
** setting is true (or undefined - it defaults to true) or if useSha1sum
** is true, then we do not trust the mtime and will examine the on-disk
** content to determine if a file really is the same.
**
** If the mtime is used, it is used only to determine if files are the same.
** If the mtime of a file has changed, we still examine the on-disk content
** to see whether or not the edit was a null-edit.
*/
void vfile_check_signature(int vid, unsigned int cksigFlags){
  int nErr = 0;
  Stmt q;
  Blob fileCksum, origCksum;
  int useMtime = (cksigFlags & CKSIG_SHA1)==0
                    && db_get_boolean("mtime-changes", 1);

  db_begin_transaction();
  db_prepare(&q, "SELECT id, %Q || pathname,"
                 "       vfile.mrid, deleted, chnged, uuid, size, mtime"
                 "  FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
                 " WHERE vid=%d ", g.zLocalRoot, vid);
  while( db_step(&q)==SQLITE_ROW ){
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
    currentSize = file_wd_size(zName);
    origSize = db_column_int64(&q, 6);
    currentMtime = file_wd_mtime(0);
    if( chnged==0 && (isDeleted || rid==0) ){
      /* "fossil rm" or "fossil add" always change the file */
      chnged = 1;
    }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){
      if( notFileIsFatal ){
        fossil_warning("not an ordinary file: %s", zName);
        nErr++;
      }
      chnged = 1;
    }
    if( origSize!=currentSize ){
      if( chnged!=1 ){







|







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
    currentSize = file_wd_size(zName);
    origSize = db_column_int64(&q, 6);
    currentMtime = file_wd_mtime(0);
    if( chnged==0 && (isDeleted || rid==0) ){
      /* "fossil rm" or "fossil add" always change the file */
      chnged = 1;
    }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){
      if( cksigFlags & CKSIG_ENOTFILE ){
        fossil_warning("not an ordinary file: %s", zName);
        nErr++;
      }
      chnged = 1;
    }
    if( origSize!=currentSize ){
      if( chnged!=1 ){
215
216
217
218
219
220
221









222
223
224
225
226
227
228
        blob_zero(&fileCksum);
      }
      if( blob_compare(&fileCksum, &origCksum) ){
        chnged = 1;
      }
      blob_reset(&origCksum);
      blob_reset(&fileCksum);









    }
    if( currentMtime!=oldMtime || chnged!=oldChnged ){
      db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d",
                    currentMtime, chnged, id);
    }
  }
  db_finalize(&q);







>
>
>
>
>
>
>
>
>







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
        blob_zero(&fileCksum);
      }
      if( blob_compare(&fileCksum, &origCksum) ){
        chnged = 1;
      }
      blob_reset(&origCksum);
      blob_reset(&fileCksum);
    }
    if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2) ){
      i64 desiredMtime;
      if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){
        if( currentMtime!=desiredMtime ){
          file_set_mtime(zName, desiredMtime);
          currentMtime = file_wd_mtime(zName);
        }
      }
    }
    if( currentMtime!=oldMtime || chnged!=oldChnged ){
      db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d",
                    currentMtime, chnged, id);
    }
  }
  db_finalize(&q);