File Annotation
Not logged in
b8a8959ec5 2007-09-23       jnc: /*
b8a8959ec5 2007-09-23       jnc: ** Copyright (c) 2007 D. Richard Hipp
b8a8959ec5 2007-09-23       jnc: **
b8a8959ec5 2007-09-23       jnc: ** This program is free software; you can redistribute it and/or
b8a8959ec5 2007-09-23       jnc: ** modify it under the terms of the GNU General Public
b8a8959ec5 2007-09-23       jnc: ** License version 2 as published by the Free Software Foundation.
b8a8959ec5 2007-09-23       jnc: **
b8a8959ec5 2007-09-23       jnc: ** This program is distributed in the hope that it will be useful,
b8a8959ec5 2007-09-23       jnc: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
b8a8959ec5 2007-09-23       jnc: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b8a8959ec5 2007-09-23       jnc: ** General Public License for more details.
b8a8959ec5 2007-09-23       jnc: **
b8a8959ec5 2007-09-23       jnc: ** You should have received a copy of the GNU General Public
b8a8959ec5 2007-09-23       jnc: ** License along with this library; if not, write to the
b8a8959ec5 2007-09-23       jnc: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
b8a8959ec5 2007-09-23       jnc: ** Boston, MA  02111-1307, USA.
b8a8959ec5 2007-09-23       jnc: **
b8a8959ec5 2007-09-23       jnc: ** Author contact information:
b8a8959ec5 2007-09-23       jnc: **   drh@hwaci.com
b8a8959ec5 2007-09-23       jnc: **   http://www.hwaci.com/drh/
b8a8959ec5 2007-09-23       jnc: **
b8a8959ec5 2007-09-23       jnc: *******************************************************************************
b8a8959ec5 2007-09-23       jnc: **
07eaead5dc 2007-09-23       jnc: ** This file contains code used to create new branches within a repository.
b8a8959ec5 2007-09-23       jnc: */
b8a8959ec5 2007-09-23       jnc: #include "config.h"
b8a8959ec5 2007-09-23       jnc: #include "branch.h"
b8a8959ec5 2007-09-23       jnc: #include <assert.h>
b8a8959ec5 2007-09-23       jnc: 
b6e22e62cf 2009-01-20       drh: /*
b6e22e62cf 2009-01-20       drh: **  fossil branch new    BRANCH-NAME ?ORIGIN-CHECK-IN? ?-bgcolor COLOR?
b6e22e62cf 2009-01-20       drh: **  argv0  argv1  argv2  argv3       argv4
b6e22e62cf 2009-01-20       drh: */
b8a8959ec5 2007-09-23       jnc: void branch_new(void){
b6e22e62cf 2009-01-20       drh:   int rootid;            /* RID of the root check-in - what we branch off of */
b6e22e62cf 2009-01-20       drh:   int brid;              /* RID of the branch check-in */
b6e22e62cf 2009-01-20       drh:   int noSign;            /* True if the branch is unsigned */
b6e22e62cf 2009-01-20       drh:   int i;                 /* Loop counter */
b6e22e62cf 2009-01-20       drh:   char *zUuid;           /* Artifact ID of origin */
b6e22e62cf 2009-01-20       drh:   Stmt q;                /* Generic query */
b6e22e62cf 2009-01-20       drh:   const char *zBranch;   /* Name of the new branch */
b6e22e62cf 2009-01-20       drh:   char *zDate;           /* Date that branch was created */
b6e22e62cf 2009-01-20       drh:   char *zComment;        /* Check-in comment for the new branch */
b6e22e62cf 2009-01-20       drh:   const char *zColor;    /* Color of the new branch */
b6e22e62cf 2009-01-20       drh:   Blob branch;           /* manifest for the new branch */
b6e22e62cf 2009-01-20       drh:   Blob parent;           /* root check-in manifest */
b6e22e62cf 2009-01-20       drh:   Manifest mParent;      /* Parsed parent manifest */
b6e22e62cf 2009-01-20       drh:   Blob mcksum;           /* Self-checksum on the manifest */
b8a8959ec5 2007-09-23       jnc: 
b8a8959ec5 2007-09-23       jnc:   noSign = find_option("nosign","",0)!=0;
b8a8959ec5 2007-09-23       jnc:   zColor = find_option("bgcolor","c",1);
b8a8959ec5 2007-09-23       jnc:   verify_all_options();
4d39bbac10 2009-01-20       drh:   if( g.argc<5 ){
4d39bbac10 2009-01-20       drh:     usage("branch new BRANCH-NAME BASE-CHECK-IN ?-bgcolor COLOR?");
b6e22e62cf 2009-01-20       drh:   }
b6e22e62cf 2009-01-20       drh:   db_find_and_open_repository(1);
b6e22e62cf 2009-01-20       drh:   noSign = db_get_int("omitsign", 0)|noSign;
b8a8959ec5 2007-09-23       jnc: 
b8a8959ec5 2007-09-23       jnc:   /* fossil branch new name */
b8a8959ec5 2007-09-23       jnc:   zBranch = g.argv[3];
2ad378d065 2007-09-23       jnc:   if( zBranch==0 || zBranch[0]==0 ){
2ad378d065 2007-09-23       jnc:     fossil_panic("branch name cannot be empty");
2ad378d065 2007-09-23       jnc:   }
b6e22e62cf 2009-01-20       drh:   if( db_exists(
b6e22e62cf 2009-01-20       drh:         "SELECT 1 FROM tagxref"
b6e22e62cf 2009-01-20       drh:         " WHERE tagtype>0"
b6e22e62cf 2009-01-20       drh:         "   AND tagid=(SELECT tagid FROM tag WHERE tagname='sym-%s')",
b6e22e62cf 2009-01-20       drh:         zBranch)!=0 ){
b6e22e62cf 2009-01-20       drh:     fossil_fatal("branch \"%s\" already exists", zBranch);
b6e22e62cf 2009-01-20       drh:   }
b8a8959ec5 2007-09-23       jnc: 
b8a8959ec5 2007-09-23       jnc:   user_select();
b8a8959ec5 2007-09-23       jnc:   db_begin_transaction();
4d39bbac10 2009-01-20       drh:   rootid = name_to_rid(g.argv[4]);
b6e22e62cf 2009-01-20       drh:   if( rootid==0 ){
b6e22e62cf 2009-01-20       drh:     fossil_fatal("unable to locate check-in off of which to branch");
b8a8959ec5 2007-09-23       jnc:   }
b8a8959ec5 2007-09-23       jnc: 
b6e22e62cf 2009-01-20       drh:   /* Create a manifest for the new branch */
b6e22e62cf 2009-01-20       drh:   blob_zero(&branch);
b6e22e62cf 2009-01-20       drh:   zComment = mprintf("Create new branch named \"%h\"", zBranch);
b6e22e62cf 2009-01-20       drh:   blob_appendf(&branch, "C %F\n", zComment);
b8a8959ec5 2007-09-23       jnc:   zDate = db_text(0, "SELECT datetime('now')");
b8a8959ec5 2007-09-23       jnc:   zDate[10] = 'T';
b6e22e62cf 2009-01-20       drh:   blob_appendf(&branch, "D %s\n", zDate);
b6e22e62cf 2009-01-20       drh: 
b6e22e62cf 2009-01-20       drh:   /* Copy all of the content from the parent into the branch */
b6e22e62cf 2009-01-20       drh:   content_get(rootid, &parent);
b6e22e62cf 2009-01-20       drh:   manifest_parse(&mParent, &parent);
b6e22e62cf 2009-01-20       drh:   if( mParent.type!=CFTYPE_MANIFEST ){
b6e22e62cf 2009-01-20       drh:     fossil_fatal("%s is not a valid check-in", g.argv[4]);
2ad378d065 2007-09-23       jnc:   }
b6e22e62cf 2009-01-20       drh:   for(i=0; i<mParent.nFile; ++i){
b6e22e62cf 2009-01-20       drh:     if( mParent.aFile[i].zPerm[0] ){
b6e22e62cf 2009-01-20       drh:       blob_appendf(&branch, "F %F %s %s\n",
b6e22e62cf 2009-01-20       drh:                    mParent.aFile[i].zName,
b6e22e62cf 2009-01-20       drh:                    mParent.aFile[i].zUuid,
b6e22e62cf 2009-01-20       drh:                    mParent.aFile[i].zPerm);
2ad378d065 2007-09-23       jnc:     }else{
b6e22e62cf 2009-01-20       drh:       blob_appendf(&branch, "F %F %s\n",
b6e22e62cf 2009-01-20       drh:                    mParent.aFile[i].zName,
b6e22e62cf 2009-01-20       drh:                    mParent.aFile[i].zUuid);
2ad378d065 2007-09-23       jnc:     }
ce08928aaa 2008-02-08       drh:   }
b6e22e62cf 2009-01-20       drh:   zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rootid);
b6e22e62cf 2009-01-20       drh:   blob_appendf(&branch, "P %s\n", zUuid);
b6e22e62cf 2009-01-20       drh:   blob_appendf(&branch, "R %s\n", mParent.zRepoCksum);
b6e22e62cf 2009-01-20       drh:   manifest_clear(&mParent);
b6e22e62cf 2009-01-20       drh: 
b6e22e62cf 2009-01-20       drh:   /* Add the symbolic branch name and the "newbranch" tag to identify
b6e22e62cf 2009-01-20       drh:   ** this as a new branch */
ce08928aaa 2008-02-08       drh:   if( zColor!=0 ){
b6e22e62cf 2009-01-20       drh:     blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
2ad378d065 2007-09-23       jnc:   }
b6e22e62cf 2009-01-20       drh:   blob_appendf(&branch, "T *sym-%F *\n", zBranch);
b6e22e62cf 2009-01-20       drh:   blob_appendf(&branch, "T +newbranch *\n");
b8a8959ec5 2007-09-23       jnc: 
b6e22e62cf 2009-01-20       drh:   /* Cancel all other symbolic tags */
b8a8959ec5 2007-09-23       jnc:   db_prepare(&q,
b6e22e62cf 2009-01-20       drh:       "SELECT tagname FROM tagxref, tag"
b6e22e62cf 2009-01-20       drh:       " WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
b6e22e62cf 2009-01-20       drh:       "   AND tagtype>0 AND tagname GLOB 'sym-*'"
b6e22e62cf 2009-01-20       drh:       " ORDER BY tagname",
b6e22e62cf 2009-01-20       drh:       rootid);
b8a8959ec5 2007-09-23       jnc:   while( db_step(&q)==SQLITE_ROW ){
b6e22e62cf 2009-01-20       drh:     const char *zTag = db_column_text(&q, 0);
b6e22e62cf 2009-01-20       drh:     blob_appendf(&branch, "T -%s *\n", zTag);
b8a8959ec5 2007-09-23       jnc:   }
b8a8959ec5 2007-09-23       jnc:   db_finalize(&q);
b8a8959ec5 2007-09-23       jnc: 
b6e22e62cf 2009-01-20       drh:   blob_appendf(&branch, "U %F\n", g.zLogin);
b6e22e62cf 2009-01-20       drh:   md5sum_blob(&branch, &mcksum);
b6e22e62cf 2009-01-20       drh:   blob_appendf(&branch, "Z %b\n", &mcksum);
b6e22e62cf 2009-01-20       drh:   if( !noSign && clearsign(&branch, &branch) ){
b8a8959ec5 2007-09-23       jnc:     Blob ans;
b8a8959ec5 2007-09-23       jnc:     blob_zero(&ans);
b8a8959ec5 2007-09-23       jnc:     prompt_user("unable to sign manifest.  continue [y/N]? ", &ans);
b8a8959ec5 2007-09-23       jnc:     if( blob_str(&ans)[0]!='y' ){
b8a8959ec5 2007-09-23       jnc:       db_end_transaction(1);
b8a8959ec5 2007-09-23       jnc:       exit(1);
b8a8959ec5 2007-09-23       jnc:     }
b8a8959ec5 2007-09-23       jnc:   }
b8a8959ec5 2007-09-23       jnc: 
b6e22e62cf 2009-01-20       drh:   brid = content_put(&branch, 0, 0);
b6e22e62cf 2009-01-20       drh:   if( brid==0 ){
b8a8959ec5 2007-09-23       jnc:     fossil_panic("trouble committing manifest: %s", g.zErrMsg);
b8a8959ec5 2007-09-23       jnc:   }
b6e22e62cf 2009-01-20       drh:   db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
b6e22e62cf 2009-01-20       drh:   if( manifest_crosslink(brid, &branch)==0 ){
b6e22e62cf 2009-01-20       drh:     fossil_panic("unable to install new manifest");
b6e22e62cf 2009-01-20       drh:   }
b6e22e62cf 2009-01-20       drh:   content_deltify(rootid, brid, 0);
b6e22e62cf 2009-01-20       drh:   zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
b6e22e62cf 2009-01-20       drh:   printf("New branch: %s\n", zUuid);
b6e22e62cf 2009-01-20       drh:   if( g.argc==3 ){
b6e22e62cf 2009-01-20       drh:     printf(
b6e22e62cf 2009-01-20       drh:       "\n"
b6e22e62cf 2009-01-20       drh:       "Note: the local check-out has not been updated to the new\n"
b6e22e62cf 2009-01-20       drh:       "      branch.  To begin working on the new branch, do this:\n"
b6e22e62cf 2009-01-20       drh:       "\n"
b6e22e62cf 2009-01-20       drh:       "      %s update %s\n",
b6e22e62cf 2009-01-20       drh:       g.argv[0], zBranch
b6e22e62cf 2009-01-20       drh:     );
b8a8959ec5 2007-09-23       jnc:   }
b8a8959ec5 2007-09-23       jnc: 
b8a8959ec5 2007-09-23       jnc: 
b8a8959ec5 2007-09-23       jnc:   /* Commit */
b8a8959ec5 2007-09-23       jnc:   db_end_transaction(0);
e4517465f3 2007-09-25       jnc: 
fff234b77c 2007-09-25       drh:   /* Do an autosync push, if requested */
49b59bc559 2008-02-09       drh:   autosync(AUTOSYNC_PUSH);
b8a8959ec5 2007-09-23       jnc: }
b8a8959ec5 2007-09-23       jnc: 
b8a8959ec5 2007-09-23       jnc: /*
b8a8959ec5 2007-09-23       jnc: ** COMMAND: branch
b8a8959ec5 2007-09-23       jnc: **
b8a8959ec5 2007-09-23       jnc: ** Usage: %fossil branch SUBCOMMAND ... ?-R|--repository FILE?
b8a8959ec5 2007-09-23       jnc: **
66b13f1015 2008-02-07       bch: ** Run various subcommands on the branches of the open repository or
b8a8959ec5 2007-09-23       jnc: ** of the repository identified by the -R or --repository option.
b8a8959ec5 2007-09-23       jnc: **
4d39bbac10 2009-01-20       drh: **    %fossil branch new BRANCH-NAME BASIS ?-bgcolor COLOR?
b8a8959ec5 2007-09-23       jnc: **
4d39bbac10 2009-01-20       drh: **        Create a new branch BRANCH-NAME off of check-in BASIS.
4d39bbac10 2009-01-20       drh: **        You can optionally give the branch a default color.
b8a8959ec5 2007-09-23       jnc: **
b8a8959ec5 2007-09-23       jnc: **    %fossil branch list
b8a8959ec5 2007-09-23       jnc: **
b8a8959ec5 2007-09-23       jnc: **        List all branches
b8a8959ec5 2007-09-23       jnc: **
b8a8959ec5 2007-09-23       jnc: */
b8a8959ec5 2007-09-23       jnc: void branch_cmd(void){
b8a8959ec5 2007-09-23       jnc:   int n;
4e683ef07b 2008-05-05       drh:   db_find_and_open_repository(1);
b8a8959ec5 2007-09-23       jnc:   if( g.argc<3 ){
b8a8959ec5 2007-09-23       jnc:     usage("new|list ...");
b8a8959ec5 2007-09-23       jnc:   }
b8a8959ec5 2007-09-23       jnc:   n = strlen(g.argv[2]);
b8a8959ec5 2007-09-23       jnc:   if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){
b8a8959ec5 2007-09-23       jnc:     branch_new();
b8a8959ec5 2007-09-23       jnc:   }else if( n>=2 && strncmp(g.argv[2],"list",n)==0 ){
b7f32a71ab 2009-01-20       drh:     Stmt q;
b7f32a71ab 2009-01-20       drh:     db_prepare(&q,
b7f32a71ab 2009-01-20       drh:       "%s"
b7f32a71ab 2009-01-20       drh:       "   AND blob.rid IN (SELECT rid FROM tagxref"
b7f32a71ab 2009-01-20       drh:       "                     WHERE tagid=%d AND tagtype==1)"
b7f32a71ab 2009-01-20       drh:       " ORDER BY event.mtime DESC",
b7f32a71ab 2009-01-20       drh:       timeline_query_for_tty(), TAG_NEWBRANCH
b7f32a71ab 2009-01-20       drh:     );
b7f32a71ab 2009-01-20       drh:     print_timeline(&q, 2000);
b7f32a71ab 2009-01-20       drh:     db_finalize(&q);
b8a8959ec5 2007-09-23       jnc:   }else{
b8a8959ec5 2007-09-23       jnc:     fossil_panic("branch subcommand should be one of: "
b8a8959ec5 2007-09-23       jnc:                  "new list");
b8a8959ec5 2007-09-23       jnc:   }
fecb3e5cc9 2009-01-20       drh: }
fecb3e5cc9 2009-01-20       drh: 
fecb3e5cc9 2009-01-20       drh: /*
bdcac62937 2009-01-21       drh: ** This routine is called while for each check-in that is rendered by
bdcac62937 2009-01-21       drh: ** the timeline of a "brlist" page.  Add some additional hyperlinks
bdcac62937 2009-01-21       drh: ** to the end of the line.
bdcac62937 2009-01-21       drh: */
bdcac62937 2009-01-21       drh: static void brlist_extra(int rid){
bdcac62937 2009-01-21       drh:   Stmt q;
bdcac62937 2009-01-21       drh:   db_prepare(&q,
e631d8af6d 2009-01-21       drh:     "SELECT substr(tagname,5) FROM tagxref, tag"
bdcac62937 2009-01-21       drh:     " WHERE tagxref.rid=%d"
bdcac62937 2009-01-21       drh:     "   AND tagxref.tagid=tag.tagid"
bdcac62937 2009-01-21       drh:     "   AND tagxref.tagtype>0"
bdcac62937 2009-01-21       drh:     "   AND tag.tagname GLOB 'sym-*'",
bdcac62937 2009-01-21       drh:     rid
bdcac62937 2009-01-21       drh:   );
bdcac62937 2009-01-21       drh:   while( db_step(&q)==SQLITE_ROW ){
bdcac62937 2009-01-21       drh:     const char *zTagName = db_column_text(&q, 0);
e631d8af6d 2009-01-21       drh:     @ [<a href="%s(g.zBaseURL)/timeline?t=%T(zTagName)">%h(zTagName)</a>]
bdcac62937 2009-01-21       drh:   }
bdcac62937 2009-01-21       drh:   db_finalize(&q);
bdcac62937 2009-01-21       drh: }
bdcac62937 2009-01-21       drh: 
bdcac62937 2009-01-21       drh: /*
fecb3e5cc9 2009-01-20       drh: ** WEBPAGE: brlist
fecb3e5cc9 2009-01-20       drh: **
fecb3e5cc9 2009-01-20       drh: ** Show a timeline of all branches
fecb3e5cc9 2009-01-20       drh: */
fecb3e5cc9 2009-01-20       drh: void brlist_page(void){
fecb3e5cc9 2009-01-20       drh:   Stmt q;
fecb3e5cc9 2009-01-20       drh: 
fecb3e5cc9 2009-01-20       drh:   login_check_credentials();
fecb3e5cc9 2009-01-20       drh:   if( !g.okRead ){ login_needed(); return; }
fecb3e5cc9 2009-01-20       drh: 
fecb3e5cc9 2009-01-20       drh:   style_header("Branches");
fecb3e5cc9 2009-01-20       drh:   login_anonymous_available();
bdcac62937 2009-01-21       drh:   @ <h2>The initial check-in for each branch:</h2>
fecb3e5cc9 2009-01-20       drh:   db_prepare(&q,
fecb3e5cc9 2009-01-20       drh:     "%s AND blob.rid IN (SELECT rid FROM tagxref WHERE tagtype>0 AND tagid=%d)"
fecb3e5cc9 2009-01-20       drh:     " ORDER BY event.mtime DESC",
fecb3e5cc9 2009-01-20       drh:     timeline_query_for_www(), TAG_NEWBRANCH
fecb3e5cc9 2009-01-20       drh:   );
bdcac62937 2009-01-21       drh:   www_print_timeline(&q, 0, brlist_extra);
fecb3e5cc9 2009-01-20       drh:   db_finalize(&q);
fecb3e5cc9 2009-01-20       drh:   @ <br clear="both">
fecb3e5cc9 2009-01-20       drh:   @ <script>
fecb3e5cc9 2009-01-20       drh:   @ function xin(id){
fecb3e5cc9 2009-01-20       drh:   @ }
fecb3e5cc9 2009-01-20       drh:   @ function xout(id){
fecb3e5cc9 2009-01-20       drh:   @ }
fecb3e5cc9 2009-01-20       drh:   @ </script>
fecb3e5cc9 2009-01-20       drh:   style_footer();
b8a8959ec5 2007-09-23       jnc: }