Coverage Report

Created: 2024-09-08 06:23

/src/git/builtin/worktree.c
Line
Count
Source (jump to first uncovered line)
1
#include "builtin.h"
2
#include "abspath.h"
3
#include "advice.h"
4
#include "checkout.h"
5
#include "config.h"
6
#include "copy.h"
7
#include "dir.h"
8
#include "environment.h"
9
#include "gettext.h"
10
#include "hex.h"
11
#include "object-file.h"
12
#include "object-name.h"
13
#include "parse-options.h"
14
#include "path.h"
15
#include "strvec.h"
16
#include "branch.h"
17
#include "read-cache-ll.h"
18
#include "refs.h"
19
#include "remote.h"
20
#include "repository.h"
21
#include "run-command.h"
22
#include "hook.h"
23
#include "sigchain.h"
24
#include "submodule.h"
25
#include "utf8.h"
26
#include "worktree.h"
27
#include "quote.h"
28
29
#define BUILTIN_WORKTREE_ADD_USAGE \
30
  N_("git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]\n" \
31
     "                 [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]")
32
33
#define BUILTIN_WORKTREE_LIST_USAGE \
34
  N_("git worktree list [-v | --porcelain [-z]]")
35
#define BUILTIN_WORKTREE_LOCK_USAGE \
36
  N_("git worktree lock [--reason <string>] <worktree>")
37
#define BUILTIN_WORKTREE_MOVE_USAGE \
38
  N_("git worktree move <worktree> <new-path>")
39
#define BUILTIN_WORKTREE_PRUNE_USAGE \
40
  N_("git worktree prune [-n] [-v] [--expire <expire>]")
41
#define BUILTIN_WORKTREE_REMOVE_USAGE \
42
  N_("git worktree remove [-f] <worktree>")
43
#define BUILTIN_WORKTREE_REPAIR_USAGE \
44
  N_("git worktree repair [<path>...]")
45
#define BUILTIN_WORKTREE_UNLOCK_USAGE \
46
  N_("git worktree unlock <worktree>")
47
48
#define WORKTREE_ADD_DWIM_ORPHAN_INFER_TEXT \
49
0
  _("No possible source branch, inferring '--orphan'")
50
51
#define WORKTREE_ADD_ORPHAN_WITH_DASH_B_HINT_TEXT \
52
0
  _("If you meant to create a worktree containing a new unborn branch\n" \
53
0
  "(branch with no commits) for this repository, you can do so\n" \
54
0
  "using the --orphan flag:\n" \
55
0
  "\n" \
56
0
  "    git worktree add --orphan -b %s %s\n")
57
58
#define WORKTREE_ADD_ORPHAN_NO_DASH_B_HINT_TEXT \
59
0
  _("If you meant to create a worktree containing a new unborn branch\n" \
60
0
  "(branch with no commits) for this repository, you can do so\n" \
61
0
  "using the --orphan flag:\n" \
62
0
  "\n" \
63
0
  "    git worktree add --orphan %s\n")
64
65
static const char * const git_worktree_usage[] = {
66
  BUILTIN_WORKTREE_ADD_USAGE,
67
  BUILTIN_WORKTREE_LIST_USAGE,
68
  BUILTIN_WORKTREE_LOCK_USAGE,
69
  BUILTIN_WORKTREE_MOVE_USAGE,
70
  BUILTIN_WORKTREE_PRUNE_USAGE,
71
  BUILTIN_WORKTREE_REMOVE_USAGE,
72
  BUILTIN_WORKTREE_REPAIR_USAGE,
73
  BUILTIN_WORKTREE_UNLOCK_USAGE,
74
  NULL
75
};
76
77
static const char * const git_worktree_add_usage[] = {
78
  BUILTIN_WORKTREE_ADD_USAGE,
79
  NULL,
80
};
81
82
static const char * const git_worktree_list_usage[] = {
83
  BUILTIN_WORKTREE_LIST_USAGE,
84
  NULL
85
};
86
87
static const char * const git_worktree_lock_usage[] = {
88
  BUILTIN_WORKTREE_LOCK_USAGE,
89
  NULL
90
};
91
92
static const char * const git_worktree_move_usage[] = {
93
  BUILTIN_WORKTREE_MOVE_USAGE,
94
  NULL
95
};
96
97
static const char * const git_worktree_prune_usage[] = {
98
  BUILTIN_WORKTREE_PRUNE_USAGE,
99
  NULL
100
};
101
102
static const char * const git_worktree_remove_usage[] = {
103
  BUILTIN_WORKTREE_REMOVE_USAGE,
104
  NULL
105
};
106
107
static const char * const git_worktree_repair_usage[] = {
108
  BUILTIN_WORKTREE_REPAIR_USAGE,
109
  NULL
110
};
111
112
static const char * const git_worktree_unlock_usage[] = {
113
  BUILTIN_WORKTREE_UNLOCK_USAGE,
114
  NULL
115
};
116
117
struct add_opts {
118
  int force;
119
  int detach;
120
  int quiet;
121
  int checkout;
122
  int orphan;
123
  const char *keep_locked;
124
};
125
126
static int show_only;
127
static int verbose;
128
static int guess_remote;
129
static timestamp_t expire;
130
131
static int git_worktree_config(const char *var, const char *value,
132
             const struct config_context *ctx, void *cb)
133
0
{
134
0
  if (!strcmp(var, "worktree.guessremote")) {
135
0
    guess_remote = git_config_bool(var, value);
136
0
    return 0;
137
0
  }
138
139
0
  return git_default_config(var, value, ctx, cb);
140
0
}
141
142
static int delete_git_dir(const char *id)
143
0
{
144
0
  struct strbuf sb = STRBUF_INIT;
145
0
  int ret;
146
147
0
  strbuf_addstr(&sb, git_common_path("worktrees/%s", id));
148
0
  ret = remove_dir_recursively(&sb, 0);
149
0
  if (ret < 0 && errno == ENOTDIR)
150
0
    ret = unlink(sb.buf);
151
0
  if (ret)
152
0
    error_errno(_("failed to delete '%s'"), sb.buf);
153
0
  strbuf_release(&sb);
154
0
  return ret;
155
0
}
156
157
static void delete_worktrees_dir_if_empty(void)
158
0
{
159
0
  rmdir(git_path("worktrees")); /* ignore failed removal */
160
0
}
161
162
static void prune_worktree(const char *id, const char *reason)
163
0
{
164
0
  if (show_only || verbose)
165
0
    fprintf_ln(stderr, _("Removing %s/%s: %s"), "worktrees", id, reason);
166
0
  if (!show_only)
167
0
    delete_git_dir(id);
168
0
}
169
170
static int prune_cmp(const void *a, const void *b)
171
0
{
172
0
  const struct string_list_item *x = a;
173
0
  const struct string_list_item *y = b;
174
0
  int c;
175
176
0
  if ((c = fspathcmp(x->string, y->string)))
177
0
      return c;
178
  /*
179
   * paths same; prune_dupes() removes all but the first worktree entry
180
   * having the same path, so sort main worktree ('util' is NULL) above
181
   * linked worktrees ('util' not NULL) since main worktree can't be
182
   * removed
183
   */
184
0
  if (!x->util)
185
0
    return -1;
186
0
  if (!y->util)
187
0
    return 1;
188
  /* paths same; sort by .git/worktrees/<id> */
189
0
  return strcmp(x->util, y->util);
190
0
}
191
192
static void prune_dups(struct string_list *l)
193
0
{
194
0
  int i;
195
196
0
  QSORT(l->items, l->nr, prune_cmp);
197
0
  for (i = 1; i < l->nr; i++) {
198
0
    if (!fspathcmp(l->items[i].string, l->items[i - 1].string))
199
0
      prune_worktree(l->items[i].util, "duplicate entry");
200
0
  }
201
0
}
202
203
static void prune_worktrees(void)
204
0
{
205
0
  struct strbuf reason = STRBUF_INIT;
206
0
  struct strbuf main_path = STRBUF_INIT;
207
0
  struct string_list kept = STRING_LIST_INIT_DUP;
208
0
  DIR *dir = opendir(git_path("worktrees"));
209
0
  struct dirent *d;
210
0
  if (!dir)
211
0
    return;
212
0
  while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) {
213
0
    char *path;
214
0
    strbuf_reset(&reason);
215
0
    if (should_prune_worktree(d->d_name, &reason, &path, expire))
216
0
      prune_worktree(d->d_name, reason.buf);
217
0
    else if (path)
218
0
      string_list_append_nodup(&kept, path)->util = xstrdup(d->d_name);
219
0
  }
