Fossil

Check-in [c18bbf69]
Login

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

Overview
Comment:merge with trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | venks-emacs
Files: files | file ages | folders
SHA1:c18bbf69eb7730fb038d3edddb5777cbabbe3009
User & Date: venkat 2010-11-08 04:52:36
Context
2010-11-08
05:23
Allow fossil update -n -v current to be used on the root directory (aborted with "outside of checkout tree" error before). check-in: b6bb1ee7 user: venkat tags: venks-emacs
04:52
merge with trunk check-in: c18bbf69 user: venkat tags: venks-emacs
00:40
Merge in changes from the venks-emacs branch. check-in: c01e3c17 user: drh tags: trunk
2010-11-07
21:11
Patches to file.c (for mingw is_dir), finfo.c (various utilities), and update.c (for verbose/nochange), to allow integration into Emacs and IDEs. check-in: 2a86bb65 user: venkat tags: venks-emacs
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/file.c.

307
308
309
310
311
312
313

314
315
316
317

318

319
320
321
322
323
324
325
326
...
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
** Also test Fossil's ability to measure attributes of a file.
*/
void cmd_test_canonical_name(void){
  int i;
  Blob x;
  blob_zero(&x);
  for(i=2; i<g.argc; i++){

    const char *zName = g.argv[i];
    file_canonical_name(zName, &x);
    printf("%s\n", blob_buffer(&x));
    blob_reset(&x);

    printf("  file_size   = %lld\n", file_size(zName));

    printf("  file_mtime  = %lld\n", file_mtime(zName));
    printf("  file_isfile = %d\n", file_isfile(zName));
    printf("  file_isexe  = %d\n", file_isexe(zName));
    printf("  file_isdir  = %d\n", file_isdir(zName));
  }
}

/*
................................................................................
** tree.  Return TRUE on success.  On failure, print and error
** message and quit if the errFatal flag is true.  If errFatal is
** false, then simply return 0.
**
** The root of the tree is defined by the g.zLocalRoot variable.
*/
int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){
  int m,n;
  Blob full;
  db_must_be_within_tree();
  file_canonical_name(zOrigName, &full);
  n = strlen(g.zLocalRoot);
  m = blob_size(&full);
  if( m<n-1 || memcmp(g.zLocalRoot, blob_buffer(&full), n-1) ){
    blob_reset(&full);
    if( errFatal ){
      fossil_fatal("file outside of checkout tree: %s", zOrigName);
    }
    return 0;
  }
  blob_zero(pOut);
  if (m == n - 1)
     return 1;
  blob_append(pOut, blob_buffer(&full)+n, blob_size(&full)-n);
  return 1;
}

/*
** COMMAND:  test-tree-name
**







>




>
|
>
|







 







|




<
|







<
<







307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
...
425
426
427
428
429
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444


445
446
447
448
449
450
451
** Also test Fossil's ability to measure attributes of a file.
*/
void cmd_test_canonical_name(void){
  int i;
  Blob x;
  blob_zero(&x);
  for(i=2; i<g.argc; i++){
    char zBuf[100];
    const char *zName = g.argv[i];
    file_canonical_name(zName, &x);
    printf("%s\n", blob_buffer(&x));
    blob_reset(&x);
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zName));
    printf("  file_size   = %s\n", zBuf);
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_mtime(zName));
    printf("  file_mtime  = %s\n", zBuf);
    printf("  file_isfile = %d\n", file_isfile(zName));
    printf("  file_isexe  = %d\n", file_isexe(zName));
    printf("  file_isdir  = %d\n", file_isdir(zName));
  }
}

/*
................................................................................
** tree.  Return TRUE on success.  On failure, print and error
** message and quit if the errFatal flag is true.  If errFatal is
** false, then simply return 0.
**
** The root of the tree is defined by the g.zLocalRoot variable.
*/
int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){
  int n;
  Blob full;
  db_must_be_within_tree();
  file_canonical_name(zOrigName, &full);
  n = strlen(g.zLocalRoot);

  if( blob_size(&full)<=n || memcmp(g.zLocalRoot, blob_buffer(&full), n) ){
    blob_reset(&full);
    if( errFatal ){
      fossil_fatal("file outside of checkout tree: %s", zOrigName);
    }
    return 0;
  }
  blob_zero(pOut);


  blob_append(pOut, blob_buffer(&full)+n, blob_size(&full)-n);
  return 1;
}

