Merge branch 'jc/maint-reset-remove-unmerged-new'
authorJunio C Hamano <gitster@pobox.com>
Tue, 21 Oct 2008 20:48:41 +0000 (13:48 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 21 Oct 2008 20:48:41 +0000 (13:48 -0700)
* jc/maint-reset-remove-unmerged-new:
reset --hard/read-tree --reset -u: remove unmerged new paths

1  2 
read-cache.c
diff --combined read-cache.c
index c229fd4d0da68b204e81e1e8127f8529abe06336,15e1a9d471daa2fd5c54a9f8562b1dfc52161213..8160022b254ca5bee6e66e976d7737767c912d43
@@@ -8,12 -8,6 +8,12 @@@
  #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"
 +#include "blob.h"
  
  /* Index extensions.
   *
@@@ -512,14 -506,6 +512,14 @@@ static struct cache_entry *create_alias
        return new;
  }
  
 +static void record_intent_to_add(struct cache_entry *ce)
 +{
 +      unsigned char sha1[20];
 +      if (write_sha1_file("", 0, blob_type, sha1))
 +              die("cannot create an empty blob in the object database");
 +      hashcpy(ce->sha1, sha1);
 +}
 +
  int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)
  {
        int size, namelen, was_same;
        unsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;
        int verbose = flags & (ADD_CACHE_VERBOSE | ADD_CACHE_PRETEND);
        int pretend = flags & ADD_CACHE_PRETEND;
 +      int intent_only = flags & ADD_CACHE_INTENT;
 +      int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|
 +                        (intent_only ? ADD_CACHE_NEW_ONLY : 0));
  
        if (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))
                return error("%s: can only add regular files, symbolic links or git-directories", path);
        ce = xcalloc(1, size);
        memcpy(ce->name, path, namelen);
        ce->ce_flags = namelen;
 -      fill_stat_cache_info(ce, st);
 +      if (!intent_only)
 +              fill_stat_cache_info(ce, st);
  
        if (trust_executable_bit && has_symlinks)
                ce->ce_mode = create_ce_mode(st_mode);
                alias->ce_flags |= CE_ADDED;
                return 0;
        }
 -      if (index_path(ce->sha1, path, st, 1))
 -              return error("unable to index file %s", path);
 +      if (!intent_only) {
 +              if (index_path(ce->sha1, path, st, 1))
 +                      return error("unable to index file %s", path);
 +      } else
 +              record_intent_to_add(ce);
 +
        if (ignore_case && alias && different_name(ce, alias))
                ce = create_alias_ce(ce, alias);
        ce->ce_flags |= CE_ADDED;
  
        if (pretend)
                ;
 -      else if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))
 +      else if (add_index_entry(istate, ce, add_option))
                return error("unable to add %s to index",path);
        if (verbose && !was_same)
                printf("add '%s'\n", path);
@@@ -608,10 -586,8 +608,10 @@@ struct cache_entry *make_cache_entry(un
        int size, len;
        struct cache_entry *ce;
  
 -      if (!verify_path(path))
 +      if (!verify_path(path)) {
 +              error("Invalid path '%s'", path);
                return NULL;
 +      }
  
        len = strlen(path);
        size = cache_entry_size(len);
@@@ -867,15 -843,13 +867,15 @@@ static int add_index_entry_with_check(s
        int ok_to_add = option & ADD_CACHE_OK_TO_ADD;
        int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
        int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
 +      int new_only = option & ADD_CACHE_NEW_ONLY;
  
        cache_tree_invalidate_path(istate->cache_tree, ce->name);
        pos = index_name_pos(istate, ce->name, ce->ce_flags);
  
        /* existing match? Just replace it. */
        if (pos >= 0) {
 -              replace_index_entry(istate, pos, ce);
 +              if (!new_only)
 +                      replace_index_entry(istate, pos, ce);
                return 0;
        }
        pos = -pos-1;
        if (!ok_to_add)
                return -1;
        if (!verify_path(ce->name))
 -              return -1;
 +              return error("Invalid path '%s'", ce->name);
  
        if (!skip_df_check &&
            check_file_directory_conflict(istate, ce, pos, ok_to_replace)) {
@@@ -1093,16 -1067,16 +1093,16 @@@ struct cache_entry *refresh_cache_entry
  
  static int verify_hdr(struct cache_header *hdr, unsigned long size)
  {
 -      SHA_CTX c;
 +      git_SHA_CTX c;
        unsigned char sha1[20];
  
        if (hdr->hdr_signature != htonl(CACHE_SIGNATURE))
                return error("bad signature");
        if (hdr->hdr_version != htonl(2))
                return error("bad index version");
 -      SHA1_Init(&c);
 -      SHA1_Update(&c, hdr, size - 20);
 -      SHA1_Final(sha1, &c);
 +      git_SHA1_Init(&c);
 +      git_SHA1_Update(&c, hdr, size - 20);
 +      git_SHA1_Final(sha1, &c);
        if (hashcmp(sha1, (unsigned char *)hdr + size - 20))
                return error("bad index file sha1 signature");
        return 0;
@@@ -1144,10 -1118,6 +1144,10 @@@ static void convert_from_disk(struct on
        ce->ce_size  = ntohl(ondisk->size);
        /* On-disk flags are just 16 bits */
        ce->ce_flags = ntohs(ondisk->flags);
 +
 +      /* For future extension: we do not understand this entry yet */
 +      if (ce->ce_flags & CE_EXTENDED)
 +              die("Unknown index entry format");
        hashcpy(ce->sha1, ondisk->sha1);
  
        len = ce->ce_flags & CE_NAMEMASK;
@@@ -1299,11 -1269,11 +1299,11 @@@ int unmerged_index(const struct index_s
  static unsigned char write_buffer[WRITE_BUFFER_SIZE];
  static unsigned long write_buffer_len;
  
 -static int ce_write_flush(SHA_CTX *context, int fd)
 +static int ce_write_flush(git_SHA_CTX *context, int fd)
  {
        unsigned int buffered = write_buffer_len;
        if (buffered) {
 -              SHA1_Update(context, write_buffer, buffered);
 +              git_SHA1_Update(context, write_buffer, buffered);
                if (write_in_full(fd, write_buffer, buffered) != buffered)
                        return -1;
                write_buffer_len = 0;
        return 0;
  }
  
 -static int ce_write(SHA_CTX *context, int fd, void *data, unsigned int len)
 +static int ce_write(git_SHA_CTX *context, int fd, void *data, unsigned int len)
  {
        while (len) {
                unsigned int buffered = write_buffer_len;
        return 0;
  }
  
 -static int write_index_ext_header(SHA_CTX *context, int fd,
 +static int write_index_ext_header(git_SHA_CTX *context, int fd,
                                  unsigned int ext, unsigned int sz)
  {
        ext = htonl(ext);
                (ce_write(context, fd, &sz, 4) < 0)) ? -1 : 0;
  }
  
 -static int ce_flush(SHA_CTX *context, int fd)
 +static int ce_flush(git_SHA_CTX *context, int fd)
  {
        unsigned int left = write_buffer_len;
  
        if (left) {
                write_buffer_len = 0;
 -              SHA1_Update(context, write_buffer, left);
 +              git_SHA1_Update(context, write_buffer, left);
        }
  
        /* Flush first if not enough space for SHA1 signature */
        }
  
        /* Append the SHA1 signature at the end */
 -      SHA1_Final(write_buffer + left, context);
 +      git_SHA1_Final(write_buffer + left, context);
        left += 20;
        return (write_in_full(fd, write_buffer, left) != left) ? -1 : 0;
  }
@@@ -1413,7 -1383,7 +1413,7 @@@ static void ce_smudge_racily_clean_entr
        }
  }
  
 -static int ce_write_entry(SHA_CTX *c, int fd, struct cache_entry *ce)
 +static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
  {
        int size = ondisk_ce_size(ce);
        struct ondisk_cache_entry *ondisk = xcalloc(1, size);
  
  int write_index(const struct index_state *istate, int newfd)
  {
 -      SHA_CTX c;
 +      git_SHA_CTX c;
        struct cache_header hdr;
        int i, err, removed;
        struct cache_entry **cache = istate->cache;
        hdr.hdr_version = htonl(2);
        hdr.hdr_entries = htonl(entries - removed);
  
 -      SHA1_Init(&c);
 +      git_SHA1_Init(&c);
        if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
                return -1;
  
  
        /* Write extension data here */
        if (istate->cache_tree) {
 -              struct strbuf sb;
 +              struct strbuf sb = STRBUF_INIT;
  
 -              strbuf_init(&sb, 0);
                cache_tree_write(&sb, istate->cache_tree);
                err = write_index_ext_header(&c, newfd, CACHE_EXT_TREE, sb.len) < 0
                        || ce_write(&c, newfd, sb.buf, sb.len) < 0;
  int read_index_unmerged(struct index_state *istate)
  {
        int i;
-       struct cache_entry **dst;
-       struct cache_entry *last = NULL;
+       int unmerged = 0;
  
        read_index(istate);
-       dst = istate->cache;
        for (i = 0; i < istate->cache_nr; i++) {
                struct cache_entry *ce = istate->cache[i];
-               if (ce_stage(ce)) {
-                       remove_name_hash(ce);
-                       if (last && !strcmp(ce->name, last->name))
-                               continue;
-                       cache_tree_invalidate_path(istate->cache_tree, ce->name);
-                       last = ce;
+               struct cache_entry *new_ce;
+               int size, len;
+               if (!ce_stage(ce))
                        continue;
-               }
-               *dst++ = ce;
+               unmerged = 1;
+               len = strlen(ce->name);
+               size = cache_entry_size(len);
+               new_ce = xcalloc(1, size);
+               hashcpy(new_ce->sha1, ce->sha1);
+               memcpy(new_ce->name, ce->name, len);
+               new_ce->ce_flags = create_ce_flags(len, 0);
+               new_ce->ce_mode = ce->ce_mode;
+               if (add_index_entry(istate, new_ce, 0))
+                       return error("%s: cannot drop to stage #0",
+                                    ce->name);
+               i = index_name_pos(istate, new_ce->name, len);
        }
-       istate->cache_nr = dst - istate->cache;
-       return !!last;
+       return unmerged;
  }
 +
 +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;
 +}
 +