220
0
  closedir(dir);
221
222
0
  strbuf_add_absolute_path(&main_path, get_git_common_dir());
223
  /* massage main worktree absolute path to match 'gitdir' content */
224
0
  strbuf_strip_suffix(&main_path, "/.");
225
0
  string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));
226
0
  prune_dups(&kept);
227
0
  string_list_clear(&kept, 1);
228
229
0
  if (!show_only)
230
0
    delete_worktrees_dir_if_empty();
231
0
  strbuf_release(&reason);
232
0
}
233
234
static int prune(int ac, const char **av, const char *prefix)
235
0
{
236
0
  struct option options[] = {
237
0
    OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
238
0
    OPT__VERBOSE(&verbose, N_("report pruned working trees")),
239
0
    OPT_EXPIRY_DATE(0, "expire", &expire,
240
0
        N_("expire working trees older than <time>")),
241
0
    OPT_END()
242
0
  };
243
244
0
  expire = TIME_MAX;
245
0
  ac = parse_options(ac, av, prefix, options, git_worktree_prune_usage,
246
0
         0);
247
0
  if (ac)
248
0
    usage_with_options(git_worktree_prune_usage, options);
249
0
  prune_worktrees();
250
0
  return 0;
251
0
}
252
253
static char *junk_work_tree;
254
static char *junk_git_dir;
255
static int is_junk;
256
static pid_t junk_pid;
257
258
static void remove_junk(void)
259
0
{
260
0
  struct strbuf sb = STRBUF_INIT;
261
0
  if (!is_junk || getpid() != junk_pid)
262
0
    return;
263
0
  if (junk_git_dir) {
264
0
    strbuf_addstr(&sb, junk_git_dir);
265
0
    remove_dir_recursively(&sb, 0);
266
0
    strbuf_reset(&sb);
267
0
  }
268
0
  if (junk_work_tree) {
269
0
    strbuf_addstr(&sb, junk_work_tree);
270
0
    remove_dir_recursively(&sb, 0);
271
0
  }
272
0
  strbuf_release(&sb);
273
0
}
274
275
static void remove_junk_on_signal(int signo)
276
0
{
277
0
  remove_junk();
278
0
  sigchain_pop(signo);
279
0
  raise(signo);
280
0
}
281
282
static const char *worktree_basename(const char *path, int *olen)
283
0
{
284
0
  const char *name;
285
0
  int len;
286
287
0
  len = strlen(path);
288
0
  while (len && is_dir_sep(path[len - 1]))
289
0
    len--;
290
291
0
  for (name = path + len - 1; name > path; name--)
292
0
    if (is_dir_sep(*name)) {
293
0
      name++;
294
0
      break;
295
0
    }
296
297
0
  *olen = len;
298
0
  return name;
299
0
}
300
301
/* check that path is viable location for worktree */
302
static void check_candidate_path(const char *path,
303
         int force,
304
         struct worktree **worktrees,
305
         const char *cmd)
306
0
{
307
0
  struct worktree *wt;
308
0
  int locked;
309
310
0
  if (file_exists(path) && !is_empty_dir(path))
311
0
    die(_("'%s' already exists"), path);
312
313
0
  wt = find_worktree_by_path(worktrees, path);
314
0
  if (!wt)
315
0
    return;
316
317
0
  locked = !!worktree_lock_reason(wt);
318
0
  if ((!locked && force) || (locked && force > 1)) {
319
0
    if (delete_git_dir(wt->id))
320
0
        die(_("unusable worktree destination '%s'"), path);
321
0
    return;
322
0
  }
323
324
0
  if (locked)
325
0
    die(_("'%s' is a missing but locked worktree;\nuse '%s -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear"), path, cmd);
326
0
  else
327
0
    die(_("'%s' is a missing but already registered worktree;\nuse '%s -f' to override, or 'prune' or 'remove' to clear"), path, cmd);
328
0
}
329
330
static void copy_sparse_checkout(const char *worktree_git_dir)
331
0
{
332
0
  char *from_file = git_pathdup("info/sparse-checkout");
333
0
  char *to_file = xstrfmt("%s/info/sparse-checkout", worktree_git_dir);
334
335
0
  if (file_exists(from_file)) {
336
0
    if (safe_create_leading_directories(to_file) ||
337
0
      copy_file(to_file, from_file, 0666))
338
0
      error(_("failed to copy '%s' to '%s'; sparse-checkout may not work correctly"),
339
0
        from_file, to_file);
340
0
  }
341
342
0
  free(from_file);
343
0
  free(to_file);
344
0
}
345
346
static void copy_filtered_worktree_config(const char *worktree_git_dir)
347
0
{
348
0
  char *from_file = git_pathdup("config.worktree");
349
0
  char *to_file = xstrfmt("%s/config.worktree", worktree_git_dir);
350
351
0
  if (file_exists(from_file)) {
352
0
    struct config_set cs = { { 0 } };
353
0
    int bare;
354
355
0
    if (safe_create_leading_directories(to_file) ||
356
0
      copy_file(to_file, from_file, 0666)) {
357
0
      error(_("failed to copy worktree config from '%s' to '%s'"),
358
0
        from_file, to_file);
359
0
      goto worktree_copy_cleanup;
360
0
    }
361
362
0
    git_configset_init(&cs);
363
0
    git_configset_add_file(&cs, from_file);
364
365
0
    if (!git_configset_get_bool(&cs, "core.bare", &bare) &&
366
0
      bare &&
367
0
      git_config_set_multivar_in_file_gently(
368
0
        to_file, "core.bare", NULL, "true", NULL, 0))
369
0
      error(_("failed to unset '%s' in '%s'"),
370
0
        "core.bare", to_file);
371
0
    if (!git_configset_get(&cs, "core.worktree") &&
372
0
      git_config_set_in_file_gently(to_file,
373
0
              "core.worktree", NULL, NULL))
374
0
      error(_("failed to unset '%s' in '%s'"),
375
0
        "core.worktree", to_file);
376
377
0
    git_configset_clear(&cs);
378
0
  }
379
380
0
worktree_copy_cleanup:
381
0
  free(from_file);
382
0
  free(to_file);
383
0
}
384
385
static int checkout_worktree(const struct add_opts *opts,
386
           struct strvec *child_env)
387
0
{
388
0
  struct child_process cp = CHILD_PROCESS_INIT;
389
0
  cp.git_cmd = 1;
390
0
  strvec_pushl(&cp.args, "reset", "--hard", "--no-recurse-submodules", NULL);
391
0
  if (opts->quiet)
392
0
    strvec_push(&cp.args, "--quiet");
393
0
  strvec_pushv(&cp.env, child_env->v);
394
0
  return run_command(&cp);
395
0
}
396
397
static int make_worktree_orphan(const char * ref, const struct add_opts *opts,
398
        struct strvec *child_env)
