Esempio n. 1
0
/*
** COMMAND: test-th-render
*/
void test_th_render(void){
  Blob in;
  if( g.argc<3 ){
    usage("FILE");
  }
  db_open_config(0); /* Needed for global "tcl" setting. */
  blob_zero(&in);
  blob_read_from_file(&in, g.argv[2]);
  Th_Render(blob_str(&in));
}
Esempio n. 2
0
/*
** COMMAND:  test-content-put
**
** Extract a blob from a file and write it into the database
*/
void test_content_put_cmd(void){
  int rid;
  Blob content;
  if( g.argc!=3 ) usage("FILENAME");
  db_must_be_within_tree();
  user_select();
  blob_read_from_file(&content, g.argv[2]);
  rid = content_put(&content);
  fossil_print("inserted as record %d\n", rid);
}
Esempio n. 3
0
/*
** Show the difference between two files, one in memory and one on disk.
**
** The difference is the set of edits needed to transform pFile1 into
** zFile2.  The content of pFile1 is in memory.  zFile2 exists on disk.
**
** Use the internal diff logic if zDiffCmd is NULL.  Otherwise call the
** command zDiffCmd to do the diffing.
*/
static void diff_file(
  Blob *pFile1,             /* In memory content to compare from */
  const char *zFile2,       /* On disk content to compare to */
  const char *zName,        /* Display name of the file */
  const char *zDiffCmd,     /* Command for comparison */
  int ignoreEolWs           /* Ignore whitespace at end of lines */
){
  if( zDiffCmd==0 ){
    Blob out;      /* Diff output text */
    Blob file2;    /* Content of zFile2 */

    /* Read content of zFile2 into memory */
    blob_zero(&file2);
    blob_read_from_file(&file2, zFile2);

    /* Compute and output the differences */
    blob_zero(&out);
    //text_diff(pFile1, &file2, &out, 5, ignoreEolWs);
    csvs_diff(pFile1, &file2, &out);
    printf("--- %s\n+++ %s\n", zName, zName);
    printf("%s\n", blob_str(&out));

    /* Release memory resources */
    blob_reset(&file2);
    blob_reset(&out);
  }else{
    int cnt = 0;
    Blob nameFile1;    /* Name of temporary file to old pFile1 content */
    Blob cmd;          /* Text of command to run */

    /* Construct a temporary file to hold pFile1 based on the name of
    ** zFile2 */
    blob_zero(&nameFile1);
    do{
      blob_reset(&nameFile1);
      blob_appendf(&nameFile1, "%s~%d", zFile2, cnt++);
    }while( access(blob_str(&nameFile1),0)==0 );
    blob_write_to_file(pFile1, blob_str(&nameFile1));

    /* Construct the external diff command */
    blob_zero(&cmd);
    blob_appendf(&cmd, "%s ", zDiffCmd);
    shell_escape(&cmd, blob_str(&nameFile1));
    blob_append(&cmd, " ", 1);
    shell_escape(&cmd, zFile2);

    /* Run the external diff command */
    portable_system(blob_str(&cmd));

    /* Delete the temporary file and clean up memory used */
    unlink(blob_str(&nameFile1));
    blob_reset(&nameFile1);
    blob_reset(&cmd);
  }
}
Esempio n. 4
0
/*
** COMMAND: test-cycle-compress
**
** Compress and uncompress each file named on the command line.
** Verify that the original content is recovered.
*/
void test_cycle_compress(void){
  int i;
  Blob b1, b2, b3;
  for(i=2; i<g.argc; i++){
    blob_read_from_file(&b1, g.argv[i]);
    blob_compress(&b1, &b2);
    blob_uncompress(&b2, &b3);
    if( blob_compare(&b1, &b3) ){
      fossil_fatal("compress/uncompress cycle failed for %s", g.argv[i]);
    }
    blob_reset(&b1);
    blob_reset(&b2);
    blob_reset(&b3);
  }
  fossil_print("ok\n");
}
Esempio n. 5
0
/*
** Do a file-by-file comparison of the content of the repository and
** the working check-out on disk.  Report any errors.
*/
void vfile_compare_repository_to_disk(int vid){
  int rc;
  Stmt q;
  Blob disk, repo;
  
  db_must_be_within_tree();
  db_prepare(&q, 
      "SELECT %Q || pathname, pathname, rid FROM vfile"
      " WHERE NOT deleted AND vid=%d AND file_is_selected(id)",
      g.zLocalRoot, vid
  );
  md5sum_init();
  while( db_step(&q)==SQLITE_ROW ){
    const char *zFullpath = db_column_text(&q, 0);
    const char *zName = db_column_text(&q, 1);
    int rid = db_column_int(&q, 2);

    blob_zero(&disk);
    if( file_wd_islink(zFullpath) ){
      rc = blob_read_link(&disk, zFullpath);
    }else{
      rc = blob_read_from_file(&disk, zFullpath);
    }
    if( rc<0 ){
      vcs_print("ERROR: cannot read file [%s]\n", zFullpath);
      blob_reset(&disk);
      continue;
    }
    blob_zero(&repo);
    content_get(rid, &repo);
    if( blob_size(&repo)!=blob_size(&disk) ){
      vcs_print("ERROR: [%s] is %d bytes on disk but %d in the repository\n",
             zName, blob_size(&disk), blob_size(&repo));
      blob_reset(&disk);
      blob_reset(&repo);
      continue;
    }
    if( blob_compare(&repo, &disk) ){
      vcs_print(
          "ERROR: [%s] is different on disk compared to the repository\n",
          zName);
    }
    blob_reset(&disk);
    blob_reset(&repo);
  }
  db_finalize(&q);
}
Esempio n. 6
0
/*
** Recursively read all files from the directory zPath and install
** every file read as a new artifact in the repository.
*/
void recon_read_dir(char *zPath){
  DIR *d;
  struct dirent *pEntry;
  Blob aContent; /* content of the just read artifact */
  static int nFileRead = 0;
  void *zUnicodePath;
  char *zUtf8Name;

  zUnicodePath = fossil_utf8_to_filename(zPath);
  d = opendir(zUnicodePath);
  if( d ){
    while( (pEntry=readdir(d))!=0 ){
      Blob path;
      char *zSubpath;

      if( pEntry->d_name[0]=='.' ){
        continue;
      }
      zUtf8Name = fossil_filename_to_utf8(pEntry->d_name);
      zSubpath = mprintf("%s/%s", zPath, zUtf8Name);
      fossil_filename_free(zUtf8Name);
      if( file_isdir(zSubpath)==1 ){
        recon_read_dir(zSubpath);
      }
      blob_init(&path, 0, 0);
      blob_appendf(&path, "%s", zSubpath);
      if( blob_read_from_file(&aContent, blob_str(&path))==-1 ){
        fossil_fatal("some unknown error occurred while reading \"%s\"", 
                     blob_str(&path));
      }
      content_put(&aContent);
      blob_reset(&path);
      blob_reset(&aContent);
      free(zSubpath);
      fossil_print("\r%d", ++nFileRead);
      fflush(stdout);
    }
    closedir(d);
  }else {
    fossil_fatal("encountered error %d while trying to open \"%s\".",
                  errno, g.argv[3]);
  }
  fossil_filename_free(zUnicodePath);
}
Esempio n. 7
0
/*
** COMMAND: test-tarball
**
** Generate a GZIP-compressed tarball in the file given by the first argument
** that contains files given in the second and subsequent arguments.
*/
void test_tarball_cmd(void){
  int i;
  Blob zip;
  Blob file;
  if( g.argc<3 ){
    usage("ARCHIVE FILE....");
  }
  sqlite3_open(":memory:", &g.db);
  tar_begin(0);
  for(i=3; i<g.argc; i++){
    blob_zero(&file);
    blob_read_from_file(&file, g.argv[i]);
    tar_add_file(g.argv[i], &file,
                 file_wd_perm(g.argv[i]), file_wd_mtime(g.argv[i]));
    blob_reset(&file);
  }
  tar_finish(&zip);
  blob_write_to_file(&zip, g.argv[2]);
}
Esempio n. 8
0
/*
** COMMAND: configuration*
**
** Usage: %vcs configuration METHOD ... ?OPTIONS?
**
** Where METHOD is one of: export import merge pull push reset.  All methods
** accept the -R or --repository option to specific a repository.
**
**    %vcs configuration export AREA FILENAME
**
**         Write to FILENAME exported configuraton information for AREA.
**         AREA can be one of:  all email project shun skin ticket user
**
**    %vcs configuration import FILENAME
**
**         Read a configuration from FILENAME, overwriting the current
**         configuration.
**
**    %vcs configuration merge FILENAME
**
**         Read a configuration from FILENAME and merge its values into
**         the current configuration.  Existing values take priority over
**         values read from FILENAME.
**
**    %vcs configuration pull AREA ?URL?
**
**         Pull and install the configuration from a different server
**         identified by URL.  If no URL is specified, then the default
**         server is used. Use the --legacy option for the older protocol
**         (when talking to servers compiled prior to 2011-04-27.)  Use
**         the --overwrite flag to completely replace local settings with
**         content received from URL.
**
**    %vcs configuration push AREA ?URL?
**
**         Push the local configuration into the remote server identified
**         by URL.  Admin privilege is required on the remote server for
**         this to work.  When the same record exists both locally and on
**         the remote end, the one that was most recently changed wins.
**         Use the --legacy flag when talking to holder servers.
**
**    %vcs configuration reset AREA
**
**         Restore the configuration to the default.  AREA as above.
**
**    %vcs configuration sync AREA ?URL?
**
**         Synchronize configuration changes in the local repository with
**         the remote repository at URL.
**
** Options:
**    -R|--repository FILE       Extract info from repository FILE
**
** See also: settings, unset
*/
void configuration_cmd(void) {
    int n;
    const char *zMethod;
    if( g.argc<3 ) {
        usage("export|import|merge|pull|reset ...");
    }
    db_find_and_open_repository(0, 0);
    db_open_config(0);
    zMethod = g.argv[2];
    n = strlen(zMethod);
    if( strncmp(zMethod, "export", n)==0 ) {
        int mask;
        const char *zSince = find_option("since",0,1);
        sqlite3_int64 iStart;
        if( g.argc!=5 ) {
            usage("export AREA FILENAME");
        }
        mask = configure_name_to_mask(g.argv[3], 1);
        if( zSince ) {
            iStart = db_multi_exec(
                         "SELECT coalesce(strftime('%%s',%Q),strftime('%%s','now',%Q))+0",
                         zSince, zSince
                     );
        } else {
            iStart = 0;
        }
        export_config(mask, g.argv[3], iStart, g.argv[4]);
    } else if( strncmp(zMethod, "import", n)==0
               || strncmp(zMethod, "merge", n)==0 ) {
        Blob in;
        int groupMask;
        if( g.argc!=4 ) usage(mprintf("%s FILENAME",zMethod));
        blob_read_from_file(&in, g.argv[3]);
        db_begin_transaction();
        if( zMethod[0]=='i' ) {
            groupMask = CONFIGSET_ALL | CONFIGSET_OVERWRITE;
        } else {
            groupMask = CONFIGSET_ALL;
        }
        configure_receive_all(&in, groupMask);
        db_end_transaction(0);
    } else if( strncmp(zMethod, "pull", n)==0
               || strncmp(zMethod, "push", n)==0
               || strncmp(zMethod, "sync", n)==0
             ) {
        int mask;
        const char *zServer;
        const char *zPw;
        int legacyFlag = 0;
        int overwriteFlag = 0;
        if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
        if( strncmp(zMethod,"pull",n)==0 ) {
            overwriteFlag = find_option("overwrite",0,0)!=0;
        }
        url_proxy_options();
        if( g.argc!=4 && g.argc!=5 ) {
            usage("pull AREA ?URL?");
        }
        mask = configure_name_to_mask(g.argv[3], 1);
        if( g.argc==5 ) {
            zServer = g.argv[4];
            zPw = 0;
            g.dontKeepUrl = 1;
        } else {
            zServer = db_get("last-sync-url", 0);
            if( zServer==0 ) {
                vcs_fatal("no server specified");
            }
            zPw = unobscure(db_get("last-sync-pw", 0));
        }
        url_parse(zServer);
        if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
        user_select();
        url_enable_proxy("via proxy: ");
        if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
        if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
        if( strncmp(zMethod, "push", n)==0 ) {
            client_sync(0,0,0,0,0,mask);
        } else if( strncmp(zMethod, "pull", n)==0 ) {
            client_sync(0,0,0,0,mask,0);
        } else {
            client_sync(0,0,0,0,mask,mask);
        }
    } else if( strncmp(zMethod, "reset", n)==0 ) {
        int mask, i;
        char *zBackup;
        if( g.argc!=4 ) usage("reset AREA");
        mask = configure_name_to_mask(g.argv[3], 1);
        zBackup = db_text(0,
                          "SELECT strftime('config-backup-%%Y%%m%%d%%H%%M%%f','now')");
        db_begin_transaction();
        export_config(mask, g.argv[3], 0, zBackup);
        for(i=0; i<count(aConfig); i++) {
            const char *zName = aConfig[i].zName;
            if( (aConfig[i].groupMask & mask)==0 ) continue;
            if( zName[0]!='@' ) {
                db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
            } else if( vcs_strcmp(zName,"@user")==0 ) {
                db_multi_exec("DELETE FROM user");
                db_create_default_users(0, 0);
            } else if( vcs_strcmp(zName,"@concealed")==0 ) {
                db_multi_exec("DELETE FROM concealed");
            } else if( vcs_strcmp(zName,"@shun")==0 ) {
                db_multi_exec("DELETE FROM shun");
            } else if( vcs_strcmp(zName,"@reportfmt")==0 ) {
                db_multi_exec("DELETE FROM reportfmt");
            }
        }
        db_end_transaction(0);
        vcs_print("Configuration reset to factory defaults.\n");
        vcs_print("To recover, use:  %s %s import %s\n",
                  vcs_nameofexe(), g.argv[1], zBackup);
    } else
    {
        vcs_fatal("METHOD should be one of:"
                  " export import merge pull push reset");
    }
}
Esempio n. 9
0
/*
** WEBPAGE: doc
** URL: /doc?name=BASELINE/PATH
** URL: /doc/BASELINE/PATH
**
** BASELINE can be either a baseline uuid prefix or magic words "tip"
** to mean the most recently checked in baseline or "ckout" to mean the
** content of the local checkout, if any.  PATH is the relative pathname
** of some file.  This method returns the file content.
**
** If PATH matches the patterns *.wiki or *.txt then formatting content
** is added before returning the file.  For all other names, the content
** is returned straight without any interpretation or processing.
*/
void doc_page(void){
  const char *zName;                /* Argument to the /doc page */
  const char *zMime;                /* Document MIME type */
  int vid = 0;                      /* Artifact of baseline */
  int rid = 0;                      /* Artifact of file */
  int i;                            /* Loop counter */
  Blob filebody;                    /* Content of the documentation file */
  char zBaseline[UUID_SIZE+1];      /* Baseline UUID */

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  zName = PD("name", "tip/index.wiki");
  for(i=0; zName[i] && zName[i]!='/'; i++){}
  if( zName[i]==0 || i>UUID_SIZE ){
    zName = "index.html";
    goto doc_not_found;
  }
  memcpy(zBaseline, zName, i);
  zBaseline[i] = 0;
  zName += i;
  while( zName[0]=='/' ){ zName++; }
  if( !file_is_simple_pathname(zName) ){
    int n = strlen(zName);
    if( n>0 && zName[n-1]=='/' ){
      zName = mprintf("%sindex.html", zName);
      if( !file_is_simple_pathname(zName) ){
        goto doc_not_found;
      }
    }else{
      goto doc_not_found;
    }
  }
  if( fossil_strcmp(zBaseline,"ckout")==0 && db_open_local()==0 ){
    sqlite3_snprintf(sizeof(zBaseline), zBaseline, "tip");
  }
  if( fossil_strcmp(zBaseline,"ckout")==0 ){
    /* Read from the local checkout */
    char *zFullpath;
    db_must_be_within_tree();
    zFullpath = mprintf("%s/%s", g.zLocalRoot, zName);
    if( !file_isfile(zFullpath) ){
      goto doc_not_found;
    }
    if( blob_read_from_file(&filebody, zFullpath)<0 ){
      goto doc_not_found;
    }
  }else{
    db_begin_transaction();
    if( fossil_strcmp(zBaseline,"tip")==0 ){
      vid = db_int(0, "SELECT objid FROM event WHERE type='ci'"
                      " ORDER BY mtime DESC LIMIT 1");
    }else{
      vid = name_to_typed_rid(zBaseline, "ci");
    }

    /* Create the baseline cache if it does not already exist */
    db_multi_exec(
      "CREATE TABLE IF NOT EXISTS vcache(\n"
      "  vid INTEGER,         -- baseline ID\n"
      "  fname TEXT,          -- filename\n"
      "  rid INTEGER,         -- artifact ID\n"
      "  UNIQUE(vid,fname,rid)\n"
      ")"
    );



    /* Check to see if the documentation file artifact ID is contained
    ** in the baseline cache */
    rid = db_int(0, "SELECT rid FROM vcache"
                    " WHERE vid=%d AND fname=%Q", vid, zName);
    if( rid==0 && db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){
      goto doc_not_found;
    }

    if( rid==0 ){
      Stmt s;
      Manifest *pM;
      ManifestFile *pFile;

      /* Add the vid baseline to the cache */
      if( db_int(0, "SELECT count(*) FROM vcache")>10000 ){
        db_multi_exec("DELETE FROM vcache");
      }
      pM = manifest_get(vid, CFTYPE_MANIFEST);
      if( pM==0 ){
        goto doc_not_found;
      }
      db_prepare(&s,
        "INSERT INTO vcache(vid,fname,rid)"
        " SELECT %d, :fname, rid FROM blob"
        "  WHERE uuid=:uuid",
        vid
      );
      manifest_file_rewind(pM);
      while( (pFile = manifest_file_next(pM,0))!=0 ){
        db_bind_text(&s, ":fname", pFile->zName);
        db_bind_text(&s, ":uuid", pFile->zUuid);
        db_step(&s);
        db_reset(&s);
      }
      db_finalize(&s);
      manifest_destroy(pM);

      /* Try again to find the file */
      rid = db_int(0, "SELECT rid FROM vcache"
                      " WHERE vid=%d AND fname=%Q", vid, zName);
    }
    if( rid==0 ){
      goto doc_not_found;
    }

    /* Get the file content */
    if( content_get(rid, &filebody)==0 ){
      goto doc_not_found;
    }
    db_end_transaction(0);
  }

  /* The file is now contained in the filebody blob.  Deliver the
  ** file to the user 
  */
  zMime = P("mimetype");
  if( zMime==0 ){
    zMime = mimetype_from_name(zName);
  }
  Th_Store("doc_name", zName);
  Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'"
                                     "  FROM blob WHERE rid=%d", vid));
  Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event"
                                  " WHERE objid=%d AND type='ci'", vid));
  if( fossil_strcmp(zMime, "application/x-fossil-wiki")==0 ){
    Blob title, tail;
    if( wiki_find_title(&filebody, &title, &tail) ){
      style_header(blob_str(&title));
      wiki_convert(&tail, 0, 0);
    }else{
      style_header("Documentation");
      wiki_convert(&filebody, 0, 0);
    }
    style_footer();
  }else if( fossil_strcmp(zMime, "text/plain")==0 ){
    style_header("Documentation");
    @ <blockquote><pre>