git-export-filter.c: add support for --expand-renames
authorKyle J. McKay <[email protected]>
Wed, 27 Aug 2014 01:14:48 +0000 (26 18:14 -0700)
committerKyle J. McKay <[email protected]>
Wed, 27 Aug 2014 01:14:48 +0000 (26 18:14 -0700)
Add support for new --expand-renames option that replaces
any incoming filerename 'R' commands with a filecopy 'C' followed
by a filedelete 'D' of the source file location instead.

The Git fast import documentation claims that "a filerename is the
same as a filecopy followed by a filedelete of the source file
location."

git-export-filter.1
git-export-filter.c
git-export-filter.txt
git-export-help.txt

index 9ebe53c..605c2a6 100644 (file)
@@ -24,7 +24,8 @@ git-export-filter \- Filter fast\-export data with optional rewrites
 \fIgit export\-filter\fR [\-\-verbose|\-v] [\-h|\-\-help] [\-\-version|\-V] [\-\-debug|\-d]
                   [\-\-authors\-file=<authors_file> [\-\-require\-authors]]
                   [\-\-branches\-file=<branches_file>] [\-\-trunk\-is\-master]
-                  [\-\-convert\-tagger=<email>] [\-\-strip\-at\-suffix] [\-\-]
+                  [\-\-convert\-tagger=<email>] [\-\-strip\-at\-suffix]
+                  [\-\-expand\-renames] [\-\-]
                   <input_file>|< <input_file>   > <output_file>
 .fi
 .sp
@@ -142,6 +143,17 @@ suffixes to the email addresses it generates in the fast\-export data and will n
 authors file\&.
 .RE
 .PP
+\-\-expand\-renames
+.RS 4
+Some importers of fast\-export data cannot handle renames but can handle copies\&. If \-\-expand\-renames is given then any instances of filerename
+\fIR\fR
+are replaced with a filecopy
+\fIC\fR
+followed by a filedelete
+\fID\fR
+instead\&.
+.RE
+.PP
 <input_file>
 .RS 4
 The fast\-export stream to read\&. If
index 792ad92..d5461f3 100644 (file)
@@ -1,7 +1,7 @@
 /*
 
 git-export-filter.c -- filter/transform git fast-export data streams
-Copyright (c) 2013 Kyle J. McKay.  All rights reserved.
+Copyright (C) 2013,2014 Kyle J. McKay.  All rights reserved.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -43,11 +43,11 @@ static const char *const gHelp =
 static const char *const gUsage =
 "git-export-filter [--authors-file file] [--branches-file file]\n"
 "  [--convert-tagger id] [--require-authors] [--trunk-is-master]\n"
-"  [--strip-at-suffix] (in | < in) > out\n"
+"  [--strip-at-suffix] [--expand-renames] (in | < in) > out\n"
 "(use git-export-filter -v -h for detailed help)\n";
 
 static const char *const gVersion =
-"git-export-filter version 1.3\n";
+"git-export-filter version 1.4\n";
 
 static const char *me = "git-export-filter";
 
@@ -61,6 +61,7 @@ static int opt_help = 0;
 static int opt_require = 0;
 static int opt_trunk_is_master = 0;
 static int opt_strip_at = 0;
+static int opt_no_renames = 0;
 
 static char *pushline = NULL;
 static char *copybuff;
@@ -250,6 +251,10 @@ int main(int argc, char *argv[])
       opt_strip_at = 1;
       continue;
     }
+    if (!strcmp(A, "--expand-renames")) {
+      opt_no_renames = 1;
+      continue;
+    }
     if (!strcmp(A, "-V") || !strcmp(A, "--version")) {
       opt_version = 1;
       continue;
@@ -596,6 +601,27 @@ static void processtag(FILE *in, FILE *out, const char *tag,
   copydata(in, out, 0, "tag missing data line");
 }
 
+static const char *find_second_space(const char *line)
+{
+  if (!line || !*line || *line == ' ' || line[1] != ' ' || line[2] == ' ')
+    return NULL;
+  if (line[2] != '"')
+    return strchr(line + 2, ' ');
+  line += 3;
+  for (;;) {
+    line += strcspn(line, "\\\"");
+    if (!*line)
+      return NULL;
+    if (*line == '\\') {
+      if (!line[1])
+        return NULL;
+      line += 2;
+      continue;
+    }
+    return line[1] == ' ' ? line + 1 : NULL;
+  }
+}
+
 static int is_inline_modify(const char *line)
 {
   if (strncmp(line, "M ", 2) != 0)
@@ -670,7 +696,16 @@ static void processcommit(FILE *in, FILE *out, const char *ref,
          !strncmp(line, "D ", 2)        || !strncmp(line, "C ", 2) ||
          !strncmp(line, "R ", 2)        || !strncmp(line, "N ", 2) ||
          !strncmp(line, "cat-blob ", 9) || !strncmp(line, "ls ", 3)) {
-    fprintf(out, "%s\n", line);
+    if (!opt_no_renames || strncmp(line, "R ", 2)) {
+      fprintf(out, "%s\n", line);
+    } else {
+      /* expand rename into copy + delete */
+      const char *space2 = find_second_space(line);
+      if (!space2)
+        die("error reading 'R' line");
+      fprintf(out, "C %s\n", line+2);
+      fprintf(out, "D %.*s\n", (int)(space2 - line) - 2, line+2);
+    }
     if (strncmp(line, "N inline", 8) == 0 || is_inline_modify(line))
       copydata(in, out, 1, "inline N or M missing data line");
     line = nextline(in);