399
0
{
400
0
  struct strbuf symref = STRBUF_INIT;
401
0
  struct child_process cp = CHILD_PROCESS_INIT;
402
403
0
  validate_new_branchname(ref, &symref, 0);
404
0
  strvec_pushl(&cp.args, "symbolic-ref", "HEAD", symref.buf, NULL);
405
0
  if (opts->quiet)
406
0
    strvec_push(&cp.args, "--quiet");
407
0
  strvec_pushv(&cp.env, child_env->v);
408
0
  strbuf_release(&symref);
409
0
  cp.git_cmd = 1;
410
0
  return run_command(&cp);
411
0
}
412
413
static int add_worktree(const char *path, const char *refname,
414
      const struct add_opts *opts)
415
0
{
416
0
  struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;
417
0
  struct strbuf sb = STRBUF_INIT, realpath = STRBUF_INIT;
418
0
  const char *name;
419
0
  struct strvec child_env = STRVEC_INIT;
420
0
  unsigned int counter = 0;
421
0
  int len, ret;
422
0
  struct strbuf symref = STRBUF_INIT;
423
0
  struct commit *commit = NULL;
424
0
  int is_branch = 0;
425
0
  struct strbuf sb_name = STRBUF_INIT;
426
0
  struct worktree **worktrees, *wt = NULL;
427
0
  struct ref_store *wt_refs;
428
429
0
  worktrees = get_worktrees();
430
0
  check_candidate_path(path, opts->force, worktrees, "add");
431
0
  free_worktrees(worktrees);
432
0
  worktrees = NULL;
433
434
  /* is 'refname' a branch or commit? */
435
0
  if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) &&
436
0
      refs_ref_exists(get_main_ref_store(the_repository), symref.buf)) {
437
0
    is_branch = 1;
438
0
    if (!opts->force)
439
0
      die_if_checked_out(symref.buf, 0);
440
0
  }
441
0
  commit = lookup_commit_reference_by_name(refname);
442
0
  if (!commit && !opts->orphan)
443
0
    die(_("invalid reference: %s"), refname);
444
445
0
  name = worktree_basename(path, &len);
446
0
  strbuf_add(&sb, name, path + len - name);
447
0
  sanitize_refname_component(sb.buf, &sb_name);
448
0
  if (!sb_name.len)
449
0
    BUG("How come '%s' becomes empty after sanitization?", sb.buf);
450
0
  strbuf_reset(&sb);
451
0
  name = sb_name.buf;
452
0
  git_path_buf(&sb_repo, "worktrees/%s", name);
453
0
  len = sb_repo.len;
454
0
  if (safe_create_leading_directories_const(sb_repo.buf))
455
0
    die_errno(_("could not create leading directories of '%s'"),
456
0
        sb_repo.buf);
457
458
0
  while (mkdir(sb_repo.buf, 0777)) {
459
0
    counter++;
460
0
    if ((errno != EEXIST) || !counter /* overflow */)
461
0
      die_errno(_("could not create directory of '%s'"),
462
0
          sb_repo.buf);
463
0
    strbuf_setlen(&sb_repo, len);
464
0
    strbuf_addf(&sb_repo, "%d", counter);
465
0
  }
466
0
  name = strrchr(sb_repo.buf, '/') + 1;
467
468
0
  junk_pid = getpid();
469
0
  atexit(remove_junk);
470
0
  sigchain_push_common(remove_junk_on_signal);
471
472
0
  junk_git_dir = xstrdup(sb_repo.buf);
473
0
  is_junk = 1;
474
475
  /*
476
   * lock the incomplete repo so prune won't delete it, unlock
477
   * after the preparation is over.
478
   */
479
0
  strbuf_addf(&sb, "%s/locked", sb_repo.buf);
480
0
  if (opts->keep_locked)
481
0
    write_file(sb.buf, "%s", opts->keep_locked);
482
0
  else
483
0
    write_file(sb.buf, _("initializing"));
484
485
0
  strbuf_addf(&sb_git, "%s/.git", path);
486
0
  if (safe_create_leading_directories_const(sb_git.buf))
487
0
    die_errno(_("could not create leading directories of '%s'"),
488
0
        sb_git.buf);
489
0
  junk_work_tree = xstrdup(path);
490
491
0
  strbuf_reset(&sb);
492
0
  strbuf_addf(&sb, "%s/gitdir", sb_repo.buf);
493
0
  strbuf_realpath(&realpath, sb_git.buf, 1);
494
0
  write_file(sb.buf, "%s", realpath.buf);
495
0
  strbuf_realpath(&realpath, get_git_common_dir(), 1);
496
0
  write_file(sb_git.buf, "gitdir: %s/worktrees/%s",
497
0
       realpath.buf, name);
498
0
  strbuf_reset(&sb);
499
0
  strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
500
0
  write_file(sb.buf, "../..");
501
502
  /*
503
   * Set up the ref store of the worktree and create the HEAD reference.
504
   */
505
0
  wt = get_linked_worktree(name, 1);
506
0
  if (!wt) {
507
0
    ret = error(_("could not find created worktree '%s'"), name);
508
0
    goto done;
509
0
  }
510
0
  wt_refs = get_worktree_ref_store(wt);
511
512
0
  ret = ref_store_create_on_disk(wt_refs, REF_STORE_CREATE_ON_DISK_IS_WORKTREE, &sb);
513
0
  if (ret)
514
0
    goto done;
515
516
0
  if (!is_branch && commit)
517
0
    ret = refs_update_ref(wt_refs, NULL, "HEAD", &commit->object.oid,
518
0
              NULL, 0, UPDATE_REFS_MSG_ON_ERR);
519
0
  else
520
0
    ret = refs_update_symref(wt_refs, "HEAD", symref.buf, NULL);
521
0
  if (ret)
522
0
    goto done;
523
524
  /*
525
   * If the current worktree has sparse-checkout enabled, then copy
526
   * the sparse-checkout patterns from the current worktree.
527
   */
528
0
  if (core_apply_sparse_checkout)
529
0
    copy_sparse_checkout(sb_repo.buf);
530
531
  /*
532
   * If we are using worktree config, then copy all current config
533
   * values from the current worktree into the new one, that way the
534
   * new worktree behaves the same as this one.
535
   */
536
0
  if (the_repository->repository_format_worktree_config)
537
0
    copy_filtered_worktree_config(sb_repo.buf);
538
539
0
  strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);
540
0
  strvec_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
541
542
0
  if (opts->orphan &&
543
0
      (ret = make_worktree_orphan(refname, opts, &child_env)))
544
0
    goto done;
545
546
0
  if (opts->checkout &&
547
0
      (ret = checkout_worktree(opts, &child_env)))
548
0
    goto done;
549
550
0
  is_junk = 0;
551
0
  FREE_AND_NULL(junk_work_tree);
552
0
  FREE_AND_NULL(junk_git_dir);
553
554
0
done:
555
0
  if (ret || !opts->keep_locked) {
556
0
    strbuf_reset(&sb);
557
0
    strbuf_addf(&sb, "%s/locked", sb_repo.buf);
558
0
    unlink_or_warn(sb.buf);
559
0
  }
560
561
  /*
562
   * Hook failure does not warrant worktree deletion, so run hook after
563
   * is_junk is cleared, but do return appropriate code when hook fails.
564
   */
