Fossil SCM

Enhance the "fossil merge" command so that if the VERSION argument is omitted, Fossil tries to merge any forks of the current branch.

drh 2013-01-14 00:21 trunk
Commit 9ee47de25474d706b9b953076324cebe9a4bf1dd
1 file changed +75 -8
+75 -8
--- src/merge.c
+++ src/merge.c
@@ -57,19 +57,22 @@
5757
5858
5959
/*
6060
** COMMAND: merge
6161
**
62
-** Usage: %fossil merge ?OPTIONS? VERSION
62
+** Usage: %fossil merge ?OPTIONS? ?VERSION?
6363
**
6464
** The argument VERSION is a version that should be merged into the
6565
** current checkout. All changes from VERSION back to the nearest
6666
** common ancestor are merged. Except, if either of the --cherrypick or
6767
** --backout options are used only the changes associated with the
6868
** single check-in VERSION are merged. The --backout option causes
6969
** the changes associated with VERSION to be removed from the current
7070
** checkout rather than added.
71
+**
72
+** If the VERSION argument is omitted, then Fossil attempts to find
73
+** a recent fork on the current branch to merge.
7174
**
7275
** Only file content is merged. The result continues to use the
7376
** file and directory names from the current checkout even if those
7477
** names might have been changed in the branch being merged in.
7578
**
@@ -131,24 +134,88 @@
131134
zBinGlob = find_option("binary",0,1);
132135
nochangeFlag = find_option("nochange","n",0)!=0;
133136
forceFlag = find_option("force","f",0)!=0;
134137
zPivot = find_option("baseline",0,1);
135138
capture_case_sensitive_option();
136
- if( g.argc!=3 ){
137
- usage("VERSION");
138
- }
139
+ verify_all_options();
139140
db_must_be_within_tree();
140141
caseSensitive = filenames_are_case_sensitive();
141142
if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
142143
vid = db_lget_int("checkout", 0);
143144
if( vid==0 ){
144145
fossil_fatal("nothing is checked out");
145146
}
146
- mid = name_to_typed_rid(g.argv[2], "ci");
147
- if( mid==0 || !is_a_version(mid) ){
148
- fossil_fatal("not a version: %s", g.argv[2]);
147
+
148
+ /* Find mid, the artifactID of the version to be merged into the current
149
+ ** check-out */
150
+ if( g.argc==3 ){
151
+ /* Mid is specified as an argument on the command-line */
152
+ mid = name_to_typed_rid(g.argv[2], "ci");
153
+ if( mid==0 || !is_a_version(mid) ){
154
+ fossil_fatal("not a version: %s", g.argv[2]);
155
+ }
156
+ }else if( g.argc==2 ){
157
+ /* No version specified on the command-line so pick the most recent
158
+ ** leaf that is (1) not the version currently checked out and (2)
159
+ ** has not already been merged into the current checkout and (3)
160
+ ** the leaf is not closed and (4) the leaf is in the same branch
161
+ ** as the current checkout.
162
+ */
163
+ Stmt q;
164
+ if( pickFlag || backoutFlag ){
165
+ fossil_fatal("cannot use --cherrypick or --backout with a fork merge");
166
+ }
167
+ mid = db_int(0,
168
+ "SELECT leaf.rid"
169
+ " FROM leaf, event"
170
+ " WHERE leaf.rid=event.objid"
171
+ " AND leaf.rid!=%d" /* Constraint (1) */
172
+ " AND leaf.rid NOT IN (SELECT merge FROM vmerge)" /* Constraint (2) */
173
+ " AND NOT EXISTS(SELECT 1 FROM tagxref" /* Constraint (3) */
174
+ " WHERE rid=leaf.rid"
175
+ " AND tagid=%d"
176
+ " AND tagtype>0)"
177
+ " AND (SELECT value FROM tagxref" /* Constraint (4) */
178
+ " WHERE tagid=%d AND rid=%d"
179
+ " AND tagtype>0"
180
+ " ORDER BY mtime DESC LIMIT 1) = "
181
+ " (SELECT value FROM tagxref"
182
+ " WHERE tagid=%d AND rid=leaf.rid"
183
+ " AND tagtype>0"
184
+ " ORDER BY mtime DESC LIMIT 1)"
185
+ " ORDER BY event.mtime DESC LIMIT 1",
186
+ vid, TAG_CLOSED, TAG_BRANCH, vid, TAG_BRANCH
187
+ );
188
+ if( mid==0 ){
189
+ fossil_fatal("no unmerged forks of branch \"%s\"",
190
+ db_text(0, "SELECT value FROM tagxref"
191
+ " WHERE tagid=%d AND rid=%d"
192
+ " AND tagtype>0"
193
+ " ORDER BY mtime DESC LIMIT 1", TAG_BRANCH, vid)
194
+ );
195
+ }
196
+ db_prepare(&q,
197
+ "SELECT blob.uuid,"
198
+ " datetime(event.mtime,'localtime'),"
199
+ " coalesce(ecomment, comment),"
200
+ " coalesce(euser, user)"
201
+ " FROM event, blob"
202
+ " WHERE event.objid=%d AND blob.rid=%d",
203
+ mid, mid
204
+ );
205
+ if( db_step(&q)==SQLITE_ROW ){
206
+ char *zCom = mprintf("Merging fork [%S] at %s by %s: \"%s\"",
207
+ db_column_text(&q, 0), db_column_text(&q, 1),
208
+ db_column_text(&q, 3), db_column_text(&q, 2));
209
+ comment_print(zCom, 0, 79);
210
+ fossil_free(zCom);
211
+ }
212
+ db_finalize(&q);
213
+ }else{
214
+ usage("?OPTIONS? ?VERSION?");
149215
}
216
+
150217
if( zPivot ){
151218
pid = name_to_typed_rid(zPivot, "ci");
152219
if( pid==0 || !is_a_version(pid) ){
153220
fossil_fatal("not a version: %s", zPivot);
154221
}
@@ -347,11 +414,11 @@
347414
"SELECT idm FROM fv WHERE idp=0 AND idv>0 AND idm>0"
348415
);
349416
while( db_step(&q)==SQLITE_ROW ){
350417
int idm = db_column_int(&q, 0);
351418
char *zName = db_text(0, "SELECT pathname FROM vfile WHERE id=%d", idm);
352
- fossil_warning("WARNING - no common ancestor: %s\n", zName);
419
+ fossil_warning("WARNING - no common ancestor: %s", zName);
353420
free(zName);
354421
db_multi_exec("UPDATE fv SET idm=0 WHERE idm=%d", idm);
355422
}
356423
db_finalize(&q);
357424
358425
--- src/merge.c
+++ src/merge.c
@@ -57,19 +57,22 @@
57
58
59 /*
60 ** COMMAND: merge
61 **
62 ** Usage: %fossil merge ?OPTIONS? VERSION
63 **
64 ** The argument VERSION is a version that should be merged into the
65 ** current checkout. All changes from VERSION back to the nearest
66 ** common ancestor are merged. Except, if either of the --cherrypick or
67 ** --backout options are used only the changes associated with the
68 ** single check-in VERSION are merged. The --backout option causes
69 ** the changes associated with VERSION to be removed from the current
70 ** checkout rather than added.
 
 
 
71 **
72 ** Only file content is merged. The result continues to use the
73 ** file and directory names from the current checkout even if those
74 ** names might have been changed in the branch being merged in.
75 **
@@ -131,24 +134,88 @@
131 zBinGlob = find_option("binary",0,1);
132 nochangeFlag = find_option("nochange","n",0)!=0;
133 forceFlag = find_option("force","f",0)!=0;
134 zPivot = find_option("baseline",0,1);
135 capture_case_sensitive_option();
136 if( g.argc!=3 ){
137 usage("VERSION");
138 }
139 db_must_be_within_tree();
140 caseSensitive = filenames_are_case_sensitive();
141 if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
142 vid = db_lget_int("checkout", 0);
143 if( vid==0 ){
144 fossil_fatal("nothing is checked out");
145 }
146 mid = name_to_typed_rid(g.argv[2], "ci");
147 if( mid==0 || !is_a_version(mid) ){
148 fossil_fatal("not a version: %s", g.argv[2]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149 }
 
150 if( zPivot ){
151 pid = name_to_typed_rid(zPivot, "ci");
152 if( pid==0 || !is_a_version(pid) ){
153 fossil_fatal("not a version: %s", zPivot);
154 }
@@ -347,11 +414,11 @@
347 "SELECT idm FROM fv WHERE idp=0 AND idv>0 AND idm>0"
348 );
349 while( db_step(&q)==SQLITE_ROW ){
350 int idm = db_column_int(&q, 0);
351 char *zName = db_text(0, "SELECT pathname FROM vfile WHERE id=%d", idm);
352 fossil_warning("WARNING - no common ancestor: %s\n", zName);
353 free(zName);
354 db_multi_exec("UPDATE fv SET idm=0 WHERE idm=%d", idm);
355 }
356 db_finalize(&q);
357
358
--- src/merge.c
+++ src/merge.c
@@ -57,19 +57,22 @@
57
58
59 /*
60 ** COMMAND: merge
61 **
62 ** Usage: %fossil merge ?OPTIONS? ?VERSION?
63 **
64 ** The argument VERSION is a version that should be merged into the
65 ** current checkout. All changes from VERSION back to the nearest
66 ** common ancestor are merged. Except, if either of the --cherrypick or
67 ** --backout options are used only the changes associated with the
68 ** single check-in VERSION are merged. The --backout option causes
69 ** the changes associated with VERSION to be removed from the current
70 ** checkout rather than added.
71 **
72 ** If the VERSION argument is omitted, then Fossil attempts to find
73 ** a recent fork on the current branch to merge.
74 **
75 ** Only file content is merged. The result continues to use the
76 ** file and directory names from the current checkout even if those
77 ** names might have been changed in the branch being merged in.
78 **
@@ -131,24 +134,88 @@
134 zBinGlob = find_option("binary",0,1);
135 nochangeFlag = find_option("nochange","n",0)!=0;
136 forceFlag = find_option("force","f",0)!=0;
137 zPivot = find_option("baseline",0,1);
138 capture_case_sensitive_option();
139 verify_all_options();
 
 
140 db_must_be_within_tree();
141 caseSensitive = filenames_are_case_sensitive();
142 if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
143 vid = db_lget_int("checkout", 0);
144 if( vid==0 ){
145 fossil_fatal("nothing is checked out");
146 }
147
148 /* Find mid, the artifactID of the version to be merged into the current
149 ** check-out */
150 if( g.argc==3 ){
151 /* Mid is specified as an argument on the command-line */
152 mid = name_to_typed_rid(g.argv[2], "ci");
153 if( mid==0 || !is_a_version(mid) ){
154 fossil_fatal("not a version: %s", g.argv[2]);
155 }
156 }else if( g.argc==2 ){
157 /* No version specified on the command-line so pick the most recent
158 ** leaf that is (1) not the version currently checked out and (2)
159 ** has not already been merged into the current checkout and (3)
160 ** the leaf is not closed and (4) the leaf is in the same branch
161 ** as the current checkout.
162 */
163 Stmt q;
164 if( pickFlag || backoutFlag ){
165 fossil_fatal("cannot use --cherrypick or --backout with a fork merge");
166 }
167 mid = db_int(0,
168 "SELECT leaf.rid"
169 " FROM leaf, event"
170 " WHERE leaf.rid=event.objid"
171 " AND leaf.rid!=%d" /* Constraint (1) */
172 " AND leaf.rid NOT IN (SELECT merge FROM vmerge)" /* Constraint (2) */
173 " AND NOT EXISTS(SELECT 1 FROM tagxref" /* Constraint (3) */
174 " WHERE rid=leaf.rid"
175 " AND tagid=%d"
176 " AND tagtype>0)"
177 " AND (SELECT value FROM tagxref" /* Constraint (4) */
178 " WHERE tagid=%d AND rid=%d"
179 " AND tagtype>0"
180 " ORDER BY mtime DESC LIMIT 1) = "
181 " (SELECT value FROM tagxref"
182 " WHERE tagid=%d AND rid=leaf.rid"
183 " AND tagtype>0"
184 " ORDER BY mtime DESC LIMIT 1)"
185 " ORDER BY event.mtime DESC LIMIT 1",
186 vid, TAG_CLOSED, TAG_BRANCH, vid, TAG_BRANCH
187 );
188 if( mid==0 ){
189 fossil_fatal("no unmerged forks of branch \"%s\"",
190 db_text(0, "SELECT value FROM tagxref"
191 " WHERE tagid=%d AND rid=%d"
192 " AND tagtype>0"
193 " ORDER BY mtime DESC LIMIT 1", TAG_BRANCH, vid)
194 );
195 }
196 db_prepare(&q,
197 "SELECT blob.uuid,"
198 " datetime(event.mtime,'localtime'),"
199 " coalesce(ecomment, comment),"
200 " coalesce(euser, user)"
201 " FROM event, blob"
202 " WHERE event.objid=%d AND blob.rid=%d",
203 mid, mid
204 );
205 if( db_step(&q)==SQLITE_ROW ){
206 char *zCom = mprintf("Merging fork [%S] at %s by %s: \"%s\"",
207 db_column_text(&q, 0), db_column_text(&q, 1),
208 db_column_text(&q, 3), db_column_text(&q, 2));
209 comment_print(zCom, 0, 79);
210 fossil_free(zCom);
211 }
212 db_finalize(&q);
213 }else{
214 usage("?OPTIONS? ?VERSION?");
215 }
216
217 if( zPivot ){
218 pid = name_to_typed_rid(zPivot, "ci");
219 if( pid==0 || !is_a_version(pid) ){
220 fossil_fatal("not a version: %s", zPivot);
221 }
@@ -347,11 +414,11 @@
414 "SELECT idm FROM fv WHERE idp=0 AND idv>0 AND idm>0"
415 );
416 while( db_step(&q)==SQLITE_ROW ){
417 int idm = db_column_int(&q, 0);
418 char *zName = db_text(0, "SELECT pathname FROM vfile WHERE id=%d", idm);
419 fossil_warning("WARNING - no common ancestor: %s", zName);
420 free(zName);
421 db_multi_exec("UPDATE fv SET idm=0 WHERE idm=%d", idm);
422 }
423 db_finalize(&q);
424
425

Keyboard Shortcuts

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