Merge branch 'lt/setup' into __/setup-n-mv
authorJunio C Hamano <junkio@cox.net>
Sat, 29 Jul 2006 08:54:54 +0000 (01:54 -0700)
committerJunio C Hamano <junkio@cox.net>
Sat, 29 Jul 2006 08:54:54 +0000 (01:54 -0700)
This merges the new built-in calling convention code into Johannes's
builtin-mv topic in order to resolve their conflicts early on.

Signed-off-by: Junio C Hamano <junkio@cox.net>
1  2 
Makefile
builtin-add.c
builtin-mv.c
builtin.h
git.c

diff --cc Makefile
Simple merge
diff --cc builtin-add.c
@@@ -82,9 -82,48 +82,9 @@@ static void fill_directory(struct dir_s
                prune_directory(dir, pathspec, baselen);
  }
  
 -static int add_file_to_index(const char *path, int verbose)
 -{
 -      int size, namelen;
 -      struct stat st;
 -      struct cache_entry *ce;
 -
 -      if (lstat(path, &st))
 -              die("%s: unable to stat (%s)", path, strerror(errno));
 -
 -      if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
 -              die("%s: can only add regular files or symbolic links", path);
 -
 -      namelen = strlen(path);
 -      size = cache_entry_size(namelen);
 -      ce = xcalloc(1, size);
 -      memcpy(ce->name, path, namelen);
 -      ce->ce_flags = htons(namelen);
 -      fill_stat_cache_info(ce, &st);
 -
 -      ce->ce_mode = create_ce_mode(st.st_mode);
 -      if (!trust_executable_bit) {
 -              /* If there is an existing entry, pick the mode bits
 -               * from it.
 -               */
 -              int pos = cache_name_pos(path, namelen);
 -              if (pos >= 0)
 -                      ce->ce_mode = active_cache[pos]->ce_mode;
 -      }
 -
 -      if (index_path(ce->sha1, path, &st, 1))
 -              die("unable to index file %s", path);
 -      if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD))
 -              die("unable to add %s to index",path);
 -      if (verbose)
 -              printf("add '%s'\n", path);
 -      cache_tree_invalidate_path(active_cache_tree, path);
 -      return 0;
 -}
 -
  static struct lock_file lock_file;
  