565
0
  if (!ret && opts->checkout && !opts->orphan) {
566
0
    struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
567
568
0
    strvec_pushl(&opt.env, "GIT_DIR", "GIT_WORK_TREE", NULL);
569
0
    strvec_pushl(&opt.args,
570
0
           oid_to_hex(null_oid()),
571
0
           oid_to_hex(&commit->object.oid),
572
0
           "1",
573
0
           NULL);
574
0
    opt.dir = path;
575
576
0
    ret = run_hooks_opt(the_repository, "post-checkout", &opt);
577
0
  }
578
579
0
  strvec_clear(&child_env);
580
0
  strbuf_release(&sb);
581
0
  strbuf_release(&symref);
582
0
  strbuf_release(&sb_repo);
583
0
  strbuf_release(&sb_git);
584
0
  strbuf_release(&sb_name);
585
0
  strbuf_release(&realpath);
586
0
  free_worktree(wt);
587
0
  return ret;
588
0
}
589
590
static void print_preparing_worktree_line(int detach,
591
            const char *branch,
592
            const char *new_branch,
593
            int force_new_branch)
594
0
{
595
0
  if (force_new_branch) {
596
0
    struct commit *commit = lookup_commit_reference_by_name(new_branch);
597
0
    if (!commit)
598
0
      fprintf_ln(stderr, _("Preparing worktree (new branch '%s')"), new_branch);
599
0
    else
600
0
      fprintf_ln(stderr, _("Preparing worktree (resetting branch '%s'; was at %s)"),
601
0
          new_branch,
602
0
          repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV));
603
0
  } else if (new_branch) {
604
0
    fprintf_ln(stderr, _("Preparing worktree (new branch '%s')"), new_branch);
605
0
  } else {
606
0
    struct strbuf s = STRBUF_INIT;
607
0
    if (!detach && !strbuf_check_branch_ref(&s, branch) &&
608
0
        refs_ref_exists(get_main_ref_store(the_repository), s.buf))
609
0
      fprintf_ln(stderr, _("Preparing worktree (checking out '%s')"),
610
0
          branch);
611
0
    else {
612
0
      struct commit *commit = lookup_commit_reference_by_name(branch);
613
0
      if (!commit)
614
0
        BUG(_("unreachable: invalid reference: %s"), branch);
615
0
      fprintf_ln(stderr, _("Preparing worktree (detached HEAD %s)"),
616
0
          repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV));
617
0
    }
618
0
    strbuf_release(&s);
619
0
  }
620
0
}
621
622
/**
623
 * Callback to short circuit iteration over refs on the first reference
624
 * corresponding to a valid oid.
625
 *
626
 * Returns 0 on failure and non-zero on success.
627
 */
628
static int first_valid_ref(const char *refname UNUSED,
629
         const char *referent UNUSED,
630
         const struct object_id *oid UNUSED,
631
         int flags UNUSED,
632
         void *cb_data UNUSED)
633
0
{
634
0
  return 1;
635
0
}
636
637
/**
638
 * Verifies HEAD and determines whether there exist any valid local references.
639
 *
640
 * - Checks whether HEAD points to a valid reference.
641
 *
642
 * - Checks whether any valid local branches exist.
643
 *
644
 * - Emits a warning if there exist any valid branches but HEAD does not point
645
 *   to a valid reference.
646
 *
647
 * Returns 1 if any of the previous checks are true, otherwise returns 0.
648
 */
649
static int can_use_local_refs(const struct add_opts *opts)
650
0
{
651
0
  if (refs_head_ref(get_main_ref_store(the_repository), first_valid_ref, NULL)) {
652
0
    return 1;
653
0
  } else if (refs_for_each_branch_ref(get_main_ref_store(the_repository), first_valid_ref, NULL)) {
654
0
    if (!opts->quiet) {
655
0
      struct strbuf path = STRBUF_INIT;
656
0
      struct strbuf contents = STRBUF_INIT;
657
658
0
      strbuf_add_real_path(&path, get_worktree_git_dir(NULL));
659
0
      strbuf_addstr(&path, "/HEAD");
660
0
      strbuf_read_file(&contents, path.buf, 64);
661
0
      strbuf_stripspace(&contents, NULL);
662
0
      strbuf_strip_suffix(&contents, "\n");
663
664
0
      warning(_("HEAD points to an invalid (or orphaned) reference.\n"
665
0
          "HEAD path: '%s'\n"
666
0
          "HEAD contents: '%s'"),
667
0
          path.buf, contents.buf);
668
0
      strbuf_release(&path);
669
0
      strbuf_release(&contents);
670
0
    }
671
0
    return 1;
672
0
  }
673
0
  return 0;
674
0
}
675
676
/**
677
 * Reports whether the necessary flags were set and whether the repository has
678
 * remote references to attempt DWIM tracking of upstream branches.
679
 *
680
 * 1. Checks that `--guess-remote` was used or `worktree.guessRemote = true`.
681
 *
682
 * 2. Checks whether any valid remote branches exist.
683
 *
684
 * 3. Checks that there exists at least one remote and emits a warning/error
685
 *    if both checks 1. and 2. are false (can be bypassed with `--force`).
686
 *
687
 * Returns 1 if checks 1. and 2. are true, otherwise 0.
688
 */
689
static int can_use_remote_refs(const struct add_opts *opts)
690
0
{
691
0
  if (!guess_remote) {
692
0
    return 0;
693
0
  } else if (refs_for_each_remote_ref(get_main_ref_store(the_repository), first_valid_ref, NULL)) {
694
0
    return 1;
695
0
  } else if (!opts->force && remote_get(NULL)) {
696
0
    die(_("No local or remote refs exist despite at least one remote\n"
697
0
          "present, stopping; use 'add -f' to override or fetch a remote first"));
698
0
  }
699
0
  return 0;
700
0
}
701
702
/**
703
 * Determines whether `--orphan` should be inferred in the evaluation of
704
 * `worktree add path/` or `worktree add -b branch path/` and emits an error
705
 * if the supplied arguments would produce an illegal combination when the
706
 * `--orphan` flag is included.
707
 *
708
 * `opts` and `opt_track` contain the other options & flags supplied to the
709
 * command.
710
 *
711
 * remote determines whether to check `can_use_remote_refs()` or not. This
712
 * is primarily to differentiate between the basic `add` DWIM and `add -b`.
713
 *
714
 * Returns 1 when inferring `--orphan`, 0 otherwise, and emits an error when
715
 * `--orphan` is inferred but doing so produces an illegal combination of
716
 * options and flags. Additionally produces an error when remote refs are
717
 * checked and the repo is in a state that looks like the user added a remote
718
 * but forgot to fetch (and did not override the warning with -f).
719
 */