index fff8cd1..f7da513 100644 (file)
@@ -12,7 +12,8 @@ SYNOPSIS
 'git export-filter' [--verbose|-v] [-h|--help] [--version|-V] [--debug|-d]
                  [--authors-file=<authors_file> [--require-authors]]
                  [--branches-file=<branches_file>] [--trunk-is-master]
-                 [--convert-tagger=<email>] [--strip-at-suffix] [--]
+                 [--convert-tagger=<email>] [--strip-at-suffix]
+                 [--expand-renames] [--]
                  <input_file>|< <input_file>   > <output_file>
 
 
@@ -103,6 +104,12 @@ The 'svn-fe' utility appends '@...' suffixes to the email addresses it
 generates in the fast-export data and will need this option to use a standard
 'git svn' authors file.
 
+--expand-renames::
+       Some importers of fast-export data cannot handle renames but can
+       handle copies.  If --expand-renames is given then any instances of
+       filerename 'R' are replaced with a filecopy 'C' followed by a
+       filedelete 'D' instead.
+
 <input_file>::
        The fast-export stream to read.  If `<input_file>` is omitted, then
        standard input will be read.
index a0c1310..616f8e9 100644 (file)
@@ -9,7 +9,8 @@ SYNOPSIS
        git export-filter [--verbose|-v] [-h|--help] [--version|-V] [--debug|-d]
                          [--authors-file=<authors_file> [--require-authors]]
                          [--branches-file=<branches_file>] [--trunk-is-master]
-                         [--convert-tagger=<email>] [--strip-at-suffix] [--]
+                         [--convert-tagger=<email>] [--strip-at-suffix]
+                         [--expand-renames] [--]
                          <input_file>|< <input_file>   > <output_file>
 
 
@@ -95,6 +96,12 @@ OPTIONS
            generates in the fast-export data and will need this option to use
            a standard git svn authors file.
 
+       --expand-renames
+           Some importers of fast-export data cannot handle renames but can
+           handle copies.  If --expand-renames is given then any instances of
+           filerename 'R' are replaced with a filecopy 'C' followed by a
+           filedelete 'D' instead.
+
        <input_file>
            The fast-export stream to read. If <input_file> is omitted, then
            standard input will be read.