- int cmd_add(int argc, const char **argv, char **envp)
+ int cmd_add(int argc, const char **argv, const char *prefix)
  {
        int i, newfd;
        int verbose = 0, show_only = 0;
diff --cc builtin-mv.c
index 42c2e39,0000000..62ae937
mode 100644,000000..100644
--- /dev/null
@@@ -1,298 -1,0 +1,297 @@@
- int cmd_mv(int argc, const char **argv, char **envp)
 +/*
 + * "git mv" builtin command
 + *
 + * Copyright (C) 2006 Johannes Schindelin
 + */
 +#include <fnmatch.h>
 +
 +#include "cache.h"
 +#include "builtin.h"
 +#include "dir.h"
 +#include "cache-tree.h"
 +#include "path-list.h"
 +
 +static const char builtin_mv_usage[] =
 +"git-mv [-n] [-f] (<source> <destination> | [-k] <source>... <destination>)";
 +
 +static const char **copy_pathspec(const char *prefix, const char **pathspec,
 +                                int count, int base_name)
 +{
 +      const char **result = xmalloc((count + 1) * sizeof(const char *));
 +      memcpy(result, pathspec, count * sizeof(const char *));
 +      result[count] = NULL;
 +      if (base_name) {
 +              int i;
 +              for (i = 0; i < count; i++) {
 +                      const char *last_slash = strrchr(result[i], '/');
 +                      if (last_slash)
 +                              result[i] = last_slash + 1;
 +              }
 +      }
 +      return get_pathspec(prefix, result);
 +}
 +
 +static void show_list(const char *label, struct path_list *list)
 +{
 +      if (list->nr > 0) {
 +              int i;
 +              printf("%s", label);
 +              for (i = 0; i < list->nr; i++)
 +                      printf("%s%s", i > 0 ? ", " : "", list->items[i].path);
 +              putchar('\n');
 +      }
 +}
 +
 +static const char *add_slash(const char *path)
 +{
 +      int len = strlen(path);
 +      if (path[len - 1] != '/') {
 +              char *with_slash = xmalloc(len + 2);
 +              memcpy(with_slash, path, len);
 +              strcat(with_slash + len, "/");
 +              return with_slash;
 +      }
 +      return path;
 +}
 +
 +static struct lock_file lock_file;
 +
-       const char *prefix = setup_git_directory();
++int cmd_mv(int argc, const char **argv, const char *prefix)
 +{
 +      int i, newfd, count;
 +      int verbose = 0, show_only = 0, force = 0, ignore_errors = 0;
 +      const char **source, **destination, **dest_path;
 +      enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX } *modes;
 +      struct stat st;
 +      struct path_list overwritten = {NULL, 0, 0, 0};
 +      struct path_list src_for_dst = {NULL, 0, 0, 0};
 +      struct path_list added = {NULL, 0, 0, 0};
 +      struct path_list deleted = {NULL, 0, 0, 0};
 +      struct path_list changed = {NULL, 0, 0, 0};
 +
 +      git_config(git_default_config);
 +
 +      newfd = hold_lock_file_for_update(&lock_file, get_index_file());
 +      if (newfd < 0)
 +              die("unable to create new index file");
 +
 +      if (read_cache() < 0)
 +              die("index file corrupt");
 +
 +      for (i = 1; i < argc; i++) {
 +              const char *arg = argv[i];
 +
 +              if (arg[0] != '-')
 +                      break;
 +              if (!strcmp(arg, "--")) {
 +                      i++;
 +                      break;
 +              }
 +              if (!strcmp(arg, "-n")) {
 +                      show_only = 1;
 +                      continue;
 +              }
 +              if (!strcmp(arg, "-f")) {
 +                      force = 1;
 +                      continue;
 +              }
 +              if (!strcmp(arg, "-k")) {
 +                      ignore_errors = 1;
 +                      continue;
 +              }
 +              die(builtin_mv_usage);
 +      }
 +      count = argc - i - 1;
 +      if (count < 1)
 +              usage(builtin_mv_usage);
 +
 +      source = copy_pathspec(prefix, argv + i, count, 0);
 +      modes = xcalloc(count, sizeof(enum update_mode));
 +      dest_path = copy_pathspec(prefix, argv + argc - 1, 1, 0);
 +
 +      if (!lstat(dest_path[0], &st) &&
 +                      S_ISDIR(st.st_mode)) {
 +              dest_path[0] = add_slash(dest_path[0]);
 +              destination = copy_pathspec(dest_path[0], argv + i, count, 1);
 +      } else {
 +              if (count != 1)
 +                      usage(builtin_mv_usage);
 +              destination = dest_path;
 +      }
 +
 +      /* Checking */
 +      for (i = 0; i < count; i++) {
 +              const char *bad = NULL;
 +
 +              if (show_only)
 +                      printf("Checking rename of '%s' to '%s'\n",
 +                              source[i], destination[i]);
 +
 +              if (lstat(source[i], &st) < 0)
 +                      bad = "bad source";
 +
 +              if (S_ISDIR(st.st_mode)) {
 +                      const char *dir = source[i], *dest_dir = destination[i];
 +                      int first, last, len = strlen(dir);
 +
 +                      if (lstat(dest_dir, &st) == 0) {
 +                              bad = "cannot move directory over file";
 +                              goto next;
 +                      }
 +
 +                      modes[i] = WORKING_DIRECTORY;
 +
 +                      first = cache_name_pos(source[i], len);
 +                      if (first >= 0)
 +                              die ("Huh? %s/ is in index?", dir);
 +
 +                      first = -1 - first;
 +                      for (last = first; last < active_nr; last++) {
 +                              const char *path = active_cache[last]->name;
 +                              if (strncmp(path, dir, len) || path[len] != '/')
 +                                      break;
 +                      }
 +
 +                      if (last - first < 1)
 +                              bad = "source directory is empty";
 +                      else if (!bad) {
 +                              int j, dst_len = strlen(dest_dir);
 +
 +                              if (last - first > 0) {
 +                                      source = realloc(source,
 +                                                      (count + last - first)
 +                                                      * sizeof(char *));
 +                                      destination = realloc(destination,
 +                                                      (count + last - first)
 +                                                      * sizeof(char *));
 +                                      modes = realloc(modes,
 +                                                      (count + last - first)
 +                                                      * sizeof(enum update_mode));
 +                              }
 +
 +                              dest_dir = add_slash(dest_dir);
 +
 +                              for (j = 0; j < last - first; j++) {
 +                                      const char *path =
 +                                              active_cache[first + j]->name;
 +                                      source[count + j] = path;
 +                                      destination[count + j] =
 +                                              prefix_path(dest_dir, dst_len,
 +                                                      path + len);
 +                                      modes[count + j] = INDEX;
 +                              }
 +                              count += last - first;
 +                      }
 +
 +                      goto next;
 +              }
 +
 +              if (!bad && lstat(destination[i], &st) == 0) {
 +                      bad = "destination exists";
 +                      if (force) {
 +                              /*
 +                               * only files can overwrite each other:
 +                               * check both source and destination
 +                               */
 +                              if (S_ISREG(st.st_mode)) {
 +                                      fprintf(stderr, "Warning: %s;"
 +                                                      " will overwrite!\n",
 +                                                      bad);
 +                                      bad = NULL;
 +                                      path_list_insert(destination[i],
 +                                                      &overwritten);
 +                              } else
 +                                      bad = "Cannot overwrite";
 +                      }
 +              }
 +
 +              if (!bad &&
 +                  !strncmp(destination[i], source[i], strlen(source[i])))
 +                      bad = "can not move directory into itself";
 +
 +              if (!bad && cache_name_pos(source[i], strlen(source[i])) < 0)
 +                      bad = "not under version control";
 +
 +              if (!bad) {
 +                      if (path_list_has_path(&src_for_dst, destination[i]))
 +                              bad = "multiple sources for the same target";
 +                      else
 +                              path_list_insert(destination[i], &src_for_dst);
 +              }
 +
 +next:
 +              if (bad) {
 +                      if (ignore_errors) {
 +                              if (--count > 0) {
 +                                      memmove(source + i, source + i + 1,
 +                                              (count - i) * sizeof(char *));
 +                                      memmove(destination + i,
 +                                              destination + i + 1,
 +                                              (count - i) * sizeof(char *));
 +                              }
 +                      } else
 +                              die ("%s, source=%s, destination=%s",
 +                                   bad, source[i], destination[i]);
 +              }
 +      }
 +
 +      for (i = 0; i < count; i++) {
 +              if (show_only || verbose)
 +                      printf("Renaming %s to %s\n",
 +                             source[i], destination[i]);
 +              if (!show_only && modes[i] != INDEX &&
 +                  rename(source[i], destination[i]) < 0 &&
 +                  !ignore_errors)
 +                      die ("renaming %s failed: %s",
 +                           source[i], strerror(errno));
 +
 +              if (modes[i] == WORKING_DIRECTORY)
 +                      continue;
 +
 +              if (cache_name_pos(source[i], strlen(source[i])) >= 0) {
 +                      path_list_insert(source[i], &deleted);
 +
 +                      /* destination can be a directory with 1 file inside */
 +                      if (path_list_has_path(&overwritten, destination[i]))
 +                              path_list_insert(destination[i], &changed);
 +                      else
 +                              path_list_insert(destination[i], &added);
 +              } else
 +                      path_list_insert(destination[i], &added);
 +      }
 +
 +        if (show_only) {
 +              show_list("Changed  : ", &changed);
 +              show_list("Adding   : ", &added);
 +              show_list("Deleting : ", &deleted);
 +      } else {
 +              for (i = 0; i < changed.nr; i++) {
 +                      const char *path = changed.items[i].path;
 +                      int i = cache_name_pos(path, strlen(path));
 +                      struct cache_entry *ce = active_cache[i];
 +
 +                      if (i < 0)
 +                              die ("Huh? Cache entry for %s unknown?", path);
 +                      refresh_cache_entry(ce, 0);
 +              }
 +
 +              for (i = 0; i < added.nr; i++) {
 +                      const char *path = added.items[i].path;
 +                      add_file_to_index(path, verbose);
 +              }
 +
 +              for (i = 0; i < deleted.nr; i++) {
 +                      const char *path = deleted.items[i].path;
 +                      remove_file_from_cache(path);
 +              }
 +
 +              if (active_cache_changed) {
 +                      if (write_cache(newfd, active_cache, active_nr) ||
 +                          close(newfd) ||
 +                          commit_lock_file(&lock_file))
 +                              die("Unable to write new index file");
 +              }
 +      }
 +
 +      return 0;
 +}
