|
12 | 12 | #include "builtin.h"
|
13 | 13 | #include "remote.h"
|
14 | 14 | #include "parse-options.h"
|
| 15 | +#include "branch.h" |
15 | 16 |
|
16 | 17 | static const char * const builtin_branch_usage[] = {
|
17 | 18 | "git-branch [options] [-r | -a]",
|
@@ -356,141 +357,6 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str
|
356 | 357 | free_ref_list(&ref_list);
|
357 | 358 | }
|
358 | 359 |
|
359 |
| -struct tracking { |
360 |
| - struct refspec spec; |
361 |
| - char *src; |
362 |
| - const char *remote; |
363 |
| - int matches; |
364 |
| -}; |
365 |
| - |
366 |
| -static int find_tracked_branch(struct remote *remote, void *priv) |
367 |
| -{ |
368 |
| - struct tracking *tracking = priv; |
369 |
| - |
370 |
| - if (!remote_find_tracking(remote, &tracking->spec)) { |
371 |
| - if (++tracking->matches == 1) { |
372 |
| - tracking->src = tracking->spec.src; |
373 |
| - tracking->remote = remote->name; |
374 |
| - } else { |
375 |
| - free(tracking->spec.src); |
376 |
| - if (tracking->src) { |
377 |
| - free(tracking->src); |
378 |
| - tracking->src = NULL; |
379 |
| - } |
380 |
| - } |
381 |
| - tracking->spec.src = NULL; |
382 |
| - } |
383 |
| - |
384 |
| - return 0; |
385 |
| -} |
386 |
| - |
387 |
| - |
388 |
| -/* |
389 |
| - * This is called when new_ref is branched off of orig_ref, and tries |
390 |
| - * to infer the settings for branch.<new_ref>.{remote,merge} from the |
391 |
| - * config. |
392 |
| - */ |
393 |
| -static int setup_tracking(const char *new_ref, const char *orig_ref) |
394 |
| -{ |
395 |
| - char key[1024]; |
396 |
| - struct tracking tracking; |
397 |
| - |
398 |
| - if (strlen(new_ref) > 1024 - 7 - 7 - 1) |
399 |
| - return error("Tracking not set up: name too long: %s", |
400 |
| - new_ref); |
401 |
| - |
402 |
| - memset(&tracking, 0, sizeof(tracking)); |
403 |
| - tracking.spec.dst = (char *)orig_ref; |
404 |
| - if (for_each_remote(find_tracked_branch, &tracking) || |
405 |
| - !tracking.matches) |
406 |
| - return 1; |
407 |
| - |
408 |
| - if (tracking.matches > 1) |
409 |
| - return error("Not tracking: ambiguous information for ref %s", |
410 |
| - orig_ref); |
411 |
| - |
412 |
| - if (tracking.matches == 1) { |
413 |
| - sprintf(key, "branch.%s.remote", new_ref); |
414 |
| - git_config_set(key, tracking.remote ? tracking.remote : "."); |
415 |
| - sprintf(key, "branch.%s.merge", new_ref); |
416 |
| - git_config_set(key, tracking.src); |
417 |
| - free(tracking.src); |
418 |
| - printf("Branch %s set up to track remote branch %s.\n", |
419 |
| - new_ref, orig_ref); |
420 |
| - } |
421 |
| - |
422 |
| - return 0; |
423 |
| -} |
424 |
| - |
425 |
| -static void create_branch(const char *name, const char *start_name, |
426 |
| - int force, int reflog, int track) |
427 |
| -{ |
428 |
| - struct ref_lock *lock; |
429 |
| - struct commit *commit; |
430 |
| - unsigned char sha1[20]; |
431 |
| - char *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20]; |
432 |
| - int forcing = 0; |
433 |
| - |
434 |
| - snprintf(ref, sizeof ref, "refs/heads/%s", name); |
435 |
| - if (check_ref_format(ref)) |
436 |
| - die("'%s' is not a valid branch name.", name); |
437 |
| - |
438 |
| - if (resolve_ref(ref, sha1, 1, NULL)) { |
439 |
| - if (!force) |
440 |
| - die("A branch named '%s' already exists.", name); |
441 |
| - else if (!is_bare_repository() && !strcmp(head, name)) |
442 |
| - die("Cannot force update the current branch."); |
443 |
| - forcing = 1; |
444 |
| - } |
445 |
| - |
446 |
| - real_ref = NULL; |
447 |
| - if (get_sha1(start_name, sha1)) |
448 |
| - die("Not a valid object name: '%s'.", start_name); |
449 |
| - |
450 |
| - switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) { |
451 |
| - case 0: |
452 |
| - /* Not branching from any existing branch */ |
453 |
| - real_ref = NULL; |
454 |
| - break; |
455 |
| - case 1: |
456 |
| - /* Unique completion -- good */ |
457 |
| - break; |
458 |
| - default: |
459 |
| - die("Ambiguous object name: '%s'.", start_name); |
460 |
| - break; |
461 |
| - } |
462 |
| - |
463 |
| - if ((commit = lookup_commit_reference(sha1)) == NULL) |
464 |
| - die("Not a valid branch point: '%s'.", start_name); |
465 |
| - hashcpy(sha1, commit->object.sha1); |
466 |
| - |
467 |
| - lock = lock_any_ref_for_update(ref, NULL, 0); |
468 |
| - if (!lock) |
469 |
| - die("Failed to lock ref for update: %s.", strerror(errno)); |
470 |
| - |
471 |
| - if (reflog) |
472 |
| - log_all_ref_updates = 1; |
473 |
| - |
474 |
| - if (forcing) |
475 |
| - snprintf(msg, sizeof msg, "branch: Reset from %s", |
476 |
| - start_name); |
477 |
| - else |
478 |
| - snprintf(msg, sizeof msg, "branch: Created from %s", |
479 |
| - start_name); |
480 |
| - |
481 |
| - /* When branching off a remote branch, set up so that git-pull |
482 |
| - automatically merges from there. So far, this is only done for |
483 |
| - remotes registered via .git/config. */ |
484 |
| - if (real_ref && track) |
485 |
| - setup_tracking(name, real_ref); |
486 |
| - |
487 |
| - if (write_ref_sha1(lock, sha1, msg) < 0) |
488 |
| - die("Failed to write ref: %s.", strerror(errno)); |
489 |
| - |
490 |
| - if (real_ref) |
491 |
| - free(real_ref); |
492 |
| -} |
493 |
| - |
494 | 360 | static void rename_branch(const char *oldname, const char *newname, int force)
|
495 | 361 | {
|
496 | 362 | char oldref[PATH_MAX], newref[PATH_MAX], logmsg[PATH_MAX*2 + 100];
|
@@ -611,7 +477,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
|
611 | 477 | else if (rename && (argc == 2))
|
612 | 478 | rename_branch(argv[0], argv[1], rename > 1);
|
613 | 479 | else if (argc <= 2)
|
614 |
| - create_branch(argv[0], (argc == 2) ? argv[1] : head, |
| 480 | + create_branch(head, argv[0], (argc == 2) ? argv[1] : head, |
615 | 481 | force_create, reflog, track);
|
616 | 482 | else
|
617 | 483 | usage_with_options(builtin_branch_usage, options);
|
|
0 commit comments