entry.con commit Merge branch 'js/run-process-parallel-api-fix' into maint (0869277)
   1#include "cache.h"
   2#include "blob.h"
   3#include "dir.h"
   4#include "streaming.h"
   5#include "submodule.h"
   6
   7static void create_directories(const char *path, int path_len,
   8                               const struct checkout *state)
   9{
  10        char *buf = xmallocz(path_len);
  11        int len = 0;
  12
  13        while (len < path_len) {
  14                do {
  15                        buf[len] = path[len];
  16                        len++;
  17                } while (len < path_len && path[len] != '/');
  18                if (len >= path_len)
  19                        break;
  20                buf[len] = 0;
  21
  22                /*
  23                 * For 'checkout-index --prefix=<dir>', <dir> is
  24                 * allowed to be a symlink to an existing directory,
  25                 * and we set 'state->base_dir_len' below, such that
  26                 * we test the path components of the prefix with the
  27                 * stat() function instead of the lstat() function.
  28                 */
  29                if (has_dirs_only_path(buf, len, state->base_dir_len))
  30                        continue; /* ok, it is already a directory. */
  31
  32                /*
  33                 * If this mkdir() would fail, it could be that there
  34                 * is already a symlink or something else exists
  35                 * there, therefore we then try to unlink it and try
  36                 * one more time to create the directory.
  37                 */
  38                if (mkdir(buf, 0777)) {
  39                        if (errno == EEXIST && state->force &&
  40                            !unlink_or_warn(buf) && !mkdir(buf, 0777))
  41                                continue;
  42                        die_errno("cannot create directory at '%s'", buf);
  43                }
  44        }
  45        free(buf);
  46}
  47
  48static void remove_subtree(struct strbuf *path)
  49{
  50        DIR *dir = opendir(path->buf);
  51        struct dirent *de;
  52        int origlen = path->len;
  53
  54        if (!dir)
  55                die_errno("cannot opendir '%s'", path->buf);
  56        while ((de = readdir(dir)) != NULL) {
  57                struct stat st;
  58
  59                if (is_dot_or_dotdot(de->d_name))
  60                        continue;
  61
  62                strbuf_addch(path, '/');
  63                strbuf_addstr(path, de->d_name);
  64                if (lstat(path->buf, &st))
  65                        die_errno("cannot lstat '%s'", path->buf);
  66                if (S_ISDIR(st.st_mode))
  67                        remove_subtree(path);
  68                else if (unlink(path->buf))
  69                        die_errno("cannot unlink '%s'", path->buf);
  70                strbuf_setlen(path, origlen);
  71        }
  72        closedir(dir);
  73        if (rmdir(path->buf))
  74                die_errno("cannot rmdir '%s'", path->buf);
  75}
  76
  77static int create_file(const char *path, unsigned int mode)
  78{
  79        mode = (mode & 0100) ? 0777 : 0666;
  80        return open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
  81}
  82
  83static void *read_blob_entry(const struct cache_entry *ce, unsigned long *size)
  84{
  85        enum object_type type;
  86        void *new = read_sha1_file(ce->oid.hash, &type, size);
  87
  88        if (new) {
  89                if (type == OBJ_BLOB)
  90                        return new;
  91                free(new);
  92        }
  93        return NULL;
  94}
  95
  96static int open_output_fd(char *path, const struct cache_entry *ce, int to_tempfile)
  97{
  98        int symlink = (ce->ce_mode & S_IFMT) != S_IFREG;
  99        if (to_tempfile) {
 100                xsnprintf(path, TEMPORARY_FILENAME_LENGTH, "%s",
 101                          symlink ? ".merge_link_XXXXXX" : ".merge_file_XXXXXX");
 102                return mkstemp(path);
 103        } else {
 104                return create_file(path, !symlink ? ce->ce_mode : 0666);
 105        }
 106}
 107
 108static int fstat_output(int fd, const struct checkout *state, struct stat *st)
 109{
 110        /* use fstat() only when path == ce->name */
 111        if (fstat_is_reliable() &&
 112            state->refresh_cache && !state->base_dir_len) {
 113                fstat(fd, st);
 114                return 1;
 115        }
 116        return 0;
 117}
 118
 119static int streaming_write_entry(const struct cache_entry *ce, char *path,
 120                                 struct stream_filter *filter,
 121                                 const struct checkout *state, int to_tempfile,
 122                                 int *fstat_done, struct stat *statbuf)
 123{
 124        int result = 0;
 125        int fd;
 126
 127        fd = open_output_fd(path, ce, to_tempfile);
 128        if (fd < 0)
 129                return -1;
 130
 131        result |= stream_blob_to_fd(fd, &ce->oid, filter, 1);
 132        *fstat_done = fstat_output(fd, state, statbuf);
 133        result |= close(fd);
 134
 135        if (result)
 136                unlink(path);
 137        return result;
 138}
 139
 140static int write_entry(struct cache_entry *ce,
 141                       char *path, const struct checkout *state, int to_tempfile)
 142{
 143        unsigned int ce_mode_s_ifmt = ce->ce_mode & S_IFMT;
 144        int fd, ret, fstat_done = 0;
 145        char *new;
 146        struct strbuf buf = STRBUF_INIT;
 147        unsigned long size;
 148        size_t wrote, newsize = 0;
 149        struct stat st;
 150        const struct submodule *sub;
 151
 152        if (ce_mode_s_ifmt == S_IFREG) {
 153                struct stream_filter *filter = get_stream_filter(ce->name,
 154                                                                 ce->oid.hash);
 155                if (filter &&
 156                    !streaming_write_entry(ce, path, filter,
 157                                           state, to_tempfile,
 158                                           &fstat_done, &st))
 159                        goto finish;
 160        }
 161
 162        switch (ce_mode_s_ifmt) {
 163        case S_IFREG:
 164        case S_IFLNK:
 165                new = read_blob_entry(ce, &size);
 166                if (!new)
 167                        return error("unable to read sha1 file of %s (%s)",
 168                                path, oid_to_hex(&ce->oid));
 169
 170                if (ce_mode_s_ifmt == S_IFLNK && has_symlinks && !to_tempfile) {
 171                        ret = symlink(new, path);
 172                        free(new);
 173                        if (ret)
 174                                return error_errno("unable to create symlink %s",
 175                                                   path);
 176                        break;
 177                }
 178
 179                /*
 180                 * Convert from git internal format to working tree format
 181                 */
 182                if (ce_mode_s_ifmt == S_IFREG &&
 183                    convert_to_working_tree(ce->name, new, size, &buf)) {
 184                        free(new);
 185                        new = strbuf_detach(&buf, &newsize);
 186                        size = newsize;
 187                }
 188
 189                fd = open_output_fd(path, ce, to_tempfile);
 190                if (fd < 0) {
 191                        free(new);
 192                        return error_errno("unable to create file %s", path);
 193                }
 194
 195                wrote = write_in_full(fd, new, size);
 196                if (!to_tempfile)
 197                        fstat_done = fstat_output(fd, state, &st);
 198                close(fd);
 199                free(new);
 200                if (wrote != size)
 201                        return error("unable to write file %s", path);
 202                break;
 203        case S_IFGITLINK:
 204                if (to_tempfile)
 205                        return error("cannot create temporary submodule %s", path);
 206                if (mkdir(path, 0777) < 0)
 207                        return error("cannot create submodule directory %s", path);
 208                sub = submodule_from_ce(ce);
 209                if (sub)
 210                        return submodule_move_head(ce->name,
 211                                NULL, oid_to_hex(&ce->oid),
 212                                state->force ? SUBMODULE_MOVE_HEAD_FORCE : 0);
 213                break;
 214        default:
 215                return error("unknown file mode for %s in index", path);
 216        }
 217
 218finish:
 219        if (state->refresh_cache) {
 220                assert(state->istate);
 221                if (!fstat_done)
 222                        lstat(ce->name, &st);
 223                fill_stat_cache_info(ce, &st);
 224                ce->ce_flags |= CE_UPDATE_IN_BASE;
 225                state->istate->cache_changed |= CE_ENTRY_CHANGED;
 226        }
 227        return 0;
 228}
 229
 230/*
 231 * This is like 'lstat()', except it refuses to follow symlinks
 232 * in the path, after skipping "skiplen".
 233 */
 234static int check_path(const char *path, int len, struct stat *st, int skiplen)
 235{
 236        const char *slash = path + len;
 237
 238        while (path < slash && *slash != '/')
 239                slash--;
 240        if (!has_dirs_only_path(path, slash - path, skiplen)) {
 241                errno = ENOENT;
 242                return -1;
 243        }
 244        return lstat(path, st);
 245}
 246
 247/*
 248 * Write the contents from ce out to the working tree.
 249 *
 250 * When topath[] is not NULL, instead of writing to the working tree
 251 * file named by ce, a temporary file is created by this function and
 252 * its name is returned in topath[], which must be able to hold at
 253 * least TEMPORARY_FILENAME_LENGTH bytes long.
 254 */
 255int checkout_entry(struct cache_entry *ce,
 256                   const struct checkout *state, char *topath)
 257{
 258        static struct strbuf path = STRBUF_INIT;
 259        struct stat st;
 260
 261        if (topath)
 262                return write_entry(ce, topath, state, 1);
 263
 264        strbuf_reset(&path);
 265        strbuf_add(&path, state->base_dir, state->base_dir_len);
 266        strbuf_add(&path, ce->name, ce_namelen(ce));
 267
 268        if (!check_path(path.buf, path.len, &st, state->base_dir_len)) {
 269                const struct submodule *sub;
 270                unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
 271                /*
 272                 * Needs to be checked before !changed returns early,
 273                 * as the possibly empty directory was not changed
 274                 */
 275                sub = submodule_from_ce(ce);
 276                if (sub) {
 277                        int err;
 278                        if (!is_submodule_populated_gently(ce->name, &err)) {
 279                                struct stat sb;
 280                                if (lstat(ce->name, &sb))
 281                                        die(_("could not stat file '%s'"), ce->name);
 282                                if (!(st.st_mode & S_IFDIR))
 283                                        unlink_or_warn(ce->name);
 284
 285                                return submodule_move_head(ce->name,
 286                                        NULL, oid_to_hex(&ce->oid), 0);
 287                        } else
 288                                return submodule_move_head(ce->name,
 289                                        "HEAD", oid_to_hex(&ce->oid),
 290                                        state->force ? SUBMODULE_MOVE_HEAD_FORCE : 0);
 291                }
 292
 293                if (!changed)
 294                        return 0;
 295                if (!state->force) {
 296                        if (!state->quiet)
 297                                fprintf(stderr,
 298                                        "%s already exists, no checkout\n",
 299                                        path.buf);
 300                        return -1;
 301                }
 302
 303                /*
 304                 * We unlink the old file, to get the new one with the
 305                 * right permissions (including umask, which is nasty
 306                 * to emulate by hand - much easier to let the system
 307                 * just do the right thing)
 308                 */
 309                if (S_ISDIR(st.st_mode)) {
 310                        /* If it is a gitlink, leave it alone! */
 311                        if (S_ISGITLINK(ce->ce_mode))
 312                                return 0;
 313                        if (!state->force)
 314                                return error("%s is a directory", path.buf);
 315                        remove_subtree(&path);
 316                } else if (unlink(path.buf))
 317                        return error_errno("unable to unlink old '%s'", path.buf);
 318        } else if (state->not_new)
 319                return 0;
 320
 321        create_directories(path.buf, path.len, state);
 322        return write_entry(ce, path.buf, state, 0);
 323}