720
static int dwim_orphan(const struct add_opts *opts, int opt_track, int remote)
721
0
{
722
0
  if (can_use_local_refs(opts)) {
723
0
    return 0;
724
0
  } else if (remote && can_use_remote_refs(opts)) {
725
0
    return 0;
726
0
  } else if (!opts->quiet) {
727
0
    fprintf_ln(stderr, WORKTREE_ADD_DWIM_ORPHAN_INFER_TEXT);
728
0
  }
729
730
0
  if (opt_track) {
731
0
    die(_("options '%s' and '%s' cannot be used together"),
732
0
        "--orphan", "--track");
733
0
  } else if (!opts->checkout) {
734
0
    die(_("options '%s' and '%s' cannot be used together"),
735
0
        "--orphan", "--no-checkout");
736
0
  }
737
0
  return 1;
738
0
}
739
740
static char *dwim_branch(const char *path, char **new_branch)
741
0
{
742
0
  int n;
743
0
  int branch_exists;
744
0
  const char *s = worktree_basename(path, &n);
745
0
  char *branchname = xstrndup(s, n);
746
0
  struct strbuf ref = STRBUF_INIT;
747
748
0
  branch_exists = !strbuf_check_branch_ref(&ref, branchname) &&
749
0
      refs_ref_exists(get_main_ref_store(the_repository),
750
0
          ref.buf);
751
0
  strbuf_release(&ref);
752
0
  if (branch_exists)
753
0
    return branchname;
754
755
0
  *new_branch = branchname;
756
0
  if (guess_remote) {
757
0
    struct object_id oid;
758
0
    char *remote = unique_tracking_name(*new_branch, &oid, NULL);
759
0
    return remote;
760
0
  }
761
0
  return NULL;
762
0
}
763
764
static int add(int ac, const char **av, const char *prefix)
765
0
{
766
0
  struct add_opts opts;
767
0
  const char *new_branch_force = NULL;
768
0
  char *path;
769
0
  const char *branch;
770
0
  char *branch_to_free = NULL;
771
0
  char *new_branch_to_free = NULL;
772
0
  const char *new_branch = NULL;
773
0
  char *opt_track = NULL;
774
0
  const char *lock_reason = NULL;
775
0
  int keep_locked = 0;
776
0
  int used_new_branch_options;
777
0
  struct option options[] = {
778
0
    OPT__FORCE(&opts.force,
779
0
         N_("checkout <branch> even if already checked out in other worktree"),
780
0
         PARSE_OPT_NOCOMPLETE),
781
0
    OPT_STRING('b', NULL, &new_branch, N_("branch"),
782
0
         N_("create a new branch")),
783
0
    OPT_STRING('B', NULL, &new_branch_force, N_("branch"),
784
0
         N_("create or reset a branch")),
785
0
    OPT_BOOL(0, "orphan", &opts.orphan, N_("create unborn branch")),
786
0
    OPT_BOOL('d', "detach", &opts.detach, N_("detach HEAD at named commit")),
787
0
    OPT_BOOL(0, "checkout", &opts.checkout, N_("populate the new working tree")),
788
0
    OPT_BOOL(0, "lock", &keep_locked, N_("keep the new working tree locked")),
789
0
    OPT_STRING(0, "reason", &lock_reason, N_("string"),
790
0
         N_("reason for locking")),
791
0
    OPT__QUIET(&opts.quiet, N_("suppress progress reporting")),
792
0
    OPT_PASSTHRU(0, "track", &opt_track, NULL,
793
0
           N_("set up tracking mode (see git-branch(1))"),
794
0
           PARSE_OPT_NOARG | PARSE_OPT_OPTARG),
795
0
    OPT_BOOL(0, "guess-remote", &guess_remote,
796
0
       N_("try to match the new branch name with a remote-tracking branch")),
797
0
    OPT_END()
798
0
  };
799
0
  int ret;
800
801
0
  memset(&opts, 0, sizeof(opts));
802
0
  opts.checkout = 1;
803
0
  ac = parse_options(ac, av, prefix, options, git_worktree_add_usage, 0);
804
0
  if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
805
0
    die(_("options '%s', '%s', and '%s' cannot be used together"), "-b", "-B", "--detach");
806
0
  if (opts.detach && opts.orphan)
807
0
    die(_("options '%s' and '%s' cannot be used together"),
808
0
        "--orphan", "--detach");
809
0
  if (opts.orphan && opt_track)
810
0
    die(_("options '%s' and '%s' cannot be used together"),
811
0
        "--orphan", "--track");
812
0
  if (opts.orphan && !opts.checkout)
813
0
    die(_("options '%s' and '%s' cannot be used together"),
814
0
        "--orphan", "--no-checkout");
815
0
  if (opts.orphan && ac == 2)
816
0
    die(_("option '%s' and commit-ish cannot be used together"),
817
0
        "--orphan");
818
0
  if (lock_reason && !keep_locked)
819
0
    die(_("the option '%s' requires '%s'"), "--reason", "--lock");
820
0
  if (lock_reason)
821
0
    opts.keep_locked = lock_reason;
822
0
  else if (keep_locked)
823
0
    opts.keep_locked = _("added with --lock");
824
825
0
  if (ac < 1 || ac > 2)
826
0
    usage_with_options(git_worktree_add_usage, options);
827
828
0
  path = prefix_filename(prefix, av[0]);
829
0
  branch = ac < 2 ? "HEAD" : av[1];
830
0
  used_new_branch_options = new_branch || new_branch_force;
831
832
0
  if (!strcmp(branch, "-"))
833
0
    branch = "@{-1}";
834
835
0
  if (new_branch_force) {
836
0
    struct strbuf symref = STRBUF_INIT;
837
838
0
    new_branch = new_branch_force;
839
840
0
    if (!opts.force &&
841
0
        !strbuf_check_branch_ref(&symref, new_branch) &&
842
0
        refs_ref_exists(get_main_ref_store(the_repository), symref.buf))
843
0
      die_if_checked_out(symref.buf, 0);
844
0
    strbuf_release(&symref);
845
0
  }
846
847
0
  if (opts.orphan && !new_branch) {
848
0
    int n;
849
0
    const char *s = worktree_basename(path, &n);
850
0
    new_branch = new_branch_to_free = xstrndup(s, n);
851
0
  } else if (opts.orphan) {
852
0
    ; /* no-op */
853
0
  } else if (opts.detach) {
854
    /* Check HEAD */
855
0
    if (!strcmp(branch, "HEAD"))
856
0
      can_use_local_refs(&opts);
857
0
  } else if (ac < 2 && new_branch) {
858
    /* DWIM: Infer --orphan when repo has no refs. */
859
0
    opts.orphan = dwim_orphan(&opts, !!opt_track, 0);
860
0
  } else if (ac < 2) {
861
    /* DWIM: Guess branch name from path. */
862
0
    char *s = dwim_branch(path, &new_branch_to_free);
863
0
    if (s)
864
0
      branch = branch_to_free = s;
865
0
    new_branch = new_branch_to_free;
866
867
    /* DWIM: Infer --orphan when repo has no refs. */
868
0
    opts.orphan = (!s) && dwim_orphan(&opts, !!opt_track, 1);
869
0
  } else if (ac == 2) {
870
0
    struct object_id oid;
871
0
    struct commit *commit;
872
0
    char *remote;
873
874
0
    commit = lookup_commit_reference_by_name(branch);
875
0
    if (!commit) {
876
0
      remote = unique_tracking_name(branch, &oid, NULL);
877
0
      if (remote) {
878
0
        new_branch = branch;
879
0
        branch = new_branch_to_free = remote;
880
0
      }
881
0
    }
882
883
0
    if (!strcmp(branch, "HEAD"))
884
0
      can_use_local_refs(&opts);
885
886
0
  }
887
888
0
  if (!opts.orphan && !lookup_commit_reference_by_name(branch)) {
889
0
    int attempt_hint = !opts.quiet && (ac < 2);
890
0
    if (attempt_hint && used_new_branch_options) {
891
0
      advise_if_enabled(ADVICE_WORKTREE_ADD_ORPHAN,
892
0
        WORKTREE_ADD_ORPHAN_WITH_DASH_B_HINT_TEXT,
893
0
        new_branch, path);
894
0
    } else if (attempt_hint) {
895
0
      advise_if_enabled(ADVICE_WORKTREE_ADD_ORPHAN,
896
0
        WORKTREE_ADD_ORPHAN_NO_DASH_B_HINT_TEXT, path);
897
0
    }
898
0
    die(_("invalid reference: %s"), branch);
899
0
  }
900
901
0
  if (!opts.quiet)
902
0
    print_preparing_worktree_line(opts.detach, branch, new_branch, !!new_branch_force);
903
904
0
  if (opts.orphan) {
905
0
    branch = new_branch;
906
0
  } else if (new_branch) {
907
0
    struct child_process cp = CHILD_PROCESS_INIT;
908
0
    cp.git_cmd = 1;
909
0
    strvec_push(&cp.args, "branch");
910
0
    if (new_branch_force)
911
0
      strvec_push(&cp.args, "--force");
912
0
    if (opts.quiet)
913
0
      strvec_push(&cp.args, "--quiet");
914
0
    strvec_push(&cp.args, new_branch);
915
0
    strvec_push(&cp.args, branch);
916
0
    if (opt_track)
917
0
      strvec_push(&cp.args, opt_track);
918
0
    if (run_command(&cp))
919
0
      return -1;
920
0
    branch = new_branch;
921
0
  } else if (opt_track) {
922
0
    die(_("--[no-]track can only be used if a new branch is created"));
923
0
  }
924
925
0
  ret = add_worktree(path, branch, &opts);
926
0
  free(path);
927
0
  free(opt_track);
928
0
  free(branch_to_free);
929
0
  free(new_branch_to_free);
930
0
  return ret;
931
0
}
932
933
static void show_worktree_porcelain(struct worktree *wt, int line_terminator)
934
0
{
935
0
  const char *reason;
936
937
0
  printf("worktree %s%c", wt->path, line_terminator);
938
0
  if (wt->is_bare)
939
0
    printf("bare%c", line_terminator);
940
0
  else {
941
0
    printf("HEAD %s%c", oid_to_hex(&wt->head_oid), line_terminator);
942
0
    if (wt->is_detached)
943
0
      printf("detached%c", line_terminator);
944
0
    else if (wt->head_ref)
945
0
      printf("branch %s%c", wt->head_ref, line_terminator);
946
0
  }
947
948
0
  reason = worktree_lock_reason(wt);
949
0
  if (reason) {
950
0
    fputs("locked", stdout);
951
0
    if (*reason) {
952
0
      fputc(' ', stdout);
953
0
      write_name_quoted(reason, stdout, line_terminator);
954
0
    } else {
955
0
      fputc(line_terminator, stdout);
956
0
    }
957
0
  }
958
959
0
  reason = worktree_prune_reason(wt, expire);
960
0
  if (reason)
961
0
    printf("prunable %s%c", reason, line_terminator);
962
963
0
  fputc(line_terminator, stdout);
964
0
}
965
966
static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
967
0
{
968
0
  struct strbuf sb = STRBUF_INIT;
969
0
  int cur_path_len = strlen(wt->path);
970
0
  int path_adj = cur_path_len - utf8_strwidth(wt->path);
971
0
  const char *reason;
972
973
0
  strbuf_addf(&sb, "%-*s ", 1 + path_maxlen + path_adj, wt->path);
974
0
  if (wt->is_bare)
975
0
    strbuf_addstr(&sb, "(bare)");
976
0
  else {
977
0
    strbuf_addf(&sb, "%-*s ", abbrev_len,
978
0
        repo_find_unique_abbrev(the_repository, &wt->head_oid, DEFAULT_ABBREV));
979
0
    if (wt->is_detached)
980
0
      strbuf_addstr(&sb, "(detached HEAD)");
981
0
    else if (wt->head_ref) {
982
0
      char *ref = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
983
0
                 wt->head_ref,
984
0
                 0);
985
0
      strbuf_addf(&sb, "[%s]", ref);
986
0
      free(ref);
987
0
    } else
988
0
      strbuf_addstr(&sb, "(error)");
989
0
  }
