Teach transport about the gitfile mechanism

The transport_get() function assumes that a regular file is a bundle rather than a local git directory. Look inside the file for the telltale "gitlink: " header to see if it is actually a gitfile. If so, do not try to process it as a bundle, but treat it as a local repository instead. Signed-off-by: Phil Hord <hordp@cisco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Phil Hord committed Oct 4, 2011 at 16:08 UTC 7ab8777e8dd365e9a5dc06eb3042903e296ef1b0
1 file changed +23 -1
transport.c
+23 -1
@@ -866,6 +866,28 @@ static int is_local(const char *url)
866 has_dos_drive_prefix(url);
867 }
868
869 +static int is_gitfile(const char *url)
870 +{
871 + struct stat st;
872 + char buf[9];
873 + int fd, len;
874 + if (stat(url, &st))
875 + return 0;
876 + if (!S_ISREG(st.st_mode))
877 + return 0;
878 + if (st.st_size < 10 || st.st_size > PATH_MAX)
879 + return 1;
880 +
881 + fd = open(url, O_RDONLY);
882 + if (fd < 0)
883 + die_errno("Error opening '%s'", url);
884 + len = read_in_full(fd, buf, sizeof(buf));
885 + close(fd);
886 + if (len != sizeof(buf))
887 + die("Error reading %s", url);
888 + return !prefixcmp(buf, "gitdir: ");
889 +}
890 +
891 static int is_file(const char *url)
892 {
893 struct stat buf;
@@ -914,7 +936,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
936 ret->fetch = fetch_objs_via_rsync;
937 ret->push = rsync_transport_push;
938 ret->smart_options = NULL;
917 - } else if (is_local(url) && is_file(url)) {
939 + } else if (is_local(url) && is_file(url) && !is_gitfile(url)) {
940 struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
941 ret->data = data;
942 ret->get_refs_list = get_refs_from_bundle;