Exemple #1
0
// FIXME - we don't cope optimally with the situation where a branch is
// created, files deleted, and then the branch tagged (without rtag).  We'll
// never know that the tag was placed on the branch; instead we'll place the tag
// on the trunk.
static void branch_graph (database_t * db,
                          tag_t *** tree_order, tag_t *** tree_order_end)
{
    // First, go through each tag, and put it on all the branches.
    for (tag_t * i = db->tags; i != db->tags_end; ++i) {
        i->changeset.unready_count = 0;
        for (version_t ** j = i->tag_files; j != i->tag_files_end; ++j) {
            if ((*j)->branch)
                record_branch_tag ((*j)->branch, i);

            if (*j != (*j)->file->versions &&
                (*j)[-1].implicit_merge &&
                (*j)[-1].used &&
                (*j)[-1].branch)
                record_branch_tag ((*j)[-1].branch, i);
        }
    }

    // Go through each branch and put record it on the tags.
    for (tag_t * i = db->tags; i != db->tags_end; ++i)
        for (branch_tag_t * j = i->tags; j != i->tags_end; ++j) {
            ARRAY_EXTEND (j->tag->parents);
            j->tag->parents_end[-1].branch = i;
            j->tag->parents_end[-1].weight = j->weight;
            ++j->tag->changeset.unready_count;
        }

    // Do a cycle breaking pass of the branches.
    heap_t heap;

    heap_init (&heap, offsetof (tag_t, changeset.ready_index), tag_compare);

    // Release all the tags that are ready right now; also sort the parent
    // lists.
    for (tag_t * i = db->tags; i != db->tags_end; ++i) {
        ARRAY_SORT (i->parents, compare_pb);
        if (i->changeset.unready_count == 0) {
            i->is_released = true;
            heap_insert (&heap, i);
        }
    }

    while (!heap_empty (&heap))
        tag_released (&heap, heap_pop (&heap), tree_order, tree_order_end);

    for (tag_t * i = db->tags; i != db->tags_end; ++i)
        while (!i->is_released) {
            break_cycle (&heap, i);
            while (!heap_empty (&heap))
                tag_released (&heap, heap_pop (&heap),
                              tree_order, tree_order_end);
        }

    heap_destroy (&heap);
}
Exemple #2
0
static void grab_by_option (FILE * out,
                            const database_t * db,
                            cvs_connection_t * s,
                            const char * r_arg,
                            const char * D_arg,
                            version_t ** fetch, version_t ** fetch_end)
{
    // Build an array of the paths that we're getting.  FIXME - if changeset
    // versions were sorted we wouldn't need this.
    const char ** paths = NULL;
    const char ** paths_end = NULL;

    for (version_t ** i = fetch; i != fetch_end; ++i) {
        version_t * v = version_live (*i);
        assert (v && v->used && v->mark == SIZE_MAX);
        ARRAY_APPEND (paths, v->file->path);
    }

    assert (paths != paths_end);

    ARRAY_SORT (paths, (int(*)(const void *, const void *)) strcmp);

    const char * d = NULL;
    ssize_t d_len = SSIZE_MAX;

    for (const char ** i = paths; i != paths_end; ++i) {
        const char * slash = strrchr (*i, '/');
        if (slash == NULL)
            continue;
        if (slash - *i == d_len && memcmp (*i, d, d_len) == 0)
            continue;
        // Tell the server about this directory.
        d = *i;
        d_len = slash - d;
        cvs_printf (s,
                    "Directory %s/%.*s\n"
                    "%s%.*s\n",
                    s->module, (int) d_len, d,
                    s->prefix, (int) d_len, d);
    }

    // Go to the main directory.
    cvs_printf (s,
                "Directory %s\n%.*s\n", s->module,
                (int) (strlen (s->prefix) - 1), s->prefix);

    // Update args:
    if (r_arg)
        cvs_printf (s, "Argument -r%s\n", r_arg);

    if (D_arg)
        cvs_printf (s, "Argument -D%s\n", D_arg);

    cvs_printf (s, "Argument -kk\n" "Argument --\n");

    for (const char ** i = paths; i != paths_end; ++i)
        cvs_printf (s, "Argument %s\n", *i);

    xfree (paths);

    cvs_printff (s, "update\n");

    read_versions (out, db, s);
}
Exemple #3
0
void create_changesets (database_t * db)
{
    size_t total_versions = 0;

    for (file_t * i = db->files; i != db->files_end; ++i)
        total_versions += i->versions_end - i->versions;

    if (total_versions == 0)
        return;

    version_t ** version_list = ARRAY_ALLOC (version_t *, total_versions);
    version_t ** vp = version_list;

    for (file_t * i = db->files; i != db->files_end; ++i)
        for (version_t * j = i->versions; j != i->versions_end; ++j)
            *vp++ = j;

    assert (vp == version_list + total_versions);

    qsort (version_list, total_versions, sizeof (version_t *),
           version_compare_qsort);

    changeset_t * current = database_new_changeset (db);
    ARRAY_APPEND (current->versions, version_list[0]);
    version_list[0]->commit = current;
    current->time = version_list[0]->time;
    current->type = ct_commit;
    for (size_t i = 1; i < total_versions; ++i) {
        version_t * next = version_list[i];
        if (!strings_match (*current->versions, next)
            || next->time - current->time > fuzz_span
            || next->time - current->versions_end[-1]->time > fuzz_gap) {
            ARRAY_TRIM (current->versions);
            current = database_new_changeset (db);
            current->time = next->time;
            current->type = ct_commit;
        }
        ARRAY_APPEND (current->versions, version_list[i]);
        version_list[i]->commit = current;
    }

    ARRAY_TRIM (current->versions);
    free (version_list);

    // Do a pass through the changesets; this breaks any cycles.
    heap_t ready_versions;
    heap_init (&ready_versions,
               offsetof (version_t, ready_index), version_compare_heap);

    prepare_for_emission (db, &ready_versions);
    ssize_t emitted_changesets = 0;
    changeset_t * changeset;
    while ((changeset = next_changeset_split (db, &ready_versions))) {
        changeset_emitted (db, &ready_versions, changeset);
        ++emitted_changesets;
    }

    // Sort the changeset version lists by file.
    for (changeset_t ** i = db->changesets; i != db->changesets_end; ++i)
        ARRAY_SORT ((*i)->versions, compare_version_by_file);

    assert (heap_empty (&ready_versions));
    assert (heap_empty (&db->ready_changesets));
    assert (emitted_changesets == db->changesets_end - db->changesets);

    heap_destroy (&ready_versions);
}