Merge branch 'rr/fi-import-marks-if-exists'
authorJunio C Hamano <gitster@pobox.com>
Thu, 10 Feb 2011 00:41:16 +0000 (16:41 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 10 Feb 2011 00:41:16 +0000 (16:41 -0800)
* rr/fi-import-marks-if-exists:
fast-import: Introduce --import-marks-if-exists

1  2 
Documentation/git-fast-import.txt
fast-import.c
t/t9300-fast-import.sh
index 02bb49886cc5f8415cec8786282681b4114a6380,32a062c991bba220f0e623afb9e89d75b3b23ed8..c3a2766b206609bb5f313db3ff37a1ebb40f8261
@@@ -78,6 -78,10 +78,10 @@@ OPTION
        set of marks.  If a mark is defined to different values,
        the last file wins.
  
+ --import-marks-if-exists=<file>::
+       Like --import-marks but instead of erroring out, silently
+       skips the file if it does not exist.
  --relative-marks::
        After specifying --relative-marks= the paths specified
        with --import-marks= and --export-marks= are relative
@@@ -534,6 -538,9 +538,6 @@@ start with double quote (`"`)
  If an `LF` or double quote must be encoded into `<path>` shell-style
  quoting should be used, e.g. `"path/with\n and \" in it"`.
  
 -Additionally, in `040000` mode, `<path>` may also be an empty string
 -(`""`) to specify the root of the tree.
 -
  The value of `<path>` must be in canonical form. That is it must not:
  
  * contain an empty directory component (e.g. `foo//bar` is invalid),
  * contain the special component `.` or `..` (e.g. `foo/./bar` and
    `foo/../bar` are invalid).
  
 +The root of the tree can be represented by an empty string as `<path>`.
 +
  It is recommended that `<path>` always be encoded using UTF-8.
  
  `filedelete`
@@@ -904,7 -909,7 +908,7 @@@ The `<dataref>` can be either a mark re
  set previously or a full 40-byte SHA-1 of a Git blob, preexisting or
  ready to be written.
  
 -output uses the same format as `git cat-file --batch`:
 +Output uses the same format as `git cat-file --batch`:
  
  ====
        <sha1> SP 'blob' SP <size> LF
@@@ -948,13 -953,6 +952,13 @@@ cat-blob:
        rather than wasting time on the early part of an import
        before the unsupported command is detected.
  
 +notes::
 +      Require that the backend support the 'notemodify' (N)
 +      subcommand to the 'commit' command.
 +      Versions of fast-import not supporting notes will exit
 +      with a message indicating so.
 +
 +
  `option`
  ~~~~~~~~
  Processes the specified option so that git fast-import behaves in a
diff --combined fast-import.c
index 970d8470ed7c350337f28570fd2c111186a7941d,c525fdaac617541852415cdfa5f7c1c9ecfe4df5..3886a1b46415ddbf66e5c2be401ad7fd2c012363
@@@ -329,6 -329,7 +329,7 @@@ static struct mark_set *marks
  static const char *export_marks_file;
  static const char *import_marks_file;
  static int import_marks_file_from_stream;
+ static int import_marks_file_ignore_missing;
  static int relative_marks_paths;
  
  /* Our last blob */
@@@ -1795,7 -1796,11 +1796,11 @@@ static void read_marks(void
  {
        char line[512];
        FILE *f = fopen(import_marks_file, "r");
-       if (!f)
+       if (f)
+               ;
+       else if (import_marks_file_ignore_missing && errno == ENOENT)
+               return; /* Marks file does not exist */
+       else
                die_errno("cannot read '%s'", import_marks_file);
        while (fgets(line, sizeof(line), f)) {
                uintmax_t mark;
@@@ -2231,12 -2236,6 +2236,12 @@@ static void file_change_m(struct branc
                p = uq.buf;
        }
  
 +      /* Git does not track empty, non-toplevel directories. */
 +      if (S_ISDIR(mode) && !memcmp(sha1, EMPTY_TREE_SHA1_BIN, 20) && *p) {
 +              tree_content_remove(&b->branch_tree, p, NULL);
 +              return;
 +      }
 +
        if (S_ISGITLINK(mode)) {
                if (inline_data)
                        die("Git links cannot be specified 'inline': %s",
@@@ -2867,7 -2866,8 +2872,8 @@@ static char* make_fast_import_path(cons
        return strbuf_detach(&abs_path, NULL);
  }
  
- static void option_import_marks(const char *marks, int from_stream)
+ static void option_import_marks(const char *marks,
+                                       int from_stream, int ignore_missing)
  {
        if (import_marks_file) {
                if (from_stream)
        import_marks_file = make_fast_import_path(marks);
        safe_create_leading_directories_const(import_marks_file);
        import_marks_file_from_stream = from_stream;
+       import_marks_file_ignore_missing = ignore_missing;
  }
  
  static void option_date_format(const char *fmt)
@@@ -2980,7 -2981,10 +2987,10 @@@ static int parse_one_feature(const cha
        if (!prefixcmp(feature, "date-format=")) {
                option_date_format(feature + 12);
        } else if (!prefixcmp(feature, "import-marks=")) {
-               option_import_marks(feature + 13, from_stream);
+               option_import_marks(feature + 13, from_stream, 0);
+       } else if (!prefixcmp(feature, "import-marks-if-exists=")) {
+               option_import_marks(feature + strlen("import-marks-if-exists="),
+                                       from_stream, 1);
        } else if (!prefixcmp(feature, "export-marks=")) {
                option_export_marks(feature + 13);
        } else if (!strcmp(feature, "cat-blob")) {
                relative_marks_paths = 0;
        } else if (!prefixcmp(feature, "force")) {
                force_update = 1;
 +      } else if (!strcmp(feature, "notes")) {
 +              ; /* do nothing; we have the feature */
        } else {
                return 0;
        }
diff --combined t/t9300-fast-import.sh
index 986bc14d58c30201e75f3d95d9b8245e997b99e9,870e55b0beece8dfa85b2dd91c620ce8786043ce..52ac0e56dce12016ab03155bd16b2b66b062fca3
@@@ -919,48 -919,6 +919,48 @@@ test_expect_success 
         git diff-tree -C --find-copies-harder -r N4 N6 >actual &&
         compare_diff_raw expect actual'
  
 +test_expect_success \
 +      'N: delete directory by copying' \
 +      'cat >expect <<-\EOF &&
 +      OBJID
 +      :100644 000000 OBJID OBJID D    foo/bar/qux
 +      OBJID
 +      :000000 100644 OBJID OBJID A    foo/bar/baz
 +      :000000 100644 OBJID OBJID A    foo/bar/qux
 +      EOF
 +       empty_tree=$(git mktree </dev/null) &&
 +       cat >input <<-INPUT_END &&
 +      commit refs/heads/N-delete
 +      committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 +      data <<COMMIT
 +      collect data to be deleted
 +      COMMIT
 +
 +      deleteall
 +      M 100644 inline foo/bar/baz
 +      data <<DATA_END
 +      hello
 +      DATA_END
 +      C "foo/bar/baz" "foo/bar/qux"
 +      C "foo/bar/baz" "foo/bar/quux/1"
 +      C "foo/bar/baz" "foo/bar/quuux"
 +      M 040000 $empty_tree foo/bar/quux
 +      M 040000 $empty_tree foo/bar/quuux
 +
 +      commit refs/heads/N-delete
 +      committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 +      data <<COMMIT
 +      delete subdirectory
 +      COMMIT
 +
 +      M 040000 $empty_tree foo/bar/qux
 +      INPUT_END
 +       git fast-import <input &&
 +       git rev-list N-delete |
 +              git diff-tree -r --stdin --root --always |
 +              sed -e "s/$_x40/OBJID/g" >actual &&
 +       test_cmp expect actual'
 +
  test_expect_success \
        'N: modify copied tree' \
        'cat >expect <<-\EOF &&
@@@ -1748,6 -1706,61 +1748,61 @@@ test_expect_success 
      'cat input | git fast-import --export-marks=other.marks &&
      grep :1 other.marks'
  
+ test_expect_success 'R: catch typo in marks file name' '
+       test_must_fail git fast-import --import-marks=nonexistent.marks </dev/null &&
+       echo "feature import-marks=nonexistent.marks" |
+       test_must_fail git fast-import
+ '
+ test_expect_success 'R: import and output marks can be the same file' '
+       rm -f io.marks &&
+       blob=$(echo hi | git hash-object --stdin) &&
+       cat >expect <<-EOF &&
+       :1 $blob
+       :2 $blob
+       EOF
+       git fast-import --export-marks=io.marks <<-\EOF &&
+       blob
+       mark :1
+       data 3
+       hi
+       EOF
+       git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF &&
+       blob
+       mark :2
+       data 3
+       hi
+       EOF
+       test_cmp expect io.marks
+ '
+ test_expect_success 'R: --import-marks=foo --output-marks=foo to create foo fails' '
+       rm -f io.marks &&
+       test_must_fail git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF
+       blob
+       mark :1
+       data 3
+       hi
+       EOF
+ '
+ test_expect_success 'R: --import-marks-if-exists' '
+       rm -f io.marks &&
+       blob=$(echo hi | git hash-object --stdin) &&
+       echo ":1 $blob" >expect &&
+       git fast-import --import-marks-if-exists=io.marks --export-marks=io.marks <<-\EOF &&
+       blob
+       mark :1
+       data 3
+       hi
+       EOF
+       test_cmp expect io.marks
+ '
  cat >input << EOF
  feature import-marks=marks.out
  feature export-marks=marks.new