Пример #1
0
/*
** Implement the "fossil bundle append BUNDLE FILE..." command.  Add
** the named files into the BUNDLE.  Create the BUNDLE if it does not
** alraedy exist.
*/
static void bundle_append_cmd(void){
  Blob content, hash;
  int i;
  Stmt q;

  verify_all_options();
  bundle_attach_file(g.argv[3], "b1", 1);
  db_prepare(&q,
    "INSERT INTO bblob(blobid, uuid, sz, delta, data, notes) "
    "VALUES(NULL, $uuid, $sz, NULL, $data, $filename)");
  db_begin_transaction();
  for(i=4; i<g.argc; i++){
    int sz;
    blob_read_from_file(&content, g.argv[i]);
    sz = blob_size(&content);
    sha1sum_blob(&content, &hash);
    blob_compress(&content, &content);
    db_bind_text(&q, "$uuid", blob_str(&hash));
    db_bind_int(&q, "$sz", sz);
    db_bind_blob(&q, "$data", &content);
    db_bind_text(&q, "$filename", g.argv[i]);
    db_step(&q);
    db_reset(&q);
    blob_reset(&content);
    blob_reset(&hash);
  }
  db_end_transaction(0);
  db_finalize(&q);
}
Пример #2
0
/* Find or create a record the value of a column and return the id */
DBint64 id_of_with_insert(DB *db, const char *table, const char *column, const char *value, int *inserted)
{
    DBStatement *select, *insert;
    DBint64 id;
    char sql[256];

    snprintf(sql, sizeof(sql), "select id from %s where %s = ?;", table, column);
    select = db_prep(db, sql);
    db_bind_text(select, 1, value);

    if (db_step(select) == DB_DONE) {
        snprintf(sql, sizeof(sql), "insert into %s (%s) values (?);", table, column);
        insert = db_prep(db, sql);
        db_bind_text(insert, 1, value);
        db_step(insert);
        id = db_last_insert_rowid(db);
        db_finalize(insert);
        *inserted = TRUE;
    } else {
        id = db_column_int64(select, 0);
        *inserted = FALSE;
    }

    db_finalize(select);

    return id;
}
Пример #3
0
void registry_set_text(Logbook *logbook, const char *path, const char *key, const char *text)
{
  DBStatement *stmt;
  if (registry_key_exists(logbook, path, key)) {
    stmt = logbook->registry_update;
  } else {
    stmt = logbook->registry_insert;
  }
  db_bind_text(stmt, 1, text);
  db_bind_text(stmt, 2, path);
  db_bind_text(stmt, 3, key);
  db_stp_res_clr(stmt);
}
Пример #4
0
int registry_key_exists(Logbook *logbook, const char *path, const char *key)
{
  int value = 1;
  DBStatement *stmt = logbook->registry_select_by_path_key;
  db_bind_text(stmt, 1, path);
  db_bind_text(stmt, 2, key);
  if (db_step(stmt) == DB_DONE) {
    value = 0;
  }
  db_reset(stmt);
  db_clear_bindings(stmt);

  return value;
}
Пример #5
0
int registry_get_int(Logbook *logbook, const char *path, const char *key)
{
  int value = 0;
  DBStatement *stmt = logbook->registry_select_by_path_key;
  db_bind_text(stmt, 1, path);
  db_bind_text(stmt, 2, key);
  if (db_step(stmt) == DB_ROW) {
    value = db_column_int(stmt, 0);
  }
  db_reset(stmt);
  db_clear_bindings(stmt);

  return value;
}
Пример #6
0
/*
** Load a vfile from a record ID.
*/
void load_vfile_from_rid(int vid){
  int rid, size;
  Stmt ins, ridq;
  Manifest *p;
  ManifestFile *pFile;

  if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
    return;
  }

  db_begin_transaction();
  p = manifest_get(vid, CFTYPE_MANIFEST, 0);
  if( p==0 ) {
    db_end_transaction(1);
    return;
  }
  db_prepare(&ins,
    "INSERT INTO vfile(vid,isexe,islink,rid,mrid,pathname) "
    " VALUES(:vid,:isexe,:islink,:id,:id,:name)");
  db_prepare(&ridq, "SELECT rid,size FROM blob WHERE uuid=:uuid");
  db_bind_int(&ins, ":vid", vid);
  manifest_file_rewind(p);
  while( (pFile = manifest_file_next(p,0))!=0 ){
    if( pFile->zUuid==0 || uuid_is_shunned(pFile->zUuid) ) continue;
    db_bind_text(&ridq, ":uuid", pFile->zUuid);
    if( db_step(&ridq)==SQLITE_ROW ){
      rid = db_column_int(&ridq, 0);
      size = db_column_int(&ridq, 1);
    }else{
      rid = 0;
      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)==PERM_EXE ));
    db_bind_int(&ins, ":id", rid);
    db_bind_text(&ins, ":name", pFile->zName);
    db_bind_int(&ins, ":islink", ( manifest_file_mperm(pFile)==PERM_LNK ));
    db_step(&ins);
    db_reset(&ins);
  }
  db_finalize(&ridq);
  db_finalize(&ins);
  manifest_destroy(p);
  db_end_transaction(0);
}
Пример #7
0
char *registry_get_text(Logbook *logbook, const char *path, const char *key)
{
  char *value = NULL;
  DBStatement *stmt = logbook->registry_select_by_path_key;
  db_bind_text(stmt, 1, path);
  db_bind_text(stmt, 2, key);
  if (db_step(stmt) == DB_ROW) {
    strncpy(logbook->registry_value, (char*)db_column_text(stmt, 0), REGISTRY_BUF_VALUE);
    logbook->registry_value[REGISTRY_BUF_VALUE-1] = '\0';
    value = logbook->registry_value;
  }
  db_reset(stmt);
  db_clear_bindings(stmt);

  return value;
}
Пример #8
0
/*
** Create a new phantom with the given UUID and return its artifact ID.
*/
int content_new(const char *zUuid, int isPrivate){
  int rid;
  static Stmt s1, s2, s3;
  
  assert( g.repositoryOpen );
  db_begin_transaction();
  if( uuid_is_shunned(zUuid) ){
    db_end_transaction(0);
    return 0;
  }
  db_static_prepare(&s1,
    "INSERT INTO blob(rcvid,size,uuid,content)"
    "VALUES(0,-1,:uuid,NULL)"
  );
  db_bind_text(&s1, ":uuid", zUuid);
  db_exec(&s1);
  rid = db_last_insert_rowid();
  db_static_prepare(&s2,
    "INSERT INTO phantom VALUES(:rid)"
  );
  db_bind_int(&s2, ":rid", rid);
  db_exec(&s2);
  if( g.markPrivate || isPrivate ){
    db_multi_exec("INSERT INTO private VALUES(%d)", rid);
  }else{
    db_static_prepare(&s3,
      "INSERT INTO unclustered VALUES(:rid)"
    );
    db_bind_int(&s3, ":rid", rid);
    db_exec(&s3);
  }
  bag_insert(&contentCache.missing, rid);
  db_end_transaction(0);
  return rid;
}
Пример #9
0
/* This is a helper routine for test-artifacts.
**
** Check to see that artifact zUuid exists in the repository.  If it does,
** return 0.  If it does not, generate an error message and return 1.
*/
static int check_exists(
  const char *zUuid,     /* The artifact we are checking for */
  unsigned flags,        /* Flags */
  Manifest *p,           /* The control artifact that references zUuid */
  const char *zRole,     /* Role of zUuid in p */
  const char *zDetail    /* Additional information, such as a filename */
){
  static Stmt q;
  int rc = 0;

  db_static_prepare(&q, "SELECT size FROM blob WHERE uuid=:uuid");
  if( zUuid==0 || zUuid[0]==0 ) return 0;
  db_bind_text(&q, ":uuid", zUuid);
  if( db_step(&q)==SQLITE_ROW ){
    int size = db_column_int(&q, 0);
    if( size<0 ) rc = 2;
  }else{
    rc = 1;
  }
  db_reset(&q);
  if( rc ){
    const char *zCFType = "control artifact";
    char *zSrc;
    char *zDate;
    char *zErrType = "MISSING";
    if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
      if( flags & MISSING_SHUNNED ) return 0;
      zErrType = "SHUNNED";
    }
    switch( p->type ){
      case CFTYPE_MANIFEST:   zCFType = "check-in";    break;
      case CFTYPE_CLUSTER:    zCFType = "cluster";     break;
      case CFTYPE_CONTROL:    zCFType = "tag";         break;
      case CFTYPE_WIKI:       zCFType = "wiki";        break;
      case CFTYPE_TICKET:     zCFType = "ticket";      break;
      case CFTYPE_ATTACHMENT: zCFType = "attachment";  break;
      case CFTYPE_EVENT:      zCFType = "event";       break;
    }
    zSrc = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid);
    if( p->rDate>0.0 ){
      zDate = db_text(0, "SELECT datetime(%.17g)", p->rDate);
    }else{
      zDate = db_text(0,
         "SELECT datetime(rcvfrom.mtime)"
         "  FROM blob, rcvfrom"
         " WHERE blob.rcvid=rcvfrom.rcvid"
         "   AND blob.rid=%d", p->rid);
    }
    fossil_print("%s: %s\n         %s %s %S (%d) %s\n",
                  zErrType, zUuid, zRole, zCFType, zSrc, p->rid, zDate);
    if( zDetail && zDetail[0] ){
      fossil_print("         %s\n", zDetail);
    }
    fossil_free(zSrc);
    fossil_free(zDate);
    rc = 1; 
  }
  return rc;
}
Пример #10
0
/*
** The input is guaranteed to be a 40-character well-formed UUID.
** Find its rid.
*/
int fast_uuid_to_rid(const char *zUuid){
  static Stmt q;
  int rid;
  db_static_prepare(&q, "SELECT rid FROM blob WHERE uuid=:uuid");
  db_bind_text(&q, ":uuid", zUuid);
  if( db_step(&q)==SQLITE_ROW ){
    rid = db_column_int(&q, 0);
  }else{
    rid = 0;
  }
  db_reset(&q);
  return rid;
}
Пример #11
0
DBint64 roles_write_entries(const gchar *id, Logbook *logbook)
{
  const gchar
    *ident,
    *name;
  gboolean
    pic,
    sic,
    fe,
    solo,
    dual,
    instruct,
    total;
  DBStatement *stmt;

  ident    = gtk_entry_get_text(GTK_ENTRY(logbook->roles_ident));
  name     = gtk_entry_get_text(GTK_ENTRY(logbook->roles_name));
  pic      = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(logbook->roles_pic));
  sic      = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(logbook->roles_sic));
  fe       = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(logbook->roles_fe));
  solo     = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(logbook->roles_solo));
  dual     = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(logbook->roles_dual));
  instruct = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(logbook->roles_instruct));
  total    = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(logbook->roles_total));
  
  /* Write entries to database */
  if (id) {
    stmt = logbook->roles_update;
    db_bind_text(stmt, ROLES_WRITE_ID, id);
  } else {
    stmt = logbook->roles_insert;
  }
  db_bind_nonempty_text_else_null(stmt, ROLES_WRITE_IDENT, ident);
  db_bind_nonempty_text_else_null(stmt, ROLES_WRITE_NAME, name);
  db_bind_int(stmt, ROLES_WRITE_PIC, pic ? 1 : 0);
  db_bind_int(stmt, ROLES_WRITE_SIC, sic ? 1 : 0);
  db_bind_int(stmt, ROLES_WRITE_FE, fe ? 1 : 0);
  db_bind_int(stmt, ROLES_WRITE_SOLO, solo ? 1 : 0);
  db_bind_int(stmt, ROLES_WRITE_DUAL, dual ? 1 : 0);
  db_bind_int(stmt, ROLES_WRITE_INSTRUCT, instruct ? 1 : 0);
  db_bind_int(stmt, ROLES_WRITE_TOTAL, total ? 1 : 0);

  db_stp_res_clr(stmt);

  if (id) {
    return 0;
  } else {
    return db_last_insert_rowid(logbook->db);
  }
}
Пример #12
0
int unique_but_for(DB *db, const char *table, const char *col, const char *value, const char *butcol, const char *butvalue)
{
    DBStatement *stmt;
    int ret;
    char sql[512];

    /* Might want to use 'like' query for case insensitivity */
    snprintf(sql, sizeof(sql), "select * from %s where %s != ? and %s = ?;", table, butcol, col);

    stmt = db_prep(db, sql);

    db_bind_text(stmt, 1, butvalue);
    db_bind_text(stmt, 2, value);

    if (db_step(stmt) == DB_DONE) {
        ret = 1;
    } else {
        ret = 0;
    }
    db_finalize(stmt);

    return ret;
}
Пример #13
0
int row_exists(DB *db, const char *table, const char *column, const char *value)
{
    DBStatement *select;
    char sql[256];
    int ret;

    snprintf(sql, sizeof(sql), "select %s from %s where %s = ?;", column, table, column);
    select = db_prep(db, sql);
    db_bind_text(select, 1, value);

    ret = (db_step(select) != DB_DONE);

    db_finalize(select);
    return ret;
}
Пример #14
0
/* Returns 1 if ident found, otherwise 0 - places utc as default value */
int tz_of_airport(DBStatement *select, const char *key, char *tz, int tz_bufsize)
{
    int found;

    db_bind_text(select, 1, key);
    found = (db_step(select) == DB_ROW);
    if (found) {
        tz[tz_bufsize - 1] = 0;
        strncpy(tz, EMPTY_IF_NULL((char *)db_column_text(select, 0)), tz_bufsize);
        if (tz[tz_bufsize - 1] != 0) {
            fprintf(stderr, "Timezone buffer passed to tz_of_airport() too small\n");
            exit(1);
        }
    }

    db_stp_res_clr(select);

    return found;
}
Пример #15
0
int find_row_id(DB *db, const char *table, const char *column, const char *value, DBint64 *r_id)
{
    DBStatement *select;
    char sql[256];

    snprintf(sql, sizeof(sql), "select id from %s where %s = ?;", table, column);
    select = db_prep(db, sql);
    db_bind_text(select, 1, value);

    if (db_step(select) == DB_DONE) {
        /* No row found */
        return 0;
    } else {
        *r_id = db_column_int64(select, 0);
    }

    db_finalize(select);

    return 1;
}
Пример #16
0
void on_reports_title_changed(GtkWidget *entry, Logbook *logbook)
{
  if (GTK_WIDGET_HAS_FOCUS(entry)) {
    reports_set_modified(logbook);
    gtk_expander_set_expanded(GTK_EXPANDER(logbook->reports_sql_expander), TRUE);
  } else {
    db_bind_text(logbook->reports_sql_by_title, 1, gtk_entry_get_text(GTK_ENTRY(logbook->reports_title)));
    db_step(logbook->reports_sql_by_title);
    fprintf(stderr, "Error's from here ...\n");
    text_view_set_text(GTK_TEXT_VIEW(logbook->reports_sql_text), (char*)db_column_text(logbook->reports_sql_by_title, 0));
    fprintf(stderr, "... to here during delete.\n");
    db_reset(logbook->reports_sql_by_title);
    db_clear_bindings(logbook->reports_sql_by_title);

    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(logbook->reports_armdel_btn), FALSE);
    gtk_widget_set_sensitive(logbook->reports_armdel_btn, TRUE);
    gtk_widget_set_sensitive(logbook->reports_del_btn, FALSE);
    gtk_widget_set_sensitive(logbook->reports_save_btn, FALSE);
  }
}
Пример #17
0
/*
** Insert an artifact into the BLOB table if it isn't there already.
** If zMark is not zero, create a cross-reference from that mark back
** to the newly inserted artifact.
**
** If saveUuid is true, then pContent is a commit record.  Record its
** UUID in gg.zPrevCheckin.
*/
static int fast_insert_content(Blob *pContent, const char *zMark, int saveUuid){
  Blob hash;
  Blob cmpr;
  int rid;

  sha1sum_blob(pContent, &hash);
  rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &hash);
  if( rid==0 ){
    static Stmt ins;
    db_static_prepare(&ins,
        "INSERT INTO blob(uuid, size, content) VALUES(:uuid, :size, :content)"
    );
    db_bind_text(&ins, ":uuid", blob_str(&hash));
    db_bind_int(&ins, ":size", gg.nData);
    blob_compress(pContent, &cmpr);
    db_bind_blob(&ins, ":content", &cmpr);
    db_step(&ins);
    db_reset(&ins);
    blob_reset(&cmpr);
    rid = db_last_insert_rowid();
  }
  if( zMark ){
    db_multi_exec(
        "INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
        "VALUES(%Q,%d,%B)",
        zMark, rid, &hash
    );
    db_multi_exec(
        "INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
        "VALUES(%B,%d,%B)",
        &hash, rid, &hash
    );
  }
  if( saveUuid ){
    fossil_free(gg.zPrevCheckin);
    gg.zPrevCheckin = fossil_strdup(blob_str(&hash));
  }
  blob_reset(&hash);
  return rid;
}
Пример #18
0
/*
** Load into table SFILE the name of every ordinary file in
** the directory pPath.   Omit the first nPrefix characters of
** of pPath when inserting into the SFILE table.
**
** Subdirectories are scanned recursively.
** Omit files named in VFILE.
**
** Files whose names begin with "." are omitted unless the SCAN_ALL
** flag is set.
**
** Any files or directories that match the glob patterns pIgnore*
** are excluded from the scan.  Name matching occurs after the
** first nPrefix characters are elided from the filename.
*/
void vfile_scan(
  Blob *pPath,           /* Directory to be scanned */
  int nPrefix,           /* Number of bytes in directory name */
  unsigned scanFlags,    /* Zero or more SCAN_xxx flags */
  Glob *pIgnore1,        /* Do not add files that match this GLOB */
  Glob *pIgnore2         /* Omit files matching this GLOB too */
){
  DIR *d;
  int origSize;
  struct dirent *pEntry;
  int skipAll = 0;
  static Stmt ins;
  static int depth = 0;
  void *zNative;

  origSize = blob_size(pPath);
  if( pIgnore1 || pIgnore2 ){
    blob_appendf(pPath, "/");
    if( glob_match(pIgnore1, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
    if( glob_match(pIgnore2, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
    blob_resize(pPath, origSize);
  }
  if( skipAll ) return;

  if( depth==0 ){
    db_prepare(&ins,
       "INSERT OR IGNORE INTO sfile(x) SELECT :file"
       "  WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE"
       " pathname=:file %s)", filename_collation()
    );
  }
  depth++;

  zNative = fossil_utf8_to_filename(blob_str(pPath));
  d = opendir(zNative);
  if( d ){
    while( (pEntry=readdir(d))!=0 ){
      char *zPath;
      char *zUtf8;
      if( pEntry->d_name[0]=='.' ){
        if( (scanFlags & SCAN_ALL)==0 ) continue;
        if( pEntry->d_name[1]==0 ) continue;
        if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
      }
      zUtf8 = fossil_filename_to_utf8(pEntry->d_name);
      blob_appendf(pPath, "/%s", zUtf8);
      zPath = blob_str(pPath);
      if( glob_match(pIgnore1, &zPath[nPrefix+1]) ||
          glob_match(pIgnore2, &zPath[nPrefix+1]) ){
        /* do nothing */
      }else if( file_wd_isdir(zPath)==1 ){
        if( !vfile_top_of_checkout(zPath) ){
          vfile_scan(pPath, nPrefix, scanFlags, pIgnore1, pIgnore2);
        }
      }else if( file_wd_isfile_or_link(zPath) ){
        if( (scanFlags & SCAN_TEMP)==0 || is_temporary_file(zUtf8) ){
          db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
          db_step(&ins);
          db_reset(&ins);
        }
      }
      fossil_filename_free(zUtf8);
      blob_resize(pPath, origSize);
    }
    closedir(d);
  }
  fossil_filename_free(zNative);

  depth--;
  if( depth==0 ){
    db_finalize(&ins);
  }
}
Пример #19
0
/*
** Impl of /json/dir. 98% of it was taken directly
** from browse.c::page_dir()
*/
static cson_value * json_page_dir_list(){
  cson_object * zPayload = NULL; /* return value */
  cson_array * zEntries = NULL; /* accumulated list of entries. */
  cson_object * zEntry = NULL;  /* a single dir/file entry. */
  cson_array * keyStore = NULL; /* garbage collector for shared strings. */
  cson_string * zKeyName = NULL;
  cson_string * zKeySize = NULL;
  cson_string * zKeyIsDir = NULL;
  cson_string * zKeyUuid = NULL;
  cson_string * zKeyTime = NULL;
  cson_string * zKeyRaw = NULL;
  char * zD = NULL;
  char const * zDX = NULL;
  int nD;
  char * zUuid = NULL;
  char const * zCI = NULL;
  Manifest * pM = NULL;
  Stmt q = empty_Stmt;
  int rid = 0;
  if( !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED, "Requires 'o' permissions.");
    return NULL;
  }
  zCI = json_find_option_cstr("checkin",NULL,"ci" );

  /* If a specific check-in is requested, fetch and parse it.  If the
  ** specific check-in does not exist, clear zCI.  zCI==0 will cause all
  ** files from all check-ins to be displayed.
  */
  if( zCI && *zCI ){
    pM = manifest_get_by_name(zCI, &rid);
    if( pM ){
      zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
    }else{
      json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
                   "Checkin name [%s] is unresolved.",
                   zCI);
      return NULL;
    }
  }

  /* Jump through some hoops to find the directory name... */
  zDX = json_find_option_cstr("name",NULL,NULL);
  if(!zDX && !g.isHTTP){
    zDX = json_command_arg(g.json.dispatchDepth+1);
  }
  if(zDX && (!*zDX || (0==strcmp(zDX,"/")))){
    zDX = NULL;
  }
  zD = zDX ? fossil_strdup(zDX) : NULL;
  nD = zD ? strlen(zD)+1 : 0;
  while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }

  sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
                          pathelementFunc, 0, 0);

  /* Compute the temporary table "localfiles" containing the names
  ** of all files and subdirectories in the zD[] directory.
  **
  ** Subdirectory names begin with "/".  This causes them to sort
  ** first and it also gives us an easy way to distinguish files
  ** from directories in the loop that follows.
  */

  if( zCI ){
    Stmt ins;
    ManifestFile *pFile;
    ManifestFile *pPrev = 0;
    int nPrev = 0;
    int c;

    db_multi_exec(
                  "CREATE TEMP TABLE json_dir_files("
                  "  n UNIQUE NOT NULL," /* file name */
                  "  fn UNIQUE NOT NULL," /* full file name */
                  "  u DEFAULT NULL," /* file uuid */
                  "  sz DEFAULT -1," /* file size */
                  "  mtime DEFAULT NULL" /* file mtime in unix epoch format */
                  ");"
                  );

    db_prepare(&ins,
               "INSERT OR IGNORE INTO json_dir_files (n,fn,u,sz,mtime) "
               "SELECT"
               "  pathelement(:path,0),"
               "  CASE WHEN %Q IS NULL THEN '' ELSE %Q||'/' END ||:abspath,"
               "  a.uuid,"
               "  a.size,"
               "  CAST(strftime('%%s',e.mtime) AS INTEGER) "
               "FROM"
               "  mlink m, "
               "  event e,"
               "  blob a,"
               "  blob b "
               "WHERE"
               " e.objid=m.mid"
               " AND a.rid=m.fid"/*FILE artifact*/
               " AND b.rid=m.mid"/*CHECKIN artifact*/
               " AND a.uuid=:uuid",
               zD, zD
               );
    manifest_file_rewind(pM);
    while( (pFile = manifest_file_next(pM,0))!=0 ){
      if( nD>0
        && ((pFile->zName[nD-1]!='/') || (0!=memcmp(pFile->zName, zD, nD-1)))
      ){
        continue;
      }
      /*printf("zD=%s, nD=%d, pFile->zName=%s\n", zD, nD, pFile->zName);*/
      if( pPrev
       && memcmp(&pFile->zName[nD],&pPrev->zName[nD],nPrev)==0
       && (pFile->zName[nD+nPrev]==0 || pFile->zName[nD+nPrev]=='/')
      ){
        continue;
      }
      db_bind_text( &ins, ":path", &pFile->zName[nD] );
      db_bind_text( &ins, ":abspath", &pFile->zName[nD] );
      db_bind_text( &ins, ":uuid", pFile->zUuid );
      db_step(&ins);
      db_reset(&ins);
      pPrev = pFile;
      for(nPrev=0; (c=pPrev->zName[nD+nPrev]) && c!='/'; nPrev++){}
      if( c=='/' ) nPrev++;
    }
    db_finalize(&ins);
  }else if( zD && *zD ){
    db_multi_exec(
      "CREATE TEMP VIEW json_dir_files AS"
      " SELECT DISTINCT(pathelement(name,%d)) AS n,"
      " %Q||'/'||name AS fn,"
      " NULL AS u, NULL AS sz, NULL AS mtime"
      " FROM filename"
      "  WHERE name GLOB '%q/*'"
      " GROUP BY n",
      nD, zD, zD
    );
  }else{
    db_multi_exec(
      "CREATE TEMP VIEW json_dir_files"
      " AS SELECT DISTINCT(pathelement(name,0)) AS n, NULL AS fn"
      " FROM filename"
    );
  }

  if(zCI){
    db_prepare( &q, "SELECT"
                "  n as name,"
                "  fn as fullname,"
                "  u as uuid,"
                "  sz as size,"
                "  mtime as mtime "
                "FROM json_dir_files ORDER BY n");
  }else{/* UUIDs are all NULL. */
    db_prepare( &q, "SELECT n, fn FROM json_dir_files ORDER BY n");
  }

  zKeyName = cson_new_string("name",4);
  zKeyUuid = cson_new_string("uuid",4);
  zKeyIsDir = cson_new_string("isDir",5);
  keyStore = cson_new_array();
  cson_array_append( keyStore, cson_string_value(zKeyName) );
  cson_array_append( keyStore, cson_string_value(zKeyUuid) );
  cson_array_append( keyStore, cson_string_value(zKeyIsDir) );

  if( zCI ){
    zKeySize = cson_new_string("size",4);
    cson_array_append( keyStore, cson_string_value(zKeySize) );
    zKeyTime = cson_new_string("timestamp",9);
    cson_array_append( keyStore, cson_string_value(zKeyTime) );
    zKeyRaw = cson_new_string("downloadPath",12);
    cson_array_append( keyStore, cson_string_value(zKeyRaw) );
  }
  zPayload = cson_new_object();
  cson_object_set_s( zPayload, zKeyName,
                     json_new_string((zD&&*zD) ? zD : "/") );
  if( zUuid ){
    cson_object_set( zPayload, "checkin", json_new_string(zUuid) );
  }

  while( (SQLITE_ROW==db_step(&q)) ){
    cson_value * name = NULL;
    char const * n = db_column_text(&q,0);
    char const isDir = ('/'==*n);
    zEntry = cson_new_object();
    if(!zEntries){
      zEntries = cson_new_array();
      cson_object_set( zPayload, "entries", cson_array_value(zEntries) );
    }
    cson_array_append(zEntries, cson_object_value(zEntry) );
    if(isDir){
      name = json_new_string( n+1 );
      cson_object_set_s(zEntry, zKeyIsDir, cson_value_true() );
    } else{
      name = json_new_string( n );
    }
    cson_object_set_s(zEntry, zKeyName, name );
    if( zCI && !isDir){
      /* Don't add the uuid/size for dir entries - that data refers to
         one of the files in that directory :/. Entries with no
         --checkin may refer to N versions, and therefore we cannot
         associate a single size and uuid with them (and fetching all
         would be overkill for most use cases).
      */
      char const * fullName = db_column_text(&q,1);
      char const * u = db_column_text(&q,2);
      sqlite_int64 const sz = db_column_int64(&q,3);
      sqlite_int64 const ts = db_column_int64(&q,4);
      cson_object_set_s(zEntry, zKeyUuid, json_new_string( u ) );
      cson_object_set_s(zEntry, zKeySize,
                        cson_value_new_integer( (cson_int_t)sz ));
      cson_object_set_s(zEntry, zKeyTime,
          cson_value_new_integer( (cson_int_t)ts ));
      cson_object_set_s(zEntry, zKeyRaw,
                        json_new_string_f("/raw/%T?name=%t",
                                          fullName, u));
    }
  }
  db_finalize(&q);
  if(pM){
    manifest_destroy(pM);
  }
  cson_free_array( keyStore );

  free( zUuid );
  free( zD );
  return cson_object_value(zPayload);
}
Пример #20
0
/*
** Check to see if the directory named in zPath is the top of a checkout.
** In other words, check to see if directory pPath contains a file named
** "_vcs_" or ".fslckout".  Return true or false.
*/
int vfile_top_of_checkout(const char *zPath){
  char *zFile;
  int fileFound = 0;

  zFile = mprintf("%s/_vcs_", zPath);
  fileFound = file_size(zFile)>=1024;
  vcs_free(zFile);
  if( !fileFound ){
    zFile = mprintf("%s/.fslckout", zPath);
    fileFound = file_size(zFile)>=1024;
    vcs_free(zFile);
  }

/*
** Load into table SFILE the name of every ordinary file in
** the directory pPath.   Omit the first nPrefix characters of
** of pPath when inserting into the SFILE table.
**
** Subdirectories are scanned recursively.
** Omit files named in VFILE.
**
** Files whose names begin with "." are omitted unless allFlag is true.
**
** Any files or directories that match the glob pattern pIgnore are 
** excluded from the scan.  Name matching occurs after the first
** nPrefix characters are elided from the filename.
*/
void vfile_scan(Blob *pPath, int nPrefix, int allFlag, Glob *pIgnore){
  DIR *d;
  int origSize;
  const char *zDir;
  struct dirent *pEntry;
  int skipAll = 0;
  static Stmt ins;
  static int depth = 0;
  char *zMbcs;

  origSize = blob_size(pPath);
  if( pIgnore ){
    blob_appendf(pPath, "/");
    if( glob_match(pIgnore, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
    blob_resize(pPath, origSize);
  }
  if( skipAll ) return;

  if( depth==0 ){
    db_prepare(&ins,
       "INSERT OR IGNORE INTO sfile(x) SELECT :file"
       "  WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE pathname=:file)"
    );
  }
  depth++;

  zDir = blob_str(pPath);
  zMbcs = vcs_utf8_to_mbcs(zDir);
  d = opendir(zMbcs);
  if( d ){
    while( (pEntry=readdir(d))!=0 ){
      char *zPath;
      char *zUtf8;
      if( pEntry->d_name[0]=='.' ){
        if( !allFlag ) continue;
        if( pEntry->d_name[1]==0 ) continue;
        if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
      }
      zUtf8 = vcs_mbcs_to_utf8(pEntry->d_name);
      blob_appendf(pPath, "/%s", zUtf8);
      vcs_mbcs_free(zUtf8);
      zPath = blob_str(pPath);
      if( glob_match(pIgnore, &zPath[nPrefix+1]) ){
        /* do nothing */
      }else if( file_wd_isdir(zPath)==1 ){
        if( !vfile_top_of_checkout(zPath) ){
          vfile_scan(pPath, nPrefix, allFlag, pIgnore);
        }
      }else if( file_wd_isfile_or_link(zPath) ){
        db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
        db_step(&ins);
        db_reset(&ins);
      }
      blob_resize(pPath, origSize);
    }
    closedir(d);
  }
  vcs_mbcs_free(zMbcs);

  depth--;
  if( depth==0 ){
    db_finalize(&ins);
  }
}
Пример #21
0
/*
** COMMAND: export
**
** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
**
** Write an export of all check-ins to standard output.  The export is
** written in the git-fast-export file format assuming the --git option is
** provided.  The git-fast-export format is currently the only VCS 
** interchange format supported, though other formats may be added in
** the future.
**
** Run this command within a checkout.  Or use the -R or --repository
** option to specify a Fossil repository to be exported.
**
** Only check-ins are exported using --git.  Git does not support tickets 
** or wiki or events or attachments, so none of those are exported.
**
** If the "--import-marks FILE" option is used, it contains a list of
** rids to skip.
**
** If the "--export-marks FILE" option is used, the rid of all commits and
** blobs written on exit for use with "--import-marks" on the next run.
**
** Options:
**   --export-marks FILE          export rids of exported data to FILE
**   --import-marks FILE          read rids of data to ignore from FILE
**   --repository|-R REPOSITORY   export the given REPOSITORY
**   
** See also: import
*/
void export_cmd(void){
  Stmt q, q2, q3;
  int i;
  Bag blobs, vers;
  const char *markfile_in;
  const char *markfile_out;

  bag_init(&blobs);
  bag_init(&vers);

  find_option("git", 0, 0);   /* Ignore the --git option for now */
  markfile_in = find_option("import-marks", 0, 1);
  markfile_out = find_option("export-marks", 0, 1);

  db_find_and_open_repository(0, 2);
  verify_all_options();
  if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }

  db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER PRIMARY KEY)");
  db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER PRIMARY KEY)");
  if( markfile_in!=0 ){
    Stmt qb,qc;
    char line[100];
    FILE *f;

    f = fossil_fopen(markfile_in, "r");
    if( f==0 ){
      fossil_fatal("cannot open %s for reading", markfile_in);
    }
    db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)");
    db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)");
    while( fgets(line, sizeof(line), f)!=0 ){
      if( *line == 'b' ){
        db_bind_text(&qb, ":rid", line + 1);
        db_step(&qb);
        db_reset(&qb);
        bag_insert(&blobs, atoi(line + 1));
      }else if( *line == 'c' ){
        db_bind_text(&qc, ":rid", line + 1);
        db_step(&qc);
        db_reset(&qc);
        bag_insert(&vers, atoi(line + 1));
      }else{
        fossil_fatal("bad input from %s: %s", markfile_in, line);
      }
    }
    db_finalize(&qb);
    db_finalize(&qc);
    fclose(f);
  }

  /* Step 1:  Generate "blob" records for every artifact that is part
  ** of a check-in 
  */
  fossil_binary_mode(stdout);
  db_multi_exec("CREATE TEMP TABLE newblob(rid INTEGER KEY, srcid INTEGER)");
  db_multi_exec("CREATE INDEX newblob_src ON newblob(srcid)");
  db_multi_exec(
    "INSERT INTO newblob"
    " SELECT DISTINCT fid,"
    "  CASE WHEN EXISTS(SELECT 1 FROM delta"
                       " WHERE rid=fid"
                       "   AND NOT EXISTS(SELECT 1 FROM oldblob"
                                         " WHERE srcid=fid))"
    "   THEN (SELECT srcid FROM delta WHERE rid=fid)"
    "   ELSE 0"
    "  END"
    " FROM mlink"
    " WHERE fid>0 AND NOT EXISTS(SELECT 1 FROM oldblob WHERE rid=fid)");
  db_prepare(&q,
    "SELECT DISTINCT fid FROM mlink"
    " WHERE fid>0 AND NOT EXISTS(SELECT 1 FROM oldblob WHERE rid=fid)");
  db_prepare(&q2, "INSERT INTO oldblob VALUES (:rid)");
  db_prepare(&q3, "SELECT rid FROM newblob WHERE srcid= (:srcid)");
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    Blob content;

    while( !bag_find(&blobs, rid) ){
      content_get(rid, &content);
      db_bind_int(&q2, ":rid", rid);
      db_step(&q2);
      db_reset(&q2);
      printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content));
      bag_insert(&blobs, rid);
      fwrite(blob_buffer(&content), 1, blob_size(&content), stdout);
      printf("\n");
      blob_reset(&content);

      db_bind_int(&q3, ":srcid", rid);
      if( db_step(&q3) != SQLITE_ROW ){
        db_reset(&q3);
        break;
      }
      rid = db_column_int(&q3, 0);
      db_reset(&q3);
    }
  }
  db_finalize(&q);
  db_finalize(&q2);
  db_finalize(&q3);

  /* Output the commit records.
  */
  db_prepare(&q,
    "SELECT strftime('%%s',mtime), objid, coalesce(comment,ecomment),"
    "       coalesce(user,euser),"
    "       (SELECT value FROM tagxref WHERE rid=objid AND tagid=%d)"
    "  FROM event"
    " WHERE type='ci' AND NOT EXISTS (SELECT 1 FROM oldcommit WHERE objid=rid)"
    " ORDER BY mtime ASC",
    TAG_BRANCH
  );
  db_prepare(&q2, "INSERT INTO oldcommit VALUES (:rid)");
  while( db_step(&q)==SQLITE_ROW ){
    Stmt q4;
    const char *zSecondsSince1970 = db_column_text(&q, 0);
    int ckinId = db_column_int(&q, 1);
    const char *zComment = db_column_text(&q, 2);
    const char *zUser = db_column_text(&q, 3);
    const char *zBranch = db_column_text(&q, 4);
    char *zBr;

    bag_insert(&vers, ckinId);
    db_bind_int(&q2, ":rid", ckinId);
    db_step(&q2);
    db_reset(&q2);
    if( zBranch==0 ) zBranch = "trunk";
    zBr = mprintf("%s", zBranch);
    for(i=0; zBr[i]; i++){
      if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
    }
    printf("commit refs/heads/%s\nmark :%d\n", zBr, COMMITMARK(ckinId));
    free(zBr);
    printf("committer");
    print_person(zUser);
    printf(" %s +0000\n", zSecondsSince1970);
    if( zComment==0 ) zComment = "null comment";
    printf("data %d\n%s\n", (int)strlen(zComment), zComment);
    db_prepare(&q3,
      "SELECT pid FROM plink"
      " WHERE cid=%d AND isprim"
      "   AND pid IN (SELECT objid FROM event)",
      ckinId
    );
    if( db_step(&q3) == SQLITE_ROW ){
      printf("from :%d\n", COMMITMARK(db_column_int(&q3, 0)));
      db_prepare(&q4,
        "SELECT pid FROM plink"
        " WHERE cid=%d AND NOT isprim"
        "   AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
        " ORDER BY pid",
        ckinId);
      while( db_step(&q4)==SQLITE_ROW ){
        printf("merge :%d\n", COMMITMARK(db_column_int(&q4,0)));
      }
      db_finalize(&q4);
    }else{
      printf("deleteall\n");
    }

    db_prepare(&q4,
      "SELECT filename.name, mlink.fid, mlink.mperm FROM mlink"
      " JOIN filename ON filename.fnid=mlink.fnid"
      " WHERE mlink.mid=%d",
      ckinId
    );
    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;
        switch( mPerm ){
          case PERM_LNK:  zPerm = "120000";   break;
          case PERM_EXE:  zPerm = "100755";   break;
          default:        zPerm = "100644";   break;
        }
        printf("M %s :%d %s\n", zPerm, BLOBMARK(zNew), zName);
      }
    }
    db_finalize(&q4);
    db_finalize(&q3);
    printf("\n");
  }
  db_finalize(&q2);
  db_finalize(&q);
  bag_clear(&blobs);
  manifest_cache_clear();


  /* Output tags */
  db_prepare(&q,
     "SELECT tagname, rid, strftime('%%s',mtime)"
     "  FROM tagxref JOIN tag USING(tagid)"
     " WHERE tagtype=1 AND tagname GLOB 'sym-*'"
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zTagname = db_column_text(&q, 0);
    char *zEncoded = 0;
    int rid = db_column_int(&q, 1);
    const char *zSecSince1970 = db_column_text(&q, 2);
    int i;
    if( rid==0 || !bag_find(&vers, rid) ) continue;
    zTagname += 4;
    zEncoded = mprintf("%s", zTagname);
    for(i=0; zEncoded[i]; i++){
      if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
    }
    printf("tag %s\n", zEncoded);
    printf("from :%d\n", COMMITMARK(rid));
    printf("tagger <tagger> %s +0000\n", zSecSince1970);
    printf("data 0\n");
    fossil_free(zEncoded);
  }
  db_finalize(&q);
  bag_clear(&vers);

  if( markfile_out!=0 ){
    FILE *f;
    f = fossil_fopen(markfile_out, "w");
    if( f == 0 ){
      fossil_fatal("cannot open %s for writing", markfile_out);
    }
    db_prepare(&q, "SELECT rid FROM oldblob");
    while( db_step(&q)==SQLITE_ROW ){
      fprintf(f, "b%d\n", db_column_int(&q, 0));
    }
    db_finalize(&q);
    db_prepare(&q, "SELECT rid FROM oldcommit");
    while( db_step(&q)==SQLITE_ROW ){
      fprintf(f, "c%d\n", db_column_int(&q, 0));
    }
    db_finalize(&q);
    if( ferror(f)!=0 || fclose(f)!=0 ) {
      fossil_fatal("error while writing %s", markfile_out);
    }
  }
}
Пример #22
0
/*
** Send "config" cards using the new format for all elements of a group
** that have recently changed.
**
** Output goes into pOut.  The groupMask identifies the group(s) to be sent.
** Send only entries whose timestamp is later than or equal to iStart.
**
** Return the number of cards sent.
*/
int configure_send_group(
    Blob *pOut,              /* Write output here */
    int groupMask,           /* Mask of groups to be send */
    sqlite3_int64 iStart     /* Only write values changed since this time */
) {
    Stmt q;
    Blob rec;
    int ii;
    int nCard = 0;

    blob_zero(&rec);
    if( groupMask & CONFIGSET_SHUN ) {
        db_prepare(&q, "SELECT mtime, quote(uuid), quote(scom) FROM shun"
                   " WHERE mtime>=%lld", iStart);
        while( db_step(&q)==SQLITE_ROW ) {
            blob_appendf(&rec,"%s %s scom %s",
                         db_column_text(&q, 0),
                         db_column_text(&q, 1),
                         db_column_text(&q, 2)
                        );
            blob_appendf(pOut, "config /shun %d\n%s\n",
                         blob_size(&rec), blob_str(&rec));
            nCard++;
            blob_reset(&rec);
        }
        db_finalize(&q);
    }
    if( groupMask & CONFIGSET_USER ) {
        db_prepare(&q, "SELECT mtime, quote(login), quote(pw), quote(cap),"
                   "       quote(info), quote(photo) FROM user"
                   " WHERE mtime>=%lld", iStart);
        while( db_step(&q)==SQLITE_ROW ) {
            blob_appendf(&rec,"%s %s pw %s cap %s info %s photo %s",
                         db_column_text(&q, 0),
                         db_column_text(&q, 1),
                         db_column_text(&q, 2),
                         db_column_text(&q, 3),
                         db_column_text(&q, 4),
                         db_column_text(&q, 5)
                        );
            blob_appendf(pOut, "config /user %d\n%s\n",
                         blob_size(&rec), blob_str(&rec));
            nCard++;
            blob_reset(&rec);
        }
        db_finalize(&q);
    }
    if( groupMask & CONFIGSET_TKT ) {
        db_prepare(&q, "SELECT mtime, quote(title), quote(owner), quote(cols),"
                   "       quote(sqlcode) FROM reportfmt"
                   " WHERE mtime>=%lld", iStart);
        while( db_step(&q)==SQLITE_ROW ) {
            blob_appendf(&rec,"%s %s owner %s cols %s sqlcode %s",
                         db_column_text(&q, 0),
                         db_column_text(&q, 1),
                         db_column_text(&q, 2),
                         db_column_text(&q, 3),
                         db_column_text(&q, 4)
                        );
            blob_appendf(pOut, "config /reportfmt %d\n%s\n",
                         blob_size(&rec), blob_str(&rec));
            nCard++;
            blob_reset(&rec);
        }
        db_finalize(&q);
    }
    if( groupMask & CONFIGSET_ADDR ) {
        db_prepare(&q, "SELECT mtime, quote(hash), quote(content) FROM concealed"
                   " WHERE mtime>=%lld", iStart);
        while( db_step(&q)==SQLITE_ROW ) {
            blob_appendf(&rec,"%s %s content %s",
                         db_column_text(&q, 0),
                         db_column_text(&q, 1),
                         db_column_text(&q, 2)
                        );
            blob_appendf(pOut, "config /concealed %d\n%s\n",
                         blob_size(&rec), blob_str(&rec));
            nCard++;
            blob_reset(&rec);
        }
        db_finalize(&q);
    }
    db_prepare(&q, "SELECT mtime, quote(name), quote(value) FROM config"
               " WHERE name=:name AND mtime>=%lld", iStart);
    for(ii=0; ii<count(aConfig); ii++) {
        if( (aConfig[ii].groupMask & groupMask)!=0 && aConfig[ii].zName[0]!='@' ) {
            db_bind_text(&q, ":name", aConfig[ii].zName);
            while( db_step(&q)==SQLITE_ROW ) {
                blob_appendf(&rec,"%s %s value %s",
                             db_column_text(&q, 0),
                             db_column_text(&q, 1),
                             db_column_text(&q, 2)
                            );
                blob_appendf(pOut, "config /config %d\n%s\n",
                             blob_size(&rec), blob_str(&rec));
                nCard++;
                blob_reset(&rec);
            }
            db_reset(&q);
        }
    }
    db_finalize(&q);
    return nCard;
}
Пример #23
0
/*
** Output a "committer" record for the given user.
*/
static void print_person(const char *zUser){
  static Stmt q;
  const char *zContact;
  char *zName;
  char *zEmail;
  int i, j;

  if( zUser==0 ){
    printf(" <unknown>");
    return;
  }
  db_static_prepare(&q, "SELECT info FROM user WHERE login=:user");
  db_bind_text(&q, ":user", zUser);
  if( db_step(&q)!=SQLITE_ROW ){
    db_reset(&q);
    for(i=0; zUser[i] && zUser[i]!='>' && zUser[i]!='<'; i++){}
    if( zUser[i]==0 ){
      printf(" %s <%s>", zUser, zUser);
      return;
    }
    zName = mprintf("%s", zUser);
    for(i=j=0; zName[i]; i++){
      if( zName[i]!='<' && zName[i]!='>' ){
        zName[j++] = zName[i];
      }
    }
    zName[j] = 0;
    printf(" %s <%s>", zName, zUser);
    free(zName);
    return;
  }
  /*
  ** We have contact information.
  ** It may or may not contain an email address.
   */
  zContact = db_column_text(&q, 0);
  for(i=0; zContact[i] && zContact[i]!='>' && zContact[i]!='<'; i++){}
  if( zContact[i]==0 ){
    /* No email address found. Take as user info if not empty */
    printf(" %s <%s>", zContact[0] ? zContact : zUser, zUser);
    db_reset(&q);
    return;
  }
  if( zContact[i]=='<' ){
    /*
    ** Found beginning of email address. Look for the end and extract
    ** the part.
     */
    zEmail = mprintf("%s", &zContact[i]);
    for(i=0; zEmail[i] && zEmail[i]!='>'; i++){}
    if( zEmail[i]=='>' ) zEmail[i+1] = 0;
  }else{
    /*
    ** Found an end marker for email, but nothing else.
     */
    zEmail = mprintf("<%s>", zUser);
  }
  /*
  ** Here zContact[i] either '<' or '>'. Extract the string _before_
  ** either as user name.
  */
  zName = mprintf("%.*s", i-1, zContact);
  for(i=j=0; zName[i]; i++){
    if( zName[i]!='"' ) zName[j++] = zName[i];
  }
  zName[j] = 0;
  printf(" %s %s", zName, zEmail);
  free(zName);
  free(zEmail);
  db_reset(&q);
}
Пример #24
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>
Пример #25
0
/*
** Scans the specified base directory for any directories within it, while
** keeping a count of how many files they each contains, either directly or
** indirectly.
**
** Subdirectories are scanned recursively.
** Omit files named in VFILE.
**
** Directories whose names begin with "." are omitted unless the SCAN_ALL
** flag is set.
**
** Any directories that match the glob patterns pIgnore* are excluded from
** the scan.  Name matching occurs after the first nPrefix characters are
** elided from the filename.
**
** Returns the total number of files found.
*/
int vfile_dir_scan(
  Blob *pPath,           /* Base directory to be scanned */
  int nPrefix,           /* Number of bytes in base directory name */
  unsigned scanFlags,    /* Zero or more SCAN_xxx flags */
  Glob *pIgnore1,        /* Do not add directories that match this GLOB */
  Glob *pIgnore2,        /* Omit directories matching this GLOB too */
  Glob *pIgnore3         /* Omit directories matching this GLOB too */
){
  int result = 0;
  DIR *d;
  int origSize;
  struct dirent *pEntry;
  int skipAll = 0;
  static Stmt ins;
  static Stmt upd;
  static int depth = 0;
  void *zNative;

  origSize = blob_size(pPath);
  if( pIgnore1 || pIgnore2 || pIgnore3 ){
    blob_appendf(pPath, "/");
    if( glob_match(pIgnore1, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
    if( glob_match(pIgnore2, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
    if( glob_match(pIgnore3, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
    blob_resize(pPath, origSize);
  }
  if( skipAll ) return result;

  if( depth==0 ){
    db_multi_exec("DROP TABLE IF EXISTS dscan_temp;"
                  "CREATE TEMP TABLE dscan_temp("
                  "  x TEXT PRIMARY KEY %s, y INTEGER)",
                  filename_collation());
    db_prepare(&ins,
       "INSERT OR IGNORE INTO dscan_temp(x, y) SELECT :file, :count"
       "  WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE"
       " pathname GLOB :file || '/*' %s)", filename_collation()
    );
    db_prepare(&upd,
       "UPDATE OR IGNORE dscan_temp SET y = coalesce(y, 0) + 1"
       "  WHERE x=:file %s",
       filename_collation()
    );
  }
  depth++;

  zNative = fossil_utf8_to_filename(blob_str(pPath));
  d = opendir(zNative);
  if( d ){
    while( (pEntry=readdir(d))!=0 ){
      char *zOrigPath;
      char *zPath;
      char *zUtf8;
      if( pEntry->d_name[0]=='.' ){
        if( (scanFlags & SCAN_ALL)==0 ) continue;
        if( pEntry->d_name[1]==0 ) continue;
        if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
      }
      zOrigPath = mprintf("%s", blob_str(pPath));
      zUtf8 = fossil_filename_to_utf8(pEntry->d_name);
      blob_appendf(pPath, "/%s", zUtf8);
      zPath = blob_str(pPath);
      if( glob_match(pIgnore1, &zPath[nPrefix+1]) ||
          glob_match(pIgnore2, &zPath[nPrefix+1]) ||
          glob_match(pIgnore3, &zPath[nPrefix+1]) ){
        /* do nothing */
      }else if( file_wd_isdir(zPath)==1 ){
        if( (scanFlags & SCAN_NESTED) || !vfile_top_of_checkout(zPath) ){
          char *zSavePath = mprintf("%s", zPath);
          int count = vfile_dir_scan(pPath, nPrefix, scanFlags, pIgnore1,
                                     pIgnore2, pIgnore3);
          db_bind_text(&ins, ":file", &zSavePath[nPrefix+1]);
          db_bind_int(&ins, ":count", count);
          db_step(&ins);
          db_reset(&ins);
          fossil_free(zSavePath);
          result += count; /* found X normal files? */
        }
      }else if( file_wd_isfile_or_link(zPath) ){
        db_bind_text(&upd, ":file", zOrigPath);
        db_step(&upd);
        db_reset(&upd);
        result++; /* found 1 normal file */
      }
      fossil_filename_free(zUtf8);
      blob_resize(pPath, origSize);
      fossil_free(zOrigPath);
    }
    closedir(d);
  }
  fossil_filename_free(zNative);

  depth--;
  if( depth==0 ){
    db_finalize(&upd);
    db_finalize(&ins);
  }
  return result;
}