Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 238 lines (214 sloc) 6.182 kb
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
1 #include "cache.h"
8e44025 Use blob_, commit_, tag_, and tree_type throughout.
Peter Eriksen authored
2 #include "blob.h"
8ca12c0 @aspotashev add is_dot_or_dotdot inline function
aspotashev authored
3 #include "dir.h"
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
4
81a9aa6 create_directories(): remove some memcpy() and strchr() calls
Kjetil Barvik authored
5 static void create_directories(const char *path, int path_len,
6 const struct checkout *state)
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
7 {
81a9aa6 create_directories(): remove some memcpy() and strchr() calls
Kjetil Barvik authored
8 char *buf = xmalloc(path_len + 1);
9 int len = 0;
10
11 while (len < path_len) {
12 do {
13 buf[len] = path[len];
14 len++;
15 } while (len < path_len && path[len] != '/');
16 if (len >= path_len)
17 break;
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
18 buf[len] = 0;
fa2e71c @gitster Do not expect unlink(2) to fail on a directory.
gitster authored
19
bad4a54 lstat_cache(): introduce has_dirs_only_path() function
Kjetil Barvik authored
20 /*
21 * For 'checkout-index --prefix=<dir>', <dir> is
22 * allowed to be a symlink to an existing directory,
23 * and we set 'state->base_dir_len' below, such that
24 * we test the path components of the prefix with the
25 * stat() function instead of the lstat() function.
26 */
5719989 lstat_cache(): swap func(length, string) into func(string, length)
Kjetil Barvik authored
27 if (has_dirs_only_path(buf, len, state->base_dir_len))
fa2e71c @gitster Do not expect unlink(2) to fail on a directory.
gitster authored
28 continue; /* ok, it is already a directory. */
29
30 /*
bad4a54 lstat_cache(): introduce has_dirs_only_path() function
Kjetil Barvik authored
31 * If this mkdir() would fail, it could be that there
32 * is already a symlink or something else exists
33 * there, therefore we then try to unlink it and try
34 * one more time to create the directory.
fa2e71c @gitster Do not expect unlink(2) to fail on a directory.
gitster authored
35 */
f312de0 [PATCH] Let umask do its work upon filesystem object creation.
Junio C Hamano authored
36 if (mkdir(buf, 0777)) {
fa2e71c @gitster Do not expect unlink(2) to fail on a directory.
gitster authored
37 if (errno == EEXIST && state->force &&
691f1a2 @raalkml replace direct calls to unlink(2) with unlink_or_warn
raalkml authored
38 !unlink_or_warn(buf) && !mkdir(buf, 0777))
fa2e71c @gitster Do not expect unlink(2) to fail on a directory.
gitster authored
39 continue;
0721c31 @trast Use die_errno() instead of die() when checking syscalls
trast authored
40 die_errno("cannot create directory at '%s'", buf);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
41 }
42 }
43 free(buf);
44 }
45
46 static void remove_subtree(const char *path)
47 {
48 DIR *dir = opendir(path);
49 struct dirent *de;
50 char pathbuf[PATH_MAX];
51 char *name;
a6080a0 @gitster War on whitespace
gitster authored
52
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
53 if (!dir)
d824cbb @trast Convert existing die(..., strerror(errno)) to die_errno()
trast authored
54 die_errno("cannot opendir '%s'", path);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
55 strcpy(pathbuf, path);
56 name = pathbuf + strlen(path);
57 *name++ = '/';
58 while ((de = readdir(dir)) != NULL) {
59 struct stat st;
8ca12c0 @aspotashev add is_dot_or_dotdot inline function
aspotashev authored
60 if (is_dot_or_dotdot(de->d_name))
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
61 continue;
62 strcpy(name, de->d_name);
63 if (lstat(pathbuf, &st))
d824cbb @trast Convert existing die(..., strerror(errno)) to die_errno()
trast authored
64 die_errno("cannot lstat '%s'", pathbuf);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
65 if (S_ISDIR(st.st_mode))
66 remove_subtree(pathbuf);
67 else if (unlink(pathbuf))
d824cbb @trast Convert existing die(..., strerror(errno)) to die_errno()
trast authored
68 die_errno("cannot unlink '%s'", pathbuf);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
69 }
70 closedir(dir);
71 if (rmdir(path))
d824cbb @trast Convert existing die(..., strerror(errno)) to die_errno()
trast authored
72 die_errno("cannot rmdir '%s'", path);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
73 }
74
d48a72f Fix replacing of a directory with a file/symlink in git-checkout-cache
Linus Torvalds authored
75 static int create_file(const char *path, unsigned int mode)
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
76 {
77 mode = (mode & 0100) ? 0777 : 0666;
781411e @raalkml trivial: O_EXCL makes O_TRUNC redundant
raalkml authored
78 return open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
79 }
80
4857c76 write_entry(): cleanup of some duplicated code
Kjetil Barvik authored
81 static void *read_blob_entry(struct cache_entry *ce, unsigned long *size)
f0807e6 @torvalds Teach "git-read-tree -u" to check out submodules as a directory
torvalds authored
82 {
83 enum object_type type;
84 void *new = read_sha1_file(ce->sha1, &type, size);
85
86 if (new) {
87 if (type == OBJ_BLOB)
88 return new;
89 free(new);
90 }
91 return NULL;
92 }
93
efbc583 entry.c: Use const qualifier for 'struct checkout' parameters
Luiz Fernando N. Capitulino authored
94 static int write_entry(struct cache_entry *ce, char *path, const struct checkout *state, int to_tempfile)
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
95 {
4857c76 write_entry(): cleanup of some duplicated code
Kjetil Barvik authored
96 unsigned int ce_mode_s_ifmt = ce->ce_mode & S_IFMT;
e4c7292 write_entry(): use fstat() instead of lstat() when file is open
Kjetil Barvik authored
97 int fd, ret, fstat_done = 0;
4857c76 write_entry(): cleanup of some duplicated code
Kjetil Barvik authored
98 char *new;
99 struct strbuf buf = STRBUF_INIT;
100 unsigned long size;
101 size_t wrote, newsize = 0;
e4c7292 write_entry(): use fstat() instead of lstat() when file is open
Kjetil Barvik authored
102 struct stat st;
4857c76 write_entry(): cleanup of some duplicated code
Kjetil Barvik authored
103
104 switch (ce_mode_s_ifmt) {
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
105 case S_IFREG:
4857c76 write_entry(): cleanup of some duplicated code
Kjetil Barvik authored
106 case S_IFLNK:
107 new = read_blob_entry(ce, &size);
f0807e6 @torvalds Teach "git-read-tree -u" to check out submodules as a directory
torvalds authored
108 if (!new)
7e44c93 @gitster 'git foo' program identifies itself without dash in die() messages
gitster authored
109 return error("git checkout-index: unable to read sha1 file of %s (%s)",
f0807e6 @torvalds Teach "git-read-tree -u" to check out submodules as a directory
torvalds authored
110 path, sha1_to_hex(ce->sha1));
1a9d7e9 @gitster attr.c: read .gitattributes from index as well.
gitster authored
111
4857c76 write_entry(): cleanup of some duplicated code
Kjetil Barvik authored
112 if (ce_mode_s_ifmt == S_IFLNK && has_symlinks && !to_tempfile) {
113 ret = symlink(new, path);
114 free(new);
115 if (ret)
116 return error("git checkout-index: unable to create symlink %s (%s)",
117 path, strerror(errno));
118 break;
119 }
120
1a9d7e9 @gitster attr.c: read .gitattributes from index as well.
gitster authored
121 /*
122 * Convert from git internal format to working tree format
123 */
4857c76 write_entry(): cleanup of some duplicated code
Kjetil Barvik authored
124 if (ce_mode_s_ifmt == S_IFREG &&
125 convert_to_working_tree(ce->name, new, size, &buf)) {
1a9d7e9 @gitster attr.c: read .gitattributes from index as well.
gitster authored
126 free(new);
c32f749 Correct some sizeof(size_t) != sizeof(unsigned long) typing errors
René Scharfe authored
127 new = strbuf_detach(&buf, &newsize);
128 size = newsize;
1a9d7e9 @gitster attr.c: read .gitattributes from index as well.
gitster authored
129 }
130
de84f99 @spearce Add --temp and --stage=all options to checkout-index.
spearce authored
131 if (to_tempfile) {
4857c76 write_entry(): cleanup of some duplicated code
Kjetil Barvik authored
132 if (ce_mode_s_ifmt == S_IFREG)
133 strcpy(path, ".merge_file_XXXXXX");
134 else
135 strcpy(path, ".merge_link_XXXXXX");
de84f99 @spearce Add --temp and --stage=all options to checkout-index.
spearce authored
136 fd = mkstemp(path);
4857c76 write_entry(): cleanup of some duplicated code
Kjetil Barvik authored
137 } else if (ce_mode_s_ifmt == S_IFREG) {
7a51ed6 @torvalds Make on-disk index representation separate from in-core one
torvalds authored
138 fd = create_file(path, ce->ce_mode);
4857c76 write_entry(): cleanup of some duplicated code
Kjetil Barvik authored
139 } else {
140 fd = create_file(path, 0666);
141 }
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
142 if (fd < 0) {
143 free(new);
7e44c93 @gitster 'git foo' program identifies itself without dash in die() messages
gitster authored
144 return error("git checkout-index: unable to create file %s (%s)",
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
145 path, strerror(errno));
146 }
6c510be @torvalds Lazy man's auto-CRLF
torvalds authored
147
93822c2 @awhitcroft short i/o: fix calls to write to use xwrite or write_in_full
awhitcroft authored
148 wrote = write_in_full(fd, new, size);
e4c7292 write_entry(): use fstat() instead of lstat() when file is open
Kjetil Barvik authored
149 /* use fstat() only when path == ce->name */
34779c5 Windows: Skip fstat/lstat optimization in write_entry()
Johannes Sixt authored
150 if (fstat_is_reliable() &&
151 state->refresh_cache && !to_tempfile && !state->base_dir_len) {
e4c7292 write_entry(): use fstat() instead of lstat() when file is open
Kjetil Barvik authored
152 fstat(fd, &st);
153 fstat_done = 1;
154 }
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
155 close(fd);
156 free(new);
157 if (wrote != size)
7e44c93 @gitster 'git foo' program identifies itself without dash in die() messages
gitster authored
158 return error("git checkout-index: unable to write file %s", path);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
159 break;
302b928 @tali rename dirlink to gitlink.
tali authored
160 case S_IFGITLINK:
f0807e6 @torvalds Teach "git-read-tree -u" to check out submodules as a directory
torvalds authored
161 if (to_tempfile)
7e44c93 @gitster 'git foo' program identifies itself without dash in die() messages
gitster authored
162 return error("git checkout-index: cannot create temporary subproject %s", path);
f0807e6 @torvalds Teach "git-read-tree -u" to check out submodules as a directory
torvalds authored
163 if (mkdir(path, 0777) < 0)
7e44c93 @gitster 'git foo' program identifies itself without dash in die() messages
gitster authored
164 return error("git checkout-index: cannot create subproject directory %s", path);
f0807e6 @torvalds Teach "git-read-tree -u" to check out submodules as a directory
torvalds authored
165 break;
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
166 default:
7e44c93 @gitster 'git foo' program identifies itself without dash in die() messages
gitster authored
167 return error("git checkout-index: unknown file mode for %s", path);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
168 }
169
6ee67f2 Fix entry.c dependency and compile problem
Linus Torvalds authored
170 if (state->refresh_cache) {
e4c7292 write_entry(): use fstat() instead of lstat() when file is open
Kjetil Barvik authored
171 if (!fstat_done)
172 lstat(ce->name, &st);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
173 fill_stat_cache_info(ce, &st);
174 }
175 return 0;
176 }
177
b6986d8 @torvalds git-checkout: be careful about untracked symlinks
torvalds authored
178 /*
179 * This is like 'lstat()', except it refuses to follow symlinks
da02ca5 @gitster check_path(): allow symlinked directories to checkout-index --prefix
gitster authored
180 * in the path, after skipping "skiplen".
b6986d8 @torvalds git-checkout: be careful about untracked symlinks
torvalds authored
181 */
61b97df @gitster entry.c: mark file-local function static
gitster authored
182 static int check_path(const char *path, int len, struct stat *st, int skiplen)
b6986d8 @torvalds git-checkout: be careful about untracked symlinks
torvalds authored
183 {
da02ca5 @gitster check_path(): allow symlinked directories to checkout-index --prefix
gitster authored
184 const char *slash = path + len;
185
186 while (path < slash && *slash != '/')
187 slash--;
188 if (!has_dirs_only_path(path, slash - path, skiplen)) {
b6986d8 @torvalds git-checkout: be careful about untracked symlinks
torvalds authored
189 errno = ENOENT;
190 return -1;
191 }
192 return lstat(path, st);
193 }
194
efbc583 entry.c: Use const qualifier for 'struct checkout' parameters
Luiz Fernando N. Capitulino authored
195 int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath)
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
196 {
095c424 @jonas Use PATH_MAX instead of MAXPATHLEN
jonas authored
197 static char path[PATH_MAX + 1];
de84f99 @spearce Add --temp and --stage=all options to checkout-index.
spearce authored
198 struct stat st;
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
199 int len = state->base_dir_len;
200
de84f99 @spearce Add --temp and --stage=all options to checkout-index.
spearce authored
201 if (topath)
202 return write_entry(ce, topath, state, 1);
203
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
204 memcpy(path, state->base_dir, len);
205 strcpy(path + len, ce->name);
81a9aa6 create_directories(): remove some memcpy() and strchr() calls
Kjetil Barvik authored
206 len += ce_namelen(ce);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
207
da02ca5 @gitster check_path(): allow symlinked directories to checkout-index --prefix
gitster authored
208 if (!check_path(path, len, &st, state->base_dir_len)) {
56cac48 @pclouds ie_match_stat(): do not ignore skip-worktree bit with CE_MATCH_IGNORE_VA...
pclouds authored
209 unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
210 if (!changed)
211 return 0;
212 if (!state->force) {
213 if (!state->quiet)
215a7ad Big tool rename.
Junio C Hamano authored
214 fprintf(stderr, "git-checkout-index: %s already exists\n", path);
4b12dae Return error when not checking out an entry due to dirtiness.
Junio C Hamano authored
215 return -1;
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
216 }
217
218 /*
219 * We unlink the old file, to get the new one with the
220 * right permissions (including umask, which is nasty
221 * to emulate by hand - much easier to let the system
222 * just do the right thing)
223 */
d48a72f Fix replacing of a directory with a file/symlink in git-checkout-cache
Linus Torvalds authored
224 if (S_ISDIR(st.st_mode)) {
f0807e6 @torvalds Teach "git-read-tree -u" to check out submodules as a directory
torvalds authored
225 /* If it is a gitlink, leave it alone! */
7a51ed6 @torvalds Make on-disk index representation separate from in-core one
torvalds authored
226 if (S_ISGITLINK(ce->ce_mode))
f0807e6 @torvalds Teach "git-read-tree -u" to check out submodules as a directory
torvalds authored
227 return 0;
d48a72f Fix replacing of a directory with a file/symlink in git-checkout-cache
Linus Torvalds authored
228 if (!state->force)
229 return error("%s is a directory", path);
230 remove_subtree(path);
971f229 @torvalds Fix possible Solaris problem in 'checkout_entry()'
torvalds authored
231 } else if (unlink(path))
232 return error("unable to unlink old '%s' (%s)", path, strerror(errno));
de84f99 @spearce Add --temp and --stage=all options to checkout-index.
spearce authored
233 } else if (state->not_new)
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
234 return 0;
81a9aa6 create_directories(): remove some memcpy() and strchr() calls
Kjetil Barvik authored
235 create_directories(path, len, state);
de84f99 @spearce Add --temp and --stage=all options to checkout-index.
spearce authored
236 return write_entry(ce, path, state, 0);
12dccc1 Make fiel checkout function available to the git library
Linus Torvalds authored
237 }
Something went wrong with that request. Please try again.