Exemple #1
0
static int 
threeway_diff(struct cache_entry **src, struct unpack_trees_options *o)
{
    struct cache_entry *m = src[1];
    struct cache_entry *p1 = src[2];
    struct cache_entry *p2 = src[3];
    GList **results = o->unpack_data;
    DiffEntry *de;

    if (m == o->df_conflict_entry)
        m = NULL;
    if (p1 == o->df_conflict_entry)
        p1 = NULL;
    if (p2 == o->df_conflict_entry)
        p2 = NULL;

    /* diff m from both p1 and p2. */
    if (m && p1 && p2) {
        if (!ce_same(m, p1) && !ce_same (m, p2)) {
            de = diff_entry_new (DIFF_TYPE_COMMITS, DIFF_STATUS_MODIFIED,
                                 m->sha1, m->name);
            *results = g_list_prepend (*results, de);
        }
    } else if (!m && p1 && p2) {
        de = diff_entry_new (DIFF_TYPE_COMMITS, DIFF_STATUS_DELETED,
                             p1->sha1, p1->name);
        *results = g_list_prepend (*results, de);
    } else if (m && !p1 && p2) {
        if (!ce_same (m, p2)) {
            de = diff_entry_new (DIFF_TYPE_COMMITS, DIFF_STATUS_MODIFIED,
                                 m->sha1, m->name);
            *results = g_list_prepend (*results, de);
        }
    } else if (m && p1 && !p2) {
        if (!ce_same (m, p1)) {
            de = diff_entry_new (DIFF_TYPE_COMMITS, DIFF_STATUS_MODIFIED,
                                 m->sha1, m->name);
            *results = g_list_prepend (*results, de);
        }
    } else if (m && !p1 && !p2) {
        de = diff_entry_new (DIFF_TYPE_COMMITS, DIFF_STATUS_ADDED,
                             m->sha1, m->name);
        *results = g_list_prepend (*results, de);
    }
    /* Nothing to do for:
     * 1. !m && p1 && !p2;
     * 2. !m && !p1 && p2;
     * 3. !m && !p1 && !p2 (should not happen)
     */

    return 0;
}
Exemple #2
0
static void
diff_two_cache_entries (struct cache_entry *tree1,
                        struct cache_entry *tree2,
                        int diff_type,
                        GList **results)
{
    DiffEntry *de;

    if (!tree1) {
        if (S_ISDIR(tree2->ce_mode)) {
            de = diff_entry_new (diff_type, DIFF_STATUS_DIR_ADDED,
                                 tree2->sha1, tree2->name);
        } else {
            de = diff_entry_new (diff_type, DIFF_STATUS_ADDED,
                                 tree2->sha1, tree2->name);
        }
        *results = g_list_prepend (*results, de);
        return;
    }

    if (!tree2) {
        if (S_ISDIR(tree1->ce_mode)) {
            de = diff_entry_new (diff_type, DIFF_STATUS_DIR_DELETED,
                                 tree1->sha1, tree1->name);
        } else {
            de = diff_entry_new (diff_type, DIFF_STATUS_DELETED,
                                 tree1->sha1, tree1->name);
        }
        *results = g_list_prepend (*results, de);
        return;
    }

    if (tree2->ce_mode != tree1->ce_mode || hashcmp(tree2->sha1, tree1->sha1) != 0) {
        if (S_ISDIR(tree2->ce_mode)) {
            de = diff_entry_new (diff_type, DIFF_STATUS_DELETED,
                                 tree1->sha1, tree1->name);
            *results = g_list_prepend (*results, de);
            de = diff_entry_new (diff_type, DIFF_STATUS_DIR_ADDED,
                                 tree2->sha1, tree2->name);
            *results = g_list_prepend (*results, de);
        } else if (S_ISDIR(tree1->ce_mode)) {
            de = diff_entry_new (diff_type, DIFF_STATUS_DIR_DELETED,
                                 tree1->sha1, tree1->name);
            *results = g_list_prepend (*results, de);
            de = diff_entry_new (diff_type, DIFF_STATUS_ADDED,
                                 tree2->sha1, tree2->name);
            *results = g_list_prepend (*results, de);
        } else {
            de = diff_entry_new (diff_type, DIFF_STATUS_MODIFIED,
                                 tree2->sha1, tree2->name);
            *results = g_list_prepend (*results, de);
        }
    }
}
Exemple #3
0
void wt_status_collect_untracked(struct index_state *index,
                                 GList **results,
                                 const char *worktree,
                                 IgnoreFunc ignore_func)
{
    int i;
    struct dir_struct dir;
    DiffEntry *de;

    memset(&dir, 0, sizeof(dir));

    read_directory(&dir, worktree, index);
    for (i = 0; i < dir.nr; i++) {
        struct dir_entry *ent = dir.entries[i];

        if (!ignore_func(ent->name, NULL)) {
            unsigned char sha1[20] = { 0 };
            de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_ADDED, sha1, ent->name);
            *results = g_list_prepend (*results, de);
        }
        free(ent);
    }

    free(dir.entries);
}
Exemple #4
0
void
wt_status_collect_changes_index (struct index_state *index,
                                 GList **results,
                                 SeafRepo *repo)
{
    SeafFSManager *fs_mgr;
    SeafCommit *head;
    int pos = 0;
    DiffEntry *de;

    fs_mgr = repo->manager->seaf->fs_mgr;
    head = seaf_commit_manager_get_commit (seaf->commit_mgr,
                                           repo->id, repo->version,
                                           repo->head->commit_id);
    if (!head) {
        seaf_warning ("Failed to get commit %s.\n", repo->head->commit_id);
        return;
    }

    mark_all_ce_unused (index);

    /* if repo is initial, we don't need to check index changes */
    if (strncmp(EMPTY_SHA1, head->root_id, 40) != 0) {
        SeafDir *root;

        /* call diff_index to get status */
        root = seaf_fs_manager_get_seafdir (fs_mgr,
                                            repo->id,
                                            repo->version,
                                            head->root_id);
        if (!root) {
            seaf_warning ("Failed to get root %s.\n", head->root_id);
            seaf_commit_unref (head);
            return;
        }

        if (diff_index(repo->id, repo->version, index, root, results) < 0)
            g_warning("diff index failed\n");
        seaf_dir_free (root);
        seaf_commit_unref (head);
        return;
    }
    seaf_commit_unref (head);

    while (1) {
        struct cache_entry *ce = next_cache_entry(index, &pos);

        if (!ce || ce_stage(ce))
            break;

        ce->ce_flags |= CE_UNPACKED;
        de = diff_entry_new (DIFF_TYPE_INDEX, DIFF_STATUS_ADDED, ce->sha1, ce->name);
        *results = g_list_prepend (*results, de);
    }
}
Exemple #5
0
/* This function only resolve "strict" rename, i.e. two files must be
 * exactly the same.
 */
