Fossil SCM

Add options to the 'tag' command to list tag values, as suggested by [forum:d4fb9400f9|forum post d4fb9400f9].

danield 2024-05-15 14:54 trunk merge
Commit ea1b76bc9abdf00f46688ff72f6a973fd5e7b0dd45e5a005f8998c0b47767212
1 file changed +53 -13
+53 -13
--- src/tag.c
+++ src/tag.c
@@ -468,12 +468,17 @@
468468
** (technote), and "tkt-" (ticket). The
469469
** prefix is stripped from the resulting
470470
** list unless --raw is provided. Ignored if
471471
** ARTIFACT-ID is provided.
472472
** --raw List raw names of tags
473
+** --sep SEP Separator when concatenating values
473474
** --tagtype TYPE List only tags of type TYPE, which must
474475
** be one of: cancel, singleton, propagated
476
+** --values List tag values
477
+** If --sep is supplied, list all values of a tag on
478
+** the same line, separated by SEP; otherwise list
479
+** each value on its own line.
475480
**
476481
** The option --raw allows the manipulation of all types of tags
477482
** used for various internal purposes in fossil. It also shows
478483
** "cancel" tags for the "find" and "list" subcommands. You should
479484
** not use this option to make changes unless you are sure what
@@ -635,10 +640,13 @@
635640
const int fRaw = find_option("raw","",0)!=0;
636641
const char *zTagType = find_option("tagtype","t",1);
637642
const int fInverse = find_option("inverse","v",0)!=0;
638643
const char *zTagPrefix = find_option("prefix","",1);
639644
int nTagType = fRaw ? -1 : 0;
645
+ int fValues = find_option("values","",0)!=0;
646
+ const char *zSep = find_option("sep","",1);
647
+
640648
641649
if( zTagType!=0 ){
642650
int l = strlen(zTagType);
643651
if( strncmp(zTagType,"cancel",l)==0 ){
644652
nTagType = 0;
@@ -650,29 +658,61 @@
650658
fossil_fatal("unrecognized tag type");
651659
}
652660
}
653661
if( g.argc==3 ){
654662
const int nTagPrefix = zTagPrefix ? (int)strlen(zTagPrefix) : 0;
655
- db_prepare(&q,
656
- "SELECT tagname FROM tag"
657
- " WHERE EXISTS(SELECT 1 FROM tagxref"
658
- " WHERE tagid=tag.tagid"
659
- " AND tagtype%s%d)"
660
- " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' "
661
- " END ORDER BY tagname COLLATE uintnocase",
662
- zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
663
- nTagType, zTagPrefix, zTagPrefix
664
- );
663
+ if( !fValues ){
664
+ db_prepare(&q,
665
+ "SELECT tagname FROM tag"
666
+ " WHERE EXISTS(SELECT 1 FROM tagxref"
667
+ " WHERE tagid=tag.tagid"
668
+ " AND tagtype%s%d)"
669
+ " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' "
670
+ " END ORDER BY tagname COLLATE uintnocase",
671
+ zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
672
+ nTagType, zTagPrefix, zTagPrefix
673
+ );
674
+ }else{
675
+ if( zSep ){
676
+ db_prepare(&q,
677
+ /* work around group_concat() with DISTINCT and custom separator */
678
+ "SELECT tagname,"
679
+ " rtrim(replace(group_concat(DISTINCT value||'@!' "
680
+ " ORDER BY value ASC), '@!,', %Q),'@!')"
681
+ " FROM tagxref, tag"
682
+ " WHERE tagxref.tagid=tag.tagid AND tagtype%s%d"
683
+ " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' END"
684
+ " GROUP BY tagname"
685
+ " ORDER BY tagname COLLATE uintnocase",
686
+ ( zSep && strlen(zSep)>0 ) ? zSep : ",",
687
+ zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
688
+ nTagType, zTagPrefix, zTagPrefix
689
+ );
690
+ }else{
691
+ db_prepare(&q,
692
+ "SELECT DISTINCT tagname, value"
693
+ " FROM tagxref, tag"
694
+ " WHERE tagxref.tagid=tag.tagid AND tagtype%s%d"
695
+ " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' END"
696
+ " ORDER BY tagname, value COLLATE uintnocase",
697
+ zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
698
+ nTagType, zTagPrefix, zTagPrefix
699
+ );
700
+ }
701
+ }
665702
while( db_step(&q)==SQLITE_ROW ){
666703
const char *zName = db_column_text(&q, 0);
704
+ const char *zValue = db_column_text(&q, 1);
705
+ int nWidth = fValues ? 20 : 0;
706
+ const char *zzValue = (fValues && zValue) ? mprintf(" %s", zValue) : "";
667707
if( fRaw ){
668
- fossil_print("%s\n", zName);
708
+ fossil_print("%-*s%s\n", nWidth, zName, zzValue);
669709
}else if( nTagPrefix>0 ){
670710
assert(db_column_bytes(&q,0)>=nTagPrefix);
671
- fossil_print("%s\n", &zName[nTagPrefix]);
711
+ fossil_print("%-*s%s\n", nWidth, &zName[nTagPrefix], zzValue);
672712
}else if( strncmp(zName, "sym-", 4)==0 ){
673
- fossil_print("%s\n", &zName[4]);
713
+ fossil_print("%-*s%s\n", nWidth, &zName[4], zzValue);
674714
}
675715
}
676716
db_finalize(&q);
677717
}else if( g.argc==4 ){
678718
char const *zObjId = g.argv[3];
679719
--- src/tag.c
+++ src/tag.c
@@ -468,12 +468,17 @@
468 ** (technote), and "tkt-" (ticket). The
469 ** prefix is stripped from the resulting
470 ** list unless --raw is provided. Ignored if
471 ** ARTIFACT-ID is provided.
472 ** --raw List raw names of tags
 
473 ** --tagtype TYPE List only tags of type TYPE, which must
474 ** be one of: cancel, singleton, propagated
 
 
 
 
475 **
476 ** The option --raw allows the manipulation of all types of tags
477 ** used for various internal purposes in fossil. It also shows
478 ** "cancel" tags for the "find" and "list" subcommands. You should
479 ** not use this option to make changes unless you are sure what
@@ -635,10 +640,13 @@
635 const int fRaw = find_option("raw","",0)!=0;
636 const char *zTagType = find_option("tagtype","t",1);
637 const int fInverse = find_option("inverse","v",0)!=0;
638 const char *zTagPrefix = find_option("prefix","",1);
639 int nTagType = fRaw ? -1 : 0;
 
 
 
640
641 if( zTagType!=0 ){
642 int l = strlen(zTagType);
643 if( strncmp(zTagType,"cancel",l)==0 ){
644 nTagType = 0;
@@ -650,29 +658,61 @@
650 fossil_fatal("unrecognized tag type");
651 }
652 }
653 if( g.argc==3 ){
654 const int nTagPrefix = zTagPrefix ? (int)strlen(zTagPrefix) : 0;
655 db_prepare(&q,
656 "SELECT tagname FROM tag"
657 " WHERE EXISTS(SELECT 1 FROM tagxref"
658 " WHERE tagid=tag.tagid"
659 " AND tagtype%s%d)"
660 " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' "
661 " END ORDER BY tagname COLLATE uintnocase",
662 zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
663 nTagType, zTagPrefix, zTagPrefix
664 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
665 while( db_step(&q)==SQLITE_ROW ){
666 const char *zName = db_column_text(&q, 0);
 
 
 
667 if( fRaw ){
668 fossil_print("%s\n", zName);
669 }else if( nTagPrefix>0 ){
670 assert(db_column_bytes(&q,0)>=nTagPrefix);
671 fossil_print("%s\n", &zName[nTagPrefix]);
672 }else if( strncmp(zName, "sym-", 4)==0 ){
673 fossil_print("%s\n", &zName[4]);
674 }
675 }
676 db_finalize(&q);
677 }else if( g.argc==4 ){
678 char const *zObjId = g.argv[3];
679
--- src/tag.c
+++ src/tag.c
@@ -468,12 +468,17 @@
468 ** (technote), and "tkt-" (ticket). The
469 ** prefix is stripped from the resulting
470 ** list unless --raw is provided. Ignored if
471 ** ARTIFACT-ID is provided.
472 ** --raw List raw names of tags
473 ** --sep SEP Separator when concatenating values
474 ** --tagtype TYPE List only tags of type TYPE, which must
475 ** be one of: cancel, singleton, propagated
476 ** --values List tag values
477 ** If --sep is supplied, list all values of a tag on
478 ** the same line, separated by SEP; otherwise list
479 ** each value on its own line.
480 **
481 ** The option --raw allows the manipulation of all types of tags
482 ** used for various internal purposes in fossil. It also shows
483 ** "cancel" tags for the "find" and "list" subcommands. You should
484 ** not use this option to make changes unless you are sure what
@@ -635,10 +640,13 @@
640 const int fRaw = find_option("raw","",0)!=0;
641 const char *zTagType = find_option("tagtype","t",1);
642 const int fInverse = find_option("inverse","v",0)!=0;
643 const char *zTagPrefix = find_option("prefix","",1);
644 int nTagType = fRaw ? -1 : 0;
645 int fValues = find_option("values","",0)!=0;
646 const char *zSep = find_option("sep","",1);
647
648
649 if( zTagType!=0 ){
650 int l = strlen(zTagType);
651 if( strncmp(zTagType,"cancel",l)==0 ){
652 nTagType = 0;
@@ -650,29 +658,61 @@
658 fossil_fatal("unrecognized tag type");
659 }
660 }
661 if( g.argc==3 ){
662 const int nTagPrefix = zTagPrefix ? (int)strlen(zTagPrefix) : 0;
663 if( !fValues ){
664 db_prepare(&q,
665 "SELECT tagname FROM tag"
666 " WHERE EXISTS(SELECT 1 FROM tagxref"
667 " WHERE tagid=tag.tagid"
668 " AND tagtype%s%d)"
669 " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' "
670 " END ORDER BY tagname COLLATE uintnocase",
671 zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
672 nTagType, zTagPrefix, zTagPrefix
673 );
674 }else{
675 if( zSep ){
676 db_prepare(&q,
677 /* work around group_concat() with DISTINCT and custom separator */
678 "SELECT tagname,"
679 " rtrim(replace(group_concat(DISTINCT value||'@!' "
680 " ORDER BY value ASC), '@!,', %Q),'@!')"
681 " FROM tagxref, tag"
682 " WHERE tagxref.tagid=tag.tagid AND tagtype%s%d"
683 " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' END"
684 " GROUP BY tagname"
685 " ORDER BY tagname COLLATE uintnocase",
686 ( zSep && strlen(zSep)>0 ) ? zSep : ",",
687 zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
688 nTagType, zTagPrefix, zTagPrefix
689 );
690 }else{
691 db_prepare(&q,
692 "SELECT DISTINCT tagname, value"
693 " FROM tagxref, tag"
694 " WHERE tagxref.tagid=tag.tagid AND tagtype%s%d"
695 " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' END"
696 " ORDER BY tagname, value COLLATE uintnocase",
697 zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
698 nTagType, zTagPrefix, zTagPrefix
699 );
700 }
701 }
702 while( db_step(&q)==SQLITE_ROW ){
703 const char *zName = db_column_text(&q, 0);
704 const char *zValue = db_column_text(&q, 1);
705 int nWidth = fValues ? 20 : 0;
706 const char *zzValue = (fValues && zValue) ? mprintf(" %s", zValue) : "";
707 if( fRaw ){
708 fossil_print("%-*s%s\n", nWidth, zName, zzValue);
709 }else if( nTagPrefix>0 ){
710 assert(db_column_bytes(&q,0)>=nTagPrefix);
711 fossil_print("%-*s%s\n", nWidth, &zName[nTagPrefix], zzValue);
712 }else if( strncmp(zName, "sym-", 4)==0 ){
713 fossil_print("%-*s%s\n", nWidth, &zName[4], zzValue);
714 }
715 }
716 db_finalize(&q);
717 }else if( g.argc==4 ){
718 char const *zObjId = g.argv[3];
719

Keyboard Shortcuts

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