2 * Copyright (C) 2005 Junio C Hamano
9 static int use_symlink
;
10 static int use_filecopy
= 1;
11 static int commits_on_stdin
;
13 static const char *path
; /* "Remote" git repository */
15 void prefetch(unsigned char *sha1
)
19 static struct packed_git
*packs
;
21 static void setup_index(unsigned char *sha1
)
23 struct packed_git
*new_pack
;
24 char filename
[PATH_MAX
];
25 strcpy(filename
, path
);
26 strcat(filename
, "/objects/pack/pack-");
27 strcat(filename
, sha1_to_hex(sha1
));
28 strcat(filename
, ".idx");
29 new_pack
= parse_pack_index_file(sha1
, filename
);
30 new_pack
->next
= packs
;
34 static int setup_indices(void)
38 char filename
[PATH_MAX
];
39 unsigned char sha1
[20];
40 sprintf(filename
, "%s/objects/pack/", path
);
41 dir
= opendir(filename
);
44 while ((de
= readdir(dir
)) != NULL
) {
45 int namelen
= strlen(de
->d_name
);
47 !has_extension(de
->d_name
, ".pack"))
49 get_sha1_hex(de
->d_name
+ 5, sha1
);
56 static int copy_file(const char *source
, char *dest
, const char *hex
,
57 int warn_if_not_exists
)
59 safe_create_leading_directories(dest
);
61 if (!link(source
, dest
)) {
62 pull_say("link %s\n", hex
);
65 /* If we got ENOENT there is no point continuing. */
66 if (errno
== ENOENT
) {
67 if (!warn_if_not_exists
)
69 return error("does not exist %s", source
);
74 if (stat(source
, &st
)) {
75 if (!warn_if_not_exists
&& errno
== ENOENT
)
77 return error("cannot stat %s: %s", source
,
80 if (!symlink(source
, dest
)) {
81 pull_say("symlink %s\n", hex
);
86 int ifd
, ofd
, status
= 0;
88 ifd
= open(source
, O_RDONLY
);
90 if (!warn_if_not_exists
&& errno
== ENOENT
)
92 return error("cannot open %s", source
);
94 ofd
= open(dest
, O_WRONLY
| O_CREAT
| O_EXCL
, 0666);
97 return error("cannot open %s", dest
);
99 status
= copy_fd(ifd
, ofd
);
102 return error("cannot write %s", dest
);
103 pull_say("copy %s\n", hex
);
106 return error("failed to copy %s with given copy methods.", hex
);
109 static int fetch_pack(const unsigned char *sha1
)
111 struct packed_git
*target
;
112 char filename
[PATH_MAX
];
115 target
= find_sha1_pack(sha1
, packs
);
117 return error("Couldn't find %s: not separate or in any pack",
120 fprintf(stderr
, "Getting pack %s\n",
121 sha1_to_hex(target
->sha1
));
122 fprintf(stderr
, " which contains %s\n",
125 sprintf(filename
, "%s/objects/pack/pack-%s.pack",
126 path
, sha1_to_hex(target
->sha1
));
127 copy_file(filename
, sha1_pack_name(target
->sha1
),
128 sha1_to_hex(target
->sha1
), 1);
129 sprintf(filename
, "%s/objects/pack/pack-%s.idx",
130 path
, sha1_to_hex(target
->sha1
));
131 copy_file(filename
, sha1_pack_index_name(target
->sha1
),
132 sha1_to_hex(target
->sha1
), 1);
133 install_packed_git(target
);
137 static int fetch_file(const unsigned char *sha1
)
139 static int object_name_start
= -1;
140 static char filename
[PATH_MAX
];
141 char *hex
= sha1_to_hex(sha1
);
142 char *dest_filename
= sha1_file_name(sha1
);
144 if (object_name_start
< 0) {
145 strcpy(filename
, path
); /* e.g. git.git */
146 strcat(filename
, "/objects/");
147 object_name_start
= strlen(filename
);
149 filename
[object_name_start
+0] = hex
[0];
150 filename
[object_name_start
+1] = hex
[1];
151 filename
[object_name_start
+2] = '/';
152 strcpy(filename
+ object_name_start
+ 3, hex
+ 2);
153 return copy_file(filename
, dest_filename
, hex
, 0);
156 int fetch(unsigned char *sha1
)
158 if (has_sha1_file(sha1
))
161 return fetch_file(sha1
) && fetch_pack(sha1
);
164 int fetch_ref(char *ref
, unsigned char *sha1
)
166 static int ref_name_start
= -1;
167 static char filename
[PATH_MAX
];
171 if (ref_name_start
< 0) {
172 sprintf(filename
, "%s/refs/", path
);
173 ref_name_start
= strlen(filename
);
175 strcpy(filename
+ ref_name_start
, ref
);
176 ifd
= open(filename
, O_RDONLY
);
179 return error("cannot open %s", filename
);
181 if (read_in_full(ifd
, hex
, 40) != 40 || get_sha1_hex(hex
, sha1
)) {
183 return error("cannot read from %s", filename
);
186 pull_say("ref %s\n", sha1_to_hex(sha1
));
190 static const char local_pull_usage
[] =
191 "git-local-fetch [-c] [-t] [-a] [-v] [-w filename] [--recover] [-l] [-s] [-n] [--stdin] commit-id path";
194 * By default we only use file copy.
195 * If -l is specified, a hard link is attempted.
196 * If -s is specified, then a symlink is attempted.
197 * If -n is _not_ specified, then a regular file-to-file copy is done.
199 int main(int argc
, const char **argv
)
202 const char **write_ref
= NULL
;
206 setup_git_directory();
207 git_config(git_default_config
);
209 while (arg
< argc
&& argv
[arg
][0] == '-') {
210 if (argv
[arg
][1] == 't')
212 else if (argv
[arg
][1] == 'c')
214 else if (argv
[arg
][1] == 'a') {
219 else if (argv
[arg
][1] == 'l')
221 else if (argv
[arg
][1] == 's')
223 else if (argv
[arg
][1] == 'n')
225 else if (argv
[arg
][1] == 'v')
227 else if (argv
[arg
][1] == 'w')
228 write_ref
= &argv
[++arg
];
229 else if (!strcmp(argv
[arg
], "--recover"))
231 else if (!strcmp(argv
[arg
], "--stdin"))
232 commits_on_stdin
= 1;
234 usage(local_pull_usage
);
237 if (argc
< arg
+ 2 - commits_on_stdin
)
238 usage(local_pull_usage
);
239 if (commits_on_stdin
) {
240 commits
= pull_targets_stdin(&commit_id
, &write_ref
);
242 commit_id
= (char **) &argv
[arg
++];
247 if (pull(commits
, commit_id
, write_ref
, path
))
250 if (commits_on_stdin
)
251 pull_targets_free(commits
, commit_id
, write_ref
);