diff --cc builtin.h
+++ b/builtin.h
@@@ -15,54 -15,53 +15,54 @@@ void cmd_usage(int show_all, const cha
  #endif
        ;
  
- extern int cmd_help(int argc, const char **argv, char **envp);
- extern int cmd_version(int argc, const char **argv, char **envp);
+ extern int cmd_help(int argc, const char **argv, const char *prefix);
+ extern int cmd_version(int argc, const char **argv, const char *prefix);
  
- extern int cmd_whatchanged(int argc, const char **argv, char **envp);
- extern int cmd_show(int argc, const char **argv, char **envp);
- extern int cmd_log(int argc, const char **argv, char **envp);
- extern int cmd_diff(int argc, const char **argv, char **envp);
- extern int cmd_format_patch(int argc, const char **argv, char **envp);
- extern int cmd_count_objects(int argc, const char **argv, char **envp);
+ extern int cmd_whatchanged(int argc, const char **argv, const char *prefix);
+ extern int cmd_show(int argc, const char **argv, const char *prefix);
+ extern int cmd_log(int argc, const char **argv, const char *prefix);
+ extern int cmd_diff(int argc, const char **argv, const char *prefix);
+ extern int cmd_format_patch(int argc, const char **argv, const char *prefix);
+ extern int cmd_count_objects(int argc, const char **argv, const char *prefix);
  
- extern int cmd_prune(int argc, const char **argv, char **envp);
+ extern int cmd_prune(int argc, const char **argv, const char *prefix);
  
- extern int cmd_push(int argc, const char **argv, char **envp);
- extern int cmd_grep(int argc, const char **argv, char **envp);
- extern int cmd_rm(int argc, const char **argv, char **envp);
- extern int cmd_add(int argc, const char **argv, char **envp);
- extern int cmd_rev_list(int argc, const char **argv, char **envp);
- extern int cmd_check_ref_format(int argc, const char **argv, char **envp);
- extern int cmd_init_db(int argc, const char **argv, char **envp);
- extern int cmd_tar_tree(int argc, const char **argv, char **envp);
- extern int cmd_upload_tar(int argc, const char **argv, char **envp);
- extern int cmd_get_tar_commit_id(int argc, const char **argv, char **envp);
- extern int cmd_ls_files(int argc, const char **argv, char **envp);
- extern int cmd_ls_tree(int argc, const char **argv, char **envp);
- extern int cmd_read_tree(int argc, const char **argv, char **envp);
- extern int cmd_commit_tree(int argc, const char **argv, char **envp);
- extern int cmd_apply(int argc, const char **argv, char **envp);
- extern int cmd_show_branch(int argc, const char **argv, char **envp);
- extern int cmd_diff_files(int argc, const char **argv, char **envp);
- extern int cmd_diff_index(int argc, const char **argv, char **envp);
- extern int cmd_diff_stages(int argc, const char **argv, char **envp);
- extern int cmd_diff_tree(int argc, const char **argv, char **envp);
- extern int cmd_cat_file(int argc, const char **argv, char **envp);
- extern int cmd_rev_parse(int argc, const char **argv, char **envp);
- extern int cmd_update_index(int argc, const char **argv, char **envp);
- extern int cmd_update_ref(int argc, const char **argv, char **envp);
- extern int cmd_fmt_merge_msg(int argc, const char **argv, char **envp);
- extern int cmd_mv(int argc, const char **argv, char **envp);
+ extern int cmd_push(int argc, const char **argv, const char *prefix);
+ extern int cmd_grep(int argc, const char **argv, const char *prefix);
+ extern int cmd_rm(int argc, const char **argv, const char *prefix);
+ extern int cmd_add(int argc, const char **argv, const char *prefix);
+ extern int cmd_rev_list(int argc, const char **argv, const char *prefix);
+ extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
+ extern int cmd_init_db(int argc, const char **argv, const char *prefix);
+ extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
+ extern int cmd_upload_tar(int argc, const char **argv, const char *prefix);
+ extern int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix);
+ extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
+ extern int cmd_ls_tree(int argc, const char **argv, const char *prefix);
+ extern int cmd_read_tree(int argc, const char **argv, const char *prefix);
+ extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);
+ extern int cmd_apply(int argc, const char **argv, const char *prefix);
+ extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
+ extern int cmd_diff_files(int argc, const char **argv, const char *prefix);
+ extern int cmd_diff_index(int argc, const char **argv, const char *prefix);
+ extern int cmd_diff_stages(int argc, const char **argv, const char *prefix);
+ extern int cmd_diff_tree(int argc, const char **argv, const char *prefix);
+ extern int cmd_cat_file(int argc, const char **argv, const char *prefix);
+ extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
+ extern int cmd_update_index(int argc, const char **argv, const char *prefix);
+ extern int cmd_update_ref(int argc, const char **argv, const char *prefix);
+ extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
++extern int cmd_mv(int argc, const char **argv, const char *prefix);
  
