Ejemplo n.º 1
0
void stage_updated_gitmodules(void)
{
	struct strbuf buf = STRBUF_INIT;
	struct stat st;
	int pos;
	struct cache_entry *ce;
	int namelen = strlen(".gitmodules");

	pos = cache_name_pos(".gitmodules", namelen);
	if (pos < 0) {
		warning(_("could not find .gitmodules in index"));
		return;
	}
	ce = active_cache[pos];
	ce->ce_flags = namelen;
	if (strbuf_read_file(&buf, ".gitmodules", 0) < 0)
		die(_("reading updated .gitmodules failed"));
	if (lstat(".gitmodules", &st) < 0)
		die_errno(_("unable to stat updated .gitmodules"));
	fill_stat_cache_info(ce, &st);
	ce->ce_mode = ce_mode_from_stat(ce, st.st_mode);
	if (remove_cache_entry_at(pos) < 0)
		die(_("unable to remove .gitmodules from index"));
	if (write_sha1_file(buf.buf, buf.len, blob_type, ce->sha1))
		die(_("adding updated .gitmodules failed"));
	if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))
		die(_("staging updated .gitmodules failed"));
}
Ejemplo n.º 2
0
static int add_one_path(const struct cache_entry *old, const char *path, int len, struct stat *st)
{
	int option, size;
	struct cache_entry *ce;

	/* Was the old index entry already up-to-date? */
	if (old && !ce_stage(old) && !ce_match_stat(old, st, 0))
		return 0;

	size = cache_entry_size(len);
	ce = xcalloc(1, size);
	memcpy(ce->name, path, len);
	ce->ce_flags = create_ce_flags(0);
	ce->ce_namelen = len;
	fill_stat_cache_info(ce, st);
	ce->ce_mode = ce_mode_from_stat(old, st->st_mode);

	if (index_path(ce->sha1, path, st,
		       info_only ? 0 : HASH_WRITE_OBJECT)) {
		free(ce);
		return -1;
	}
	option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
	option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
	if (add_cache_entry(ce, option))
		return error("%s: cannot add to the index - missing --add option?", path);
	return 0;
}
Ejemplo n.º 3
0
static int
checkout_entry (struct cache_entry *ce,
                struct unpack_trees_options *o,
                gboolean recover_merge,
                const char *conflict_suffix)
{
    int base_len = strlen(o->base);
    int len = ce_namelen(ce);
    int full_len;
    char path[PATH_MAX];
    int offset;
    struct stat st;
    char file_id[41];

    if (!len) {
        g_warning ("entry name should not be empty.\n");
        return -1;
    }

    snprintf (path, PATH_MAX, "%s/", o->base);

    /* first create all leading directories. */
    full_len = base_len + len + 1;
    offset = base_len + 1;
    while (offset < full_len) {
        do {
            path[offset] = ce->name[offset-base_len-1];
            offset++;
        } while (offset < full_len && ce->name[offset-base_len-1] != '/');
        if (offset >= full_len)
            break;
        path[offset] = 0;

        if (g_lstat (path, &st) == 0 && S_ISDIR(st.st_mode))
            continue;
        
        if (ccnet_mkdir (path, 0777) < 0) {
            g_warning ("Failed to create directory %s.\n", path);
            return -1;
        }
    }
    path[offset] = 0;

    if (!S_ISDIR(ce->ce_mode)) {
        /* In case that we're replacing an empty dir with a file,
         * we need first to remove the empty dir.
         */
        if (g_lstat (path, &st) == 0 && S_ISDIR(st.st_mode)) {
            if (g_rmdir (path) < 0) {
                g_warning ("Failed to remove dir %s: %s\n", path, strerror(errno));
                /* Don't quit since we can handle conflict later. */
            }
        }
    } else {
        /* For simplicity, we just don't checkout the empty dir if there is
         * already a file with the same name in the worktree.
         * This implies, you can't remove a file then create an empty directory
         * with the same name. But it's a rare requirement.
         */
        if (g_mkdir (path, 0777) < 0) {
            g_warning ("Failed to create empty dir %s.\n", path);
        }
        return 0;
    }

    if (!o->reset && g_lstat (path, &st) == 0 && S_ISREG(st.st_mode) &&
        (ce->ce_ctime.sec != st.st_ctime || ce->ce_mtime.sec != st.st_mtime))
    {
        /* If we're recovering an interrupted merge, we don't know whether
         * the file was changed by checkout or by the user. So we have to
         * calculate the sha1 for that file and compare it with the one in
         * cache entry.
         */
        if (!recover_merge || 
            compare_file_content (path, &st, ce->sha1, o->crypt) != 0) {
            g_warning ("File %s is changed. Skip checking out.\n", path);
            return -1;
        }

        /* Recover merge and file content matches index entry.
         * We were interrupted before updating the index, update index
         * entry timestamp now.
         */
        goto update_cache;
    }

    /* then checkout the file. */
    rawdata_to_hex (ce->sha1, file_id, 20);
    if (seaf_fs_manager_checkout_file (seaf->fs_mgr, file_id,
                                       path, ce->ce_mode,
                                       o->crypt, conflict_suffix) < 0) {
        g_warning ("Failed to checkout file %s.\n", path);
        return -1;
    }

update_cache:
    /* finally fill cache_entry info */
    g_lstat (path, &st);
    fill_stat_cache_info (ce, &st);

    return 0;
}
Ejemplo n.º 4
0
static int
checkout_entry (struct cache_entry *ce,
                struct unpack_trees_options *o,
                gboolean recover_merge,
                const char *conflict_head_id,
                GHashTable *conflict_hash,
                GHashTable *no_conflict_hash)
{
    char *path_in, *path;
    SeafStat st;
    char file_id[41];
    gboolean case_conflict = FALSE;
    gboolean force_conflict = FALSE;

    path_in = g_build_path ("/", o->base, ce->name, NULL);
#ifndef __linux__
    path = build_case_conflict_free_path (o->base, ce->name,
                                          conflict_hash, no_conflict_hash,
                                          &case_conflict,
                                          FALSE);
#else
    path = build_checkout_path (o->base, ce->name, ce_namelen(ce));
#endif

    g_free (path_in);
    if (!path)
        return -1;

    if (!S_ISDIR(ce->ce_mode)) {
        /* In case that we're replacing an empty dir with a file,
         * we need first to remove the empty dir.
         */
        if (seaf_stat (path, &st) == 0 && S_ISDIR(st.st_mode)) {
            if (g_rmdir (path) < 0) {
                g_warning ("Failed to remove dir %s: %s\n", path, strerror(errno));
                /* Don't quit since we can handle conflict later. */
            }
        }
    } else {
        if (g_mkdir (path, 0777) < 0) {
            g_warning ("Failed to create empty dir %s in checkout.\n", path);
            g_free (path);
            return -1;
        }
        if (ce->ce_mtime.sec != 0 &&
            seaf_set_file_time (path, ce->ce_mtime.sec) < 0) {
            g_warning ("Failed to set mtime for %s.\n", path);
        }
        goto update_cache;
    }

    if (!o->reset && seaf_stat (path, &st) == 0 && S_ISREG(st.st_mode) &&
        (ce->current_mtime != st.st_mtime))
    {
        /* If we're recovering an interrupted merge, we don't know whether
         * the file was changed by checkout or by the user. So we have to
         * calculate the sha1 for that file and compare it with the one in
         * cache entry.
         */
        if (!recover_merge || 
            compare_file_content (path, &st, ce->sha1, o->crypt, o->version) != 0) {
            g_warning ("File %s is changed. Checkout to conflict file.\n", path);
            force_conflict = TRUE;
        } else {
            /* Recover merge and file content matches index entry.
             * We were interrupted before updating the index, update index
             * entry timestamp now.
             */
            goto update_cache;
        }
    }

    /* then checkout the file. */
    gboolean conflicted = FALSE;
    rawdata_to_hex (ce->sha1, file_id, 20);
    if (seaf_fs_manager_checkout_file (seaf->fs_mgr,
                                       o->repo_id,
                                       o->version,
                                       file_id,
                                       path,
                                       ce->ce_mode,
                                       ce->ce_mtime.sec,
                                       o->crypt,
                                       ce->name,
                                       conflict_head_id,
                                       force_conflict,
                                       &conflicted) < 0) {
        g_warning ("Failed to checkout file %s.\n", path);
        g_free (path);
        return -1;
    }

    /* If case conflict, this file has been checked out to another path.
     * Remove the current entry, otherwise it won't be removed later
     * since it's timestamp is 0.
     */
    if (case_conflict) {
        ce->ce_flags |= CE_REMOVE;
        g_free (path);
        return 0;
    }

    if (conflicted) {
        g_free (path);
        return 0;
    }

update_cache:
    /* finally fill cache_entry info */
    /* Only update index if we checked out the file without any error
     * or conflicts. The timestamp of the entry will remain 0 if error
     * or conflicted.
     */
    seaf_stat (path, &st);
    fill_stat_cache_info (ce, &st);

    g_free (path);
    return 0;
}