clone: use computed length in guess_dir_name

Commit 7e837c6 (clone: simplify string handling in guess_dir_name(), 2015-07-09) changed clone to use strip_suffix instead of hand-rolled pointer manipulation. However, strip_suffix will strip from the end of a NUL-terminated string, and we may have already stripped some characters (like directory separators, or "/.git"). This leads to commands like: git clone host:foo.git/ failing to strip the ".git". We must instead convert our pointer arithmetic into a computed length and feed that to strip_suffix_mem, which will then reduce the length further for us. It would be nicer if we could drop the pointer manipulation entirely, and just continually strip using strip_suffix. But that doesn't quite work for two reasons: 1. The early suffixes we're stripping are not constant; we need to look for is_dir_sep, which could be one of several characters. 2. Mid-way through the stripping we compute the pointer "start", which shows us the beginning of the pathname. Which really give us two lengths to work with: the offset from the start of the string, and from the start of the path. By using pointers for the early part, we can just compute the length from "start" when we need it. Signed-off-by: Jeff King <peff@peff.net> Acked-by: Sebastian Schuberth <sschuberth@gmail.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Aug 10, 2015 at 17:48 UTC db2e220447f7b02278d64417c8f05f73710f5b8b
2 files changed +8 -7
builtin/clone.c
+2 -1
@@ -174,7 +174,8 @@ static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
174 /*
175 * Strip .{bundle,git}.
176 */
177 - strip_suffix(start, is_bundle ? ".bundle" : ".git" , &len);
177 + len = end - start;
178 + strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
179
180 if (is_bare)
181 dir = xstrfmt("%.*s.git", (int)len, start);
t/t5603-clone-dirname.sh
+6 -6
@@ -47,7 +47,7 @@ test_clone_dir host:foo foo.git bare
47 test_clone_dir host:foo.git foo
48 test_clone_dir host:foo.git foo.git bare
49 test_clone_dir host:foo/.git foo
50 -test_clone_dir host:foo/.git foo.git bare fail
50 +test_clone_dir host:foo/.git foo.git bare
51
52 # similar, but using ssh URL rather than host:path syntax
53 test_clone_dir ssh://host/foo foo
@@ -55,22 +55,22 @@ test_clone_dir ssh://host/foo foo.git bare
55 test_clone_dir ssh://host/foo.git foo
56 test_clone_dir ssh://host/foo.git foo.git bare
57 test_clone_dir ssh://host/foo/.git foo
58 -test_clone_dir ssh://host/foo/.git foo.git bare fail
58 +test_clone_dir ssh://host/foo/.git foo.git bare
59
60 # we should remove trailing slashes and .git suffixes
61 test_clone_dir ssh://host/foo/ foo
62 test_clone_dir ssh://host/foo/// foo
63 test_clone_dir ssh://host/foo/.git/ foo
64 -test_clone_dir ssh://host/foo.git/ foo fail
65 -test_clone_dir ssh://host/foo.git/// foo fail
64 +test_clone_dir ssh://host/foo.git/ foo
65 +test_clone_dir ssh://host/foo.git/// foo
66 test_clone_dir ssh://host/foo///.git/ foo
67 test_clone_dir ssh://host/foo/.git/// foo
68
69 test_clone_dir host:foo/ foo
70 test_clone_dir host:foo/// foo
71 -test_clone_dir host:foo.git/ foo fail
71 +test_clone_dir host:foo.git/ foo
72 test_clone_dir host:foo/.git/ foo
73 -test_clone_dir host:foo.git/// foo fail
73 +test_clone_dir host:foo.git/// foo
74 test_clone_dir host:foo///.git/ foo
75 test_clone_dir host:foo/.git/// foo
76