Re: [PATCH v4 24/27] prune: strategies for linked checkouts

2014-03-05 Thread Junio C Hamano
Nguyễn Thái Ngọc Duy  pclo...@gmail.com writes:

 + if (get_device_or_die(path) != get_device_or_die(get_git_dir())) {
 + strbuf_reset(sb);
 + strbuf_addf(sb, %s/locked, sb_repo.buf);
 + write_file(sb.buf, 1, located on a different file system\n);
 + keep_locked = 1;
 + } else {
 + strbuf_reset(sb);
 + strbuf_addf(sb, %s/link, sb_repo.buf);
 + (void)link(sb_git.buf, sb.buf);
 + }

Just in case you did not realize, casting the return away with
(void) will not squelch this out of the compiler:

builtin/checkout.c: In function 'prepare_linked_checkout':
builtin/checkout.c:947:3: error: ignoring return value of 'link', declared 
with attribute warn_unused_result [-Werror=unused-result]

It still feels fishy to see we attempt to link but we do not care
if it works or not to me, with or without the unused result
issue.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 24/27] prune: strategies for linked checkouts

2014-03-01 Thread Nguyễn Thái Ngọc Duy
(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 

Re: [PATCH v4 24/27] prune: strategies for linked checkouts

2014-03-01 Thread Torsten Bögershausen
On 2014-03-01 13.13, Nguyễn Thái Ngọc Duy wrote:
[]
  
 +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;

Is this only related to Windows ?
Do we have other file systems, which return st_dev == 0 ?
Should we check that path[0] != '/', or better !is_dir_sep(path[0]) ?
Do we need has_dos_drive_prefix() ?

As a first suggestion, would this be better:

 + if (!buf.st_dev)
 + buf.st_dev = toupper(real_path(path)[0]);

(End of loose thinking)
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 24/27] prune: strategies for linked checkouts

2014-03-01 Thread Duy Nguyen
On Sun, Mar 2, 2014 at 12:12 AM, Torsten Bögershausen tbo...@web.de wrote:
 On 2014-03-01 13.13, Nguyễn Thái Ngọc Duy wrote:
 []

 +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;

 Is this only related to Windows ?

Yes. At least the treatment is Windows specific. If st_dev == 0 in
other cases, then we have to deal with them case-by-case.

 Do we have other file systems, which return st_dev == 0 ?
 Should we check that path[0] != '/', or better !is_dir_sep(path[0]) ?
 Do we need has_dos_drive_prefix() ?

real_path() returns an absolute path, so we're guaranteed its first
character is the drive letter, right? (I tried to confirm this by
reading read_path_internal, but it's a bit complex, and I don't have
Windows machine to quickly test it out)


 As a first suggestion, would this be better:

 + if (!buf.st_dev)
 + buf.st_dev = toupper(real_path(path)[0]);

 (End of loose thinking)



-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html