Diff
Not logged in

Differences From:

File src/tag.c part of check-in [9395aba4f4] - Timeline now responses to comment and user properties. by drh on 2007-09-22 12:38:05. [view]

To:

File src/tag.c part of check-in [3b5514ed82] - The "tag" command allows tag artifacts to be inserted for creating and cancelling tags and properties. Timeline responds to bgcolor, br-bgcolor, comment, and user properties. by drh on 2007-09-22 15:50:14. [view]

@@ -43,9 +43,9 @@
   const char *zValue,  /* Value of the tag.  Might be NULL */
   double mtime         /* Timestamp on the tag */
 ){
   PQueue queue;
-  Stmt s, ins;
+  Stmt s, ins, eventupdate;
   pqueue_init(&queue);
   pqueue_insert(&queue, pid, 0.0);
   db_prepare(&s,
      "SELECT cid, plink.mtime,"
@@ -62,10 +62,16 @@
        tagid, zValue
     );
     db_bind_double(&ins, ":mtime", mtime);
   }else{
+    zValue = 0;
     db_prepare(&ins,
        "DELETE FROM tagxref WHERE tagid=%d AND rid=:rid", tagid
+    );
+  }
+  if( tagid==TAG_BR_BGCOLOR ){
+    db_prepare(&eventupdate,
+      "UPDATE event SET brbgcolor=%Q WHERE objid=:rid", zValue
     );
   }
   while( (pid = pqueue_extract(&queue))!=0 ){
     db_bind_int(&s, ":pid", pid);
@@ -77,15 +83,23 @@
         pqueue_insert(&queue, cid, mtime);
         db_bind_int(&ins, ":rid", cid);
         db_step(&ins);
         db_reset(&ins);
+        if( tagid==TAG_BR_BGCOLOR ){
+          db_bind_int(&eventupdate, ":rid", cid);
+          db_step(&eventupdate);
+          db_reset(&eventupdate);
+        }
       }
     }
     db_reset(&s);
   }
   pqueue_clear(&queue);
   db_finalize(&ins);
   db_finalize(&s);
