rebase: Support preserving merges in non-interactive mode
[gitweb.git] / read-cache.c
index f0ba2247980cc938cc3f821a18e3b328966c4e06..5b1b3ad03b6d7294ca06b5b1053799958ad831c7 100644 (file)
@@ -8,6 +8,11 @@
 #include "cache-tree.h"
 #include "refs.h"
 #include "dir.h"
+#include "tree.h"
+#include "commit.h"
+#include "diff.h"
+#include "diffcore.h"
+#include "revision.h"
 
 /* Index extensions.
  *
@@ -1159,7 +1164,7 @@ int read_index_from(struct index_state *istate, const char *path)
        size_t mmap_size;
 
        errno = EBUSY;
-       if (istate->alloc)
+       if (istate->initialized)
                return istate->cache_nr;
 
        errno = ENOENT;
@@ -1199,6 +1204,7 @@ int read_index_from(struct index_state *istate, const char *path)
         * index size
         */
        istate->alloc = xmalloc(estimate_cache_size(mmap_size, istate->cache_nr));
+       istate->initialized = 1;
 
        src_offset = sizeof(*hdr);
        dst_offset = 0;
@@ -1247,10 +1253,12 @@ int discard_index(struct index_state *istate)
        istate->cache_nr = 0;
        istate->cache_changed = 0;
        istate->timestamp = 0;
+       istate->name_hash_initialized = 0;
        free_hash(&istate->name_hash);
        cache_tree_free(&(istate->cache_tree));
        free(istate->alloc);
        istate->alloc = NULL;
+       istate->initialized = 0;
 
        /* no need to throw away allocated active_cache */
        return 0;
@@ -1481,3 +1489,59 @@ int read_index_unmerged(struct index_state *istate)
        istate->cache_nr = dst - istate->cache;
        return !!last;
 }
+
+struct update_callback_data
+{
+       int flags;
+       int add_errors;
+};
+
+static void update_callback(struct diff_queue_struct *q,
+                           struct diff_options *opt, void *cbdata)
+{
+       int i;
+       struct update_callback_data *data = cbdata;
+
+       for (i = 0; i < q->nr; i++) {
+               struct diff_filepair *p = q->queue[i];
+               const char *path = p->one->path;
+               switch (p->status) {
+               default:
+                       die("unexpected diff status %c", p->status);
+               case DIFF_STATUS_UNMERGED:
+               case DIFF_STATUS_MODIFIED:
+               case DIFF_STATUS_TYPE_CHANGED:
+                       if (add_file_to_index(&the_index, path, data->flags)) {
+                               if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
+                                       die("updating files failed");
+                               data->add_errors++;
+                       }
+                       break;
+               case DIFF_STATUS_DELETED:
+                       if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
+                               break;
+                       if (!(data->flags & ADD_CACHE_PRETEND))
+                               remove_file_from_index(&the_index, path);
+                       if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
+                               printf("remove '%s'\n", path);
+                       break;
+               }
+       }
+}
+
+int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
+{
+       struct update_callback_data data;
+       struct rev_info rev;
+       init_revisions(&rev, prefix);
+       setup_revisions(0, NULL, &rev, NULL);
+       rev.prune_data = pathspec;
+       rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
+       rev.diffopt.format_callback = update_callback;
+       data.flags = flags;
+       data.add_errors = 0;
+       rev.diffopt.format_callback_data = &data;
+       run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
+       return !!data.add_errors;
+}
+