Skip to content

Commit afd6284

Browse files
committed
Merge branch 'ph/transport-with-gitfile'
* ph/transport-with-gitfile: Fix is_gitfile() for files too small or larger than PATH_MAX to be a gitfile Add test showing git-fetch groks gitfiles Teach transport about the gitfile mechanism Learn to handle gitfiles in enter_repo enter_repo: do not modify input
2 parents 8963314 + 3ac6437 commit afd6284

File tree

5 files changed

+58
-20
lines changed

5 files changed

+58
-20
lines changed

cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ int safe_create_leading_directories(char *path);
736736
int safe_create_leading_directories_const(const char *path);
737737
int mkdir_in_gitdir(const char *path);
738738
extern char *expand_user_path(const char *path);
739-
char *enter_repo(char *path, int strict);
739+
const char *enter_repo(const char *path, int strict);
740740
static inline int is_absolute_path(const char *path)
741741
{
742742
return is_dir_sep(path[0]) || has_dos_drive_prefix(path);

daemon.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,11 @@ static void NORETURN daemon_die(const char *err, va_list params)
108108
exit(1);
109109
}
110110

111-
static char *path_ok(char *directory)
111+
static const char *path_ok(char *directory)
112112
{
113113
static char rpath[PATH_MAX];
114114
static char interp_path[PATH_MAX];
115-
char *path;
115+
const char *path;
116116
char *dir;
117117

118118
dir = directory;

path.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ char *expand_user_path(const char *path)
283283
* links. User relative paths are also returned as they are given,
284284
* except DWIM suffixing.
285285
*/
286-
char *enter_repo(char *path, int strict)
286+
const char *enter_repo(const char *path, int strict)
287287
{
288288
static char used_path[PATH_MAX];
289289
static char validated_path[PATH_MAX];
@@ -295,16 +295,19 @@ char *enter_repo(char *path, int strict)
295295
static const char *suffix[] = {
296296
".git/.git", "/.git", ".git", "", NULL,
297297
};
298+
const char *gitfile;
298299
int len = strlen(path);
299300
int i;
300-
while ((1 < len) && (path[len-1] == '/')) {
301-
path[len-1] = 0;
301+
while ((1 < len) && (path[len-1] == '/'))
302302
len--;
303-
}
303+
304304
if (PATH_MAX <= len)
305305
return NULL;
306-
if (path[0] == '~') {
307-
char *newpath = expand_user_path(path);
306+
strncpy(used_path, path, len); used_path[len] = 0 ;
307+
strcpy(validated_path, used_path);
308+
309+
if (used_path[0] == '~') {
310+
char *newpath = expand_user_path(used_path);
308311
if (!newpath || (PATH_MAX - 10 < strlen(newpath))) {
309312
free(newpath);
310313
return NULL;
@@ -316,24 +319,23 @@ char *enter_repo(char *path, int strict)
316319
* anyway.
317320
*/
318321
strcpy(used_path, newpath); free(newpath);
319-
strcpy(validated_path, path);
320-
path = used_path;
321322
}
322323
else if (PATH_MAX - 10 < len)
323324
return NULL;
324-
else {
325-
path = strcpy(used_path, path);
326-
strcpy(validated_path, path);
327-
}
328-
len = strlen(path);
325+
len = strlen(used_path);
329326
for (i = 0; suffix[i]; i++) {
330-
strcpy(path + len, suffix[i]);
331-
if (!access(path, F_OK)) {
327+
strcpy(used_path + len, suffix[i]);
328+
if (!access(used_path, F_OK)) {
332329
strcat(validated_path, suffix[i]);
333330
break;
334331
}
335332
}
336-
if (!suffix[i] || chdir(path))
333+
if (!suffix[i])
334+
return NULL;
335+
gitfile = read_gitfile(used_path) ;
336+
if (gitfile)
337+
strcpy(used_path, gitfile);
338+
if (chdir(used_path))
337339
return NULL;
338340
path = validated_path;
339341
}

t/t5601-clone.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,20 @@ test_expect_success 'clone from .git file' '
206206
git clone dst/.git dst2
207207
'
208208

209+
test_expect_success 'fetch from .git gitfile' '
210+
(
211+
cd dst2 &&
212+
git fetch ../dst/.git
213+
)
214+
'
215+
216+
test_expect_success 'fetch from gitfile parent' '
217+
(
218+
cd dst2 &&
219+
git fetch ../dst
220+
)
221+
'
222+
209223
test_expect_success 'clone separate gitdir where target already exists' '
210224
rm -rf dst &&
211225
test_must_fail git clone --separate-git-dir realgitdir src dst

transport.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,28 @@ static int is_local(const char *url)
859859
has_dos_drive_prefix(url);
860860
}
861861

862+
static int is_gitfile(const char *url)
863+
{
864+
struct stat st;
865+
char buf[9];
866+
int fd, len;
867+
if (stat(url, &st))
868+
return 0;
869+
if (!S_ISREG(st.st_mode))
870+
return 0;
871+
if (st.st_size < 10 || st.st_size > 9 + PATH_MAX)
872+
return 0;
873+
874+
fd = open(url, O_RDONLY);
875+
if (fd < 0)
876+
die_errno("Error opening '%s'", url);
877+
len = read_in_full(fd, buf, sizeof(buf));
878+
close(fd);
879+
if (len != sizeof(buf))
880+
die("Error reading %s", url);
881+
return !prefixcmp(buf, "gitdir: ");
882+
}
883+
862884
static int is_file(const char *url)
863885
{
864886
struct stat buf;
@@ -907,7 +929,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
907929
ret->fetch = fetch_objs_via_rsync;
908930
ret->push = rsync_transport_push;
909931
ret->smart_options = NULL;
910-
} else if (is_local(url) && is_file(url)) {
932+
} else if (is_local(url) && is_file(url) && !is_gitfile(url)) {
911933
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
912934
ret->data = data;
913935
ret->get_refs_list = get_refs_from_bundle;

0 commit comments

Comments
 (0)