Index: src/checkin.c
==================================================================
--- src/checkin.c
+++ src/checkin.c
@@ -1641,13 +1641,12 @@
" WHERE (vmerge.id=-1 OR vmerge.id=-2)"
" ORDER BY 1");
while( db_step(&q)==SQLITE_ROW ){
const char *zCherrypickUuid = db_column_text(&q, 0);
int mid = db_column_int(&q, 1);
- if( mid != vid ){
- blob_appendf(pOut, "Q %s\n", zCherrypickUuid);
- }
+ if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
+ blob_appendf(pOut, "Q %s\n", zCherrypickUuid);
}
db_finalize(&q);
if( p->pCksum ) blob_appendf(pOut, "R %b\n", p->pCksum);
zColor = p->zColor;
@@ -1673,19 +1672,19 @@
while( db_step(&q)==SQLITE_ROW ){
const char *zIntegrateUuid = db_column_text(&q, 0);
int rid = db_column_int(&q, 1);
if( is_a_leaf(rid) && !db_exists("SELECT 1 FROM tagxref "
" WHERE tagid=%d AND rid=%d AND tagtype>0", TAG_CLOSED, rid)){
-#if 0
/* Make sure the check-in manifest of the resulting merge child does not
** include a +close tag referring to the leaf check-in on a private
** branch, so as not to generate a missing artifact reference on
- ** repository clones without that private branch. The merge command
- ** should have dropped the --integrate option, at this point. */
- assert( !content_is_private(rid) );
-#endif
- blob_appendf(pOut, "T +closed %s\n", zIntegrateUuid);
+ ** repository clones without that private branch. Instead, the leaf of
+ ** the private branch will be closed later by a separate private control
+ ** artifact. */
+ if( !content_is_private(rid) ){
+ blob_appendf(pOut, "T +closed %s\n", zIntegrateUuid);
+ }
}
}
db_finalize(&q);
if( p->azTag ){
@@ -2076,10 +2075,11 @@
Blob muuid; /* Manifest uuid */
Blob cksum1, cksum2; /* Before and after commit checksums */
Blob cksum1b; /* Checksum recorded in the manifest */
int szD; /* Size of the delta manifest */
int szB; /* Size of the baseline manifest */
+ int nClosedPrivateLeaves = 0; /* Number of closed private leafs */
int nConflict = 0; /* Number of unresolved merge conflicts */
int abortCommit = 0; /* Abort the commit due to text format conversions */
Blob ans; /* Answer to continuation prompts */
char cReply; /* First character of ans */
int bRecheck = 0; /* Repeat fork and closed-branch checks*/
@@ -2561,12 +2561,52 @@
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
db_prepare(&q, "SELECT mhash,merge FROM vmerge WHERE id=-4");
while( db_step(&q)==SQLITE_ROW ){
const char *zIntegrateUuid = db_column_text(&q, 0);
- if( is_a_leaf(db_column_int(&q, 1)) ){
- fossil_print("Closed: %s\n", zIntegrateUuid);
+ int rid = db_column_int(&q, 1);
+ if( is_a_leaf(rid) ){
+ if( !content_is_private(rid) ){
+ fossil_print("Closed: %s\n", zIntegrateUuid);
+ }else{
+ /* Close leaves of private branches by separate private control
+ ** artifacts. */
+ Blob bCtrl; /* Control artifact to close the private leaf */
+ char *zCtrlDate; /* Timestamp of check-in plus N seconds */
+ Blob bCtrlXsum; /* Checksum of the control artifact */
+ int iCtrlRid; /* RID of the control artifact */
+ if( db_exists(
+ "SELECT 1 FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>0",
+ TAG_CLOSED, rid) ){
+ continue; /* Already closed. */
+ }
+ nClosedPrivateLeaves++;
+ blob_zero(&bCtrl);
+ zCtrlDate = db_text(0,
+ "SELECT"
+ " strftime('%%Y-%%m-%%dT%%H:%%M:%%f',mtime,'+%d seconds')"
+ " FROM event WHERE objid=%d",
+ nClosedPrivateLeaves, nvid);
+ blob_appendf(&bCtrl, "D %z\n", date_in_standard_format(zCtrlDate));
+ if( zCtrlDate ) fossil_free(zCtrlDate);
+ blob_appendf(&bCtrl, "T +closed %s\n", zIntegrateUuid);
+ blob_appendf(&bCtrl, "U %F\n",
+ sCiInfo.zUserOvrd ? sCiInfo.zUserOvrd : login_name());
+ md5sum_blob(&bCtrl, &bCtrlXsum);
+ blob_appendf(&bCtrl, "Z %b\n", &bCtrlXsum);
+ blob_reset(&bCtrlXsum);
+ iCtrlRid = content_put_ex(&bCtrl, 0, 0, 0, /*isPrivate=*/1);
+ if( iCtrlRid==0 ){
+ fossil_fatal("trouble committing control artifact: %s", g.zErrMsg);
+ }
+ fossil_print("Closed: %s (private)\n", zIntegrateUuid);
+ if( dryRunFlag ) fossil_print("%s", blob_str(&bCtrl));
+ if( manifest_crosslink(iCtrlRid, &bCtrl,
+ dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){
+ fossil_fatal("%s", g.zErrMsg);
+ }
+ }
}else{
fossil_print("Not_Closed: %s (not a leaf any more)\n", zIntegrateUuid);
}
}
db_finalize(&q);
Index: src/merge.c
==================================================================
--- src/merge.c
+++ src/merge.c
@@ -404,17 +404,10 @@
" Use --force to override.\n");
return;
}
if( integrateFlag && !is_a_leaf(mid)){
fossil_warning("ignoring --integrate: %s is not a leaf", g.argv[2]);
- integrateFlag = 0;
- }
- if( integrateFlag && content_is_private(mid) ){
- fossil_warning(
- "ignoring --integrate: %s is on a private branch"
- "\n Use \"fossil amend --close\" (after commit) to close the leaf.",
- g.argv[2]);
integrateFlag = 0;
}
if( verboseFlag ){
print_checkin_description(mid, 12,
integrateFlag ? "integrate:" : "merge-from:");
Index: www/private.wiki
==================================================================
--- www/private.wiki
+++ www/private.wiki
@@ -40,18 +40,18 @@
A private branch created with Fossil version 1.30 or newer can also be
converted into a public branch using the fossil publish
command. However, there is no way to convert a private branch created with
older versions of Fossil into a public branch.
-The --integrate option of fossil merge (to close
-the merged branch when committing) is ignored for a private branch -- or the
-check-in manifest of the resulting merge child would include a
-+close tag referring to the leaf check-in on the private branch,
-and generate a missing artifact reference on repository clones without that
-private branch. It's still possible to close the leaf of the private branch
-(after committing the merge child) with the fossil amend --close
-command.
+If the --integrate option of fossil merge (to close
+the merged branch when committing) is used for a private branch, a separate
+control artifact to apply the +close tag is created and added to
+the repository during the commit process. Managing the +close
+tag directly from the check-in manifest of the resulting merge child would
+generate a reference to the leaf check-in on the private branch, and generate
+a missing artifact reference (a "phantom") on repository clones without that
+private branch.