Example #1
0
/*
 * One-way merge.
 *
 * The rule is:
 * - take the stat information from stage0, take the data from stage1
 */
int oneway_merge(const struct cache_entry * const *src,
		 struct unpack_trees_options *o)
{
	const struct cache_entry *old = src[0];
	const struct cache_entry *a = src[1];

	if (o->merge_size != 1)
		return error("Cannot do a oneway merge of %d trees",
			     o->merge_size);

	if (!a || a == o->df_conflict_entry)
		return deleted_entry(old, old, o);

	if (old && same(old, a)) {
		int update = 0;
		if (o->reset && o->update && !ce_uptodate(old) && !ce_skip_worktree(old)) {
			struct stat st;
			if (lstat(old->name, &st) ||
			    ie_match_stat(o->src_index, old, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE))
				update |= CE_UPDATE;
		}
		add_entry(o, old, update, 0);
		return 0;
	}
	return merged_entry(a, old, o);
}
Example #2
0
static void *preload_thread(void *_data)
{
	int nr;
	struct thread_data *p = _data;
	struct index_state *index = p->index;
	struct cache_entry **cep = index->cache + p->offset;
	struct cache_def cache;

	memset(&cache, 0, sizeof(cache));
	nr = p->nr;
	if (nr + p->offset > index->cache_nr)
		nr = index->cache_nr - p->offset;

	do {
		struct cache_entry *ce = *cep++;
		struct stat st;

		if (ce_stage(ce))
			continue;
		if (ce_uptodate(ce))
			continue;
		if (!ce_path_match(ce, p->pathspec))
			continue;
		if (threaded_has_symlink_leading_path(&cache, ce->name, ce_namelen(ce)))
			continue;
		if (lstat(ce->name, &st))
			continue;
		if (ie_match_stat(index, ce, &st, CE_MATCH_RACY_IS_DIRTY))
			continue;
		ce_mark_uptodate(ce);
	} while (--nr > 0);
	return NULL;
}
Example #3
0
/*
 * This gets called when there was no index entry for the tree entry 'dst',
 * but we found a file in the working tree that 'lstat()' said was fine,
 * and we're on a case-insensitive filesystem.
 *
 * See if we can find a case-insensitive match in the index that also
 * matches the stat information, and assume it's that other file!
 */
