Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Junio C Hamano committed Oct 21, 2011
2 parents 8963314 + 3ac6437 commit afd6284
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 20 deletions.
2 changes: 1 addition & 1 deletion cache.h
Expand Up @@ -736,7 +736,7 @@ int safe_create_leading_directories(char *path);
int safe_create_leading_directories_const(const char *path);
int mkdir_in_gitdir(const char *path);
extern char *expand_user_path(const char *path);
char *enter_repo(char *path, int strict);
const char *enter_repo(const char *path, int strict);
static inline int is_absolute_path(const char *path)
{
return is_dir_sep(path[0]) || has_dos_drive_prefix(path);
Expand Down
4 changes: 2 additions & 2 deletions daemon.c
Expand Up @@ -108,11 +108,11 @@ static void NORETURN daemon_die(const char *err, va_list params)
exit(1);
}

static char *path_ok(char *directory)
static const char *path_ok(char *directory)
{
static char rpath[PATH_MAX];
static char interp_path[PATH_MAX];
char *path;
const char *path;
char *dir;

dir = directory;
Expand Down
34 changes: 18 additions & 16 deletions path.c
Expand Up @@ -283,7 +283,7 @@ char *expand_user_path(const char *path)
* links. User relative paths are also returned as they are given,
* except DWIM suffixing.
*/
char *enter_repo(char *path, int strict)
const char *enter_repo(const char *path, int strict)
{
static char used_path[PATH_MAX];
static char validated_path[PATH_MAX];
Expand All @@ -295,16 +295,19 @@ char *enter_repo(char *path, int strict)
static const char *suffix[] = {
".git/.git", "/.git", ".git", "", NULL,
};
const char *gitfile;
int len = strlen(path);
int i;
while ((1 < len) && (path[len-1] == '/')) {
path[len-1] = 0;
while ((1 < len) && (path[len-1] == '/'))
len--;
}

if (PATH_MAX <= len)
return NULL;
if (path[0] == '~') {
char *newpath = expand_user_path(path);
strncpy(used_path, path, len); used_path[len] = 0 ;
strcpy(validated_path, used_path);

if (used_path[0] == '~') {
char *newpath = expand_user_path(used_path);
if (!newpath || (PATH_MAX - 10 < strlen(newpath))) {
free(newpath);
return NULL;
Expand All @@ -316,24 +319,23 @@ char *enter_repo(char *path, int strict)
* anyway.
*/
strcpy(used_path, newpath); free(newpath);
strcpy(validated_path, path);
path = used_path;
}
else if (PATH_MAX - 10 < len)
return NULL;
else {
path = strcpy(used_path, path);
strcpy(validated_path, path);
}
len = strlen(path);
len = strlen(used_path);
for (i = 0; suffix[i]; i++) {
strcpy(path + len, suffix[i]);
if (!access(path, F_OK)) {
strcpy(used_path + len, suffix[i]);
if (!access(used_path, F_OK)) {
strcat(validated_path, suffix[i]);
break;
}
}
if (!suffix[i] || chdir(path))
if (!suffix[i])
return NULL;
gitfile = read_gitfile(used_path) ;
if (gitfile)
strcpy(used_path, gitfile);
if (chdir(used_path))
return NULL;
path = validated_path;
}
Expand Down
14 changes: 14 additions & 0 deletions t/t5601-clone.sh
Expand Up @@ -206,6 +206,20 @@ test_expect_success 'clone from .git file' '
git clone dst/.git dst2
'

test_expect_success 'fetch from .git gitfile' '
(
cd dst2 &&
git fetch ../dst/.git
)
'

test_expect_success 'fetch from gitfile parent' '
(
cd dst2 &&
git fetch ../dst
)
'

test_expect_success 'clone separate gitdir where target already exists' '
rm -rf dst &&
test_must_fail git clone --separate-git-dir realgitdir src dst
Expand Down
24 changes: 23 additions & 1 deletion transport.c
Expand Up @@ -859,6 +859,28 @@ static int is_local(const char *url)
has_dos_drive_prefix(url);
}

static int is_gitfile(const char *url)
{
struct stat st;
char buf[9];
int fd, len;
if (stat(url, &st))
return 0;
if (!S_ISREG(st.st_mode))
return 0;
if (st.st_size < 10 || st.st_size > 9 + PATH_MAX)
return 0;

fd = open(url, O_RDONLY);
if (fd < 0)
die_errno("Error opening '%s'", url);
len = read_in_full(fd, buf, sizeof(buf));
close(fd);
if (len != sizeof(buf))
die("Error reading %s", url);
return !prefixcmp(buf, "gitdir: ");
}

static int is_file(const char *url)
{
struct stat buf;
Expand Down Expand Up @@ -907,7 +929,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->fetch = fetch_objs_via_rsync;
ret->push = rsync_transport_push;
ret->smart_options = NULL;
} else if (is_local(url) && is_file(url)) {
} else if (is_local(url) && is_file(url) && !is_gitfile(url)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
ret->get_refs_list = get_refs_from_bundle;
Expand Down

0 comments on commit afd6284

Please sign in to comment.