worktree: new place for "git prune --worktrees"
Commit 23af91d
(prune: strategies for linked checkouts - 2014-11-30)
adds "--worktrees" to "git prune" without realizing that "git prune" is
for object database only. This patch moves the same functionality to a
new command "git worktree".
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
This commit is contained in:
parent
e1c1ab9d25
commit
df0b6cfbda
1
.gitignore
vendored
1
.gitignore
vendored
@ -171,6 +171,7 @@
|
|||||||
/git-verify-tag
|
/git-verify-tag
|
||||||
/git-web--browse
|
/git-web--browse
|
||||||
/git-whatchanged
|
/git-whatchanged
|
||||||
|
/git-worktree
|
||||||
/git-write-tree
|
/git-write-tree
|
||||||
/git-core-*/?*
|
/git-core-*/?*
|
||||||
/gitweb/GITWEB-BUILD-OPTIONS
|
/gitweb/GITWEB-BUILD-OPTIONS
|
||||||
|
@ -48,9 +48,6 @@ OPTIONS
|
|||||||
--expire <time>::
|
--expire <time>::
|
||||||
Only expire loose objects older than <time>.
|
Only expire loose objects older than <time>.
|
||||||
|
|
||||||
--worktrees::
|
|
||||||
Prune dead working tree information in $GIT_DIR/worktrees.
|
|
||||||
|
|
||||||
<head>...::
|
<head>...::
|
||||||
In addition to objects
|
In addition to objects
|
||||||
reachable from any of our references, keep objects
|
reachable from any of our references, keep objects
|
||||||
|
48
Documentation/git-worktree.txt
Normal file
48
Documentation/git-worktree.txt
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
git-worktree(1)
|
||||||
|
===============
|
||||||
|
|
||||||
|
NAME
|
||||||
|
----
|
||||||
|
git-worktree - Manage multiple worktrees
|
||||||
|
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
--------
|
||||||
|
[verse]
|
||||||
|
'git worktree prune' [-n] [-v] [--expire <expire>]
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Manage multiple worktrees attached to the same repository. These are
|
||||||
|
created by the command `git checkout --to`.
|
||||||
|
|
||||||
|
COMMANDS
|
||||||
|
--------
|
||||||
|
prune::
|
||||||
|
|
||||||
|
Prune working tree information in $GIT_DIR/worktrees.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
|
||||||
|
-n::
|
||||||
|
--dry-run::
|
||||||
|
Do not remove anything; just report what it would
|
||||||
|
remove.
|
||||||
|
|
||||||
|
-v::
|
||||||
|
--verbose::
|
||||||
|
Report all removals.
|
||||||
|
|
||||||
|
--expire <time>::
|
||||||
|
Only expire unused worktrees older than <time>.
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
--------
|
||||||
|
|
||||||
|
linkgit:git-checkout[1]
|
||||||
|
|
||||||
|
GIT
|
||||||
|
---
|
||||||
|
Part of the linkgit:git[1] suite
|
1
Makefile
1
Makefile
@ -886,6 +886,7 @@ BUILTIN_OBJS += builtin/var.o
|
|||||||
BUILTIN_OBJS += builtin/verify-commit.o
|
BUILTIN_OBJS += builtin/verify-commit.o
|
||||||
BUILTIN_OBJS += builtin/verify-pack.o
|
BUILTIN_OBJS += builtin/verify-pack.o
|
||||||
BUILTIN_OBJS += builtin/verify-tag.o
|
BUILTIN_OBJS += builtin/verify-tag.o
|
||||||
|
BUILTIN_OBJS += builtin/worktree.o
|
||||||
BUILTIN_OBJS += builtin/write-tree.o
|
BUILTIN_OBJS += builtin/write-tree.o
|
||||||
|
|
||||||
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
|
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
|
||||||
|
@ -133,6 +133,7 @@ extern int cmd_verify_commit(int argc, const char **argv, const char *prefix);
|
|||||||
extern int cmd_verify_tag(int argc, const char **argv, const char *prefix);
|
extern int cmd_verify_tag(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_version(int argc, const char **argv, const char *prefix);
|
extern int cmd_version(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_whatchanged(int argc, const char **argv, const char *prefix);
|
extern int cmd_whatchanged(int argc, const char **argv, const char *prefix);
|
||||||
|
extern int cmd_worktree(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_write_tree(int argc, const char **argv, const char *prefix);
|
extern int cmd_write_tree(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_verify_pack(int argc, const char **argv, const char *prefix);
|
extern int cmd_verify_pack(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_show_ref(int argc, const char **argv, const char *prefix);
|
extern int cmd_show_ref(int argc, const char **argv, const char *prefix);
|
||||||
|
@ -293,7 +293,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
|
|||||||
argv_array_pushl(&reflog, "reflog", "expire", "--all", NULL);
|
argv_array_pushl(&reflog, "reflog", "expire", "--all", NULL);
|
||||||
argv_array_pushl(&repack, "repack", "-d", "-l", NULL);
|
argv_array_pushl(&repack, "repack", "-d", "-l", NULL);
|
||||||
argv_array_pushl(&prune, "prune", "--expire", NULL);
|
argv_array_pushl(&prune, "prune", "--expire", NULL);
|
||||||
argv_array_pushl(&prune_worktrees, "prune", "--worktrees", "--expire", NULL);
|
argv_array_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL);
|
||||||
argv_array_pushl(&rerere, "rerere", "gc", NULL);
|
argv_array_pushl(&rerere, "rerere", "gc", NULL);
|
||||||
|
|
||||||
gc_config();
|
gc_config();
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include "reachable.h"
|
#include "reachable.h"
|
||||||
#include "parse-options.h"
|
#include "parse-options.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "dir.h"
|
|
||||||
|
|
||||||
static const char * const prune_usage[] = {
|
static const char * const prune_usage[] = {
|
||||||
N_("git prune [-n] [-v] [--expire <time>] [--] [<head>...]"),
|
N_("git prune [-n] [-v] [--expire <time>] [--] [<head>...]"),
|
||||||
@ -76,95 +75,6 @@ static int prune_subdir(int nr, const char *path, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int prune_worktree(const char *id, struct strbuf *reason)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
char *path;
|
|
||||||
int fd, len;
|
|
||||||
|
|
||||||
if (!is_directory(git_path("worktrees/%s", id))) {
|
|
||||||
strbuf_addf(reason, _("Removing worktrees/%s: not a valid directory"), id);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (file_exists(git_path("worktrees/%s/locked", id)))
|
|
||||||
return 0;
|
|
||||||
if (stat(git_path("worktrees/%s/gitdir", id), &st)) {
|
|
||||||
strbuf_addf(reason, _("Removing worktrees/%s: gitdir file does not exist"), id);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
fd = open(git_path("worktrees/%s/gitdir", id), O_RDONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
strbuf_addf(reason, _("Removing worktrees/%s: unable to read gitdir file (%s)"),
|
|
||||||
id, strerror(errno));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
len = st.st_size;
|
|
||||||
path = xmalloc(len + 1);
|
|
||||||
read_in_full(fd, path, len);
|
|
||||||
close(fd);
|
|
||||||
while (len && (path[len - 1] == '\n' || path[len - 1] == '\r'))
|
|
||||||
len--;
|
|
||||||
if (!len) {
|
|
||||||
strbuf_addf(reason, _("Removing worktrees/%s: invalid gitdir file"), id);
|
|
||||||
free(path);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
path[len] = '\0';
|
|
||||||
if (!file_exists(path)) {
|
|
||||||
struct stat st_link;
|
|
||||||
free(path);
|
|
||||||
/*
|
|
||||||
* the repo is moved manually and has not been
|
|
||||||
* accessed since?
|
|
||||||
*/
|
|
||||||
if (!stat(git_path("worktrees/%s/link", id), &st_link) &&
|
|
||||||
st_link.st_nlink > 1)
|
|
||||||
return 0;
|
|
||||||
if (st.st_mtime <= expire) {
|
|
||||||
strbuf_addf(reason, _("Removing worktrees/%s: gitdir file points to non-existent location"), id);
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(path);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void prune_worktrees(void)
|
|
||||||
{
|
|
||||||
struct strbuf reason = STRBUF_INIT;
|
|
||||||
struct strbuf path = STRBUF_INIT;
|
|
||||||
DIR *dir = opendir(git_path("worktrees"));
|
|
||||||
struct dirent *d;
|
|
||||||
int ret;
|
|
||||||
if (!dir)
|
|
||||||
return;
|
|
||||||
while ((d = readdir(dir)) != NULL) {
|
|
||||||
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
|
|
||||||
continue;
|
|
||||||
strbuf_reset(&reason);
|
|
||||||
if (!prune_worktree(d->d_name, &reason))
|
|
||||||
continue;
|
|
||||||
if (show_only || verbose)
|
|
||||||
printf("%s\n", reason.buf);
|
|
||||||
if (show_only)
|
|
||||||
continue;
|
|
||||||
strbuf_reset(&path);
|
|
||||||
strbuf_addstr(&path, git_path("worktrees/%s", d->d_name));
|
|
||||||
ret = remove_dir_recursively(&path, 0);
|
|
||||||
if (ret < 0 && errno == ENOTDIR)
|
|
||||||
ret = unlink(path.buf);
|
|
||||||
if (ret)
|
|
||||||
error(_("failed to remove: %s"), strerror(errno));
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
if (!show_only)
|
|
||||||
rmdir(git_path("worktrees"));
|
|
||||||
strbuf_release(&reason);
|
|
||||||
strbuf_release(&path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write errors (particularly out of space) can result in
|
* Write errors (particularly out of space) can result in
|
||||||
* failed temporary packs (and more rarely indexes and other
|
* failed temporary packs (and more rarely indexes and other
|
||||||
@ -191,12 +101,10 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
|
|||||||
{
|
{
|
||||||
struct rev_info revs;
|
struct rev_info revs;
|
||||||
struct progress *progress = NULL;
|
struct progress *progress = NULL;
|
||||||
int do_prune_worktrees = 0;
|
|
||||||
const struct option options[] = {
|
const struct option options[] = {
|
||||||
OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
|
OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
|
||||||
OPT__VERBOSE(&verbose, N_("report pruned objects")),
|
OPT__VERBOSE(&verbose, N_("report pruned objects")),
|
||||||
OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
|
OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
|
||||||
OPT_BOOL(0, "worktrees", &do_prune_worktrees, N_("prune .git/worktrees")),
|
|
||||||
OPT_EXPIRY_DATE(0, "expire", &expire,
|
OPT_EXPIRY_DATE(0, "expire", &expire,
|
||||||
N_("expire objects older than <time>")),
|
N_("expire objects older than <time>")),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
@ -210,13 +118,6 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
|
argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
|
||||||
|
|
||||||
if (do_prune_worktrees) {
|
|
||||||
if (argc)
|
|
||||||
die(_("--worktrees does not take extra arguments"));
|
|
||||||
prune_worktrees();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (argc--) {
|
while (argc--) {
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
const char *name = *argv++;
|
const char *name = *argv++;
|
||||||
|
133
builtin/worktree.c
Normal file
133
builtin/worktree.c
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#include "cache.h"
|
||||||
|
#include "builtin.h"
|
||||||
|
#include "dir.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
|
static const char * const worktree_usage[] = {
|
||||||
|
N_("git worktree prune [<options>]"),
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int show_only;
|
||||||
|
static int verbose;
|
||||||
|
static unsigned long expire;
|
||||||
|
|
||||||
|
static int prune_worktree(const char *id, struct strbuf *reason)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
char *path;
|
||||||
|
int fd, len;
|
||||||
|
|
||||||
|
if (!is_directory(git_path("worktrees/%s", id))) {
|
||||||
|
strbuf_addf(reason, _("Removing worktrees/%s: not a valid directory"), id);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (file_exists(git_path("worktrees/%s/locked", id)))
|
||||||
|
return 0;
|
||||||
|
if (stat(git_path("worktrees/%s/gitdir", id), &st)) {
|
||||||
|
strbuf_addf(reason, _("Removing worktrees/%s: gitdir file does not exist"), id);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fd = open(git_path("worktrees/%s/gitdir", id), O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
strbuf_addf(reason, _("Removing worktrees/%s: unable to read gitdir file (%s)"),
|
||||||
|
id, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
len = st.st_size;
|
||||||
|
path = xmalloc(len + 1);
|
||||||
|
read_in_full(fd, path, len);
|
||||||
|
close(fd);
|
||||||
|
while (len && (path[len - 1] == '\n' || path[len - 1] == '\r'))
|
||||||
|
len--;
|
||||||
|
if (!len) {
|
||||||
|
strbuf_addf(reason, _("Removing worktrees/%s: invalid gitdir file"), id);
|
||||||
|
free(path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
path[len] = '\0';
|
||||||
|
if (!file_exists(path)) {
|
||||||
|
struct stat st_link;
|
||||||
|
free(path);
|
||||||
|
/*
|
||||||
|
* the repo is moved manually and has not been
|
||||||
|
* accessed since?
|
||||||
|
*/
|
||||||
|
if (!stat(git_path("worktrees/%s/link", id), &st_link) &&
|
||||||
|
st_link.st_nlink > 1)
|
||||||
|
return 0;
|
||||||
|
if (st.st_mtime <= expire) {
|
||||||
|
strbuf_addf(reason, _("Removing worktrees/%s: gitdir file points to non-existent location"), id);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prune_worktrees(void)
|
||||||
|
{
|
||||||
|
struct strbuf reason = STRBUF_INIT;
|
||||||
|
struct strbuf path = STRBUF_INIT;
|
||||||
|
DIR *dir = opendir(git_path("worktrees"));
|
||||||
|
struct dirent *d;
|
||||||
|
int ret;
|
||||||
|
if (!dir)
|
||||||
|
return;
|
||||||
|
while ((d = readdir(dir)) != NULL) {
|
||||||
|
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
|
||||||
|
continue;
|
||||||
|
strbuf_reset(&reason);
|
||||||
|
if (!prune_worktree(d->d_name, &reason))
|
||||||
|
continue;
|
||||||
|
if (show_only || verbose)
|
||||||
|
printf("%s\n", reason.buf);
|
||||||
|
if (show_only)
|
||||||
|
continue;
|
||||||
|
strbuf_reset(&path);
|
||||||
|
strbuf_addstr(&path, git_path("worktrees/%s", d->d_name));
|
||||||
|
ret = remove_dir_recursively(&path, 0);
|
||||||
|
if (ret < 0 && errno == ENOTDIR)
|
||||||
|
ret = unlink(path.buf);
|
||||||
|
if (ret)
|
||||||
|
error(_("failed to remove: %s"), strerror(errno));
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
if (!show_only)
|
||||||
|
rmdir(git_path("worktrees"));
|
||||||
|
strbuf_release(&reason);
|
||||||
|
strbuf_release(&path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int prune(int ac, const char **av, const char *prefix)
|
||||||
|
{
|
||||||
|
struct option options[] = {
|
||||||
|
OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
|
||||||
|
OPT__VERBOSE(&verbose, N_("report pruned objects")),
|
||||||
|
OPT_EXPIRY_DATE(0, "expire", &expire,
|
||||||
|
N_("expire objects older than <time>")),
|
||||||
|
OPT_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
expire = ULONG_MAX;
|
||||||
|
ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
|
||||||
|
if (ac)
|
||||||
|
usage_with_options(worktree_usage, options);
|
||||||
|
prune_worktrees();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_worktree(int ac, const char **av, const char *prefix)
|
||||||
|
{
|
||||||
|
struct option options[] = {
|
||||||
|
OPT_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ac < 2)
|
||||||
|
usage_with_options(worktree_usage, options);
|
||||||
|
if (!strcmp(av[1], "prune"))
|
||||||
|
return prune(ac - 1, av + 1, prefix);
|
||||||
|
usage_with_options(worktree_usage, options);
|
||||||
|
}
|
@ -138,4 +138,5 @@ git-verify-pack plumbinginterrogators
|
|||||||
git-verify-tag ancillaryinterrogators
|
git-verify-tag ancillaryinterrogators
|
||||||
gitweb ancillaryinterrogators
|
gitweb ancillaryinterrogators
|
||||||
git-whatchanged ancillaryinterrogators
|
git-whatchanged ancillaryinterrogators
|
||||||
|
git-worktree mainporcelain
|
||||||
git-write-tree plumbingmanipulators
|
git-write-tree plumbingmanipulators
|
||||||
|
1
git.c
1
git.c
@ -484,6 +484,7 @@ static struct cmd_struct commands[] = {
|
|||||||
{ "verify-tag", cmd_verify_tag, RUN_SETUP },
|
{ "verify-tag", cmd_verify_tag, RUN_SETUP },
|
||||||
{ "version", cmd_version },
|
{ "version", cmd_version },
|
||||||
{ "whatchanged", cmd_whatchanged, RUN_SETUP },
|
{ "whatchanged", cmd_whatchanged, RUN_SETUP },
|
||||||
|
{ "worktree", cmd_worktree, RUN_SETUP },
|
||||||
{ "write-tree", cmd_write_tree, RUN_SETUP },
|
{ "write-tree", cmd_write_tree, RUN_SETUP },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,15 +8,15 @@ test_expect_success initialize '
|
|||||||
git commit --allow-empty -m init
|
git commit --allow-empty -m init
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'prune --worktrees on normal repo' '
|
test_expect_success 'worktree prune on normal repo' '
|
||||||
git prune --worktrees &&
|
git worktree prune &&
|
||||||
test_must_fail git prune --worktrees abc
|
test_must_fail git worktree prune abc
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'prune files inside $GIT_DIR/worktrees' '
|
test_expect_success 'prune files inside $GIT_DIR/worktrees' '
|
||||||
mkdir .git/worktrees &&
|
mkdir .git/worktrees &&
|
||||||
: >.git/worktrees/abc &&
|
: >.git/worktrees/abc &&
|
||||||
git prune --worktrees --verbose >actual &&
|
git worktree prune --verbose >actual &&
|
||||||
cat >expect <<EOF &&
|
cat >expect <<EOF &&
|
||||||
Removing worktrees/abc: not a valid directory
|
Removing worktrees/abc: not a valid directory
|
||||||
EOF
|
EOF
|
||||||
@ -31,7 +31,7 @@ test_expect_success 'prune directories without gitdir' '
|
|||||||
cat >expect <<EOF &&
|
cat >expect <<EOF &&
|
||||||
Removing worktrees/def: gitdir file does not exist
|
Removing worktrees/def: gitdir file does not exist
|
||||||
EOF
|
EOF
|
||||||
git prune --worktrees --verbose >actual &&
|
git worktree prune --verbose >actual &&
|
||||||
test_i18ncmp expect actual &&
|
test_i18ncmp expect actual &&
|
||||||
! test -d .git/worktrees/def &&
|
! test -d .git/worktrees/def &&
|
||||||
! test -d .git/worktrees
|
! test -d .git/worktrees
|
||||||
@ -42,7 +42,7 @@ test_expect_success SANITY 'prune directories with unreadable gitdir' '
|
|||||||
: >.git/worktrees/def/def &&
|
: >.git/worktrees/def/def &&
|
||||||
: >.git/worktrees/def/gitdir &&
|
: >.git/worktrees/def/gitdir &&
|
||||||
chmod u-r .git/worktrees/def/gitdir &&
|
chmod u-r .git/worktrees/def/gitdir &&
|
||||||
git prune --worktrees --verbose >actual &&
|
git worktree prune --verbose >actual &&
|
||||||
test_i18ngrep "Removing worktrees/def: unable to read gitdir file" actual &&
|
test_i18ngrep "Removing worktrees/def: unable to read gitdir file" actual &&
|
||||||
! test -d .git/worktrees/def &&
|
! test -d .git/worktrees/def &&
|
||||||
! test -d .git/worktrees
|
! test -d .git/worktrees
|
||||||
@ -52,7 +52,7 @@ test_expect_success 'prune directories with invalid gitdir' '
|
|||||||
mkdir -p .git/worktrees/def/abc &&
|
mkdir -p .git/worktrees/def/abc &&
|
||||||
: >.git/worktrees/def/def &&
|
: >.git/worktrees/def/def &&
|
||||||
: >.git/worktrees/def/gitdir &&
|
: >.git/worktrees/def/gitdir &&
|
||||||
git prune --worktrees --verbose >actual &&
|
git worktree prune --verbose >actual &&
|
||||||
test_i18ngrep "Removing worktrees/def: invalid gitdir file" actual &&
|
test_i18ngrep "Removing worktrees/def: invalid gitdir file" actual &&
|
||||||
! test -d .git/worktrees/def &&
|
! test -d .git/worktrees/def &&
|
||||||
! test -d .git/worktrees
|
! test -d .git/worktrees
|
||||||
@ -62,7 +62,7 @@ test_expect_success 'prune directories with gitdir pointing to nowhere' '
|
|||||||
mkdir -p .git/worktrees/def/abc &&
|
mkdir -p .git/worktrees/def/abc &&
|
||||||
: >.git/worktrees/def/def &&
|
: >.git/worktrees/def/def &&
|
||||||
echo "$(pwd)"/nowhere >.git/worktrees/def/gitdir &&
|
echo "$(pwd)"/nowhere >.git/worktrees/def/gitdir &&
|
||||||
git prune --worktrees --verbose >actual &&
|
git worktree prune --verbose >actual &&
|
||||||
test_i18ngrep "Removing worktrees/def: gitdir file points to non-existent location" actual &&
|
test_i18ngrep "Removing worktrees/def: gitdir file points to non-existent location" actual &&
|
||||||
! test -d .git/worktrees/def &&
|
! test -d .git/worktrees/def &&
|
||||||
! test -d .git/worktrees
|
! test -d .git/worktrees
|
||||||
@ -72,7 +72,7 @@ test_expect_success 'not prune locked checkout' '
|
|||||||
test_when_finished rm -r .git/worktrees &&
|
test_when_finished rm -r .git/worktrees &&
|
||||||
mkdir -p .git/worktrees/ghi &&
|
mkdir -p .git/worktrees/ghi &&
|
||||||
: >.git/worktrees/ghi/locked &&
|
: >.git/worktrees/ghi/locked &&
|
||||||
git prune --worktrees &&
|
git worktree prune &&
|
||||||
test -d .git/worktrees/ghi
|
test -d .git/worktrees/ghi
|
||||||
'
|
'
|
||||||
|
|
||||||
@ -82,14 +82,14 @@ test_expect_success 'not prune recent checkouts' '
|
|||||||
mkdir -p .git/worktrees/jlm &&
|
mkdir -p .git/worktrees/jlm &&
|
||||||
echo "$(pwd)"/zz >.git/worktrees/jlm/gitdir &&
|
echo "$(pwd)"/zz >.git/worktrees/jlm/gitdir &&
|
||||||
rmdir zz &&
|
rmdir zz &&
|
||||||
git prune --worktrees --verbose --expire=2.days.ago &&
|
git worktree prune --verbose --expire=2.days.ago &&
|
||||||
test -d .git/worktrees/jlm
|
test -d .git/worktrees/jlm
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'not prune proper checkouts' '
|
test_expect_success 'not prune proper checkouts' '
|
||||||
test_when_finished rm -r .git/worktrees &&
|
test_when_finished rm -r .git/worktrees &&
|
||||||
git checkout "--to=$PWD/nop" --detach master &&
|
git checkout "--to=$PWD/nop" --detach master &&
|
||||||
git prune --worktrees &&
|
git worktree prune &&
|
||||||
test -d .git/worktrees/nop
|
test -d .git/worktrees/nop
|
||||||
'
|
'
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user