Blame


1 86c3caaf 2018-03-09 stsp /*
2 86c3caaf 2018-03-09 stsp * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
3 86c3caaf 2018-03-09 stsp *
4 86c3caaf 2018-03-09 stsp * Permission to use, copy, modify, and distribute this software for any
5 86c3caaf 2018-03-09 stsp * purpose with or without fee is hereby granted, provided that the above
6 86c3caaf 2018-03-09 stsp * copyright notice and this permission notice appear in all copies.
7 86c3caaf 2018-03-09 stsp *
8 86c3caaf 2018-03-09 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 86c3caaf 2018-03-09 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 86c3caaf 2018-03-09 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 86c3caaf 2018-03-09 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 86c3caaf 2018-03-09 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 86c3caaf 2018-03-09 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 86c3caaf 2018-03-09 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 86c3caaf 2018-03-09 stsp */
16 86c3caaf 2018-03-09 stsp
17 86c3caaf 2018-03-09 stsp #include <sys/stat.h>
18 86c3caaf 2018-03-09 stsp
19 86c3caaf 2018-03-09 stsp #include <string.h>
20 86c3caaf 2018-03-09 stsp #include <stdio.h>
21 86c3caaf 2018-03-09 stsp #include <stdlib.h>
22 86c3caaf 2018-03-09 stsp #include <fcntl.h>
23 86c3caaf 2018-03-09 stsp #include <errno.h>
24 86c3caaf 2018-03-09 stsp #include <unistd.h>
25 86c3caaf 2018-03-09 stsp
26 86c3caaf 2018-03-09 stsp #include "got_error.h"
27 86c3caaf 2018-03-09 stsp #include "got_repository.h"
28 86c3caaf 2018-03-09 stsp #include "got_refs.h"
29 86c3caaf 2018-03-09 stsp #include "got_worktree.h"
30 86c3caaf 2018-03-09 stsp
31 86c3caaf 2018-03-09 stsp #include "got_worktree_priv.h"
32 86c3caaf 2018-03-09 stsp #include "got_path_priv.h"
33 86c3caaf 2018-03-09 stsp
34 86c3caaf 2018-03-09 stsp const struct got_error *
35 86c3caaf 2018-03-09 stsp got_worktree_init(const char *path, struct got_reference *head_ref,
36 86c3caaf 2018-03-09 stsp struct got_repository *repo)
37 86c3caaf 2018-03-09 stsp {
38 86c3caaf 2018-03-09 stsp const struct got_error *err = NULL;
39 86c3caaf 2018-03-09 stsp char *abspath = NULL;
40 86c3caaf 2018-03-09 stsp char *normpath = NULL;
41 86c3caaf 2018-03-09 stsp char *gotpath = NULL;
42 86c3caaf 2018-03-09 stsp char *indexpath = NULL;
43 86c3caaf 2018-03-09 stsp char *headpath = NULL;
44 86c3caaf 2018-03-09 stsp char *repopath = NULL;
45 86c3caaf 2018-03-09 stsp char *refstr = NULL;
46 86c3caaf 2018-03-09 stsp char *path_repos = NULL;
47 86c3caaf 2018-03-09 stsp char buf[4];
48 86c3caaf 2018-03-09 stsp ssize_t n;
49 86c3caaf 2018-03-09 stsp int fd;
50 86c3caaf 2018-03-09 stsp
51 86c3caaf 2018-03-09 stsp if (got_path_is_absolute(path)) {
52 86c3caaf 2018-03-09 stsp abspath = strdup(path);
53 86c3caaf 2018-03-09 stsp if (abspath == NULL)
54 86c3caaf 2018-03-09 stsp return got_error(GOT_ERR_NO_MEM);
55 86c3caaf 2018-03-09 stsp } else {
56 86c3caaf 2018-03-09 stsp abspath = got_path_get_absolute(path);
57 86c3caaf 2018-03-09 stsp if (abspath == NULL)
58 86c3caaf 2018-03-09 stsp return got_error(GOT_ERR_BAD_PATH);
59 86c3caaf 2018-03-09 stsp }
60 86c3caaf 2018-03-09 stsp
61 86c3caaf 2018-03-09 stsp /* Create top-level directory (may already exist). */
62 86c3caaf 2018-03-09 stsp normpath = got_path_normalize(abspath);
63 86c3caaf 2018-03-09 stsp if (normpath == NULL) {
64 86c3caaf 2018-03-09 stsp err = got_error(GOT_ERR_BAD_PATH);
65 86c3caaf 2018-03-09 stsp goto done;
66 86c3caaf 2018-03-09 stsp }
67 86c3caaf 2018-03-09 stsp if (mkdir(normpath, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
68 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
69 86c3caaf 2018-03-09 stsp goto done;
70 86c3caaf 2018-03-09 stsp }
71 86c3caaf 2018-03-09 stsp
72 86c3caaf 2018-03-09 stsp /* Create .got directory (may already exist). */
73 86c3caaf 2018-03-09 stsp if (asprintf(&gotpath, "%s/%s", normpath, GOT_WORKTREE_GOT_DIR) == -1) {
74 86c3caaf 2018-03-09 stsp err = got_error(GOT_ERR_NO_MEM);
75 86c3caaf 2018-03-09 stsp goto done;
76 86c3caaf 2018-03-09 stsp }
77 86c3caaf 2018-03-09 stsp if (mkdir(gotpath, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
78 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
79 86c3caaf 2018-03-09 stsp goto done;
80 86c3caaf 2018-03-09 stsp }
81 86c3caaf 2018-03-09 stsp
82 86c3caaf 2018-03-09 stsp /* Create an empty file index. */
83 86c3caaf 2018-03-09 stsp if (asprintf(&indexpath, "%s/%s", gotpath, GOT_WORKTREE_FILE_INDEX)
84 86c3caaf 2018-03-09 stsp == -1) {
85 86c3caaf 2018-03-09 stsp err = got_error(GOT_ERR_NO_MEM);
86 86c3caaf 2018-03-09 stsp goto done;
87 86c3caaf 2018-03-09 stsp }
88 86c3caaf 2018-03-09 stsp fd = open(indexpath, O_RDWR | O_CREAT | O_EXCL | O_EXLOCK | O_NOFOLLOW,
89 86c3caaf 2018-03-09 stsp GOT_DEFAULT_FILE_MODE);
90 86c3caaf 2018-03-09 stsp if (fd == -1) {
91 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
92 86c3caaf 2018-03-09 stsp goto done;
93 86c3caaf 2018-03-09 stsp }
94 86c3caaf 2018-03-09 stsp n = read(fd, buf, sizeof(buf));
95 86c3caaf 2018-03-09 stsp if (n != 0) {
96 86c3caaf 2018-03-09 stsp err = (n == -1 ? got_error_from_errno() :
97 86c3caaf 2018-03-09 stsp got_error(GOT_ERR_WORKTREE_EXISTS));
98 86c3caaf 2018-03-09 stsp close(fd);
99 86c3caaf 2018-03-09 stsp goto done;
100 86c3caaf 2018-03-09 stsp }
101 86c3caaf 2018-03-09 stsp if (close(fd) == -1) {
102 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
103 86c3caaf 2018-03-09 stsp goto done;
104 86c3caaf 2018-03-09 stsp }
105 86c3caaf 2018-03-09 stsp
106 86c3caaf 2018-03-09 stsp /* Write the HEAD reference. */
107 86c3caaf 2018-03-09 stsp refstr = got_ref_to_str(head_ref);
108 86c3caaf 2018-03-09 stsp if (refstr == NULL) {
109 86c3caaf 2018-03-09 stsp err = got_error(GOT_ERR_NO_MEM);
110 86c3caaf 2018-03-09 stsp goto done;
111 86c3caaf 2018-03-09 stsp }
112 86c3caaf 2018-03-09 stsp if (asprintf(&headpath, "%s/%s", gotpath, GOT_REF_HEAD) == -1) {
113 86c3caaf 2018-03-09 stsp err = got_error(GOT_ERR_NO_MEM);
114 86c3caaf 2018-03-09 stsp goto done;
115 86c3caaf 2018-03-09 stsp }
116 86c3caaf 2018-03-09 stsp fd = open(headpath, O_RDWR | O_CREAT | O_EXCL | O_EXLOCK | O_NOFOLLOW,
117 86c3caaf 2018-03-09 stsp GOT_DEFAULT_FILE_MODE);
118 86c3caaf 2018-03-09 stsp if (fd == -1) {
119 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
120 86c3caaf 2018-03-09 stsp goto done;
121 86c3caaf 2018-03-09 stsp }
122 86c3caaf 2018-03-09 stsp n = read(fd, buf, sizeof(buf));
123 86c3caaf 2018-03-09 stsp if (n != 0) {
124 86c3caaf 2018-03-09 stsp err = (n == -1 ? got_error_from_errno() :
125 86c3caaf 2018-03-09 stsp got_error(GOT_ERR_WORKTREE_EXISTS));
126 86c3caaf 2018-03-09 stsp close(fd);
127 86c3caaf 2018-03-09 stsp goto done;
128 86c3caaf 2018-03-09 stsp }
129 86c3caaf 2018-03-09 stsp n = write(fd, refstr, strlen(refstr));
130 86c3caaf 2018-03-09 stsp if (n != strlen(refstr)) {
131 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
132 86c3caaf 2018-03-09 stsp close(fd);
133 86c3caaf 2018-03-09 stsp goto done;
134 86c3caaf 2018-03-09 stsp }
135 86c3caaf 2018-03-09 stsp n = write(fd, "\n", 1);
136 86c3caaf 2018-03-09 stsp if (n != 1) {
137 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
138 86c3caaf 2018-03-09 stsp close(fd);
139 86c3caaf 2018-03-09 stsp goto done;
140 86c3caaf 2018-03-09 stsp }
141 86c3caaf 2018-03-09 stsp if (close(fd) == -1) {
142 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
143 86c3caaf 2018-03-09 stsp goto done;
144 86c3caaf 2018-03-09 stsp }
145 86c3caaf 2018-03-09 stsp
146 86c3caaf 2018-03-09 stsp /* Store path to repository. */
147 f0e4a7b7 2018-03-10 stsp if (asprintf(&repopath, "%s/%s", gotpath, GOT_WORKTREE_REPOSITORY)
148 f0e4a7b7 2018-03-10 stsp == -1) {
149 86c3caaf 2018-03-09 stsp err = got_error(GOT_ERR_NO_MEM);
150 86c3caaf 2018-03-09 stsp goto done;
151 86c3caaf 2018-03-09 stsp }
152 86c3caaf 2018-03-09 stsp fd = open(repopath, O_RDWR | O_CREAT | O_EXCL | O_EXLOCK | O_NOFOLLOW,
153 86c3caaf 2018-03-09 stsp GOT_DEFAULT_FILE_MODE);
154 86c3caaf 2018-03-09 stsp if (fd == -1) {
155 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
156 86c3caaf 2018-03-09 stsp goto done;
157 86c3caaf 2018-03-09 stsp }
158 86c3caaf 2018-03-09 stsp n = read(fd, buf, sizeof(buf));
159 86c3caaf 2018-03-09 stsp if (n != 0) {
160 86c3caaf 2018-03-09 stsp err = (n == -1 ? got_error_from_errno() :
161 86c3caaf 2018-03-09 stsp got_error(GOT_ERR_WORKTREE_EXISTS));
162 86c3caaf 2018-03-09 stsp close(fd);
163 86c3caaf 2018-03-09 stsp goto done;
164 86c3caaf 2018-03-09 stsp }
165 86c3caaf 2018-03-09 stsp path_repos = got_repo_get_path(repo);
166 86c3caaf 2018-03-09 stsp if (path_repos == NULL) {
167 86c3caaf 2018-03-09 stsp err = got_error(GOT_ERR_NO_MEM);
168 86c3caaf 2018-03-09 stsp goto done;
169 86c3caaf 2018-03-09 stsp }
170 86c3caaf 2018-03-09 stsp n = write(fd, path_repos, strlen(path_repos));
171 86c3caaf 2018-03-09 stsp if (n != strlen(path_repos)) {
172 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
173 86c3caaf 2018-03-09 stsp close(fd);
174 86c3caaf 2018-03-09 stsp goto done;
175 86c3caaf 2018-03-09 stsp }
176 86c3caaf 2018-03-09 stsp n = write(fd, "\n", 1);
177 86c3caaf 2018-03-09 stsp if (n != 1) {
178 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
179 86c3caaf 2018-03-09 stsp close(fd);
180 86c3caaf 2018-03-09 stsp goto done;
181 86c3caaf 2018-03-09 stsp }
182 86c3caaf 2018-03-09 stsp if (close(fd) == -1) {
183 86c3caaf 2018-03-09 stsp err = got_error_from_errno();
184 86c3caaf 2018-03-09 stsp goto done;
185 86c3caaf 2018-03-09 stsp }
186 86c3caaf 2018-03-09 stsp
187 86c3caaf 2018-03-09 stsp done:
188 86c3caaf 2018-03-09 stsp free(abspath);
189 86c3caaf 2018-03-09 stsp free(normpath);
190 86c3caaf 2018-03-09 stsp free(gotpath);
191 86c3caaf 2018-03-09 stsp free(indexpath);
192 86c3caaf 2018-03-09 stsp free(headpath);
193 86c3caaf 2018-03-09 stsp free(repopath);
194 86c3caaf 2018-03-09 stsp free(refstr);
195 86c3caaf 2018-03-09 stsp free(path_repos);
196 86c3caaf 2018-03-09 stsp return err;
197 86c3caaf 2018-03-09 stsp }
198 86c3caaf 2018-03-09 stsp
199 86c3caaf 2018-03-09 stsp const struct got_error *
200 86c3caaf 2018-03-09 stsp got_worktree_open(struct got_worktree **worktree, const char *path)
201 86c3caaf 2018-03-09 stsp {
202 86c3caaf 2018-03-09 stsp return NULL;
203 86c3caaf 2018-03-09 stsp }
204 86c3caaf 2018-03-09 stsp
205 86c3caaf 2018-03-09 stsp void
206 86c3caaf 2018-03-09 stsp got_worktree_close(struct got_worktree *worktree)
207 86c3caaf 2018-03-09 stsp {
208 86c3caaf 2018-03-09 stsp }
209 86c3caaf 2018-03-09 stsp
210 86c3caaf 2018-03-09 stsp char *
211 86c3caaf 2018-03-09 stsp got_worktree_get_repo_path(struct got_worktree *worktree)
212 86c3caaf 2018-03-09 stsp {
213 86c3caaf 2018-03-09 stsp return strdup(worktree->path_repo);
214 86c3caaf 2018-03-09 stsp }
215 86c3caaf 2018-03-09 stsp
216 86c3caaf 2018-03-09 stsp struct got_reference *
217 86c3caaf 2018-03-09 stsp got_worktree_get_head(struct got_worktree *worktree)
218 86c3caaf 2018-03-09 stsp {
219 86c3caaf 2018-03-09 stsp return NULL;
220 86c3caaf 2018-03-09 stsp }
221 86c3caaf 2018-03-09 stsp
222 86c3caaf 2018-03-09 stsp const struct got_error *
223 86c3caaf 2018-03-09 stsp got_worktree_set_head(struct got_worktree *worktree, struct got_reference *head,
224 86c3caaf 2018-03-09 stsp struct got_repository *repo)
225 86c3caaf 2018-03-09 stsp {
226 86c3caaf 2018-03-09 stsp return NULL;
227 86c3caaf 2018-03-09 stsp }
228 86c3caaf 2018-03-09 stsp
229 86c3caaf 2018-03-09 stsp const struct got_error *
230 86c3caaf 2018-03-09 stsp got_worktree_checkout_files(struct got_worktree *worktree,
231 86c3caaf 2018-03-09 stsp struct got_repository *repo)
232 86c3caaf 2018-03-09 stsp {
233 86c3caaf 2018-03-09 stsp return NULL;
234 86c3caaf 2018-03-09 stsp }