2 * Copyright (C) 2005 Junio C Hamano
8 static int use_link
= 0;
9 static int use_symlink
= 0;
10 static int use_filecopy
= 1;
11 static int commits_on_stdin
= 0;
13 static const char *path
; /* "Remote" git repository */
15 void prefetch(unsigned char *sha1
)
19 static struct packed_git
*packs
= NULL
;
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
, namelen
, ".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
)
68 fprintf(stderr
, "does not exist %s\n", source
);
74 if (stat(source
, &st
)) {
75 if (!warn_if_not_exists
&& errno
== ENOENT
)
77 fprintf(stderr
, "cannot stat %s: %s\n", source
,
81 if (!symlink(source
, dest
)) {
82 pull_say("symlink %s\n", hex
);
87 int ifd
, ofd
, status
= 0;
89 ifd
= open(source
, O_RDONLY
);
91 if (!warn_if_not_exists
&& errno
== ENOENT
)
93 fprintf(stderr
, "cannot open %s\n", source
);
96 ofd
= open(dest
, O_WRONLY
| O_CREAT
| O_EXCL
, 0666);
98 fprintf(stderr
, "cannot open %s\n", dest
);
102 status
= copy_fd(ifd
, ofd
);
105 fprintf(stderr
, "cannot write %s\n", dest
);
107 pull_say("copy %s\n", hex
);
110 fprintf(stderr
, "failed to copy %s with given copy methods.\n", hex
);
114 static int fetch_pack(const unsigned char *sha1
)
116 struct packed_git
*target
;
117 char filename
[PATH_MAX
];
120 target
= find_sha1_pack(sha1
, packs
);
122 return error("Couldn't find %s: not separate or in any pack",
125 fprintf(stderr
, "Getting pack %s\n",
126 sha1_to_hex(target
->sha1
));
127 fprintf(stderr
, " which contains %s\n",
130 sprintf(filename
, "%s/objects/pack/pack-%s.pack",
131 path
, sha1_to_hex(target
->sha1
));
132 copy_file(filename
, sha1_pack_name(target
->sha1
),
133 sha1_to_hex(target
->sha1
), 1);
134 sprintf(filename
, "%s/objects/pack/pack-%s.idx",
135 path
, sha1_to_hex(target
->sha1
));
136 copy_file(filename
, sha1_pack_index_name(target
->sha1
),
137 sha1_to_hex(target
->sha1
), 1);
138 install_packed_git(target
);
142 static int fetch_file(const unsigned char *sha1
)
144 static int object_name_start
= -1;
145 static char filename
[PATH_MAX
];
146 char *hex
= sha1_to_hex(sha1
);
147 char *dest_filename
= sha1_file_name(sha1
);
149 if (object_name_start
< 0) {
150 strcpy(filename
, path
); /* e.g. git.git */
151 strcat(filename
, "/objects/");
152 object_name_start
= strlen(filename
);
154 filename
[object_name_start
+0] = hex
[0];
155 filename
[object_name_start
+1] = hex
[1];
156 filename
[object_name_start
+2] = '/';
157 strcpy(filename
+ object_name_start
+ 3, hex
+ 2);
158 return copy_file(filename
, dest_filename
, hex
, 0);
161 int fetch(unsigned char *sha1
)
163 if (has_sha1_file(sha1
))
166 return fetch_file(sha1
) && fetch_pack(sha1
);
169 int fetch_ref(char *ref
, unsigned char *sha1
)
171 static int ref_name_start
= -1;
172 static char filename
[PATH_MAX
];
176 if (ref_name_start
< 0) {
177 sprintf(filename
, "%s/refs/", path
);
178 ref_name_start
= strlen(filename
);
180 strcpy(filename
+ ref_name_start
, ref
);
181 ifd
= open(filename
, O_RDONLY
);
184 fprintf(stderr
, "cannot open %s\n", filename
);
187 if (read(ifd
, hex
, 40) != 40 || get_sha1_hex(hex
, sha1
)) {
189 fprintf(stderr
, "cannot read from %s\n", filename
);
193 pull_say("ref %s\n", sha1_to_hex(sha1
));
197 static const char local_pull_usage
[] =
198 "git-local-fetch [-c] [-t] [-a] [-v] [-w filename] [--recover] [-l] [-s] [-n] [--stdin] commit-id path";
201 * By default we only use file copy.
202 * If -l is specified, a hard link is attempted.
203 * If -s is specified, then a symlink is attempted.
204 * If -n is _not_ specified, then a regular file-to-file copy is done.
206 int main(int argc
, const char **argv
)
209 const char **write_ref
= NULL
;
214 setup_git_directory();
215 git_config(git_default_config
);
217 while (arg
< argc
&& argv
[arg
][0] == '-') {
218 if (argv
[arg
][1] == 't')
220 else if (argv
[arg
][1] == 'c')
222 else if (argv
[arg
][1] == 'a') {
227 else if (argv
[arg
][1] == 'l')
229 else if (argv
[arg
][1] == 's')
231 else if (argv
[arg
][1] == 'n')
233 else if (argv
[arg
][1] == 'v')
235 else if (argv
[arg
][1] == 'w')
236 write_ref
= &argv
[++arg
];
237 else if (!strcmp(argv
[arg
], "--recover"))
239 else if (!strcmp(argv
[arg
], "--stdin"))
240 commits_on_stdin
= 1;
242 usage(local_pull_usage
);
245 if (argc
< arg
+ 2 - commits_on_stdin
)
246 usage(local_pull_usage
);
247 if (commits_on_stdin
) {
248 commits
= pull_targets_stdin(&commit_id
, &write_ref
);
250 commit_id
= (char **) &argv
[arg
++];
255 if (pull(commits
, commit_id
, write_ref
, path
))
258 if (commits_on_stdin
)
259 pull_targets_free(commits
, commit_id
, write_ref
);