Fossil

Check-in [7b82a73b]
Login

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

Overview
Comment:Remove the --yes option from the "revert" command. In its place, make the "revert" opration undoable.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7b82a73bd39b7f864d69978bd1fbfbfadb6339c7
User & Date: drh 2009-12-17 21:22:52
Context
2009-12-17
22:55
Enhancements to the "update" command. Missing files are reverted. One or more files can be specified on the "update" command line after the VERSION and only the files named will be updated. check-in: 2d996b08 user: drh tags: trunk
21:22
Remove the --yes option from the "revert" command. In its place, make the "revert" opration undoable. check-in: 7b82a73b user: drh tags: trunk
18:47
If a file in the check-out is changed to something other than a file (like a directory) then raise an error when checking file signatures. Also fix a problem with the new multi-file "revert" command and add some comments to "update". check-in: d861fe77 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/diffcmd.c.

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
...
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
** Do a diff against a single file named in g.argv[2] from version zFrom
** against the same file on disk.
*/
static void diff_one_against_disk(const char *zFrom, const char *zDiffCmd){
  Blob fname;
  Blob content;
  file_tree_name(g.argv[2], &fname, 1);
  historical_version_of_file(zFrom, blob_str(&fname), &content);
  diff_file(&content, g.argv[2], g.argv[2], zDiffCmd);
  blob_reset(&content);
  blob_reset(&fname);
}

/*
** Run a diff between the version zFrom and files on disk.  zFrom might
................................................................................
  const char *zDiffCmd
){
  char *zName;
  Blob fname;
  Blob v1, v2;
  file_tree_name(g.argv[2], &fname, 1);
  zName = blob_str(&fname);
  historical_version_of_file(zFrom, zName, &v1);
  historical_version_of_file(zTo, zName, &v2);
  diff_file_mem(&v1, &v2, zName, zDiffCmd);
  blob_reset(&v1);
  blob_reset(&v2);
  blob_reset(&fname);
}

/*







|







 







|
|







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
...
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
** Do a diff against a single file named in g.argv[2] from version zFrom
** against the same file on disk.
*/
static void diff_one_against_disk(const char *zFrom, const char *zDiffCmd){
  Blob fname;
  Blob content;
  file_tree_name(g.argv[2], &fname, 1);
  historical_version_of_file(zFrom, blob_str(&fname), &content, 0);
  diff_file(&content, g.argv[2], g.argv[2], zDiffCmd);
  blob_reset(&content);
  blob_reset(&fname);
}

/*
** Run a diff between the version zFrom and files on disk.  zFrom might
................................................................................
  const char *zDiffCmd
){
  char *zName;
  Blob fname;
  Blob v1, v2;
  file_tree_name(g.argv[2], &fname, 1);
  zName = blob_str(&fname);
  historical_version_of_file(zFrom, zName, &v1, 0);
  historical_version_of_file(zTo, zName, &v2, 0);
  diff_file_mem(&v1, &v2, zName, zDiffCmd);
  blob_reset(&v1);
  blob_reset(&v2);
  blob_reset(&fname);
}

/*

Changes to src/undo.c.

187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
}

/*
** COMMAND: undo
**
** Usage: %fossil undo ?FILENAME...?
**
** Undo the most recent update or merge operation.  If FILENAME is
** specified then restore the content of the named file(s) but otherwise
** leave the update or merge in effect.
**
** A single level of undo/redo is supported.  The undo/redo stack
** is cleared by the commit and checkout commands.
*/
void undo_cmd(void){
  int undo_available;
  db_must_be_within_tree();
................................................................................
}

/*
** COMMAND: redo
**
** Usage: %fossil redo ?FILENAME...?
**
** Redo the an update or merge operation that has been undone by the
** undo command.  If FILENAME is specified then restore the changes
** associated with the named file(s) but otherwise leave the update
** or merge undone.
**
** A single level of undo/redo is supported.  The undo/redo stack
** is cleared by the commit and checkout commands.
*/
void redo_cmd(void){







|

|







 







|
|







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
}

/*
** COMMAND: undo
**
** Usage: %fossil undo ?FILENAME...?
**
** Undo the most recent update or merge or revert operation.  If FILENAME is
** specified then restore the content of the named file(s) but otherwise
** leave the update or merge or revert in effect.
**
** A single level of undo/redo is supported.  The undo/redo stack
** is cleared by the commit and checkout commands.
*/
void undo_cmd(void){
  int undo_available;
  db_must_be_within_tree();
................................................................................
}

