276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
|
#define BRL_BOTH 0x003 /* Show both open and closed branches */
#define BRL_OPEN_CLOSED_MASK 0x003
#define BRL_ORDERBY_MTIME 0x004 /* Sort by MTIME. (otherwise sort by name)*/
#define BRL_REVERSE 0x008 /* Reverse the sort order */
#define BRL_PRIVATE 0x010 /* Show only private branches */
#define BRL_MERGED 0x020 /* Show only merged branches */
#define BRL_UNMERGED 0x040 /* Show only unmerged branches */
#endif /* INTERFACE */
/*
** Prepare a query that will list branches.
**
** If the BRL_ORDERBY_MTIME flag is set and nLimitMRU ("Limit Most Recently Used
** style") is a non-zero number, the result is limited to nLimitMRU entries, and
** the BRL_REVERSE flag is applied in an outer query after processing the limit,
** so that it's possible to generate short lists with the most recently modified
** branches sorted chronologically in either direction, as does the "branch lsh"
** command.
** For other cases, the outer query is also generated, but works as a no-op. The
** code to build the outer query is marked with *//* OUTER QUERY *//* comments.
*/
void branch_prepare_list_query(
Stmt *pQuery,
int brFlags,
const char *zBrNameGlob,
int nLimitMRU
){
Blob sql;
blob_init(&sql, 0, 0);
brlist_create_temp_table();
/* Ignore nLimitMRU if no chronological sort requested. */
if( (brFlags & BRL_ORDERBY_MTIME)==0 ) nLimitMRU = 0;
/* Undocumented: invert negative values for nLimitMRU, so that command-line
** arguments similar to `head -5' with "option numbers" are possible. */
if( nLimitMRU<0 ) nLimitMRU = -nLimitMRU;
blob_append_sql(&sql,"SELECT name, isprivate, mergeto FROM ("); /* OUTER QUERY */
switch( brFlags & BRL_OPEN_CLOSED_MASK ){
case BRL_CLOSED_ONLY: {
blob_append_sql(&sql,
"SELECT name, isprivate, mtime, mergeto FROM tmp_brlist WHERE isclosed"
);
break;
}
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
|
#define BRL_BOTH 0x003 /* Show both open and closed branches */
#define BRL_OPEN_CLOSED_MASK 0x003
#define BRL_ORDERBY_MTIME 0x004 /* Sort by MTIME. (otherwise sort by name)*/
#define BRL_REVERSE 0x008 /* Reverse the sort order */
#define BRL_PRIVATE 0x010 /* Show only private branches */
#define BRL_MERGED 0x020 /* Show only merged branches */
#define BRL_UNMERGED 0x040 /* Show only unmerged branches */
#define BRL_LIST_USERS 0x080 /* Populate list of users participating */
#endif /* INTERFACE */
/*
** Prepare a query that will list branches.
**
** If the BRL_ORDERBY_MTIME flag is set and nLimitMRU ("Limit Most Recently Used
** style") is a non-zero number, the result is limited to nLimitMRU entries, and
** the BRL_REVERSE flag is applied in an outer query after processing the limit,
** so that it's possible to generate short lists with the most recently modified
** branches sorted chronologically in either direction, as does the "branch lsh"
** command.
** For other cases, the outer query is also generated, but works as a no-op. The
** code to build the outer query is marked with *//* OUTER QUERY *//* comments.
*/
void branch_prepare_list_query(
Stmt *pQuery,
int brFlags,
const char *zBrNameGlob,
int nLimitMRU,
const char *zUser
){
Blob sql;
blob_init(&sql, 0, 0);
brlist_create_temp_table();
/* Ignore nLimitMRU if no chronological sort requested. */
if( (brFlags & BRL_ORDERBY_MTIME)==0 ) nLimitMRU = 0;
/* Undocumented: invert negative values for nLimitMRU, so that command-line
** arguments similar to `head -5' with "option numbers" are possible. */
if( nLimitMRU<0 ) nLimitMRU = -nLimitMRU;
/* OUTER QUERY */
blob_append_sql(&sql,"SELECT name, isprivate, mergeto,");
if( brFlags & BRL_LIST_USERS ){
blob_append_sql(&sql,
" (SELECT group_concat(user) FROM ("
" SELECT DISTINCT * FROM ("
" SELECT coalesce(euser,user) AS user"
" FROM event"
" WHERE type='ci' AND objid IN ("
" SELECT rid FROM tagxref WHERE value=name)"
" ORDER BY 1)))"
);
}else{
blob_append_sql(&sql, " NULL");
}
blob_append_sql(&sql," FROM (");
/* INNER QUERY */
switch( brFlags & BRL_OPEN_CLOSED_MASK ){
case BRL_CLOSED_ONLY: {
blob_append_sql(&sql,
"SELECT name, isprivate, mtime, mergeto FROM tmp_brlist WHERE isclosed"
);
break;
}
|
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
|
"SELECT name, isprivate, mtime, mergeto FROM tmp_brlist WHERE NOT isclosed"
);
break;
}
}
if( brFlags & BRL_PRIVATE ) blob_append_sql(&sql, " AND isprivate");
if( brFlags & BRL_MERGED ) blob_append_sql(&sql, " AND mergeto IS NOT NULL");
if(zBrNameGlob) blob_append_sql(&sql, " AND (name GLOB %Q)", zBrNameGlob);
if( brFlags & BRL_ORDERBY_MTIME ){
blob_append_sql(&sql, " ORDER BY -mtime");
}else{
blob_append_sql(&sql, " ORDER BY name COLLATE nocase");
}
if( brFlags & BRL_REVERSE && !nLimitMRU ){
blob_append_sql(&sql," DESC");
|
|
>
>
>
>
>
|
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
|
"SELECT name, isprivate, mtime, mergeto FROM tmp_brlist WHERE NOT isclosed"
);
break;
}
}
if( brFlags & BRL_PRIVATE ) blob_append_sql(&sql, " AND isprivate");
if( brFlags & BRL_MERGED ) blob_append_sql(&sql, " AND mergeto IS NOT NULL");
if( zBrNameGlob ) blob_append_sql(&sql, " AND (name GLOB %Q)", zBrNameGlob);
if( zUser && zUser[0] ) blob_append_sql(&sql,
" AND EXISTS (SELECT 1 FROM event WHERE type='ci' AND (user=%Q OR euser=%Q)"
" AND objid in (SELECT rid FROM tagxref WHERE value=tmp_brlist.name))",
zUser, zUser
);
if( brFlags & BRL_ORDERBY_MTIME ){
blob_append_sql(&sql, " ORDER BY -mtime");
}else{
blob_append_sql(&sql, " ORDER BY name COLLATE nocase");
}
if( brFlags & BRL_REVERSE && !nLimitMRU ){
blob_append_sql(&sql," DESC");
|
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
|
fossil_print("%s: open as of %s on %.16s\n", zBrName, zDate, zUuid);
}
}
}else if( strncmp(zCmd,"list",n)==0 ||
strncmp(zCmd, "ls", n)==0 ||
strcmp(zCmd, "lsh")==0 ){
Stmt q;
int vid;
char *zCurrent = 0;
const char *zBrNameGlob = 0;
int nLimit = 0;
int brFlags = BRL_OPEN_ONLY;
if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH;
if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY;
if( find_option("t",0,0)!=0 ) brFlags |= BRL_ORDERBY_MTIME;
if( find_option("r",0,0)!=0 ) brFlags |= BRL_REVERSE;
if( find_option("p",0,0)!=0 ) brFlags |= BRL_PRIVATE;
if( find_option("merged","m",0)!=0 ) brFlags |= BRL_MERGED;
if( find_option("unmerged","M",0)!=0 ) brFlags |= BRL_UNMERGED;
if ( (brFlags & BRL_MERGED) && (brFlags & BRL_UNMERGED) ){
fossil_fatal("flags --merged and --unmerged are mutually exclusive");
}
if( strcmp(zCmd, "lsh")==0 ){
nLimit = 5;
if( g.argc>4 || (g.argc==4 && (nLimit = atoi(g.argv[3]))==0) ){
fossil_fatal("the lsh subcommand allows one optional numeric argument");
}
brFlags |= BRL_ORDERBY_MTIME;
}else{
if( g.argc >= 4 ) zBrNameGlob = g.argv[3];
}
if( g.localOpen ){
vid = db_lget_int("checkout", 0);
zCurrent = db_text(0, "SELECT value FROM tagxref"
" WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
}
branch_prepare_list_query(&q, brFlags, zBrNameGlob, nLimit);
while( db_step(&q)==SQLITE_ROW ){
const char *zBr = db_column_text(&q, 0);
int isPriv = db_column_int(&q, 1)==1;
const char *zMergeTo = db_column_text(&q, 2);
int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
if( (brFlags & BRL_MERGED) && fossil_strcmp(zCurrent,zMergeTo)!=0 ){
continue;
}
if( (brFlags & BRL_UNMERGED) && (fossil_strcmp(zCurrent,zMergeTo)==0
|| isCur) ){
continue;
}
fossil_print("%s%s%s\n",
( (brFlags & BRL_PRIVATE) ? " " : ( isPriv ? "#" : " ") ),
(isCur ? "* " : " "), zBr);
}
db_finalize(&q);
}else if( strncmp(zCmd,"new",n)==0 ){
branch_new();
}else if( strncmp(zCmd,"close",5)==0 ){
if(g.argc<4){
usage("branch close branch-name(s)...");
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
|
fossil_print("%s: open as of %s on %.16s\n", zBrName, zDate, zUuid);
}
}
}else if( strncmp(zCmd,"list",n)==0 ||
strncmp(zCmd, "ls", n)==0 ||
strcmp(zCmd, "lsh")==0 ){
Stmt q;
Blob txt = empty_blob;
int vid;
char *zCurrent = 0;
const char *zBrNameGlob = 0;
const char *zUser = find_option("username",0,1);
const char *zUsersOpt = find_option("users",0,1);
int nUsers = zUsersOpt ? atoi(zUsersOpt) : 0;
int nLimit = 0;
int brFlags = BRL_OPEN_ONLY;
if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH;
if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY;
if( find_option("t",0,0)!=0 ) brFlags |= BRL_ORDERBY_MTIME;
if( find_option("r",0,0)!=0 ) brFlags |= BRL_REVERSE;
if( find_option("p",0,0)!=0 ) brFlags |= BRL_PRIVATE;
if( find_option("merged","m",0)!=0 ) brFlags |= BRL_MERGED;
if( find_option("unmerged","M",0)!=0 ) brFlags |= BRL_UNMERGED;
if( find_option("self",0,0)!=0 ){
if( zUser ){
fossil_fatal("flags --username and --self are mutually exclusive");
}
user_select();
zUser = login_name();
}
verify_all_options();
if ( (brFlags & BRL_MERGED) && (brFlags & BRL_UNMERGED) ){
fossil_fatal("flags --merged and --unmerged are mutually exclusive");
}
if( zUsersOpt ){
if( nUsers <= 0) fossil_fatal("With --users, N must be positive");
brFlags |= BRL_LIST_USERS;
}
if( strcmp(zCmd, "lsh")==0 ){
nLimit = 5;
if( g.argc>4 || (g.argc==4 && (nLimit = atoi(g.argv[3]))==0) ){
fossil_fatal("the lsh subcommand allows one optional numeric argument");
}
brFlags |= BRL_ORDERBY_MTIME;
}else{
if( g.argc >= 4 ) zBrNameGlob = g.argv[3];
}
if( g.localOpen ){
vid = db_lget_int("checkout", 0);
zCurrent = db_text(0, "SELECT value FROM tagxref"
" WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
}
branch_prepare_list_query(&q, brFlags, zBrNameGlob, nLimit, zUser);
blob_init(&txt, 0, 0);
while( db_step(&q)==SQLITE_ROW ){
const char *zBr = db_column_text(&q, 0);
int isPriv = db_column_int(&q, 1)==1;
const char *zMergeTo = db_column_text(&q, 2);
int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
const char *zUsers = db_column_text(&q, 3);
if( (brFlags & BRL_MERGED) && fossil_strcmp(zCurrent,zMergeTo)!=0 ){
continue;
}
if( (brFlags & BRL_UNMERGED) && (fossil_strcmp(zCurrent,zMergeTo)==0
|| isCur) ){
continue;
}
blob_appendf(&txt, "%s%s%s",
( (brFlags & BRL_PRIVATE) ? " " : ( isPriv ? "#" : " ") ),
(isCur ? "* " : " "), zBr);
if( nUsers ){
char c;
const char *cp;
const char *pComma = 0;
int commas = 0;
for( cp = zUsers; ( c = *cp ) != 0; cp++ ){
if( c == ',' ){
commas++;
if( commas == nUsers ) pComma = cp;
}
}
if( pComma ){
blob_appendf(&txt, " (%.*s,... %i more)",
pComma - zUsers, zUsers, commas + 1 - nUsers);
}else{
blob_appendf(&txt, " (%s)", zUsers);
}
}
fossil_print("%s\n", blob_str(&txt));
blob_reset(&txt);
}
db_finalize(&q);
}else if( strncmp(zCmd,"new",n)==0 ){
branch_new();
}else if( strncmp(zCmd,"close",5)==0 ){
if(g.argc<4){
usage("branch close branch-name(s)...");
|