Fossil

Check-in [2a86bb65]
Login

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

Overview
Comment: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.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | venks-emacs
Files: files | file ages | folders
SHA1:2a86bb65aac6075fd061637c94c9589a2b148816
User & Date: venkat 2010-11-07 21:11:42
Context
2010-11-08
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
18:48
Fix alphabetical missort. check-in: d156b686 user: venkat tags: venks-emacs
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/file.c.

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
** 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
**







|




>
|







>
>







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
** 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
**

Changes to src/finfo.c.

19
20
21
22
23
24
25
26















27
28
29
30
31
32
33
34
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
*/
#include "config.h"
#include "finfo.h"

/*
** COMMAND: finfo
** 
** Usage: %fossil finfo FILENAME















**
** 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){
  Stmt q;
  int vid;









  Blob dest;

































































  const char *zFilename;
  const char *zLimit;
  const char *zOffset;
  int iLimit, iOffset;

  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_panic("no checkout to finfo files in");

  }
  zLimit = find_option("limit",0,1);
  iLimit = zLimit ? atoi(zLimit) : -1;
  zOffset = find_option("offset",0,1);
  iOffset = zOffset ? atoi(zOffset) : 0;

  if (g.argc<3) {
    usage("FILENAME");
  }
  file_tree_name(g.argv[2], &dest, 1);




  zFilename = blob_str(&dest);
  db_prepare(&q,
    "SELECT "
    "       (SELECT uuid FROM blob WHERE rid=mlink.fid),"  /* New file */
    "       (SELECT uuid FROM blob WHERE rid=mlink.mid),"  /* The check-in */
    "       date(event.mtime,'localtime'),"
    "       coalesce(event.ecomment, event.comment),"
    "       coalesce(event.euser, event.user)"
    "  FROM mlink, event"
    " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"

    "   AND event.objid=mlink.mid"

    " ORDER BY event.mtime DESC LIMIT %d OFFSET %d /*sort*/",
    zFilename, iLimit, iOffset
  );



 
  printf("History of %s\n", zFilename);
  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;

    printf("%s ", zDate);
    if( zFileUuid==0 ){
      zOut = sqlite3_mprintf("[%.10s] DELETED %s (user: %s)",
                              zCiUuid, zCom, zUser);
    }else{
      zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])",
                              zCiUuid, zCom, zUser, zFileUuid);
    }
    comment_print(zOut, 11, 79);
    sqlite3_free(zOut);







  }

  db_finalize(&q);
  blob_reset(&dest);

}


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







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







<

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







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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
193
*/
#include "config.h"
#include "finfo.h"

/*
** COMMAND: finfo
** 
** Usage: %fossil finfo {?-l|--log? / -s|--status / --p|--print} FILENAME
**
** Print the complete change history for a single file going backwards
** in time.  The default is -l.
**
** For the -l|--log option: If "-b|--brief" is specified one line per revision
** is printed, otherwise the full comment is printed.  The "--limit N"
** and "--offset P" options limits the output to the first N changes
** after skipping P changes.
**
** In the -s form prints the status as <status> <revision>.  This is
** a quick status and does not check for up-to-date-ness of the file.
**
** 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
**

Changes to src/update.c.

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
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
...
262
263
264
265
266
267
268



269

270
271
272
273
274
275
276
      fossil_fatal("Multiple descendants");
    }
    tid = db_int(0, "SELECT rid FROM leaves, event"
                    " WHERE event.objid=leaves.rid"
                    " ORDER BY event.mtime DESC"); 
  }

  if( tid==vid ) return;  /* Nothing to update */
  db_begin_transaction();
  vfile_check_signature(vid, 1);
  if( !nochangeFlag ) undo_begin();
  load_vfile_from_rid(tid);

  /*
  ** The record.fn field is used to match files against each other.  The
................................................................................
  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 */
    char *zSep = "(";      /* Separator in the list of filenames */
    Blob treename;         /* Normalized filename */
    int i;                 /* Loop counter */

    blob_zero(&sql);
    blob_append(&sql, "DELETE FROM fv WHERE fn NOT IN ", -1);
    for(i=3; i<g.argc; i++){
      file_tree_name(g.argv[i], &treename, 1);




      blob_appendf(&sql, "%s'%q'", zSep, blob_str(&treename));







      blob_reset(&treename);
      zSep = ",";
    }
    blob_append(&sql, ")", -1);

    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 ){



      printf("UNCHANGED %s\n", zName);

    }
    free(zFullPath);
  }
  db_finalize(&q);
  
  /*
  ** Clean up the mid and pid VFILE entries.  Then commit the changes.







|







 







<




|


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

<

<
>







 







>
>
>
|
>







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
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
      fossil_fatal("Multiple descendants");
    }
    tid = db_int(0, "SELECT rid FROM leaves, event"
                    " WHERE event.objid=leaves.rid"
                    " ORDER BY event.mtime DESC"); 
  }

  if( !verboseFlag && (tid==vid)) return;  /* Nothing to update */
  db_begin_transaction();
  vfile_check_signature(vid, 1);
  if( !nochangeFlag ) undo_begin();
  load_vfile_from_rid(tid);

  /*
  ** The record.fn field is used to match files against each other.  The
................................................................................
  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.