218
}
219
220
/*
221
- * This is called when new_ref is branched off of orig_ref, and tries
222
- * to infer the settings for branch.<new_ref>.{remote,merge} from the
223
- * config.
221
+ * Used internally to set the branch.<new_ref>.{remote,merge} config
222
+ * settings so that branch 'new_ref' tracks 'orig_ref'. Unlike
223
+ * dwim_and_setup_tracking(), this does not do DWIM, i.e. "origin/main"
224
+ * will not be expanded to "refs/remotes/origin/main", so it is not safe
225
+ * for 'orig_ref' to be raw user input.
226
*/
227
static void setup_tracking(const char *new_ref, const char *orig_ref,
228
enum branch_track track, int quiet)
343
"will track its remote counterpart, you may want to use\n"
344
"\"git push -u\" to set the upstream config as you push.");
345
344
-void create_branch(struct repository *r,
345
- const char *name, const char *start_name,
346
- int force, int clobber_head_ok, int reflog,
347
- int quiet, enum branch_track track)
346
+/**
347
+ * DWIMs a user-provided ref to determine the starting point for a
348
+ * branch and validates it, where:
349
+ *
350
+ * - r is the repository to validate the branch for
351
+ *
352
+ * - start_name is the ref that we would like to test. This is
353
+ * expanded with DWIM and assigned to out_real_ref.
354
+ *
355
+ * - track is the tracking mode of the new branch. If tracking is
356
+ * explicitly requested, start_name must be a branch (because
357
+ * otherwise start_name cannot be tracked)
358
+ *
359
+ * - out_oid is an out parameter containing the object_id of start_name
360
+ *
361
+ * - out_real_ref is an out parameter containing the full, 'real' form
362
+ * of start_name e.g. refs/heads/main instead of main
363
+ *
364
+ */
365
+static void dwim_branch_start(struct repository *r, const char *start_name,
366
+ enum branch_track track, char **out_real_ref,
367
+ struct object_id *out_oid)
368
{
369
struct commit *commit;
370
struct object_id oid;
371
char *real_ref;
352
- struct strbuf ref = STRBUF_INIT;
353
- int forcing = 0;
354
- int dont_change_ref = 0;
372
int explicit_tracking = 0;
373
374
if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
375
explicit_tracking = 1;
376
360
- if ((track == BRANCH_TRACK_OVERRIDE || clobber_head_ok)
361
- ? validate_branchname(name, &ref)
362
- : validate_new_branchname(name, &ref, force)) {
363
- if (!force)
364
- dont_change_ref = 1;
365
- else
366
- forcing = 1;
367
- }
368
-
377
real_ref = NULL;
378
if (get_oid_mb(start_name, &oid)) {
379
if (explicit_tracking) {
410
411
if ((commit = lookup_commit_reference(r, &oid)) == NULL)
412
die(_("Not a valid branch point: '%s'."), start_name);
405
- oidcpy(&oid, &commit->object.oid);
413
+ if (out_real_ref) {
414
+ *out_real_ref = real_ref;
415
+ real_ref = NULL;
416
+ }
417
+ if (out_oid)
418
+ oidcpy(out_oid, &commit->object.oid);
419
+
420
+ FREE_AND_NULL(real_ref);
421
+}
422
+
423
+void create_branch(struct repository *r,
424
+ const char *name, const char *start_name,
425
+ int force, int clobber_head_ok, int reflog,
426
+ int quiet, enum branch_track track)
427
+{
428
+ struct object_id oid;
429
+ char *real_ref;
430
+ struct strbuf ref = STRBUF_INIT;
431
+ int forcing = 0;
432
+ int dont_change_ref = 0;
433
+
434
+ if ((track == BRANCH_TRACK_OVERRIDE || clobber_head_ok)
435
+ ? validate_branchname(name, &ref)
436
+ : validate_new_branchname(name, &ref, force)) {
437
+ if (!force)
438
+ dont_change_ref = 1;
439
+ else
440
+ forcing = 1;
441
+ }
442
+
443
+ dwim_branch_start(r, start_name, track, &real_ref, &oid);
444
445
if (reflog)
446
log_all_ref_updates = LOG_REFS_NORMAL;
474
free(real_ref);
475
}
476
477
+void dwim_and_setup_tracking(struct repository *r, const char *new_ref,
478
+ const char *orig_ref, enum branch_track track,
479
+ int quiet)
480
+{
481
+ char *real_orig_ref;
482
+ dwim_branch_start(r, orig_ref, track, &real_orig_ref, NULL);
483
+ setup_tracking(new_ref, real_orig_ref, track, quiet);
484
+}
485
+
486
void remove_merge_branch_state(struct repository *r)
487
{
488
unlink(git_path_merge_head(r));