]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/tools/git/importgit
chmod +x the git commit message prep hook
[FreeBSD/FreeBSD.git] / tools / tools / git / importgit
1 #!/bin/sh
2 #
3 # Copyright (c) 2015 Ryan Stone. All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 # 1. Redistributions of source code must retain the above copyright
9 #    notice, this list of conditions and the following disclaimer.
10 # 2. Redistributions in binary form must reproduce the above copyright
11 #    notice, this list of conditions and the following disclaimer in the
12 #    documentation and/or other materials provided with the distribution.
13 #
14 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 # SUCH DAMAGE.
25 #
26 # $FreeBSD$
27
28 usage()
29 {
30         echo "Usage: importgit <-c commit | -r c1..c2> -g /path/to/git/repo [-n]" >&2
31 }
32
33 error()
34 {
35         local print_usage
36
37         if [ "$1" = "-u" ]
38         then
39                 shift
40                 print_usage=1
41         else
42                 print_usage=
43         fi
44
45         echo "$@" >&2
46         if [ -n "$print_usage" ]
47         then
48                 usage
49         fi
50         exit 1
51 }
52
53 unset git_repo range commit dry_run
54
55 while getopts ":c:g:nr:" o
56 do
57         case "$o" in
58         c)
59                 range="${OPTARG}~..${OPTARG}"
60                 ;;
61         g)
62                 git_repo=$OPTARG
63                 ;;
64         n)
65                 dry_run=1
66                 ;;
67         r)
68                 range=$OPTARG
69                 ;;
70         *)
71                 error -u "Unrecognized argument '-$OPTARG'"
72         esac
73 done
74
75 shift $((OPTIND - 1))
76 OPTIND=1
77
78 if [ -n "$1" ]
79 then
80         error -u "Unrecognized argument $1"
81 fi
82
83 if [ -z "$range" ]
84 then
85         error -u "-c or -r argument is mandatory"
86 fi
87
88 if ! echo "$range" | egrep -qs '^[^.]+\.\.[^.]*$'
89 then
90         error -u "$range is not a range of commits.  Did you mean '-c $range'?"
91 fi
92
93 if [ -z "$git_repo" ]
94 then
95         error -u "-g <repo> argument is mandatory"
96 fi
97
98 if ! type git > /dev/null 2> /dev/null
99 then
100         error "Install devel/git first"
101 fi
102
103 GIT="git -C $git_repo"
104
105 if ! $GIT rev-parse --git-dir 2> /dev/null > /dev/null
106 then
107         error "$git_repo does not seem to be a git repo"
108 fi
109
110 if ! type svn > /dev/null 2> /dev/null
111 then
112         error "Install devel/subversion first"
113 fi
114
115 if [ -n "$(svn status)" ]
116 then
117         error "Working tree is not clean"
118 fi
119
120 if ! svn --non-interactive ls > /dev/null
121 then
122         error "Could not communicate with svn server.  Is your ssh key loaded?"
123 fi
124
125 $GIT log --format=%H $range | tail -r | while read -r commit
126 do
127         echo "Applying `$GIT show -s --oneline $commit`"
128
129         if [ -n "$($GIT show --diff-filter=CDRTUXB $commit)" ]
130         then
131                 error "Commit performed unsupported change (e.g. delete/rename)"
132         fi
133
134         if [ "$($GIT show -s --format=%P $commit | wc -w)" -ne 1 ]
135         then
136                 error "Cannot import merge commits"
137         fi
138
139         $GIT diff --diff-filter=A --name-only \
140             ${commit}~..$commit | while read -r newfile
141         do
142                 if [ -f "$newfile" ]
143                 then
144                         error "New file $newfile already exists in tree"
145                 fi
146         done
147
148         # The previous while loop ran in a subshell, so we have to check if it
149         # exited with an error and bail out if so.
150         ret=$?
151         if [ "$ret" -ne 0 ]
152         then
153                 exit $ret
154         fi
155
156         if [ -n "$dry_run" ]
157         then
158                 continue
159         fi
160
161         $GIT show $commit | patch -p 1 -s || \
162             error "Failed to apply patch"
163
164         $GIT diff --diff-filter=A --name-only \
165             ${commit}~..$commit | while read -r newfile
166         do
167                 svn add --parents --depth=infinity $newfile || \
168                     error "Failed to add new file"
169         done
170
171         # The previous while loop ran in a subshell, so we have to check if it
172         # exited with an error and bail out if so.
173         ret=$?
174         if [ "$ret" -ne 0 ]
175         then
176                 exit $ret
177         fi
178
179         $GIT show -s --format='%B' $commit | svn commit -F - || \
180             error "Failed to commit"
181 done
182