static int icase_exists(struct unpack_trees_options *o, const char *name, int len, struct stat *st)
{
	const struct cache_entry *src;

	src = index_file_exists(o->src_index, name, len, 1);
	return src && !ie_match_stat(o->src_index, src, st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
}
Example #4
0
/*
 * Has a file changed or has a submodule new commits or a dirty work tree?
 *
 * Return 1 when changes are detected, 0 otherwise. If the DIRTY_SUBMODULES
 * option is set, the caller does not only want to know if a submodule is
 * modified at all but wants to know all the conditions that are met (new
 * commits, untracked content and/or modified content).
 */
static int match_stat_with_submodule(struct diff_options *diffopt,
				     const struct cache_entry *ce,
				     struct stat *st, unsigned ce_option,
				     unsigned *dirty_submodule)
{
	int changed = ie_match_stat(diffopt->repo->index, ce, st, ce_option);
	if (S_ISGITLINK(ce->ce_mode)) {
		struct diff_flags orig_flags = diffopt->flags;
		if (!diffopt->flags.override_submodule_config)
			set_diffopt_flags_from_submodule_config(diffopt, ce->name);
		if (diffopt->flags.ignore_submodules)
			changed = 0;
		else if (!diffopt->flags.ignore_dirty_submodules &&
			 (!changed || diffopt->flags.dirty_submodules))
			*dirty_submodule = is_submodule_modified(ce->name,
								 diffopt->flags.ignore_untracked_in_submodules);
		diffopt->flags = orig_flags;
	}
	return changed;
}
Example #5
0
/*
 * When a CE gets turned into an unmerged entry, we
 * want it to be up-to-date
 */
static int verify_uptodate_1(const struct cache_entry *ce,
			     struct unpack_trees_options *o,
			     enum unpack_trees_error_types error_type)
{
	struct stat st;

	if (o->index_only)
		return 0;

	/*
	 * CE_VALID and CE_SKIP_WORKTREE cheat, we better check again
	 * if this entry is truly up-to-date because this file may be
	 * overwritten.
	 */
	if ((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce))
		; /* keep checking */
	else if (o->reset || ce_uptodate(ce))
		return 0;

	if (!lstat(ce->name, &st)) {
		int flags = CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE;
		unsigned changed = ie_match_stat(o->src_index, ce, &st, flags);
		if (!changed)
			return 0;
		/*
		 * NEEDSWORK: the current default policy is to allow
		 * submodule to be out of sync wrt the superproject
		 * index.  This needs to be tightened later for
		 * submodules that are marked to be automatically
		 * checked out.
		 */
		if (S_ISGITLINK(ce->ce_mode))
			return 0;
		errno = 0;
	}
	if (errno == ENOENT)
		return 0;
	return o->gently ? -1 :
		add_rejected_path(o, error_type, ce->name);
}
Example #6
0
static void *preload_thread(void *_data)
{
	int nr;
	struct thread_data *p = _data;
	struct index_state *index = p->index;
	struct cache_entry **cep = index->cache + p->offset;
	struct cache_def cache = CACHE_DEF_INIT;

	nr = p->nr;
	if (nr + p->offset > index->cache_nr)
		nr = index->cache_nr - p->offset;

	do {
		struct cache_entry *ce = *cep++;
		struct stat st;

		if (ce_stage(ce))
			continue;
		if (S_ISGITLINK(ce->ce_mode))
			continue;
		if (ce_uptodate(ce))
			continue;
		if (ce_skip_worktree(ce))
			continue;
		if (ce->ce_flags & CE_FSMONITOR_VALID)
			continue;
		if (!ce_path_match(index, ce, &p->pathspec, NULL))
			continue;
		if (threaded_has_symlink_leading_path(&cache, ce->name, ce_namelen(ce)))
			continue;
		if (lstat(ce->name, &st))
			continue;
		if (ie_match_stat(index, ce, &st, CE_MATCH_RACY_IS_DIRTY|CE_MATCH_IGNORE_FSMONITOR))
			continue;
		ce_mark_uptodate(ce);
		mark_fsmonitor_valid(ce);
	} while (--nr > 0);
	cache_def_clear(&cache);
	return NULL;
}
Example #7
0
void wt_status_collect_changes_worktree(struct index_state *index,
                                        GList **results,
                                        const char *worktree)
{
    DiffEntry *de;
    int entries, i;

    GList *ignore_list = seaf_repo_load_ignore_files (worktree);

    entries = index->cache_nr;
    for (i = 0; i < entries; i++) {
        char *realpath;
        SeafStat st;
        struct cache_entry *ce = index->cache[i];
        int changed = 0;

        if (ce_stage(ce)) {
            int mask = 0;

            mask |= 1 << ce_stage(ce);
            while (i < entries) {
                struct cache_entry *nce = index->cache[i];

                if (strcmp(ce->name, nce->name))
                    break;

                mask |= 1 << ce_stage(nce);
                i++;
            }

            /*
             * Compensate for loop update
             */
            i--;

            de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_UNMERGED,
                                 ce->sha1, ce->name);
            de->unmerge_state = diff_unmerged_state (mask);
            *results = g_list_prepend (*results, de);

            continue;
        }

        if (ce_uptodate(ce) || ce_skip_worktree(ce))
            continue;

        realpath = g_build_path (PATH_SEPERATOR, worktree, ce->name, NULL);
        if (seaf_stat(realpath, &st) < 0) {
            if (errno != ENOENT && errno != ENOTDIR)
                changed = -1;
            else
                changed = 1;
        }

        if (changed) {
            if (changed < 0) {
                g_warning ("Faile to stat %s: %s\n", ce->name, strerror(errno));
                g_free (realpath);
                continue;
            }

            if (ce->ce_ctime.sec == 0) {
                g_free (realpath);
                continue;
            }

            de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_DELETED,
                                 ce->sha1, ce->name);
            *results = g_list_prepend (*results, de);
            g_free (realpath);
            continue;
        }

        if (S_ISDIR (ce->ce_mode)) {
            g_free (realpath);
            continue;
        }

        /* Don't check changes to ignored files.
         * This can happen when a file is committed and then added to
         * ignore.txt. After that changes to this file will not committed,
         * and it should be ignored here.
         */
        if (seaf_repo_check_ignore_file (ignore_list, realpath)) {
            g_free (realpath);
            continue;
        }

        g_free (realpath);

        changed = ie_match_stat (index, ce, &st, 0);
        if (!changed) {
            ce_mark_uptodate (ce);
            continue;
        }

        de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_MODIFIED,
                             ce->sha1, ce->name);
        *results = g_list_prepend (*results, de);
    }

    seaf_repo_free_ignore_files (ignore_list);
}
Example #8
0
void wt_status_collect_changes_worktree(struct index_state *index,
                                        GList **results,
                                        const char *worktree,
                                        IgnoreFunc ignore_func)
{
    DiffEntry *de;
    int entries, i;

    entries = index->cache_nr;
    for (i = 0; i < entries; i++) {
        char *realpath;
        struct stat st;
        struct cache_entry *ce = index->cache[i];
        int changed = 0;

        if (ce_stage(ce)) {
            int mask = 0;

            mask |= 1 << ce_stage(ce);
            while (i < entries) {
                struct cache_entry *nce = index->cache[i];

                if (strcmp(ce->name, nce->name))
                    break;

                mask |= 1 << ce_stage(nce);
                i++;
            }

            /*
             * Compensate for loop update
             */
            i--;

            de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_UNMERGED,
                                 ce->sha1, ce->name);
            de->unmerge_state = diff_unmerged_state (mask);
            *results = g_list_prepend (*results, de);

            continue;
        }

        if (ce_uptodate(ce) || ce_skip_worktree(ce))
            continue;

        realpath = g_build_path (PATH_SEPERATOR, worktree, ce->name, NULL);
        if (g_lstat(realpath, &st) < 0) {
            if (errno != ENOENT && errno != ENOTDIR)
                changed = -1;
            changed = 1;
        }

        if (changed) {
            if (changed < 0) {
                g_warning ("Faile to stat %s: %s\n", ce->name, strerror(errno));
                g_free (realpath);
                continue;
            }

            de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_DELETED,
                                 ce->sha1, ce->name);
            *results = g_list_prepend (*results, de);
            g_free (realpath);
            continue;
        }

        if (S_ISDIR (ce->ce_mode)) {
            if (!S_ISDIR (st.st_mode) ||
                !is_empty_dir (realpath, ignore_func)) {
                de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_DIR_DELETED,
                                     ce->sha1, ce->name);
                *results = g_list_prepend (*results, de);
            }
            g_free (realpath);
            continue;
        }
        g_free (realpath);

        changed = ie_match_stat (index, ce, &st, 0);
        if (!changed) {
            ce_mark_uptodate (ce);
            continue;
        }

        de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_MODIFIED,
                             ce->sha1, ce->name);
        *results = g_list_prepend (*results, de);
    }
}