+  if( tagid==TAG_BR_BGCOLOR ){
+    db_finalize(&eventupdate);
+  }
 }
 
 /*
 ** Propagate all propagatable tags in pid to its children.
@@ -145,10 +159,31 @@
   );
   db_bind_double(&s, ":mtime", mtime);
   db_step(&s);
   db_finalize(&s);
+  if( addFlag==0 ){
+    zValue = 0;
+  }
+  switch( tagid ){
+    case TAG_BGCOLOR: {
+      db_multi_exec("UPDATE event SET bgcolor=%Q WHERE objid=%d", zValue, rid);
+      break;
+    }
+    case TAG_BR_BGCOLOR: {
+      db_multi_exec("UPDATE event SET brbgcolor=%Q WHERE objid=%d", zValue,rid);
+      break;
+    }
+    case TAG_COMMENT: {
+      db_multi_exec("UPDATE event SET ecomment=%Q WHERE objid=%d", zValue, rid);
+      break;
+    }
+    case TAG_USER: {
+      db_multi_exec("UPDATE event SET euser=%Q WHERE objid=%d", zValue, rid);
+      break;
+    }
+  }
   if( strncmp(zTag, "br", 2)==0 ){
-    tag_propagate(rid, tagid, 1, zValue, mtime);
+    tag_propagate(rid, tagid, addFlag, zValue, mtime);
   }
 }
 
 
@@ -202,5 +237,164 @@
   }
   db_begin_transaction();
   tag_insert(zTag, 0, 0, -1, 0.0, rid);
   db_end_transaction(0);
+}
+
+/*
+** Add a control record to the repository that either creates
+** or cancels a tag.
+*/
+static void tag_add_artifact(
+  const char *zTagname,       /* The tag to add or cancel */
+  const char *zObjName,       /* Name of object attached to */
+  const char *zValue,         /* Value for the tag.  Might be NULL */
+  int addFlag                 /* True to add.  false to cancel */
+){
+  int rid;
+  int nrid;
+  char *zDate;
+  Blob uuid;
+  Blob ctrl;
+  Blob cksum;
+
+  user_select();
+  rid = name_to_rid(zObjName);
+  blob_zero(&uuid);
+  db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
+  blob_zero(&ctrl);
+
+  if( validate16(zTagname, strlen(zTagname)) ){
+    fossil_fatal("invalid tag name \"%s\" - might be confused with a UUID",
+                 zTagname);
+  }
+  zDate = db_text(0, "SELECT datetime('now')");
+  zDate[10] = 'T';
+  blob_appendf(&ctrl, "D %s\n", zDate);
+  blob_appendf(&ctrl, "T %c%F %b", addFlag ? '+' : '-', zTagname, &uuid);
+  if( addFlag && zValue && zValue[0] ){
+    blob_appendf(&ctrl, " %F\n", zValue);
+  }else{
+    blob_appendf(&ctrl, "\n");
+  }
+  blob_appendf(&ctrl, "U %F\n", g.zLogin);
+  md5sum_blob(&ctrl, &cksum);
+  blob_appendf(&ctrl, "Z %b\n", &cksum);
+  db_begin_transaction();
+  nrid = content_put(&ctrl, 0, 0);
+  manifest_crosslink(nrid, &ctrl);
+  db_end_transaction(0);
+}
+
+/*
+** COMMAND: tag
+** Usage: %fossil tag SUBCOMMAND ...
+**
+** Run various subcommands to control tags and properties
+**
+**     %fossil tag add TAGNAME UUID ?VALUE?
+**
+**         Add a new tag or property to UUID.
+**
+**     %fossil tag delete TAGNAME UUID
+**
+**         Delete the tag TAGNAME from UUID
+**
+**     %fossil tag find TAGNAME
+**
+**         List all baselines that use TAGNAME
+**
+**     %fossil tag list ?UUID?
+**
+**         List all tags, or if UUID is supplied, list
+**         all tags and their values for UUID.
+*/
+void tag_cmd(void){
+  int n;
+  db_find_and_open_repository();
+  if( g.argc<3 ){
+    goto tag_cmd_usage;
+  }
+  n = strlen(g.argv[2]);
+  if( n==0 ){
+    goto tag_cmd_usage;
+  }
+
+  if( strncmp(g.argv[2],"add",n)==0 ){
+    char *zValue;
+    if( g.argc!=5 && g.argc!=6 ){
+      usage("tag add TAGNAME UUID ?VALUE?");
+    }
+    zValue = g.argc==6 ? g.argv[5] : 0;
+    tag_add_artifact(g.argv[3], g.argv[4], zValue, 1);
+  }else
+
+  if( strncmp(g.argv[2],"delete",n)==0 ){
+    if( g.argc!=5 ){
+      usage("tag delete TAGNAME UUID");
+    }
+    tag_add_artifact(g.argv[3], g.argv[4], 0, 0);
+  }else
+
+  if( strncmp(g.argv[2],"find",n)==0 ){
+    Stmt q;
+    if( g.argc!=4 ){
+      usage("tag find TAGNAME");
+    }
+    db_prepare(&q,
+      "SELECT blob.uuid FROM tagxref, blob"
+      " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
+      "   AND blob.rid=tagxref.rid", g.argv[3]
+    );
+    while( db_step(&q)==SQLITE_ROW ){
+      printf("%s\n", db_column_text(&q, 0));
+    }
+    db_finalize(&q);
+  }else
+
+  if( strncmp(g.argv[2],"list",n)==0 ){
+    Stmt q;
+    if( g.argc==3 ){
+      db_prepare(&q,
+        "SELECT tagname"
+        "  FROM tag"
+        " WHERE EXISTS(SELECT 1 FROM tagxref"
+        "               WHERE tagid=tag.tagid"
+        "                 AND addflag)"
+        " ORDER BY tagname"
+      );
+      while( db_step(&q)==SQLITE_ROW ){
+        printf("%s\n", db_column_text(&q, 0));
+      }
+      db_finalize(&q);
+    }else if( g.argc==4 ){
+      int rid = name_to_rid(g.argv[3]);
+      db_prepare(&q,
+        "SELECT tagname, value"
+        "  FROM tagxref, tag"
+        " WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
+        "   AND addflag"
+        " ORDER BY tagname",
+        rid
+      );
+      while( db_step(&q)==SQLITE_ROW ){
+        const char *zName = db_column_text(&q, 0);
+        const char *zValue = db_column_text(&q, 1);
+        if( zValue ){
+          printf("%s=%s\n", zName, zValue);
+        }else{
+          printf("%s\n", zName);
+        }
+      }
+      db_finalize(&q);
+    }else{
+      usage("tag list ?UUID?");
+    }
+  }else
+  {
+    goto tag_cmd_usage;
+  }
+  return;
+
+tag_cmd_usage:
+  usage("add|delete|find|list ...");
 }