990
991
0
  reason = worktree_lock_reason(wt);
992
0
  if (verbose && reason && *reason)
993
0
    strbuf_addf(&sb, "\n\tlocked: %s", reason);
994
0
  else if (reason)
995
0
    strbuf_addstr(&sb, " locked");
996
997
0
  reason = worktree_prune_reason(wt, expire);
998
0
  if (verbose && reason)
999
0
    strbuf_addf(&sb, "\n\tprunable: %s", reason);
1000
0
  else if (reason)
1001
0
    strbuf_addstr(&sb, " prunable");
1002
1003
0
  printf("%s\n", sb.buf);
1004
0
  strbuf_release(&sb);
1005
0
}
1006
1007
static void measure_widths(struct worktree **wt, int *abbrev, int *maxlen)
1008
0
{
1009
0
  int i;
1010
1011
0
  for (i = 0; wt[i]; i++) {
1012
0
    int sha1_len;
1013
0
    int path_len = strlen(wt[i]->path);
1014
1015
0
    if (path_len > *maxlen)
1016
0
      *maxlen = path_len;
1017
0
    sha1_len = strlen(repo_find_unique_abbrev(the_repository, &wt[i]->head_oid, *abbrev));
1018
0
    if (sha1_len > *abbrev)
1019
0
      *abbrev = sha1_len;
1020
0
  }
1021
0
}
1022
1023
static int pathcmp(const void *a_, const void *b_)
1024
0
{
1025
0
  const struct worktree *const *a = a_;
1026
0
  const struct worktree *const *b = b_;
1027
0
  return fspathcmp((*a)->path, (*b)->path);
1028
0
}
1029
1030
static void pathsort(struct worktree **wt)
1031
0
{
1032
0
  int n = 0;
1033
0
  struct worktree **p = wt;
1034
1035
0
  while (*p++)
1036
0
    n++;
1037
0
  QSORT(wt, n, pathcmp);
1038
0
}
1039
1040
static int list(int ac, const char **av, const char *prefix)
1041
0
{
1042
0
  int porcelain = 0;
1043
0
  int line_terminator = '\n';
1044
1045
0
  struct option options[] = {
1046
0
    OPT_BOOL(0, "porcelain", &porcelain, N_("machine-readable output")),
1047
0
    OPT__VERBOSE(&verbose, N_("show extended annotations and reasons, if available")),
1048
0
    OPT_EXPIRY_DATE(0, "expire", &expire,
1049
0
        N_("add 'prunable' annotation to worktrees older than <time>")),
1050
0
    OPT_SET_INT('z', NULL, &line_terminator,
1051
0
          N_("terminate records with a NUL character"), '\0'),
1052
0
    OPT_END()
1053
0
  };
1054
1055
0
  expire = TIME_MAX;
1056
0
  ac = parse_options(ac, av, prefix, options, git_worktree_list_usage, 0);
1057
0
  if (ac)
1058
0
    usage_with_options(git_worktree_list_usage, options);
1059
0
  else if (verbose && porcelain)
1060
0
    die(_("options '%s' and '%s' cannot be used together"), "--verbose", "--porcelain");
1061
0
  else if (!line_terminator && !porcelain)
1062
0
    die(_("the option '%s' requires '%s'"), "-z", "--porcelain");
1063
0
  else {
1064
0
    struct worktree **worktrees = get_worktrees();
1065
0
    int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i;
1066
1067
    /* sort worktrees by path but keep main worktree at top */
1068
0
    pathsort(worktrees + 1);
1069
1070
0
    if (!porcelain)
1071
0
      measure_widths(worktrees, &abbrev, &path_maxlen);
1072
1073
0
    for (i = 0; worktrees[i]; i++) {
1074
0
      if (porcelain)
1075
0
        show_worktree_porcelain(worktrees[i],
1076
0
              line_terminator);
1077
0
      else
1078
0
        show_worktree(worktrees[i], path_maxlen, abbrev);
1079
0
    }
1080
0
    free_worktrees(worktrees);
1081
0
  }
1082
0
  return 0;
1083
0
}
1084
1085
static int lock_worktree(int ac, const char **av, const char *prefix)
1086
0
{
1087
0
  const char *reason = "", *old_reason;
1088
0
  struct option options[] = {
1089
0
    OPT_STRING(0, "reason", &reason, N_("string"),
1090
0
         N_("reason for locking")),
1091
0
    OPT_END()
1092
0
  };
1093
0
  struct worktree **worktrees, *wt;
1094
1095
0
  ac = parse_options(ac, av, prefix, options, git_worktree_lock_usage, 0);
1096
0
  if (ac != 1)
1097
0
    usage_with_options(git_worktree_lock_usage, options);
1098
1099
0
  worktrees = get_worktrees();
1100
0
  wt = find_worktree(worktrees, prefix, av[0]);
1101
0
  if (!wt)
1102
0
    die(_("'%s' is not a working tree"), av[0]);
1103
0
  if (is_main_worktree(wt))
1104
0
    die(_("The main working tree cannot be locked or unlocked"));
1105
1106
0
  old_reason = worktree_lock_reason(wt);
1107
0
  if (old_reason) {
1108
0
    if (*old_reason)
1109
0
      die(_("'%s' is already locked, reason: %s"),
1110
0
          av[0], old_reason);
1111
0
    die(_("'%s' is already locked"), av[0]);
1112
0
  }
1113
1114
0
  write_file(git_common_path("worktrees/%s/locked", wt->id),
1115
0
       "%s", reason);
1116
0
  free_worktrees(worktrees);
1117
0
  return 0;
1118
0
}
1119
1120
static int unlock_worktree(int ac, const char **av, const char *prefix)
1121
0
{
1122
0
  struct option options[] = {
1123
0
    OPT_END()
1124
0
  };
1125
0
  struct worktree **worktrees, *wt;
1126
0
  int ret;
1127
1128
0
  ac = parse_options(ac, av, prefix, options, git_worktree_unlock_usage, 0);
1129
0
  if (ac != 1)
1130
0
    usage_with_options(git_worktree_unlock_usage, options);
1131
1132
0
  worktrees = get_worktrees();
1133
0
  wt = find_worktree(worktrees, prefix, av[0]);
1134
0
  if (!wt)
1135
0
    die(_("'%s' is not a working tree"), av[0]);
1136
0
  if (is_main_worktree(wt))
1137
0
    die(_("The main working tree cannot be locked or unlocked"));
1138
0
  if (!worktree_lock_reason(wt))
1139
0
    die(_("'%s' is not locked"), av[0]);
1140
0
  ret = unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id));
