Example #1
0
/*
** Output the differences between two versions of a single file.
** zFrom and zTo are the check-ins containing the two file versions.
** The filename is contained in g.argv[2].
*/
static void diff_one_two_versions(
  const char *zFrom,
  const char *zTo,
  const char *zDiffCmd,
  int ignoreEolWs
){
  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, ignoreEolWs);
  blob_reset(&v1);
  blob_reset(&v2);
  blob_reset(&fname);
}
Example #2
0
/*
** 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,        /* Name of file */
  const char *zDiffCmd,     /* Use this "diff" command */
  int ignoreEolWs           /* Ignore whitespace changes at end of lines */
){
  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, ignoreEolWs);
  blob_reset(&content);
  blob_reset(&fname);
}
Example #3
0
/*
** COMMAND: cat
**
** Usage: %fossil cat FILENAME ... ?OPTIONS?
**
** Print on standard output the content of one or more files as they exist
** in the repository.  The version currently checked out is shown by default.
** Other versions may be specified using the -r option.
**
** Options:
**    -R|--repository FILE       Extract artifacts from repository FILE
**    -r VERSION                 The specific check-in containing the file
**
** See also: finfo
*/
void cat_cmd(void){
  int i;
  int rc;
  Blob content, fname;
  const char *zRev;
  db_find_and_open_repository(0, 0);
  zRev = find_option("r","r",1);

  /* We should be done with options.. */
  verify_all_options();

  for(i=2; i<g.argc; i++){
    file_tree_name(g.argv[i], &fname, 0, 1);
    blob_zero(&content);
    rc = historical_version_of_file(zRev, blob_str(&fname), &content, 0,0,0,2);
    if( rc==2 ){
      fossil_fatal("no such file: %s", g.argv[i]);
    }
    blob_write_to_file(&content, "-");
    blob_reset(&fname);
    blob_reset(&content);
  }
}
Example #4
0
/*
** 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 FILE was part of a rename operation, both the original file
** and the renamed file are reverted.
**
** Revert all files if no file name is provided.
**
** If a file is reverted accidently, it can be restored using
** the "fossil undo" command.
**
** Options:
**   -r REVISION    revert given FILE(s) back to given REVISION
**
** See also: redo, undo, update
*/
void revert_cmd(void) {
    const char *zFile;
    const char *zRevision;
    Blob record;
    int i;
    int errCode;
    Stmt q;

    undo_capture_command_line();
    zRevision = find_option("revision", "r", 1);
    verify_all_options();

    if( g.argc<2 ) {
        usage("?OPTIONS? [FILE] ...");
    }
    if( zRevision && g.argc<3 ) {
        fossil_fatal("the --revision option does not work for the entire tree");
    }
    db_must_be_within_tree();
    db_begin_transaction();
    undo_begin();
    db_multi_exec("CREATE TEMP TABLE torevert(name UNIQUE);");

    if( g.argc>2 ) {
        for(i=2; i<g.argc; i++) {
            Blob fname;
            zFile = mprintf("%/", g.argv[i]);
            blob_zero(&fname);
            file_tree_name(zFile, &fname, 0, 1);
            db_multi_exec(
                "REPLACE INTO torevert VALUES(%B);"
                "INSERT OR IGNORE INTO torevert"
                " SELECT pathname"
                "   FROM vfile"
                "  WHERE origname=%B;",
                &fname, &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 OR IGNORE INTO torevert "
            " SELECT pathname"
            "   FROM vfile "
            "  WHERE chnged OR deleted OR rid=0 OR pathname!=origname;"
        );
    }
    db_multi_exec(
        "INSERT OR IGNORE INTO torevert"
        " SELECT origname"
        "   FROM vfile"
        "  WHERE origname!=pathname AND pathname IN (SELECT name FROM torevert);"
    );
    blob_zero(&record);
    db_prepare(&q, "SELECT name FROM torevert");
    if( zRevision==0 ) {
        int vid = db_lget_int("checkout", 0);
        zRevision = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
    }
    while( db_step(&q)==SQLITE_ROW ) {
        int isExe = 0;
        int isLink = 0;
        char *zFull;
        zFile = db_column_text(&q, 0);
        zFull = mprintf("%/%/", g.zLocalRoot, zFile);
        errCode = historical_version_of_file(zRevision, zFile, &record,
                                             &isLink, &isExe, 0, 2);
        if( errCode==2 ) {
            if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q OR origname=%Q",
                       zFile, zFile)==0 ) {
                fossil_print("UNMANAGE %s\n", zFile);
            } else {
                undo_save(zFile);
                file_delete(zFull);
                fossil_print("DELETE   %s\n", zFile);
            }
            db_multi_exec(
                "UPDATE OR REPLACE vfile"
                "   SET pathname=origname, origname=NULL"
                " WHERE pathname=%Q AND origname!=pathname;"
                "DELETE FROM vfile WHERE pathname=%Q",
                zFile, zFile
            );
        } else {
            sqlite3_int64 mtime;
            undo_save(zFile);
            if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(0)) ) {
                file_delete(zFull);
            }
            if( isLink ) {
                symlink_create(blob_str(&record), zFull);
            } else {
                blob_write_to_file(&record, zFull);
            }
            file_wd_setexe(zFull, isExe);
            fossil_print("REVERT   %s\n", zFile);
            mtime = file_wd_mtime(zFull);
            db_multi_exec(
                "UPDATE vfile"
                "   SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d,mrid=rid"
                " WHERE pathname=%Q OR origname=%Q",
                mtime, isExe, isLink, zFile, zFile
            );
        }
        blob_reset(&record);
        free(zFull);
    }
    db_finalize(&q);
    undo_finish();
    db_end_transaction(0);
}
Example #5
0
/*
** COMMAND: finfo
**
** Usage: %fossil finfo ?OPTIONS? FILENAME
**
** Print the complete change history for a single file going backwards
** in time.  The default mode is -l.
**
** For the -l|--log mode: If "-b|--brief" is specified one line per revision
** is printed, otherwise the full comment is printed.  The "-n|--limit N"
** and "--offset P" options limits the output to the first N changes
** after skipping P changes.
**
** In the -s mode prints the status as <status> <revision>.  This is
** a quick status and does not check for up-to-date-ness of the file.
**
** In the -p mode, there's an optional flag "-r|--revision REVISION".
** The specified version (or the latest checked out version) is printed
** to stdout.  The -p mode is another form of the "cat" command.
**
** Options:
**   -b|--brief           display a brief (one line / revision) summary
**   --case-sensitive B   Enable or disable case-sensitive filenames.  B is a
**                        boolean: "yes", "no", "true", "false", etc.
**   -l|--log             select log mode (the default)
**   -n|--limit N         Display the first N changes (default unlimited).
**                        N<=0 means no limit.
**   --offset P           skip P changes
**   -p|--print           select print mode
**   -r|--revision R      print the given revision (or ckout, if none is given)
**                        to stdout (only in print mode)
**   -s|--status          select status mode (print a status indicator for FILE)
**   -W|--width <num>     Width of lines (default is to auto-detect). Must be
**                        >22 or 0 (= no limit, resulting in a single line per
**                        entry).
**
** See also: artifact, cat, descendants, info, leaves
*/
void finfo_cmd(void){
  db_must_be_within_tree();
  if( find_option("status","s",0) ){
    Stmt q;
    Blob line;
    Blob fname;
    int vid;

    /* We should be done with options.. */
    verify_all_options();

    if( g.argc!=3 ) usage("-s|--status FILENAME");
    vid = db_lget_int("checkout", 0);
    if( vid==0 ){
      fossil_fatal("no checkout to finfo files in");
    }
    vfile_check_signature(vid, CKSIG_ENOTFILE);
    file_tree_name(g.argv[2], &fname, 0, 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 ) {
      Blob uuid;
      int isDeleted = db_column_int(&q, 1);
      int isNew = db_column_int(&q,2) == 0;
      int chnged = db_column_int(&q,3);
      int renamed = db_column_int(&q,4);

      blob_zero(&uuid);
      db_blob(&uuid,
           "SELECT uuid FROM blob, mlink, vfile WHERE "
           "blob.rid = mlink.mid AND mlink.fid = vfile.rid AND "
           "vfile.pathname=%B %s",
           &fname, filename_collation()
      );
      if( isNew ){
        blob_appendf(&line, "new");
      }else if( isDeleted ){
        blob_appendf(&line, "deleted");
      }else if( renamed ){
        blob_appendf(&line, "renamed");
      }else if( chnged ){
        blob_appendf(&line, "edited");
      }else{
        blob_appendf(&line, "unchanged");
      }
      blob_appendf(&line, " ");
      blob_appendf(&line, " %10.10s", blob_str(&uuid));
      blob_reset(&uuid);
    }else{
      blob_appendf(&line, "unknown 0000000000");
    }
    db_finalize(&q);
    fossil_print("%s\n", blob_str(&line));
    blob_reset(&fname);
    blob_reset(&line);
  }else if( find_option("print","p",0) ){
    Blob record;
    Blob fname;
    const char *zRevision = find_option("revision", "r", 1);

    /* We should be done with options.. */
    verify_all_options();

    file_tree_name(g.argv[2], &fname, 0, 1);
    if( zRevision ){
      historical_version_of_file(zRevision, blob_str(&fname), &record, 0,0,0,0);
    }else{
      int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                       &fname, filename_collation());
      if( rid==0 ){
        fossil_fatal("no history for file: %b", &fname);
      }
      content_get(rid, &record);
    }
    blob_write_to_file(&record, "-");
    blob_reset(&record);
    blob_reset(&fname);
  }else{
    Blob line;
    Stmt q;
    Blob fname;
    int rid;
    const char *zFilename;
    const char *zLimit;
    const char *zWidth;
    const char *zOffset;
    int iLimit, iOffset, iBrief, iWidth;

    if( find_option("log","l",0) ){
      /* this is the default, no-op */
    }
    zLimit = find_option("limit","n",1);
    zWidth = find_option("width","W",1);
    iLimit = zLimit ? atoi(zLimit) : -1;
    zOffset = find_option("offset",0,1);
    iOffset = zOffset ? atoi(zOffset) : 0;
    iBrief = (find_option("brief","b",0) == 0);
    if( iLimit==0 ){
      iLimit = -1;
    }
    if( zWidth ){
      iWidth = atoi(zWidth);
      if( (iWidth!=0) && (iWidth<=22) ){
        fossil_fatal("-W|--width value must be >22 or 0");
      }
    }else{
      iWidth = -1;
    }

    /* We should be done with options.. */
    verify_all_options();

    if( g.argc!=3 ){
      usage("?-l|--log? ?-b|--brief? FILENAME");
    }
    file_tree_name(g.argv[2], &fname, 0, 1);
    rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                 &fname, filename_collation());
    if( rid==0 ){
      fossil_fatal("no history for file: %b", &fname);
    }
    zFilename = blob_str(&fname);
    db_prepare(&q,
        "SELECT DISTINCT b.uuid, ci.uuid, date(event.mtime%s),"
        "       coalesce(event.ecomment, event.comment),"
        "       coalesce(event.euser, event.user),"
        "       (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
                                " AND tagxref.rid=mlink.mid)" /* Tags */
        "  FROM mlink, blob b, event, blob ci, filename"
        " WHERE filename.name=%Q %s"
        "   AND mlink.fnid=filename.fnid"
        "   AND b.rid=mlink.fid"
        "   AND event.objid=mlink.mid"
        "   AND event.objid=ci.rid"
        " ORDER BY event.mtime DESC LIMIT %d OFFSET %d",
        timeline_utc(), TAG_BRANCH, zFilename, filename_collation(),
        iLimit, iOffset
    );
    blob_zero(&line);
    if( iBrief ){
      fossil_print("History of %s\n", blob_str(&fname));
    }
    while( db_step(&q)==SQLITE_ROW ){
      const char *zFileUuid = db_column_text(&q, 0);
      const char *zCiUuid = db_column_text(&q,1);
      const char *zDate = db_column_text(&q, 2);
      const char *zCom = db_column_text(&q, 3);
      const char *zUser = db_column_text(&q, 4);
      const char *zBr = db_column_text(&q, 5);
      char *zOut;
      if( zBr==0 ) zBr = "trunk";
      if( iBrief ){
        fossil_print("%s ", zDate);
        zOut = mprintf(
           "[%S] %s (user: %s, artifact: [%S], branch: %s)",
           zCiUuid, zCom, zUser, zFileUuid, zBr);
        comment_print(zOut, zCom, 11, iWidth, g.comFmtFlags);
        fossil_free(zOut);
      }else{
        blob_reset(&line);
        blob_appendf(&line, "%S ", zCiUuid);
        blob_appendf(&line, "%.10s ", zDate);
        blob_appendf(&line, "%8.8s ", zUser);
        blob_appendf(&line, "%8.8s ", zBr);
        blob_appendf(&line,"%-39.39s", zCom );
        comment_print(blob_str(&line), zCom, 0, iWidth, g.comFmtFlags);
      }
    }
    db_finalize(&q);
    blob_reset(&fname);
  }
}
Example #6
0
File: finfo.c Project: oopos/fossil
/*
** COMMAND: finfo
**
** Usage: %fossil finfo ?OPTIONS? FILENAME
**
** Print the complete change history for a single file going backwards
** in time.  The default is -l.
**
** For the -l|--log option: If "-b|--brief" is specified one line per revision
** is printed, otherwise the full comment is printed.  The "--limit N"
** and "--offset P" options limits the output to the first N changes
** after skipping P changes.
**
** In the -s form prints the status as <status> <revision>.  This is
** a quick status and does not check for up-to-date-ness of the file.
**
** In the -p form, there's an optional flag "-r|--revision REVISION".
** The specified version (or the latest checked out version) is printed
** to stdout.
**
** Options:
**   --brief|-b           display a brief (one line / revision) summary
**   --limit N            display the first N changes
**   --log|-l             select log mode (the default)
**   --offset P           skip P changes
**   -p                   select print mode
**   --revision|-r R      print the given revision (or ckout, if none is given)
**                        to stdout (only in print mode)
**   -s                   select status mode (print a status indicator for FILE)
**   --case-sensitive B   Enable or disable case-sensitive filenames.  B is a
**                        boolean: "yes", "no", "true", "false", etc.
**
** See also: artifact, descendants, info, leaves
*/
void finfo_cmd(void) {
    capture_case_sensitive_option();
    db_must_be_within_tree();
    if (find_option("status","s",0)) {
        Stmt q;
        Blob line;
        Blob fname;
        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 ) {
            Blob uuid;
            int isDeleted = db_column_int(&q, 1);
            int isNew = db_column_int(&q,2) == 0;
            int chnged = db_column_int(&q,3);
            int renamed = db_column_int(&q,4);

            blob_zero(&uuid);
            db_blob(&uuid,
                    "SELECT uuid FROM blob, mlink, vfile WHERE "
                    "blob.rid = mlink.mid AND mlink.fid = vfile.rid AND "
                    "vfile.pathname=%B %s",
                    &fname, filename_collation()
                   );
            if( isNew ) {
                blob_appendf(&line, "new");
            } else if( isDeleted ) {
                blob_appendf(&line, "deleted");
            } else if( renamed ) {
                blob_appendf(&line, "renamed");
            } else if( chnged ) {
                blob_appendf(&line, "edited");
            } else {
                blob_appendf(&line, "unchanged");
            }
            blob_appendf(&line, " ");
            blob_appendf(&line, " %10.10s", blob_str(&uuid));
            blob_reset(&uuid);
        } else {
            blob_appendf(&line, "unknown 0000000000");
        }
        db_finalize(&q);
        fossil_print("%s\n", blob_str(&line));
        blob_reset(&fname);
        blob_reset(&line);
    } else if( find_option("print","p",0) ) {
        Blob record;
        Blob fname;
        const char *zRevision = find_option("revision", "r", 1);

        file_tree_name(g.argv[2], &fname, 1);
        if( zRevision ) {
            historical_version_of_file(zRevision, blob_str(&fname), &record, 0, 0, 0);
        } else {
            int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                             &fname, filename_collation());
            if( rid==0 ) {
                fossil_fatal("no history for file: %b", &fname);
            }
            content_get(rid, &record);
        }
        blob_write_to_file(&record, "-");
        blob_reset(&record);
        blob_reset(&fname);
    } else {
        Blob line;
        Stmt q;
        Blob fname;
        int rid;
        const char *zFilename;
        const char *zLimit;
        const char *zOffset;
        int iLimit, iOffset, iBrief;

        if( find_option("log","l",0) ) {
            /* this is the default, no-op */
        }
        zLimit = find_option("limit",0,1);
        iLimit = zLimit ? atoi(zLimit) : -1;
        zOffset = find_option("offset",0,1);
        iOffset = zOffset ? atoi(zOffset) : 0;
        iBrief = (find_option("brief","b",0) == 0);
        if( g.argc!=3 ) {
            usage("?-l|--log? ?-b|--brief? FILENAME");
        }
        file_tree_name(g.argv[2], &fname, 1);
        rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                     &fname, filename_collation());
        if( rid==0 ) {
            fossil_fatal("no history for file: %b", &fname);
        }
        zFilename = blob_str(&fname);
        db_prepare(&q,
                   "SELECT b.uuid, ci.uuid, date(event.mtime,'localtime'),"
                   "       coalesce(event.ecomment, event.comment),"
                   "       coalesce(event.euser, event.user)"
                   "  FROM mlink, blob b, event, blob ci, filename"
                   " WHERE filename.name=%Q %s"
                   "   AND mlink.fnid=filename.fnid"
                   "   AND b.rid=mlink.fid"
                   "   AND event.objid=mlink.mid"
                   "   AND event.objid=ci.rid"
                   " ORDER BY event.mtime DESC LIMIT %d OFFSET %d",
                   zFilename, filename_collation(), iLimit, iOffset
                  );
        blob_zero(&line);
        if( iBrief ) {
            fossil_print("History of %s\n", blob_str(&fname));
        }
        while( db_step(&q)==SQLITE_ROW ) {
            const char *zFileUuid = db_column_text(&q, 0);
            const char *zCiUuid = db_column_text(&q,1);
            const char *zDate = db_column_text(&q, 2);
            const char *zCom = db_column_text(&q, 3);
            const char *zUser = db_column_text(&q, 4);
            char *zOut;
            if( iBrief ) {
                fossil_print("%s ", zDate);
                zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])",
                                       zCiUuid, zCom, zUser, zFileUuid);
                comment_print(zOut, 11, 79);
                sqlite3_free(zOut);
            } else {
                blob_reset(&line);
                blob_appendf(&line, "%.10s ", zCiUuid);
                blob_appendf(&line, "%.10s ", zDate);
                blob_appendf(&line, "%8.8s ", zUser);
                blob_appendf(&line,"%-40.40s\n", zCom );
                comment_print(blob_str(&line), 0, 79);
            }
        }
        db_finalize(&q);
        blob_reset(&fname);
    }
}