Fossil SCM

Add the "merge-in:NAME" name type, similar to "root:NAME" except that it finds the youngest anscestor of NAME that is in the branch from which the branch of NAME derived.

drh 2019-08-27 01:47 vdiff-improvements
Commit dcd8f1d8f494601afcaed6bd0a7336758303b638b586a97f641a7f35ce9ee49a
+27
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,37 @@
1818
** This file contains code used to create new branches within a repository.
1919
*/
2020
#include "config.h"
2121
#include "branch.h"
2222
#include <assert.h>
23
+
24
+/*
25
+** If RID refers to a check-in, return the name of the branch for that
26
+** check-in.
27
+**
28
+** Space to hold the returned value is obtained from fossil_malloc()
29
+** and should be freed by the caller.
30
+*/
31
+char *branch_of_rid(int rid){
32
+ char *zBr = 0;
33
+ static Stmt q;
34
+ db_static_prepare(&q,
35
+ "SELECT value FROM tagxref"
36
+ " WHERE rid=$rid AND tagid=%d"
37
+ " AND tagtype>0", TAG_BRANCH);
38
+ db_bind_int(&q, "$rid", rid);
39
+ if( db_step(&q)==SQLITE_ROW ){
40
+ zBr = fossil_strdup(db_column_text(&q,0));
41
+ }
42
+ db_reset(&q);
43
+ if( zBr==0 ){
44
+ static char *zMain = 0;
45
+ if( zMain==0 ) zMain = db_get("main-branch","trunk");
46
+ zBr = fossil_strdup(zMain);
47
+ }
48
+ return zBr;
49
+}
2350
2451
/*
2552
** fossil branch new NAME BASIS ?OPTIONS?
2653
** argv0 argv1 argv2 argv3 argv4
2754
*/
2855
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,37 @@
18 ** This file contains code used to create new branches within a repository.
19 */
20 #include "config.h"
21 #include "branch.h"
22 #include <assert.h>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
24 /*
25 ** fossil branch new NAME BASIS ?OPTIONS?
26 ** argv0 argv1 argv2 argv3 argv4
27 */
28
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,37 @@
18 ** This file contains code used to create new branches within a repository.
19 */
20 #include "config.h"
21 #include "branch.h"
22 #include <assert.h>
23
24 /*
25 ** If RID refers to a check-in, return the name of the branch for that
26 ** check-in.
27 **
28 ** Space to hold the returned value is obtained from fossil_malloc()
29 ** and should be freed by the caller.
30 */
31 char *branch_of_rid(int rid){
32 char *zBr = 0;
33 static Stmt q;
34 db_static_prepare(&q,
35 "SELECT value FROM tagxref"
36 " WHERE rid=$rid AND tagid=%d"
37 " AND tagtype>0", TAG_BRANCH);
38 db_bind_int(&q, "$rid", rid);
39 if( db_step(&q)==SQLITE_ROW ){
40 zBr = fossil_strdup(db_column_text(&q,0));
41 }
42 db_reset(&q);
43 if( zBr==0 ){
44 static char *zMain = 0;
45 if( zMain==0 ) zMain = db_get("main-branch","trunk");
46 zBr = fossil_strdup(zMain);
47 }
48 return zBr;
49 }
50
51 /*
52 ** fossil branch new NAME BASIS ?OPTIONS?
53 ** argv0 argv1 argv2 argv3 argv4
54 */
55
--- src/descendants.c
+++ src/descendants.c
@@ -183,10 +183,35 @@
183183
"INSERT INTO ok"
184184
" SELECT rid FROM ancestor;",
185185
rid, rid, directOnly ? "AND plink.isPrim" : "", N
186186
);
187187
}
188
+
189
+/*
190
+** Compute the youngest ancestor of record ID rid that is a member of
191
+** branch zBranch.
192
+*/
193
+int compute_youngest_ancestor_in_branch(int rid, const char *zBranch){
194
+ return db_int(0,
195
+ "WITH RECURSIVE "
196
+ " ancestor(rid, mtime) AS ("
197
+ " SELECT %d, mtime FROM event WHERE objid=%d "
198
+ " UNION "
199
+ " SELECT plink.pid, event.mtime"
200
+ " FROM ancestor, plink, event"
201
+ " WHERE plink.cid=ancestor.rid"
202
+ " AND event.objid=plink.pid"
203
+ " ORDER BY mtime DESC"
204
+ " )"
205
+ " SELECT ancestor.rid FROM ancestor"
206
+ " WHERE EXISTS(SELECT 1 FROM tagxref"
207
+ " WHERE tagid=%d AND tagxref.rid=ancestor.rid"
208
+ " AND value=%Q AND tagtype>0)"
209
+ " LIMIT 1",
210
+ rid, rid, TAG_BRANCH, zBranch
211
+ );
212
+}
188213
189214
/*
190215
** Compute all direct ancestors (merge ancestors do not count)
191216
** for the check-in rid and put them in a table named "ancestor".
192217
** Label each generation with consecutive integers going backwards
193218
--- src/descendants.c
+++ src/descendants.c
@@ -183,10 +183,35 @@
183 "INSERT INTO ok"
184 " SELECT rid FROM ancestor;",
185 rid, rid, directOnly ? "AND plink.isPrim" : "", N
186 );
187 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
189 /*
190 ** Compute all direct ancestors (merge ancestors do not count)
191 ** for the check-in rid and put them in a table named "ancestor".
192 ** Label each generation with consecutive integers going backwards
193
--- src/descendants.c
+++ src/descendants.c
@@ -183,10 +183,35 @@
183 "INSERT INTO ok"
184 " SELECT rid FROM ancestor;",
185 rid, rid, directOnly ? "AND plink.isPrim" : "", N
186 );
187 }
188
189 /*
190 ** Compute the youngest ancestor of record ID rid that is a member of
191 ** branch zBranch.
192 */
193 int compute_youngest_ancestor_in_branch(int rid, const char *zBranch){
194 return db_int(0,
195 "WITH RECURSIVE "
196 " ancestor(rid, mtime) AS ("
197 " SELECT %d, mtime FROM event WHERE objid=%d "
198 " UNION "
199 " SELECT plink.pid, event.mtime"
200 " FROM ancestor, plink, event"
201 " WHERE plink.cid=ancestor.rid"
202 " AND event.objid=plink.pid"
203 " ORDER BY mtime DESC"
204 " )"
205 " SELECT ancestor.rid FROM ancestor"
206 " WHERE EXISTS(SELECT 1 FROM tagxref"
207 " WHERE tagid=%d AND tagxref.rid=ancestor.rid"
208 " AND value=%Q AND tagtype>0)"
209 " LIMIT 1",
210 rid, rid, TAG_BRANCH, zBranch
211 );
212 }
213
214 /*
215 ** Compute all direct ancestors (merge ancestors do not count)
216 ** for the check-in rid and put them in a table named "ancestor".
217 ** Label each generation with consecutive integers going backwards
218
+22 -12
--- src/info.c
+++ src/info.c
@@ -1206,10 +1206,11 @@
12061206
const char *zFrom;
12071207
const char *zTo;
12081208
const char *zRe;
12091209
const char *zW;
12101210
const char *zGlob;
1211
+ char *zQuery;
12111212
ReCompiled *pRe = 0;
12121213
login_check_credentials();
12131214
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
12141215
login_anonymous_available();
12151216
load_control();
@@ -1217,13 +1218,17 @@
12171218
diffType = atoi(PD("diff","2"));
12181219
cookie_render();
12191220
zRe = P("regex");
12201221
if( zRe ) re_compile(&pRe, zRe, 0);
12211222
zBranch = P("branch");
1222
- if( zBranch && zBranch[0] ){
1223
+ if( zBranch && zBranch[0]==0 ) zBranch = 0;
1224
+ if( zBranch ){
1225
+ zQuery = mprintf("branch=%T", zBranch);
12231226
cgi_replace_parameter("from", mprintf("root:%s", zBranch));
12241227
cgi_replace_parameter("to", zBranch);
1228
+ }else{
1229
+ zQuery = mprintf("from=%T&to=%T",PD("from",""),PD("to",""));
12251230
}
12261231
pTo = vdiff_parse_manifest("to", &ridTo);
12271232
if( pTo==0 ) return;
12281233
pFrom = vdiff_parse_manifest("from", &ridFrom);
12291234
if( pFrom==0 ) return;
@@ -1233,34 +1238,38 @@
12331238
if(zGlob && !*zGlob){
12341239
zGlob = NULL;
12351240
}
12361241
diffFlags = construct_diff_flags(diffType);
12371242
zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
1238
- style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
1243
+ if( zBranch==0 ){
1244
+ style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
1245
+ }
12391246
if( diffType!=0 ){
1240
- style_submenu_element("Hide Diff", "%R/vdiff?from=%T&to=%T&diff=0%s%T%s",
1241
- zFrom, zTo,
1247
+ style_submenu_element("Hide Diff", "%R/vdiff?%s&diff=0%s%T%s",
1248
+ zQuery,
12421249
zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
12431250
}
12441251
if( diffType!=2 ){
12451252
style_submenu_element("Side-by-Side Diff",
1246
- "%R/vdiff?from=%T&to=%T&diff=2%s%T%s",
1247
- zFrom, zTo,
1253
+ "%R/vdiff?%s&diff=2%s%T%s",
1254
+ zQuery,
12481255
zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
12491256
}
12501257
if( diffType!=1 ) {
12511258
style_submenu_element("Unified Diff",
1252
- "%R/vdiff?from=%T&to=%T&diff=1%s%T%s",
1253
- zFrom, zTo,
1259
+ "%R/vdiff?%s&diff=1%s%T%s",
1260
+ zQuery,
1261
+ zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1262
+ }
1263
+ if( zBranch==0 ){
1264
+ style_submenu_element("Invert",
1265
+ "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom,
12541266
zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
12551267
}
1256
- style_submenu_element("Invert",
1257
- "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom,
1258
- zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
12591268
if( zGlob ){
12601269
style_submenu_element("Clear glob",
1261
- "%R/vdiff?from=%T&to=%T&%s", zFrom, zTo, zW);
1270
+ "%R/vdiff?%s&%s", zQuery, zW);
12621271
}else{
12631272
style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW);
12641273
}
12651274
if( diffType!=0 ){
12661275
style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
@@ -1279,10 +1288,11 @@
12791288
if( zGlob ){
12801289
@ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p>
12811290
}
12821291
@<hr /><p>
12831292
}
1293
+ fossil_free(zQuery);
12841294
12851295
manifest_file_rewind(pFrom);
12861296
pFileFrom = manifest_file_next(pFrom, 0);
12871297
manifest_file_rewind(pTo);
12881298
pFileTo = manifest_file_next(pTo, 0);
12891299
--- src/info.c
+++ src/info.c
@@ -1206,10 +1206,11 @@
1206 const char *zFrom;
1207 const char *zTo;
1208 const char *zRe;
1209 const char *zW;
1210 const char *zGlob;
 
1211 ReCompiled *pRe = 0;
1212 login_check_credentials();
1213 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1214 login_anonymous_available();
1215 load_control();
@@ -1217,13 +1218,17 @@
1217 diffType = atoi(PD("diff","2"));
1218 cookie_render();
1219 zRe = P("regex");
1220 if( zRe ) re_compile(&pRe, zRe, 0);
1221 zBranch = P("branch");
1222 if( zBranch && zBranch[0] ){
 
 
1223 cgi_replace_parameter("from", mprintf("root:%s", zBranch));
1224 cgi_replace_parameter("to", zBranch);
 
 
1225 }
1226 pTo = vdiff_parse_manifest("to", &ridTo);
1227 if( pTo==0 ) return;
1228 pFrom = vdiff_parse_manifest("from", &ridFrom);
1229 if( pFrom==0 ) return;
@@ -1233,34 +1238,38 @@
1233 if(zGlob && !*zGlob){
1234 zGlob = NULL;
1235 }
1236 diffFlags = construct_diff_flags(diffType);
1237 zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
1238 style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
 
 
1239 if( diffType!=0 ){
1240 style_submenu_element("Hide Diff", "%R/vdiff?from=%T&to=%T&diff=0%s%T%s",
1241 zFrom, zTo,
1242 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1243 }
1244 if( diffType!=2 ){
1245 style_submenu_element("Side-by-Side Diff",
1246 "%R/vdiff?from=%T&to=%T&diff=2%s%T%s",
1247 zFrom, zTo,
1248 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1249 }
1250 if( diffType!=1 ) {
1251 style_submenu_element("Unified Diff",
1252 "%R/vdiff?from=%T&to=%T&diff=1%s%T%s",
1253 zFrom, zTo,
 
 
 
 
 
1254 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1255 }
1256 style_submenu_element("Invert",
1257 "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom,
1258 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1259 if( zGlob ){
1260 style_submenu_element("Clear glob",
1261 "%R/vdiff?from=%T&to=%T&%s", zFrom, zTo, zW);
1262 }else{
1263 style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW);
1264 }
1265 if( diffType!=0 ){
1266 style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
@@ -1279,10 +1288,11 @@
1279 if( zGlob ){
1280 @ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p>
1281 }
1282 @<hr /><p>
1283 }
 
1284
1285 manifest_file_rewind(pFrom);
1286 pFileFrom = manifest_file_next(pFrom, 0);
1287 manifest_file_rewind(pTo);
1288 pFileTo = manifest_file_next(pTo, 0);
1289
--- src/info.c
+++ src/info.c
@@ -1206,10 +1206,11 @@
1206 const char *zFrom;
1207 const char *zTo;
1208 const char *zRe;
1209 const char *zW;
1210 const char *zGlob;
1211 char *zQuery;
1212 ReCompiled *pRe = 0;
1213 login_check_credentials();
1214 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1215 login_anonymous_available();
1216 load_control();
@@ -1217,13 +1218,17 @@
1218 diffType = atoi(PD("diff","2"));
1219 cookie_render();
1220 zRe = P("regex");
1221 if( zRe ) re_compile(&pRe, zRe, 0);
1222 zBranch = P("branch");
1223 if( zBranch && zBranch[0]==0 ) zBranch = 0;
1224 if( zBranch ){
1225 zQuery = mprintf("branch=%T", zBranch);
1226 cgi_replace_parameter("from", mprintf("root:%s", zBranch));
1227 cgi_replace_parameter("to", zBranch);
1228 }else{
1229 zQuery = mprintf("from=%T&to=%T",PD("from",""),PD("to",""));
1230 }
1231 pTo = vdiff_parse_manifest("to", &ridTo);
1232 if( pTo==0 ) return;
1233 pFrom = vdiff_parse_manifest("from", &ridFrom);
1234 if( pFrom==0 ) return;
@@ -1233,34 +1238,38 @@
1238 if(zGlob && !*zGlob){
1239 zGlob = NULL;
1240 }
1241 diffFlags = construct_diff_flags(diffType);
1242 zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
1243 if( zBranch==0 ){
1244 style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
1245 }
1246 if( diffType!=0 ){
1247 style_submenu_element("Hide Diff", "%R/vdiff?%s&diff=0%s%T%s",
1248 zQuery,
1249 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1250 }
1251 if( diffType!=2 ){
1252 style_submenu_element("Side-by-Side Diff",
1253 "%R/vdiff?%s&diff=2%s%T%s",
1254 zQuery,
1255 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1256 }
1257 if( diffType!=1 ) {
1258 style_submenu_element("Unified Diff",
1259 "%R/vdiff?%s&diff=1%s%T%s",
1260 zQuery,
1261 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1262 }
1263 if( zBranch==0 ){
1264 style_submenu_element("Invert",
1265 "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom,
1266 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1267 }
 
 
 
1268 if( zGlob ){
1269 style_submenu_element("Clear glob",
1270 "%R/vdiff?%s&%s", zQuery, zW);
1271 }else{
1272 style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW);
1273 }
1274 if( diffType!=0 ){
1275 style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
@@ -1279,10 +1288,11 @@
1288 if( zGlob ){
1289 @ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p>
1290 }
1291 @<hr /><p>
1292 }
1293 fossil_free(zQuery);
1294
1295 manifest_file_rewind(pFrom);
1296 pFileFrom = manifest_file_next(pFrom, 0);
1297 manifest_file_rewind(pTo);
1298 pFileTo = manifest_file_next(pTo, 0);
1299
+51 -25
--- src/name.c
+++ src/name.c
@@ -108,21 +108,25 @@
108108
return zEDate;
109109
}
110110
111111
/*
112112
** Return the RID that is the "root" of the branch that contains
113
-** check-in "rid" if inBranch==0 or the first check-in in the branch
114
-** if inBranch==1.
113
+** check-in "rid". Details depending on eType:
114
+**
115
+** eType==0 The check-in of the parent branch off of which
116
+** the branch containing RID originally diverged.
117
+**
118
+** eType==1 The first check-in of the branch that contains RID.
119
+**
120
+** eType==2 The youngest ancestor of RID that is on the branch
121
+** from which the branch containing RID diverged.
115122
*/
116
-int start_of_branch(int rid, int inBranch){
123
+int start_of_branch(int rid, int eType){
117124
Stmt q;
118125
int rc;
119
- char *zBr;
120
- zBr = db_text("trunk","SELECT value FROM tagxref"
121
- " WHERE rid=%d AND tagid=%d"
122
- " AND tagtype>0",
123
- rid, TAG_BRANCH);
126
+ int ans = rid;
127
+ char *zBr = branch_of_rid(rid);
124128
db_prepare(&q,
125129
"SELECT pid, EXISTS(SELECT 1 FROM tagxref"
126130
" WHERE tagid=%d AND tagtype>0"
127131
" AND value=%Q AND rid=plink.pid)"
128132
" FROM plink"
@@ -130,18 +134,23 @@
130134
TAG_BRANCH, zBr
131135
);
132136
fossil_free(zBr);
133137
do{
134138
db_reset(&q);
135
- db_bind_int(&q, ":cid", rid);
139
+ db_bind_int(&q, ":cid", ans);
136140
rc = db_step(&q);
137141
if( rc!=SQLITE_ROW ) break;
138
- if( inBranch && db_column_int(&q,1)==0 ) break;
139
- rid = db_column_int(&q, 0);
140
- }while( db_column_int(&q, 1)==1 && rid>0 );
142
+ if( eType==1 && db_column_int(&q,1)==0 ) break;
143
+ ans = db_column_int(&q, 0);
144
+ }while( db_column_int(&q, 1)==1 && ans>0 );
141145
db_finalize(&q);
142
- return rid;
146
+ if( eType==2 && ans>0 ){
147
+ zBr = branch_of_rid(ans);
148
+ ans = compute_youngest_ancestor_in_branch(rid, zBr);
149
+ fossil_free(zBr);
150
+ }
151
+ return ans;
143152
}
144153
145154
/*
146155
** Convert a symbolic name into a RID. Acceptable forms:
147156
**
@@ -165,10 +174,11 @@
165174
**
166175
** The zType parameter specifies the type of artifact: ci, t, w, e, g, f.
167176
** If zType is NULL or "" or "*" then any type of artifact will serve.
168177
** If zType is "br" then find the first check-in of the named branch
169178
** rather than the last.
179
+**
170180
** zType is "ci" in most use cases since we are usually searching for
171181
** a check-in.
172182
**
173183
** Note that the input zTag for types "t" and "e" is the artifact hash of
174184
** the ticket-change or technote-change artifact, not the randomly generated
@@ -270,14 +280,19 @@
270280
);
271281
if( startOfBranch ) rid = start_of_branch(rid,1);
272282
return rid;
273283
}
274284
275
- /* root:TAG -> The origin of the branch */
276
- if( memcmp(zTag, "root:", 5)==0 ){
285
+ /* root:BR -> The origin of the branch named BR */
286
+ if( strncmp(zTag, "root:", 5)==0 ){
277287
rid = symbolic_name_to_rid(zTag+5, zType);
278288
return start_of_branch(rid, 0);
289
+ }
290
+ /* rootx:BR -> Most recent merge-in for the branch name BR */
291
+ if( strncmp(zTag, "merge-in:", 9)==0 ){
292
+ rid = symbolic_name_to_rid(zTag+9, zType);
293
+ return start_of_branch(rid, 2);
279294
}
280295
281296
/* symbolic-name ":" date-time */
282297
nTag = strlen(zTag);
283298
for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
@@ -465,26 +480,37 @@
465480
}
466481
467482
/*
468483
** COMMAND: test-name-to-id
469484
**
470
-** Convert a name to a full artifact ID.
485
+** Usage: %fossil test-name-to-id [--count N] NAME
486
+**
487
+** Convert a NAME to a full artifact ID. Repeat the conversion N
488
+** times (for timing purposes) if the --count option is given.
471489
*/
472490
void test_name_to_id(void){
473491
int i;
492
+ int n = 0;
474493
Blob name;
475494
db_must_be_within_tree();
476495
for(i=2; i<g.argc; i++){
477
- blob_init(&name, g.argv[i], -1);
478
- fossil_print("%s -> ", g.argv[i]);
479
- if( name_to_uuid(&name, 1, "*") ){
480
- fossil_print("ERROR: %s\n", g.zErrMsg);
481
- fossil_error_reset();
482
- }else{
483
- fossil_print("%s\n", blob_buffer(&name));
484
- }
485
- blob_reset(&name);
496
+ if( strcmp(g.argv[i],"--count")==0 && i+1<g.argc ){
497
+ i++;
498
+ n = atoi(g.argv[i]);
499
+ continue;
500
+ }
501
+ do{
502
+ blob_init(&name, g.argv[i], -1);
503
+ fossil_print("%s -> ", g.argv[i]);
504
+ if( name_to_uuid(&name, 1, "*") ){
505
+ fossil_print("ERROR: %s\n", g.zErrMsg);
506
+ fossil_error_reset();
507
+ }else{
508
+ fossil_print("%s\n", blob_buffer(&name));
509
+ }
510
+ blob_reset(&name);
511
+ }while( n-- > 0 );
486512
}
487513
}
488514
489515
/*
490516
** Convert a name to a rid. If the name can be any of the various forms
491517
--- src/name.c
+++ src/name.c
@@ -108,21 +108,25 @@
108 return zEDate;
109 }
110
111 /*
112 ** Return the RID that is the "root" of the branch that contains
113 ** check-in "rid" if inBranch==0 or the first check-in in the branch
114 ** if inBranch==1.
 
 
 
 
 
 
 
115 */
116 int start_of_branch(int rid, int inBranch){
117 Stmt q;
118 int rc;
119 char *zBr;
120 zBr = db_text("trunk","SELECT value FROM tagxref"
121 " WHERE rid=%d AND tagid=%d"
122 " AND tagtype>0",
123 rid, TAG_BRANCH);
124 db_prepare(&q,
125 "SELECT pid, EXISTS(SELECT 1 FROM tagxref"
126 " WHERE tagid=%d AND tagtype>0"
127 " AND value=%Q AND rid=plink.pid)"
128 " FROM plink"
@@ -130,18 +134,23 @@
130 TAG_BRANCH, zBr
131 );
132 fossil_free(zBr);
133 do{
134 db_reset(&q);
135 db_bind_int(&q, ":cid", rid);
136 rc = db_step(&q);
137 if( rc!=SQLITE_ROW ) break;
138 if( inBranch && db_column_int(&q,1)==0 ) break;
139 rid = db_column_int(&q, 0);
140 }while( db_column_int(&q, 1)==1 && rid>0 );
141 db_finalize(&q);
142 return rid;
 
 
 
 
 
143 }
144
145 /*
146 ** Convert a symbolic name into a RID. Acceptable forms:
147 **
@@ -165,10 +174,11 @@
165 **
166 ** The zType parameter specifies the type of artifact: ci, t, w, e, g, f.
167 ** If zType is NULL or "" or "*" then any type of artifact will serve.
168 ** If zType is "br" then find the first check-in of the named branch
169 ** rather than the last.
 
170 ** zType is "ci" in most use cases since we are usually searching for
171 ** a check-in.
172 **
173 ** Note that the input zTag for types "t" and "e" is the artifact hash of
174 ** the ticket-change or technote-change artifact, not the randomly generated
@@ -270,14 +280,19 @@
270 );
271 if( startOfBranch ) rid = start_of_branch(rid,1);
272 return rid;
273 }
274
275 /* root:TAG -> The origin of the branch */
276 if( memcmp(zTag, "root:", 5)==0 ){
277 rid = symbolic_name_to_rid(zTag+5, zType);
278 return start_of_branch(rid, 0);
 
 
 
 
 
279 }
280
281 /* symbolic-name ":" date-time */
282 nTag = strlen(zTag);
283 for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
@@ -465,26 +480,37 @@
465 }
466
467 /*
468 ** COMMAND: test-name-to-id
469 **
470 ** Convert a name to a full artifact ID.
 
 
 
471 */
472 void test_name_to_id(void){
473 int i;
 
474 Blob name;
475 db_must_be_within_tree();
476 for(i=2; i<g.argc; i++){
477 blob_init(&name, g.argv[i], -1);
478 fossil_print("%s -> ", g.argv[i]);
479 if( name_to_uuid(&name, 1, "*") ){
480 fossil_print("ERROR: %s\n", g.zErrMsg);
481 fossil_error_reset();
482 }else{
483 fossil_print("%s\n", blob_buffer(&name));
484 }
485 blob_reset(&name);
 
 
 
 
 
 
 
486 }
487 }
488
489 /*
490 ** Convert a name to a rid. If the name can be any of the various forms
491
--- src/name.c
+++ src/name.c
@@ -108,21 +108,25 @@
108 return zEDate;
109 }
110
111 /*
112 ** Return the RID that is the "root" of the branch that contains
113 ** check-in "rid". Details depending on eType:
114 **
115 ** eType==0 The check-in of the parent branch off of which
116 ** the branch containing RID originally diverged.
117 **
118 ** eType==1 The first check-in of the branch that contains RID.
119 **
120 ** eType==2 The youngest ancestor of RID that is on the branch
121 ** from which the branch containing RID diverged.
122 */
123 int start_of_branch(int rid, int eType){
124 Stmt q;
125 int rc;
126 int ans = rid;
127 char *zBr = branch_of_rid(rid);
 
 
 
128 db_prepare(&q,
129 "SELECT pid, EXISTS(SELECT 1 FROM tagxref"
130 " WHERE tagid=%d AND tagtype>0"
131 " AND value=%Q AND rid=plink.pid)"
132 " FROM plink"
@@ -130,18 +134,23 @@
134 TAG_BRANCH, zBr
135 );
136 fossil_free(zBr);
137 do{
138 db_reset(&q);
139 db_bind_int(&q, ":cid", ans);
140 rc = db_step(&q);
141 if( rc!=SQLITE_ROW ) break;
142 if( eType==1 && db_column_int(&q,1)==0 ) break;
143 ans = db_column_int(&q, 0);
144 }while( db_column_int(&q, 1)==1 && ans>0 );
145 db_finalize(&q);
146 if( eType==2 && ans>0 ){
147 zBr = branch_of_rid(ans);
148 ans = compute_youngest_ancestor_in_branch(rid, zBr);
149 fossil_free(zBr);
150 }
151 return ans;
152 }
153
154 /*
155 ** Convert a symbolic name into a RID. Acceptable forms:
156 **
@@ -165,10 +174,11 @@
174 **
175 ** The zType parameter specifies the type of artifact: ci, t, w, e, g, f.
176 ** If zType is NULL or "" or "*" then any type of artifact will serve.
177 ** If zType is "br" then find the first check-in of the named branch
178 ** rather than the last.
179 **
180 ** zType is "ci" in most use cases since we are usually searching for
181 ** a check-in.
182 **
183 ** Note that the input zTag for types "t" and "e" is the artifact hash of
184 ** the ticket-change or technote-change artifact, not the randomly generated
@@ -270,14 +280,19 @@
280 );
281 if( startOfBranch ) rid = start_of_branch(rid,1);
282 return rid;
283 }
284
285 /* root:BR -> The origin of the branch named BR */
286 if( strncmp(zTag, "root:", 5)==0 ){
287 rid = symbolic_name_to_rid(zTag+5, zType);
288 return start_of_branch(rid, 0);
289 }
290 /* rootx:BR -> Most recent merge-in for the branch name BR */
291 if( strncmp(zTag, "merge-in:", 9)==0 ){
292 rid = symbolic_name_to_rid(zTag+9, zType);
293 return start_of_branch(rid, 2);
294 }
295
296 /* symbolic-name ":" date-time */
297 nTag = strlen(zTag);
298 for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
@@ -465,26 +480,37 @@
480 }
481
482 /*
483 ** COMMAND: test-name-to-id
484 **
485 ** Usage: %fossil test-name-to-id [--count N] NAME
486 **
487 ** Convert a NAME to a full artifact ID. Repeat the conversion N
488 ** times (for timing purposes) if the --count option is given.
489 */
490 void test_name_to_id(void){
491 int i;
492 int n = 0;
493 Blob name;
494 db_must_be_within_tree();
495 for(i=2; i<g.argc; i++){
496 if( strcmp(g.argv[i],"--count")==0 && i+1<g.argc ){
497 i++;
498 n = atoi(g.argv[i]);
499 continue;
500 }
501 do{
502 blob_init(&name, g.argv[i], -1);
503 fossil_print("%s -> ", g.argv[i]);
504 if( name_to_uuid(&name, 1, "*") ){
505 fossil_print("ERROR: %s\n", g.zErrMsg);
506 fossil_error_reset();
507 }else{
508 fossil_print("%s\n", blob_buffer(&name));
509 }
510 blob_reset(&name);
511 }while( n-- > 0 );
512 }
513 }
514
515 /*
516 ** Convert a name to a rid. If the name can be any of the various forms
517

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button