1141
0
  free_worktrees(worktrees);
1142
0
  return ret;
1143
0
}
1144
1145
static void validate_no_submodules(const struct worktree *wt)
1146
0
{
1147
0
  struct index_state istate = INDEX_STATE_INIT(the_repository);
1148
0
  struct strbuf path = STRBUF_INIT;
1149
0
  int i, found_submodules = 0;
1150
1151
0
  if (is_directory(worktree_git_path(the_repository, wt, "modules"))) {
1152
    /*
1153
     * There could be false positives, e.g. the "modules"
1154
     * directory exists but is empty. But it's a rare case and
1155
     * this simpler check is probably good enough for now.
1156
     */
1157
0
    found_submodules = 1;
1158
0
  } else if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"),
1159
0
           get_worktree_git_dir(wt)) > 0) {
1160
0
    for (i = 0; i < istate.cache_nr; i++) {
1161
0
      struct cache_entry *ce = istate.cache[i];
1162
0
      int err;
1163
1164
0
      if (!S_ISGITLINK(ce->ce_mode))
1165
0
        continue;
1166
1167
0
      strbuf_reset(&path);
1168
0
      strbuf_addf(&path, "%s/%s", wt->path, ce->name);
1169
0
      if (!is_submodule_populated_gently(path.buf, &err))
1170
0
        continue;
1171
1172
0
      found_submodules = 1;
1173
0
      break;
1174
0
    }
1175
0
  }
1176
0
  discard_index(&istate);
1177
0
  strbuf_release(&path);
1178
1179
0
  if (found_submodules)
1180
0
    die(_("working trees containing submodules cannot be moved or removed"));
1181
0
}
1182
1183
static int move_worktree(int ac, const char **av, const char *prefix)
1184
0
{
1185
0
  int force = 0;
1186
0
  struct option options[] = {
1187
0
    OPT__FORCE(&force,
1188
0
       N_("force move even if worktree is dirty or locked"),
1189
0
       PARSE_OPT_NOCOMPLETE),
1190
0
    OPT_END()
1191
0
  };
1192
0
  struct worktree **worktrees, *wt;
1193
0
  struct strbuf dst = STRBUF_INIT;
1194
0
  struct strbuf errmsg = STRBUF_INIT;
1195
0
  const char *reason = NULL;
1196
0
  char *path;
1197
1198
0
  ac = parse_options(ac, av, prefix, options, git_worktree_move_usage,
1199
0
         0);
1200
0
  if (ac != 2)
1201
0
    usage_with_options(git_worktree_move_usage, options);
1202
1203
0
  path = prefix_filename(prefix, av[1]);
1204
0
  strbuf_addstr(&dst, path);
1205
0
  free(path);
1206
1207
0
  worktrees = get_worktrees();
1208
0
  wt = find_worktree(worktrees, prefix, av[0]);
1209
0
  if (!wt)
1210
0
    die(_("'%s' is not a working tree"), av[0]);
1211
0
  if (is_main_worktree(wt))
1212
0
    die(_("'%s' is a main working tree"), av[0]);
1213
0
  if (is_directory(dst.buf)) {
1214
0
    const char *sep = find_last_dir_sep(wt->path);
1215
1216
0
    if (!sep)
1217
0
      die(_("could not figure out destination name from '%s'"),
1218
0
          wt->path);
1219
0
    strbuf_trim_trailing_dir_sep(&dst);
1220
0
    strbuf_addstr(&dst, sep);
1221
0
  }
1222
0
  check_candidate_path(dst.buf, force, worktrees, "move");
1223
1224
0
  validate_no_submodules(wt);
1225
1226
0
  if (force < 2)
1227
0
    reason = worktree_lock_reason(wt);
1228
0
  if (reason) {
1229
0
    if (*reason)
1230
0
      die(_("cannot move a locked working tree, lock reason: %s\nuse 'move -f -f' to override or unlock first"),
1231
0
          reason);
1232
0
    die(_("cannot move a locked working tree;\nuse 'move -f -f' to override or unlock first"));
1233
0
  }
1234
0
  if (validate_worktree(wt, &errmsg, 0))
1235
0
    die(_("validation failed, cannot move working tree: %s"),
1236
0
        errmsg.buf);
1237
0
  strbuf_release(&errmsg);
1238
1239
0
  if (rename(wt->path, dst.buf) == -1)
1240
0
    die_errno(_("failed to move '%s' to '%s'"), wt->path, dst.buf);
1241
1242
0
  update_worktree_location(wt, dst.buf);
1243
1244
0
  strbuf_release(&dst);
1245
0
  free_worktrees(worktrees);
1246
0
  return 0;
1247
0
}
1248
1249
/*
1250
 * Note, "git status --porcelain" is used to determine if it's safe to
1251
 * delete a whole worktree. "git status" does not ignore user
1252
 * configuration, so if a normal "git status" shows "clean" for the
1253
 * user, then it's ok to remove it.
1254
 *
1255
 * This assumption may be a bad one. We may want to ignore
1256
 * (potentially bad) user settings and only delete a worktree when
1257
 * it's absolutely safe to do so from _our_ point of view because we
1258
 * know better.
1259
 */