/*
** COMMAND:  test-tree-name
**

Changes to src/finfo.c.

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

78
79
80

81

82
83

84
85

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
**
** 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.
**
** The -p form, there's an optional flag "-r|--revision REVISION".  The
** specified version (or the latest checked out version) is printed to
** stdout.
**
** Print the change history for a single file.
**
** The "--limit N" and "--offset P" options limit the output to the first
** N changes after skipping P changes.
*/
void finfo_cmd(void){
  int vid;

  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_panic("no checkout to finfo files in");
  }
  vfile_check_signature(vid, 1);
  if (find_option("status","s",0)) {
      Stmt q;
      Blob line;
      Blob fname;

      if (g.argc != 3) {
	  usage("-s|--status FILENAME");
      }
      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", &fname);
      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",&fname);

	  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);
      printf("%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);
      } else {
	  int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname);
	  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", &fname);
      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"
		 " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
		 "   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, iLimit, iOffset
	  );
      blob_zero(&line);
      if (iBrief) {
	  printf("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) {
	      printf("%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);
  }
}


/*
** WEBPAGE: finfo
** URL: /finfo?name=FILENAME







<
<
<
<
<











|
|
|

<
|
<
|
|
|
|
|
|
|
|
|
|
|

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

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







35
36
37
38
39
40
41





42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

79
80

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
**
** 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.
**
** The -p form, there's an optional flag "-r|--revision REVISION".  The
** specified version (or the latest checked out version) is printed to
** stdout.





*/
void finfo_cmd(void){
  int vid;

  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_panic("no checkout to finfo files in");
  }
  vfile_check_signature(vid, 1);
  if (find_option("status","s",0)) {
    Stmt q;
    Blob line;
    Blob fname;


    if( g.argc!=3 ) usage("-s|--status FILENAME");

    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", &fname);
    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",
           &fname
      );
      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);
    printf("%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);
    }else{
      int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname);
      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", &fname);
    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"
        " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
        "   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, iLimit, iOffset
    );
    blob_zero(&line);
    if( iBrief ){
      printf("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 ){
        printf("%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);
  }
}


/*
** WEBPAGE: finfo
** URL: /finfo?name=FILENAME

Changes to src/setup.c.

1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
  db_end_transaction(0);
}

/*
** WEBPAGE: setup_logo
*/
void setup_logo(void){
  const char *zMime = "image/gif";
  const char *aImg = P("im");
  int szImg = atoi(PD("im:bytes","0"));
  if( szImg>0 ){
    zMime = PD("im:mimetype","image/gif");
  }
  login_check_credentials();
  if( !g.okSetup ){







|







1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
  db_end_transaction(0);
}

/*
** WEBPAGE: setup_logo
*/
void setup_logo(void){
  const char *zMime = db_get("logo-mimetype","image/gif");
  const char *aImg = P("im");
  int szImg = atoi(PD("im:bytes","0"));
  if( szImg>0 ){
    zMime = PD("im:mimetype","image/gif");
  }
  login_check_credentials();
  if( !g.okSetup ){

Changes to src/style.c.

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  va_start(ap, zTitleFormat);
  zTitle = vmprintf(zTitleFormat, ap);
  va_end(ap);
  
  cgi_destination(CGI_HEADER);
  cgi_printf("%s",
     "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""
     " \"http://www.x3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
  
  if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1);

  /* Generate the header up through the main menu */
  Th_Store("project_name", db_get("project-name","Unnamed Fossil Project"));
  Th_Store("title", zTitle);
  Th_Store("baseurl", g.zBaseURL);







|







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  va_start(ap, zTitleFormat);
  zTitle = vmprintf(zTitleFormat, ap);
  va_end(ap);
  
  cgi_destination(CGI_HEADER);
  cgi_printf("%s",
     "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""
     " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
  
  if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1);

  /* Generate the header up through the main menu */
  Th_Store("project_name", db_get("project-name","Unnamed Fossil Project"));
  Th_Store("title", zTitle);
  Th_Store("baseurl", g.zBaseURL);

Changes to src/update.c.

41
42
43
44
45
46
47
48


49
50
51
52
53
54
55
...
164
165
166
167
168
169
170
171

172
173
174
175
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

197
198
199
200
201
202
203
...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
** If the VERSION argument is omitted, then the leaf of the subtree
** that begins at the current version is used, if there is only a single
** leaf.  VERSION can also be "current" to select the leaf of the current
** version or "latest" to select the most recent check-in.
**
** If one or more FILES are listed after the VERSION then only the
** named files are candidates to be updated.  If FILES is omitted, all
** files in the current checkout are subject to be updated.


**
** The -n or --nochange option causes this command to do a "dry run".  It
** prints out what would have happened but does not actually make any
** changes to the current checkout or the repository.
**
** The -v or --verbose option prints status information about unchanged
** files in addition to those file that actually do change.
................................................................................
      "UPDATE fv SET idv=%d, ridv=%d, chnged=%d WHERE fn=%Q",
      id, rid, chnged, fn
    );
  }
  db_finalize(&q);

  /* If FILES appear on the command-line, remove from the "fv" table
  ** every entry that is not named on the command-line.

  */
  if( g.argc>=4 ){
    Blob sql;              /* SQL statement to purge unwanted entries */
    Blob treename;         /* Normalized filename */
    int i;                 /* Loop counter */


    blob_zero(&sql);
    blob_append(&sql, "DELETE FROM fv WHERE ", -1);
    for(i=3; i<g.argc; i++){
      file_tree_name(g.argv[i], &treename, 1);
      if (file_isdir(g.argv[i]) == 1) {
	  if (blob_size(&treename) > 0) {
	      blob_appendf(&sql, "fn NOT GLOB '%b/*' ", &treename);
	  } else {
	      blob_appendf(&sql, "fn NOT GLOB '*' ");
	  }
      } else {
	  blob_appendf(&sql, "fn <> %B ", &treename);
      }
      if (i < g.argc - 1) {
	  blob_append(&sql, "AND ", -1);
      }
      blob_reset(&treename);
    }
    fprintf(stderr, "%s\n", blob_str(&sql));

    db_multi_exec(blob_str(&sql));
    blob_reset(&sql);
  }

  db_prepare(&q, 
    "SELECT fn, idv, ridv, idt, ridt, chnged FROM fv ORDER BY 1"
  );
................................................................................
        printf("***** Cannot merge binary file %s\n", zName);
      }
      blob_reset(&v);
      blob_reset(&e);
      blob_reset(&t);
      blob_reset(&r);
    }else if( verboseFlag ){
	if (chnged) {
	    printf("EDITED %s\n", zName);
	} else {
	    printf("UNCHANGED %s\n", zName);
	}
    }
    free(zFullPath);
  }
  db_finalize(&q);
  
  /*
  ** Clean up the mid and pid VFILE entries.  Then commit the changes.







|
>
>







 







|
>





>



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







 







|
|
|
|
|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
** If the VERSION argument is omitted, then the leaf of the subtree
** that begins at the current version is used, if there is only a single
** leaf.  VERSION can also be "current" to select the leaf of the current
** version or "latest" to select the most recent check-in.
**
** If one or more FILES are listed after the VERSION then only the
** named files are candidates to be updated.  If FILES is omitted, all
** files in the current checkout are subject to be updated.  Using
** a directory name for one of the FILES arguments is the same as
** using every subdirectory and file beneath that directory.
**
** The -n or --nochange option causes this command to do a "dry run".  It
** prints out what would have happened but does not actually make any
** changes to the current checkout or the repository.
**
** The -v or --verbose option prints status information about unchanged
** files in addition to those file that actually do change.
................................................................................
      "UPDATE fv SET idv=%d, ridv=%d, chnged=%d WHERE fn=%Q",
      id, rid, chnged, fn
    );
  }
  db_finalize(&q);

  /* If FILES appear on the command-line, remove from the "fv" table
  ** every entry that is not named on the command-line or which is not
  ** in a directory named on the command-line.
  */
  if( g.argc>=4 ){
    Blob sql;              /* SQL statement to purge unwanted entries */
    Blob treename;         /* Normalized filename */
    int i;                 /* Loop counter */
    const char *zSep;      /* Term separator */

    blob_zero(&sql);
    blob_append(&sql, "DELETE FROM fv WHERE ", -1);
    zSep = "";
    for(i=3; i<g.argc; i++){
      file_tree_name(g.argv[i], &treename, 1);
      if( file_isdir(g.argv[i])==1 ){
        if( blob_size(&treename)>0 ){
          blob_appendf(&sql, "%sfn NOT GLOB '%b/*' ", zSep, &treename);
        }else{
          blob_reset(&sql);
          blob_append(&sql, "DELETE FROM fv", -1);
          break;
        }
      }else{
        blob_appendf(&sql, "%sfn<>%B ", zSep, &treename);
      }
      zSep = "AND ";
      blob_reset(&treename);
    }
    /* fprintf(stderr, "%s\n", blob_str(&sql)); */
    db_multi_exec(blob_str(&sql));
    blob_reset(&sql);
  }

  db_prepare(&q, 
    "SELECT fn, idv, ridv, idt, ridt, chnged FROM fv ORDER BY 1"
  );
................................................................................
        printf("***** Cannot merge binary file %s\n", zName);
      }
      blob_reset(&v);
      blob_reset(&e);
      blob_reset(&t);
      blob_reset(&r);
    }else if( verboseFlag ){
      if( chnged ){
        printf("EDITED %s\n", zName);
      }else{
        printf("UNCHANGED %s\n", zName);
      }
    }
    free(zFullPath);
  }
  db_finalize(&q);
  
  /*
  ** Clean up the mid and pid VFILE entries.  Then commit the changes.