/*
** COMMAND: redo
**
** Usage: %fossil redo ?FILENAME...?
**
** Redo the an update or merge or revert operation that has been undone
** by the undo command.  If FILENAME is specified then restore the changes
** associated with the named file(s) but otherwise leave the update
** or merge undone.
**
** A single level of undo/redo is supported.  The undo/redo stack
** is cleared by the commit and checkout commands.
*/
void redo_cmd(void){

Changes to src/update.c.

251
252
253
254
255
256
257
258

259
260
261
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277
278
279
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
305

306
307
308
309
310
311
312
313
314
315
316
317


318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339


340
341
342
343


344

345
346
347





348
349

350
351
352
353
354
355
356

357

/*
** Get the contents of a file within a given revision.
*/
int historical_version_of_file(
  const char *revision,    /* The baseline name containing the file */
  const char *file,        /* Full treename of the file */
  Blob *content            /* Put the content here */

){
  Blob mfile;
  Manifest m;
  int i, rid=0;
  
  if( revision ){
    rid = name_to_rid(revision);
  }else{
    rid = db_lget_int("checkout", 0);
  }
  if( !is_a_version(rid) ){

    fossil_fatal("no such check-out: %s", revision);
  }
  content_get(rid, &mfile);
  
  if( manifest_parse(&m, &mfile) ){
    for(i=0; i<m.nFile; i++){
      if( strcmp(m.aFile[i].zName, file)==0 ){
        rid = uuid_to_rid(m.aFile[i].zUuid, 0);
        return content_get(rid, content);
      }
    }

    fossil_fatal("file %s does not exist in baseline: %s", file, revision);
  }else{


    fossil_panic("could not parse manifest for baseline: %s", revision);
  }
  return 0;
}


/*
** COMMAND: revert
**
** Usage: %fossil revert ?--yes? ?-r REVISION? FILE ...
**
** Revert to the current repository version of FILE, or to
** the version associated with baseline REVISION if the -r flag
** appears.  This command will confirm your operation unless the
** file is missing or the --yes option is used.
**/



void revert_cmd(void){
  char *zFile;
  const char *zRevision;
  Blob fname;
  Blob record;
  Blob ans;
  int i;

  int rid = 0;
  int yesFlag;
  int yesRevert;
  
  yesFlag = find_option("yes", "y", 0)!=0;
  zRevision = find_option("revision", "r", 1);
  verify_all_options();
  
  if( g.argc<3 ){
    usage("?OPTIONS FILE ...");
  }
  db_must_be_within_tree();



  for(i=2; i<g.argc; i++){
    zFile = mprintf("%/", g.argv[i]);
    file_tree_name(zFile, &fname, 1);
    yesRevert = yesFlag;
    if( !yesRevert && access(zFile, 0) ) yesRevert = 1;  
    if( yesRevert==0 ){
      char *prompt = mprintf("revert file %B? this will"
                             " destroy local changes (y/N)? ",
                             &fname);
      blob_zero(&ans);
      prompt_user(prompt, &ans);
      free( prompt );
      if( blob_str(&ans)[0]=='y' ){
        yesRevert = 1;
      }
      blob_reset(&ans);
    }

    if( yesRevert==1 && zRevision!=0 ){
      historical_version_of_file(zRevision, zFile, &record);
    }else if( yesRevert==1 ){


      rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname);
      if( rid==0 ){
        fossil_panic("no history for file: %b", &fname);
      }


      content_get(rid, &record);

    }
  
    if( yesRevert==1 ){





      blob_write_to_file(&record, zFile);
      printf("%s reverted\n", zFile);

      blob_reset(&record);
      blob_reset(&fname);
    }else{
      printf("revert canceled\n");
    }
    free(zFile);
  }

}







|
>











>











>
|
<
>
>


|






|



|
<
|
>
>
>





<

>

<
<

<




|


>
>




<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
|
<
>
>


<
<
>
>
|
>
|
|
<
>
>
>
>
>


>
|
|
<
<
<


>

251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
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
305
306
307
308
309

310
311
312


313

314
315
316
317
318
319
320
321
322
323
324
325
326











327



328
329

330
331
332
333


334
335
336
337
338
339

340
341
342
343
344
345
346
347
348
349



350
351
352
353

/*
** Get the contents of a file within a given revision.
*/
int historical_version_of_file(
  const char *revision,    /* The baseline name containing the file */
  const char *file,        /* Full treename of the file */
  Blob *content,           /* Put the content here */
  int errCode              /* Error code if file not found.  Panic if 0. */
){
  Blob mfile;
  Manifest m;
  int i, rid=0;
  
  if( revision ){
    rid = name_to_rid(revision);
  }else{
    rid = db_lget_int("checkout", 0);
  }
  if( !is_a_version(rid) ){
    if( errCode>0 ) return errCode;
    fossil_fatal("no such check-out: %s", revision);
  }
  content_get(rid, &mfile);
  
  if( manifest_parse(&m, &mfile) ){
    for(i=0; i<m.nFile; i++){
      if( strcmp(m.aFile[i].zName, file)==0 ){
        rid = uuid_to_rid(m.aFile[i].zUuid, 0);
        return content_get(rid, content);
      }
    }
    if( errCode<=0 ){
      fossil_fatal("file %s does not exist in baseline: %s", file, revision);

    }
  }else if( errCode<=0 ){
    fossil_panic("could not parse manifest for baseline: %s", revision);
  }
  return errCode;
}


/*
** COMMAND: revert
**
** Usage: %fossil revert ?-r REVISION? FILE ...
**
** Revert to the current repository version of FILE, or to
** the version associated with baseline REVISION if the -r flag
** appears.

**
** If a file is reverted accidently, it can be restored using
** the "fossil undo" command.
*/
void revert_cmd(void){
  char *zFile;
  const char *zRevision;
  Blob fname;
  Blob record;

  int i;
  int errCode;
  int rid = 0;


  

  zRevision = find_option("revision", "r", 1);
  verify_all_options();
  
  if( g.argc<3 ){
    usage("?OPTIONS? FILE ...");
  }
  db_must_be_within_tree();
  db_begin_transaction();
  undo_begin();

  for(i=2; i<g.argc; i++){
    zFile = mprintf("%/", g.argv[i]);
    file_tree_name(zFile, &fname, 1);















    if( zRevision!=0 ){
      errCode = historical_version_of_file(zRevision, blob_str(&fname),

                                           &record, 2);
    }else{
      rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname);
      if( rid==0 ){


        errCode = 2;
      }else{
        content_get(rid, &record);
        errCode = 0;
      }
    }


    if( errCode==2 ){
      fossil_warning("file not in repository: %s", zFile);
    }else{
      undo_save(blob_str(&fname));
      blob_write_to_file(&record, zFile);
      printf("%s reverted\n", zFile);
    }
    blob_reset(&record);
    blob_reset(&fname);



    free(zFile);
  }
  db_end_transaction(0);
}