]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - tools/libxfs-apply
4 # libxfs-apply <repo> <commit ID or patchfile>
11 echo " libxfs-apply [--verbose] --source <repodir> --commit <commit_id>"
12 echo " libxfs-apply --patch <patchfile>"
14 echo "libxfs-apply should be run in the destination git repository."
23 # output to stderr so it is not caught by file redirects
32 # filterdiff 0.3.4 is the first version that handles git diff metadata (almost)
33 # correctly. It just doesn't work properly in prior versions, so those versions
34 # can't be used to extract the commit message prior to the diff. Hence just
35 # abort and tell the user to upgrade if an old version is detected. We need to
36 # check against x.y.z version numbers here.
37 _version
=`filterdiff --version | cut -d " " -f 5`
38 _major
=`echo $_version | cut -d "." -f 1`
39 _minor
=`echo $_version | cut -d "." -f 2`
40 _patch
=`echo $_version | cut -d "." -f 3`
41 if [ $_major -eq 0 ]; then
42 if [ $_minor -lt 3 ]; then
43 fail
"filterdiff $_version found. 0.3.4 or greater is required."
45 if [ $_minor -eq 3 -a $_patch -le 3 ]; then
46 fail
"filterdiff $_version found. 0.3.4 or greater is required."
50 # We should see repository contents we recognise, both at the source and
51 # destination. Kernel repositorys will have fs/xfs/libxfs, and xfsprogs
52 # repositories will have libxcmd.
56 if [ ! -d "fs/xfs/libxfs" -a ! -d "libxcmd" ]; then
57 usage
"$1 repository contents not recognised!"
59 if [ -d "$REPO/libxcmd" ]; then
70 while [ $# -gt 0 ]; do
72 --source) REPO
=$2 ; shift ;;
73 --patch) PATCH
=$2; shift ;;
74 --commit) COMMIT_ID
=$2 ; shift ;;
75 --verbose) VERBOSE
=true
;;
81 if [ -n "$PATCH" ]; then
82 if [ -n "$REPO" -o -n "$COMMIT_ID" ]; then
83 usage
"Need to specify either patch or source repo/commit"
86 elif [ -z "$REPO" -o -z "$COMMIT_ID" ]; then
87 usage
"Need to specify both source repo and commit id"
90 check_repo Destination
92 # Are we using guilt? This works even if no patch is applied.
93 guilt top
&> /dev
/null
98 #this is pulled from the guilt code to handle commit ids sanely.
99 # usage: munge_hash_range <hash range>
102 # <hash> - one commit
103 # <hash>.. - hash until head (excludes hash, includes head)
104 # ..<hash> - until hash (includes hash)
105 # <hash1>..<hash2> - from hash to hash (inclusive)
107 # The output of this function is suitable to be passed to "git rev-list"
112 # double .. or space is illegal
121 # e.g., "v0.19-rc1..v0.19"
122 echo ${1%%..*}..
${1#*..};;
132 # Filter the patch into the right format & files for the other tree
133 filter_kernel_patch
()
136 local _libxfs_files
=""
138 # The files we will try to apply to
139 _libxfs_files
=`mktemp`
140 ls -1 fs
/xfs
/libxfs
/*.
[ch
] |
sed -e "s%.*/\(.*\)%*\1%" > $_libxfs_files
142 # Create the new patch
143 # filterdiff will have screwed up files that source/sink /dev/null.
144 # fix that up with some sed magic.
149 --addoldprefix=a
/fs
/xfs
/ \
150 --addnewprefix=b
/fs
/xfs
/ \
152 sed -e 's, [ab]\/fs\/xfs\/\(\/dev\/null\), \1,' \
159 filter_xfsprogs_patch
()
162 local _libxfs_files
=""
164 # The files we will try to apply to. We need to pull this from the
165 # patch, as the may be libxfs files added in this patch and so we
166 # need to capture them.
167 _libxfs_files
=`mktemp`
168 #ls -1 libxfs/*.[ch] | sed -e "s%.*/\(.*\)%*libxfs/\1%" > $_libxfs_files
169 lsdiff
$_patch |
sed -e "s%.*/\(.*\)%*libxfs/\1%" > $_libxfs_files
171 # Create the new patch
172 # filterdiff will have screwed up files that source/sink /dev/null.
173 # fix that up with some sed magic.
181 sed -e 's, [ab]\/\(\/dev\/null\), \1,' \
187 fixup_header_format
()
193 local _new_hdr
=$_hdr.new
195 # there's a bug in filterdiff that leaves a line at the end of the
196 # header in the filtered git show output like:
198 # difflibxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
200 # split the header on that (convenient!)
201 sed -e /^difflib
/q
$_patch > $_hdr
203 BEGIN { difflib_seen = 0; index_seen = 0 }
204 /^difflib/ { difflib_seen++; next }
205 /^index/ { if (++index_seen == 1) { next } }
206 // { if (difflib_seen) { print $0 } }' > $_diff
208 # the header now has the format:
209 # commit 0d5a75e9e23ee39cd0d8a167393dcedb4f0f47b2
210 # Author: Eric Sandeen <sandeen@sandeen.net>
211 # Date: Wed Jun 1 17:38:15 2016 +1000
213 # xfs: make several functions static
215 # Signed-off-by: Dave Chinner <david@fromorbit.com>
217 #difflibxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
219 # We want to format it like a normal patch with a line to say what repo
220 # and commit it was sourced from:
222 # xfs: make several functions static
224 # From: Eric Sandeen <sandeen@sandeen.net>
226 # Source kernel commit: 0d5a75e9e23ee39cd0d8a167393dcedb4f0f47b2
230 # To do this, use sed to first strip whitespace, then pass it into awk
231 # to rearrange the headers.
232 sed -e 's/^ *//' $_hdr |
awk -v src
=$_source '
246 /^Date:/ { date_seen=1; next }
252 if (subject_seen == 0) {
253 if (length($0) != 0) {
259 if (subject_seen == 1) {
264 print "Source " src " commit: " commit
270 # now output the new patch
281 local _current_commit
=$3
282 local _new_patch
=`mktemp`
283 local _source
="kernel"
285 # filter just the libxfs parts of the patch
286 if [ $SOURCE == "xfsprogs" ]; then
288 [ -n "$VERBOSE" ] || lsdiff
$_patch |
grep -q "[ab]/libxfs/"
289 if [ $?
-ne 0 ]; then
290 echo "Doesn't look like an xfsprogs patch with libxfs changes"
291 echo "Skipping commit $_current_commit"
295 filter_kernel_patch
$_patch > $_new_patch
297 elif [ $SOURCE == "kernel" ]; then
299 [ -n "$VERBOSE" ] || lsdiff
$_patch |
grep -q "[ab]/fs/xfs/libxfs/"
300 if [ $?
-ne 0 ]; then
301 echo "Doesn't look like a kernel patch with libxfs changes"
302 echo "Skipping commit $_current_commit"
306 filter_xfsprogs_patch
$_patch > $_new_patch
308 fail
"Unknown source repo type: $SOURCE"
311 # now munge the header to be in the correct format.
312 fixup_header_format
$_source $_new_patch > $_new_patch.2
314 if [ -n "$VERBOSE" ]; then
315 echo "Filtered patch from $REPO contains:"
319 # Ok, now apply with guilt or patch; either may fail and require a force
320 # and/or a manual reject fixup
321 if [ $GUILT -eq 1 ]; then
322 [ -n "$VERBOSE" ] ||
echo "$REPO looks like a guilt directory."
323 PATCHES
=`guilt applied | wc -l`
324 if [ -n "$VERBOSE" -a $PATCHES -gt 0 ]; then
325 echo -n "Top patch is: "
329 guilt import
-P $_patch_name $_new_patch.2
331 if [ $?
-eq 0 ]; then
334 echo "Guilt push failed!"
335 read -r -p "Skip of Fail [s|F]? " response
336 if [ -z "$response" -o "$response" != "s" ]; then
337 echo "Force push patch, fix and refresh."
338 echo "Restart from commit $_current_commit"
339 fail
"Manual cleanup required!"
341 echo "Skipping. Manual series file cleanup needed!"
345 echo "Applying with patch utility:"
346 patch -p1 < $_new_patch.2
347 echo "Patch was applied in $REPO; check for rejects, etc"
353 # name a guilt patch. Code is lifted from guilt import-commit.
356 s
=`git log --no-decorate --pretty=oneline -1 $1 | cut -c 42-`
358 # Try to convert the first line of the commit message to a
360 fname
=`printf %s "$s" | \
361 sed -e "s/&/and/g" -e "s/[ :]/_/g" -e "s,[/\\],-,g" \
362 -e "s/['\\[{}]//g" -e 's/]//g' -e 's/\*/-/g' \
363 -e 's/\?/-/g' -e 's/\.\.\.*/./g' -e 's/^\.//' \
364 -e 's/\.patch$//' -e 's/\.$//' | tr A-Z a-z`
366 # Try harder to make it a legal commit name by
367 # removing all but a few safe characters.
368 fname
=`echo $fname|tr -d -c _a-zA-Z0-9---/\\n`
373 # single patch is easy.
374 if [ -z "$COMMIT_ID" ]; then
380 # switch to source repo and get individual commit IDs
382 # git rev-list gives us a list in reverse chronological order, so we need to
383 # reverse that to give us the order we require.
384 pushd $REPO > /dev
/null
386 hashr
=`munge_hash_range $COMMIT_ID`
387 if [ $SOURCE == "kernel" ]; then
388 hashr
="$hashr -- fs/xfs/libxfs"
390 hashr
="$hashr -- libxfs"
393 # grab and echo the list of commits for confirmation
394 echo "Commits to apply:"
395 commit_list
=`git rev-list $hashr | tac`
396 git log
--oneline $hashr |
tac
397 read -r -p "Proceed [y|N]? " response
398 if [ -z "$response" -o "$response" != "y" ]; then
404 for commit
in $commit_list; do
406 # switch to source repo and pull commit into a patch file
407 pushd $REPO > /dev
/null
408 git show
$commit > $PATCH || usage
"Bad source commit ID!"
409 patch_name
=`name_patch $commit`
412 apply_patch
$PATCH $patch_name $commit