void
diff_resolve_renames (GList **diff_entries)
{
    GHashTable *deleted;
    GList *p;
    GList *added = NULL;
    DiffEntry *de;

    /* Hash and equal functions for raw sha1. */
    deleted = g_hash_table_new (ccnet_sha1_hash, ccnet_sha1_equal);

    /* Collect all "deleted" entries. */
    for (p = *diff_entries; p != NULL; p = p->next) {
        de = p->data;
        if (de->status == DIFF_STATUS_DELETED)
            g_hash_table_insert (deleted, de->sha1, p);
    }

    /* Collect all "added" entries into a separate list. */
    for (p = *diff_entries; p != NULL; p = p->next) {
        de = p->data;
        if (de->status == DIFF_STATUS_ADDED)
            added = g_list_prepend (added, p);
    }

    /* For each "added" entry, if we find a "deleted" entry with
     * the same content, we find a rename pair.
     */
    p = added;
    while (p != NULL) {
        GList *p_add, *p_del;
        DiffEntry *de_add, *de_del, *de_rename;

        p_add = p->data;
        de_add = p_add->data;

        p_del = g_hash_table_lookup (deleted, de_add->sha1);
        if (p_del) {
            de_del = p_del->data;
            de_rename = diff_entry_new (de_del->type, DIFF_STATUS_RENAMED, 
                                        de_del->sha1, de_del->name);
            de_rename->new_name = g_strdup(de_add->name);

            *diff_entries = g_list_delete_link (*diff_entries, p_add);
            *diff_entries = g_list_delete_link (*diff_entries, p_del);
            *diff_entries = g_list_prepend (*diff_entries, de_rename);

            g_hash_table_remove (deleted, de_add->sha1);
        }

        p = g_list_delete_link (p, p);
    }

    g_hash_table_destroy (deleted);
}
Exemple #6
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);
}
Exemple #7
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);
    }
}