- extern int cmd_write_tree(int argc, const char **argv, char **envp);
+ extern int cmd_write_tree(int argc, const char **argv, const char *prefix);
  extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);
  
- extern int cmd_mailsplit(int argc, const char **argv, char **envp);
+ extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);
  extern int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip);
  
- extern int cmd_mailinfo(int argc, const char **argv, char **envp);
+ extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);
  extern int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, const char *msg, const char *patch);
  
- extern int cmd_stripspace(int argc, const char **argv, char **envp);
+ extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
  extern void stripspace(FILE *in, FILE *out);
  #endif
diff --cc git.c
--- 1/git.c
--- 2/git.c
+++ b/git.c
@@@ -198,11 -258,10 +258,11 @@@ static void handle_internal_command(in
                { "mailsplit", cmd_mailsplit },
                { "mailinfo", cmd_mailinfo },
                { "stripspace", cmd_stripspace },
-               { "update-index", cmd_update_index },
-               { "update-ref", cmd_update_ref },
-               { "fmt-merge-msg", cmd_fmt_merge_msg },
-               { "prune", cmd_prune },
-               { "mv", cmd_mv },
+               { "update-index", cmd_update_index, NEEDS_PREFIX },
+               { "update-ref", cmd_update_ref, NEEDS_PREFIX },
+               { "fmt-merge-msg", cmd_fmt_merge_msg, NEEDS_PREFIX },
+               { "prune", cmd_prune, NEEDS_PREFIX },
++              { "mv", cmd_mv, NEEDS_PREFIX },
        };
        int i;