(alias R=$GIT_COMMON_DIR/repos/id)
- linked checkouts are supposed to keep its location in $R/gitdir up
to date. The use case is auto fixup after a manual checkout move.
- linked checkouts are supposed to update mtime of $R/gitdir. If
$R/gitdir's mtime is older than a limit, and it points to nowhere,
repos/id is to be pruned.
- git checkout --to is supposed to create $R/locked if the new repo
is on a different partition than the shared one. The main use case
is when the checkout is on a portable device and may not be
available at prune time.
If $R/locked exists, repos/id is not supposed to be pruned. If
$R/locked exists and $R/gitdir's mtime is older than a really long
limit, warn about old unused repo.
- git checkout --to is supposed to make a hard link named $R/link
pointing to the .git file on supported file systems to help detect
the user manually deleting the checkout. If $R/link exists and its
link count is greated than 1, the repo is kept.
Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
Documentation/git-prune.txt| 3 ++
Documentation/gitrepository-layout.txt | 19 +
builtin/checkout.c | 36 -
builtin/prune.c| 74 ++
compat/mingw.h | 1 +
git-compat-util.h | 4 ++
setup.c| 13 ++
7 files changed, 149 insertions(+), 1 deletion(-)
diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt
index 058ac0d..7babf11 100644
--- a/Documentation/git-prune.txt
+++ b/Documentation/git-prune.txt
@@ -48,6 +48,9 @@ OPTIONS
--expire time::
Only expire loose objects older than time.
+--repos::
+ Prune directories in $GIT_DIR/repos.
+
head...::
In addition to objects
reachable from any of our references, keep objects
diff --git a/Documentation/gitrepository-layout.txt
b/Documentation/gitrepository-layout.txt
index 418e5c8..2dc6901 100644
--- a/Documentation/gitrepository-layout.txt
+++ b/Documentation/gitrepository-layout.txt
@@ -252,6 +252,25 @@ repos::
$GIT_COMMON_DIR is set and $GIT_COMMON_DIR/repos will be
used instead.
+repos/id/gitdir::
+ A text file containing the absolute path back to the .git file
+ that points to here. This is used to check if the linked
+ repository has been manually removed and there is no need to
+ keep this directory any more. mtime of this file should be
+ updated every time the linked repository is accessed.
+
+repos/id/locked::
+ If this file exists, the linked repository may be on a
+ portable device and not available. It does not mean that the
+ linked repository is gone and `repos/id` could be
+ removed. The file's content contains a reason string on why
+ the repository is locked.
+
+repos/id/link::
+ If this file exists, it is a hard link to the linked .git
+ file. It is used to detect if the linked repository is
+ manually removed.
+
SEE ALSO
linkgit:git-init[1],
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 1675808..1fc85d3 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -854,6 +854,17 @@ static void remove_junk_on_signal(int signo)
raise(signo);
}
+static dev_t get_device_or_die(const char *path)
+{
+ struct stat buf;
+ if (stat(path, buf))
+ die_errno(failed to stat '%s', path);
+ /* Ah Windows! Make different drives different partitions */
+ if (is_windows())
+ buf.st_dev = toupper(real_path(path)[0]);
+ return buf.st_dev;
+}
+
static int prepare_linked_checkout(const struct checkout_opts *opts,
struct branch_info *new)
{
@@ -862,7 +873,7 @@ static int prepare_linked_checkout(const struct
checkout_opts *opts,
const char *path = opts-new_worktree, *name;
struct stat st;
struct child_process cp;
- int counter = 0, len, ret;
+ int counter = 0, len, keep_locked = 0, ret;
if (!new-commit)
die(_(no branch specified));
@@ -898,12 +909,18 @@ static int prepare_linked_checkout(const struct
checkout_opts *opts,
junk_git_dir = sb_repo.buf;
is_junk = 1;
+ strbuf_addf(sb, %s/locked, sb_repo.buf);
+ write_file(sb.buf, 1, initializing\n);
+
strbuf_addf(sb_git, %s/.git, path);
if (safe_create_leading_directories_const(sb_git.buf))
die_errno(_(could not create leading directories of '%s'),
sb_git.buf);
junk_work_tree = path;
+ strbuf_reset(sb);
+ strbuf_addf(sb, %s/gitdir, sb_repo.buf);
+ write_file(sb.buf, 1, %s\n, real_path(sb_git.buf));
write_file(sb_git.buf, 1, gitdir: %s/repos/%s\n,
real_path(get_git_common_dir()), name);
/*
@@ -912,12 +929,24