1260
static void check_clean_worktree(struct worktree *wt,
1261
         const char *original_path)
1262
0
{
1263
0
  struct child_process cp;
1264
0
  char buf[1];
1265
0
  int ret;
1266
1267
  /*
1268
   * Until we sort this out, all submodules are "dirty" and
1269
   * will abort this function.
1270
   */
1271
0
  validate_no_submodules(wt);
1272
1273
0
  child_process_init(&cp);
1274
0
  strvec_pushf(&cp.env, "%s=%s/.git",
1275
0
         GIT_DIR_ENVIRONMENT, wt->path);
1276
0
  strvec_pushf(&cp.env, "%s=%s",
1277
0
         GIT_WORK_TREE_ENVIRONMENT, wt->path);
1278
0
  strvec_pushl(&cp.args, "status",
1279
0
         "--porcelain", "--ignore-submodules=none",
1280
0
         NULL);
1281
0
  cp.git_cmd = 1;
1282
0
  cp.dir = wt->path;
1283
0
  cp.out = -1;
1284
0
  ret = start_command(&cp);
1285
0
  if (ret)
1286
0
    die_errno(_("failed to run 'git status' on '%s'"),
1287
0
        original_path);
1288
0
  ret = xread(cp.out, buf, sizeof(buf));
1289
0
  if (ret)
1290
0
    die(_("'%s' contains modified or untracked files, use --force to delete it"),
1291
0
        original_path);
1292
0
  close(cp.out);
1293
0
  ret = finish_command(&cp);
1294
0
  if (ret)
1295
0
    die_errno(_("failed to run 'git status' on '%s', code %d"),
1296
0
        original_path, ret);
1297
0
}
1298
1299
static int delete_git_work_tree(struct worktree *wt)
1300
0
{
1301
0
  struct strbuf sb = STRBUF_INIT;
1302
0
  int ret = 0;
1303
1304
0
  strbuf_addstr(&sb, wt->path);
1305
0
  if (remove_dir_recursively(&sb, 0)) {
1306
0
    error_errno(_("failed to delete '%s'"), sb.buf);
1307
0
    ret = -1;
1308
0
  }
1309
0
  strbuf_release(&sb);
1310
0
  return ret;
1311
0
}
1312
1313
static int remove_worktree(int ac, const char **av, const char *prefix)
1314
0
{
1315
0
  int force = 0;
1316
0
  struct option options[] = {
1317
0
    OPT__FORCE(&force,
1318
0
       N_("force removal even if worktree is dirty or locked"),
1319
0
       PARSE_OPT_NOCOMPLETE),
1320
0
    OPT_END()
1321
0
  };
1322
0
  struct worktree **worktrees, *wt;
1323
0
  struct strbuf errmsg = STRBUF_INIT;
1324
0
  const char *reason = NULL;
1325
0
  int ret = 0;
1326
1327
0
  ac = parse_options(ac, av, prefix, options, git_worktree_remove_usage, 0);
1328
0
  if (ac != 1)
1329
0
    usage_with_options(git_worktree_remove_usage, options);
1330
1331
0
  worktrees = get_worktrees();
1332
0
  wt = find_worktree(worktrees, prefix, av[0]);
1333
0
  if (!wt)
1334
0
    die(_("'%s' is not a working tree"), av[0]);
1335
0
  if (is_main_worktree(wt))
1336
0
    die(_("'%s' is a main working tree"), av[0]);
1337
0
  if (force < 2)
1338
0
    reason = worktree_lock_reason(wt);
1339
0
  if (reason) {
1340
0
    if (*reason)
1341
0
      die(_("cannot remove a locked working tree, lock reason: %s\nuse 'remove -f -f' to override or unlock first"),
1342
0
          reason);
1343
0
    die(_("cannot remove a locked working tree;\nuse 'remove -f -f' to override or unlock first"));
1344
0
  }
1345
0
  if (validate_worktree(wt, &errmsg, WT_VALIDATE_WORKTREE_MISSING_OK))
1346
0
    die(_("validation failed, cannot remove working tree: %s"),
1347
0
        errmsg.buf);
1348
0
  strbuf_release(&errmsg);
1349
1350
0
  if (file_exists(wt->path)) {
1351
0
    if (!force)
1352
0
      check_clean_worktree(wt, av[0]);
1353
1354
0
    ret |= delete_git_work_tree(wt);
1355
0
  }
1356
  /*
1357
   * continue on even if ret is non-zero, there's no going back
1358
   * from here.
1359
   */
1360
0
  ret |= delete_git_dir(wt->id);
1361
0
  delete_worktrees_dir_if_empty();
1362
1363
0
  free_worktrees(worktrees);
1364
0
  return ret;
1365
0
}
1366
1367
static void report_repair(int iserr, const char *path, const char *msg, void *cb_data)
1368
0
{
1369
0
  if (!iserr) {
1370
0
    fprintf_ln(stderr, _("repair: %s: %s"), msg, path);
1371
0
  } else {
1372
0
    int *exit_status = (int *)cb_data;
1373
0
    fprintf_ln(stderr, _("error: %s: %s"), msg, path);
1374
0
    *exit_status = 1;
1375
0
  }
1376
0
}
1377
1378
static int repair(int ac, const char **av, const char *prefix)
1379
0
{
1380
0
  const char **p;
1381
0
  const char *self[] = { ".", NULL };
1382
0
  struct option options[] = {
1383
0
    OPT_END()
1384
0
  };
1385
0
  int rc = 0;
1386
1387
0
  ac = parse_options(ac, av, prefix, options, git_worktree_repair_usage, 0);
1388
0
  p = ac > 0 ? av : self;
1389
0
  for (; *p; p++)
1390
0
    repair_worktree_at_path(*p, report_repair, &rc);
1391
0
  repair_worktrees(report_repair, &rc);
1392
0
  return rc;
1393
0
}
1394
1395
int cmd_worktree(int ac, const char **av, const char *prefix)
1396
0
{
1397
0
  parse_opt_subcommand_fn *fn = NULL;
1398
0
  struct option options[] = {
1399
0
    OPT_SUBCOMMAND("add", &fn, add),
1400
0
    OPT_SUBCOMMAND("prune", &fn, prune),
1401
0
    OPT_SUBCOMMAND("list", &fn, list),
1402
0
    OPT_SUBCOMMAND("lock", &fn, lock_worktree),
1403
0
    OPT_SUBCOMMAND("unlock", &fn, unlock_worktree),
1404
0
    OPT_SUBCOMMAND("move", &fn, move_worktree),
1405
0
    OPT_SUBCOMMAND("remove", &fn, remove_worktree),
1406
0
    OPT_SUBCOMMAND("repair", &fn, repair),
1407
0
    OPT_END()
1408
0
  };
1409
1410
0
  git_config(git_worktree_config, NULL);
1411
1412
0
  if (!prefix)
1413
0
    prefix = "";
1414
1415
0
  ac = parse_options(ac, av, prefix, options, git_worktree_usage, 0);
1416
1417
0
  prepare_repo_settings(the_repository);
1418
0
  the_repository->settings.command_requires_full_index = 0;
1419
1420
0
  return fn(ac, av, prefix);
1421
0
}