Fossil SCM

Add branch ls --users to list users participating in branches.

preben 2023-09-28 17:16 filter-branch-ls-by-user
Commit 4615e2072af5381adafdd95b7de76ca6aa03c068af524ced438a424c8a90d100
1 file changed +55 -4
+55 -4
--- src/branch.c
+++ src/branch.c
@@ -278,10 +278,11 @@
278278
#define BRL_ORDERBY_MTIME 0x004 /* Sort by MTIME. (otherwise sort by name)*/
279279
#define BRL_REVERSE 0x008 /* Reverse the sort order */
280280
#define BRL_PRIVATE 0x010 /* Show only private branches */
281281
#define BRL_MERGED 0x020 /* Show only merged branches */
282282
#define BRL_UNMERGED 0x040 /* Show only unmerged branches */
283
+#define BRL_LIST_USERS 0x080 /* Populate list of users participating */
283284
284285
#endif /* INTERFACE */
285286
286287
/*
287288
** Prepare a query that will list branches.
@@ -308,11 +309,27 @@
308309
/* Ignore nLimitMRU if no chronological sort requested. */
309310
if( (brFlags & BRL_ORDERBY_MTIME)==0 ) nLimitMRU = 0;
310311
/* Undocumented: invert negative values for nLimitMRU, so that command-line
311312
** arguments similar to `head -5' with "option numbers" are possible. */
312313
if( nLimitMRU<0 ) nLimitMRU = -nLimitMRU;
313
- blob_append_sql(&sql,"SELECT name, isprivate, mergeto FROM ("); /* OUTER QUERY */
314
+ /* OUTER QUERY */
315
+ blob_append_sql(&sql,"SELECT name, isprivate, mergeto,");
316
+ if( brFlags & BRL_LIST_USERS ){
317
+ blob_append_sql(&sql,
318
+ " (SELECT group_concat(user) FROM ("
319
+ " SELECT DISTINCT * FROM ("
320
+ " SELECT coalesce(euser,user) AS user"
321
+ " FROM event"
322
+ " WHERE type='ci' AND objid IN ("
323
+ " SELECT rid FROM tagxref WHERE value=name)"
324
+ " ORDER BY 1)))"
325
+ );
326
+ }else{
327
+ blob_append_sql(&sql, " NULL");
328
+ }
329
+ blob_append_sql(&sql," FROM (");
330
+ /* INNER QUERY */
314331
switch( brFlags & BRL_OPEN_CLOSED_MASK ){
315332
case BRL_CLOSED_ONLY: {
316333
blob_append_sql(&sql,
317334
"SELECT name, isprivate, mtime, mergeto FROM tmp_brlist WHERE isclosed"
318335
);
@@ -627,12 +644,13 @@
627644
** -m|--merged List branches merged into the current branch
628645
** -M|--unmerged List branches not merged into the current branch
629646
** -p List only private branches
630647
** -r Reverse the sort order
631648
** -t Show recently changed branches first
632
-** --username USER List only branches with check-ins by USER
633
-** --self List only branches with check-ins by the current user
649
+** --self List only branches where you participate
650
+** --username USER List only branches where USER participate
651
+** --users N List up to N users partipiating
634652
**
635653
** The current branch is marked with an asterisk. Private branches are
636654
** marked with a hash sign.
637655
**
638656
** If GLOB is given, show only branches matching the pattern.
@@ -697,14 +715,17 @@
697715
}
698716
}else if( strncmp(zCmd,"list",n)==0 ||
699717
strncmp(zCmd, "ls", n)==0 ||
700718
strcmp(zCmd, "lsh")==0 ){
701719
Stmt q;
720
+ Blob txt = empty_blob;
702721
int vid;
703722
char *zCurrent = 0;
704723
const char *zBrNameGlob = 0;
705724
const char *zUser = find_option("username",0,1);
725
+ const char *zUsersOpt = find_option("users",0,1);
726
+ int nUsers = zUsersOpt ? atoi(zUsersOpt) : 0;
706727
int nLimit = 0;
707728
int brFlags = BRL_OPEN_ONLY;
708729
if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH;
709730
if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY;
710731
if( find_option("t",0,0)!=0 ) brFlags |= BRL_ORDERBY_MTIME;
@@ -721,41 +742,71 @@
721742
}
722743
723744
if ( (brFlags & BRL_MERGED) && (brFlags & BRL_UNMERGED) ){
724745
fossil_fatal("flags --merged and --unmerged are mutually exclusive");
725746
}
747
+ if( zUsersOpt ){
748
+ if( nUsers <= 0) fossil_fatal("With --users, N must be positive");
749
+ brFlags |= BRL_LIST_USERS;
750
+ }
726751
if( strcmp(zCmd, "lsh")==0 ){
727752
nLimit = 5;
728753
if( g.argc>4 || (g.argc==4 && (nLimit = atoi(g.argv[3]))==0) ){
729754
fossil_fatal("the lsh subcommand allows one optional numeric argument");
730755
}
731756
brFlags |= BRL_ORDERBY_MTIME;
732757
}else{
758
+ if( (g.argc == 4 || g.argc == 5)
759
+ && fossil_strcmp(g.argv[g.argc-1], "--user") == 0 ){
760
+ fossil_fatal("Missing argument for --user");
761
+ }
733762
if( g.argc >= 4 ) zBrNameGlob = g.argv[3];
734763
}
735764
736765
if( g.localOpen ){
737766
vid = db_lget_int("checkout", 0);
738767
zCurrent = db_text(0, "SELECT value FROM tagxref"
739768
" WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
740769
}
741770
branch_prepare_list_query(&q, brFlags, zBrNameGlob, nLimit, zUser);
771
+ blob_init(&txt, 0, 0);
742772
while( db_step(&q)==SQLITE_ROW ){
743773
const char *zBr = db_column_text(&q, 0);
744774
int isPriv = zCurrent!=0 && db_column_int(&q, 1)==1;
745775
const char *zMergeTo = db_column_text(&q, 2);
746776
int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
777
+ const char *zUsers = db_column_text(&q, 3);
747778
if( (brFlags & BRL_MERGED) && fossil_strcmp(zCurrent,zMergeTo)!=0 ){
748779
continue;
749780
}
750781
if( (brFlags & BRL_UNMERGED) && (fossil_strcmp(zCurrent,zMergeTo)==0
751782
|| isCur) ){
752783
continue;
753784
}
754
- fossil_print("%s%s%s\n",
785
+ blob_appendf(&txt, "%s%s%s",
755786
( (brFlags & BRL_PRIVATE) ? " " : ( isPriv ? "#" : " ") ),
756787
(isCur ? "* " : " "), zBr);
788
+ if( nUsers ){
789
+ char c;
790
+ const char *cp;
791
+ const char *pComma = 0;
792
+ int commas = 0;
793
+ for( cp = zUsers; ( c = *cp ) != 0; cp++ ){
794
+ if( c == ',' ){
795
+ commas++;
796
+ if( commas == nUsers ) pComma = cp;
797
+ }
798
+ }
799
+ if( pComma ){
800
+ blob_appendf(&txt, " (%.*s,... %i more)",
801
+ pComma - zUsers, zUsers, commas + 1 - nUsers);
802
+ }else{
803
+ blob_appendf(&txt, " (%s)", zUsers);
804
+ }
805
+ }
806
+ fossil_print("%s\n", blob_str(&txt));
807
+ blob_reset(&txt);
757808
}
758809
db_finalize(&q);
759810
}else if( strncmp(zCmd,"new",n)==0 ){
760811
branch_new();
761812
}else if( strncmp(zCmd,"close",5)==0 ){
762813
--- src/branch.c
+++ src/branch.c
@@ -278,10 +278,11 @@
278 #define BRL_ORDERBY_MTIME 0x004 /* Sort by MTIME. (otherwise sort by name)*/
279 #define BRL_REVERSE 0x008 /* Reverse the sort order */
280 #define BRL_PRIVATE 0x010 /* Show only private branches */
281 #define BRL_MERGED 0x020 /* Show only merged branches */
282 #define BRL_UNMERGED 0x040 /* Show only unmerged branches */
 
283
284 #endif /* INTERFACE */
285
286 /*
287 ** Prepare a query that will list branches.
@@ -308,11 +309,27 @@
308 /* Ignore nLimitMRU if no chronological sort requested. */
309 if( (brFlags & BRL_ORDERBY_MTIME)==0 ) nLimitMRU = 0;
310 /* Undocumented: invert negative values for nLimitMRU, so that command-line
311 ** arguments similar to `head -5' with "option numbers" are possible. */
312 if( nLimitMRU<0 ) nLimitMRU = -nLimitMRU;
313 blob_append_sql(&sql,"SELECT name, isprivate, mergeto FROM ("); /* OUTER QUERY */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314 switch( brFlags & BRL_OPEN_CLOSED_MASK ){
315 case BRL_CLOSED_ONLY: {
316 blob_append_sql(&sql,
317 "SELECT name, isprivate, mtime, mergeto FROM tmp_brlist WHERE isclosed"
318 );
@@ -627,12 +644,13 @@
627 ** -m|--merged List branches merged into the current branch
628 ** -M|--unmerged List branches not merged into the current branch
629 ** -p List only private branches
630 ** -r Reverse the sort order
631 ** -t Show recently changed branches first
632 ** --username USER List only branches with check-ins by USER
633 ** --self List only branches with check-ins by the current user
 
634 **
635 ** The current branch is marked with an asterisk. Private branches are
636 ** marked with a hash sign.
637 **
638 ** If GLOB is given, show only branches matching the pattern.
@@ -697,14 +715,17 @@
697 }
698 }else if( strncmp(zCmd,"list",n)==0 ||
699 strncmp(zCmd, "ls", n)==0 ||
700 strcmp(zCmd, "lsh")==0 ){
701 Stmt q;
 
702 int vid;
703 char *zCurrent = 0;
704 const char *zBrNameGlob = 0;
705 const char *zUser = find_option("username",0,1);
 
 
706 int nLimit = 0;
707 int brFlags = BRL_OPEN_ONLY;
708 if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH;
709 if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY;
710 if( find_option("t",0,0)!=0 ) brFlags |= BRL_ORDERBY_MTIME;
@@ -721,41 +742,71 @@
721 }
722
723 if ( (brFlags & BRL_MERGED) && (brFlags & BRL_UNMERGED) ){
724 fossil_fatal("flags --merged and --unmerged are mutually exclusive");
725 }
 
 
 
 
726 if( strcmp(zCmd, "lsh")==0 ){
727 nLimit = 5;
728 if( g.argc>4 || (g.argc==4 && (nLimit = atoi(g.argv[3]))==0) ){
729 fossil_fatal("the lsh subcommand allows one optional numeric argument");
730 }
731 brFlags |= BRL_ORDERBY_MTIME;
732 }else{
 
 
 
 
733 if( g.argc >= 4 ) zBrNameGlob = g.argv[3];
734 }
735
736 if( g.localOpen ){
737 vid = db_lget_int("checkout", 0);
738 zCurrent = db_text(0, "SELECT value FROM tagxref"
739 " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
740 }
741 branch_prepare_list_query(&q, brFlags, zBrNameGlob, nLimit, zUser);
 
742 while( db_step(&q)==SQLITE_ROW ){
743 const char *zBr = db_column_text(&q, 0);
744 int isPriv = zCurrent!=0 && db_column_int(&q, 1)==1;
745 const char *zMergeTo = db_column_text(&q, 2);
746 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
 
747 if( (brFlags & BRL_MERGED) && fossil_strcmp(zCurrent,zMergeTo)!=0 ){
748 continue;
749 }
750 if( (brFlags & BRL_UNMERGED) && (fossil_strcmp(zCurrent,zMergeTo)==0
751 || isCur) ){
752 continue;
753 }
754 fossil_print("%s%s%s\n",
755 ( (brFlags & BRL_PRIVATE) ? " " : ( isPriv ? "#" : " ") ),
756 (isCur ? "* " : " "), zBr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
757 }
758 db_finalize(&q);
759 }else if( strncmp(zCmd,"new",n)==0 ){
760 branch_new();
761 }else if( strncmp(zCmd,"close",5)==0 ){
762
--- src/branch.c
+++ src/branch.c
@@ -278,10 +278,11 @@
278 #define BRL_ORDERBY_MTIME 0x004 /* Sort by MTIME. (otherwise sort by name)*/
279 #define BRL_REVERSE 0x008 /* Reverse the sort order */
280 #define BRL_PRIVATE 0x010 /* Show only private branches */
281 #define BRL_MERGED 0x020 /* Show only merged branches */
282 #define BRL_UNMERGED 0x040 /* Show only unmerged branches */
283 #define BRL_LIST_USERS 0x080 /* Populate list of users participating */
284
285 #endif /* INTERFACE */
286
287 /*
288 ** Prepare a query that will list branches.
@@ -308,11 +309,27 @@
309 /* Ignore nLimitMRU if no chronological sort requested. */
310 if( (brFlags & BRL_ORDERBY_MTIME)==0 ) nLimitMRU = 0;
311 /* Undocumented: invert negative values for nLimitMRU, so that command-line
312 ** arguments similar to `head -5' with "option numbers" are possible. */
313 if( nLimitMRU<0 ) nLimitMRU = -nLimitMRU;
314 /* OUTER QUERY */
315 blob_append_sql(&sql,"SELECT name, isprivate, mergeto,");
316 if( brFlags & BRL_LIST_USERS ){
317 blob_append_sql(&sql,
318 " (SELECT group_concat(user) FROM ("
319 " SELECT DISTINCT * FROM ("
320 " SELECT coalesce(euser,user) AS user"
321 " FROM event"
322 " WHERE type='ci' AND objid IN ("
323 " SELECT rid FROM tagxref WHERE value=name)"
324 " ORDER BY 1)))"
325 );
326 }else{
327 blob_append_sql(&sql, " NULL");
328 }
329 blob_append_sql(&sql," FROM (");
330 /* INNER QUERY */
331 switch( brFlags & BRL_OPEN_CLOSED_MASK ){
332 case BRL_CLOSED_ONLY: {
333 blob_append_sql(&sql,
334 "SELECT name, isprivate, mtime, mergeto FROM tmp_brlist WHERE isclosed"
335 );
@@ -627,12 +644,13 @@
644 ** -m|--merged List branches merged into the current branch
645 ** -M|--unmerged List branches not merged into the current branch
646 ** -p List only private branches
647 ** -r Reverse the sort order
648 ** -t Show recently changed branches first
649 ** --self List only branches where you participate
650 ** --username USER List only branches where USER participate
651 ** --users N List up to N users partipiating
652 **
653 ** The current branch is marked with an asterisk. Private branches are
654 ** marked with a hash sign.
655 **
656 ** If GLOB is given, show only branches matching the pattern.
@@ -697,14 +715,17 @@
715 }
716 }else if( strncmp(zCmd,"list",n)==0 ||
717 strncmp(zCmd, "ls", n)==0 ||
718 strcmp(zCmd, "lsh")==0 ){
719 Stmt q;
720 Blob txt = empty_blob;
721 int vid;
722 char *zCurrent = 0;
723 const char *zBrNameGlob = 0;
724 const char *zUser = find_option("username",0,1);
725 const char *zUsersOpt = find_option("users",0,1);
726 int nUsers = zUsersOpt ? atoi(zUsersOpt) : 0;
727 int nLimit = 0;
728 int brFlags = BRL_OPEN_ONLY;
729 if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH;
730 if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY;
731 if( find_option("t",0,0)!=0 ) brFlags |= BRL_ORDERBY_MTIME;
@@ -721,41 +742,71 @@
742 }
743
744 if ( (brFlags & BRL_MERGED) && (brFlags & BRL_UNMERGED) ){
745 fossil_fatal("flags --merged and --unmerged are mutually exclusive");
746 }
747 if( zUsersOpt ){
748 if( nUsers <= 0) fossil_fatal("With --users, N must be positive");
749 brFlags |= BRL_LIST_USERS;
750 }
751 if( strcmp(zCmd, "lsh")==0 ){
752 nLimit = 5;
753 if( g.argc>4 || (g.argc==4 && (nLimit = atoi(g.argv[3]))==0) ){
754 fossil_fatal("the lsh subcommand allows one optional numeric argument");
755 }
756 brFlags |= BRL_ORDERBY_MTIME;
757 }else{
758 if( (g.argc == 4 || g.argc == 5)
759 && fossil_strcmp(g.argv[g.argc-1], "--user") == 0 ){
760 fossil_fatal("Missing argument for --user");
761 }
762 if( g.argc >= 4 ) zBrNameGlob = g.argv[3];
763 }
764
765 if( g.localOpen ){
766 vid = db_lget_int("checkout", 0);
767 zCurrent = db_text(0, "SELECT value FROM tagxref"
768 " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
769 }
770 branch_prepare_list_query(&q, brFlags, zBrNameGlob, nLimit, zUser);
771 blob_init(&txt, 0, 0);
772 while( db_step(&q)==SQLITE_ROW ){
773 const char *zBr = db_column_text(&q, 0);
774 int isPriv = zCurrent!=0 && db_column_int(&q, 1)==1;
775 const char *zMergeTo = db_column_text(&q, 2);
776 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
777 const char *zUsers = db_column_text(&q, 3);
778 if( (brFlags & BRL_MERGED) && fossil_strcmp(zCurrent,zMergeTo)!=0 ){
779 continue;
780 }
781 if( (brFlags & BRL_UNMERGED) && (fossil_strcmp(zCurrent,zMergeTo)==0
782 || isCur) ){
783 continue;
784 }
785 blob_appendf(&txt, "%s%s%s",
786 ( (brFlags & BRL_PRIVATE) ? " " : ( isPriv ? "#" : " ") ),
787 (isCur ? "* " : " "), zBr);
788 if( nUsers ){
789 char c;
790 const char *cp;
791 const char *pComma = 0;
792 int commas = 0;
793 for( cp = zUsers; ( c = *cp ) != 0; cp++ ){
794 if( c == ',' ){
795 commas++;
796 if( commas == nUsers ) pComma = cp;
797 }
798 }
799 if( pComma ){
800 blob_appendf(&txt, " (%.*s,... %i more)",
801 pComma - zUsers, zUsers, commas + 1 - nUsers);
802 }else{
803 blob_appendf(&txt, " (%s)", zUsers);
804 }
805 }
806 fossil_print("%s\n", blob_str(&txt));
807 blob_reset(&txt);
808 }
809 db_finalize(&q);
810 }else if( strncmp(zCmd,"new",n)==0 ){
811 branch_new();
812 }else if( strncmp(zCmd,"close",5)==0 ){
813

Keyboard Shortcuts

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