Skip to content

Instantly share code, notes, and snippets.

@jaalto
Forked from bcachet/splitpatch.rb
Last active December 18, 2015 16:36
Show Gist options
  • Save jaalto/5751141 to your computer and use it in GitHub Desktop.
Save jaalto/5751141 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
#
# splitpatch is a simple script to split a patch up into multiple patch files.
# if the --hunks option is provided on the command line, each hunk gets its
# own patchfile.
#
# Copyright (C) 2007 Peter Hutterer <peter@cs.unisa.edu.au>
#
# 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
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# Changes
#
# 2013-06-10 Jari Aalto <jari.aalto@cante.net>
#
# Use split parts separated by a dash(-), not dot(.) and which are
# zero-based. Format: FILENAME-NNN.patch for hunks and
# FILENAME.patch-NNN for regular files (if file already existsed).
#
# Add options --help, --version and short option for -H (hunks).
PROGRAM = "splitpatch"
VERSION = 0.1
LICENSE = "GPL-2+" # See official acronyms: https://spdx.org/licenses/
AUTHOR = "Peter Hutterer <peter@cs.unisa.edu.au>"
class Splitter
def initialize(file)
@filename = file
end
def validFile?
return File.exist?(@filename) && File.readable?(@filename)
end
# Split the patchfile by files
def splitByFile
outfile = nil
stream = open(@filename)
until (stream.eof?)
line = stream.readline
# we need to create a new file
if (line =~ /--- .*/) == 0
if (outfile)
outfile.close_write
end
#find filename
tokens = line.split(" ")
tokens = tokens[1].split(":")
tokens = tokens[0].split("/")
filename = tokens[-1]
filename << ".patch"
if File.exists?(filename)
puts "File #{filename} already exists. Renaming patch."
appendix = 0
zero = appendix.to_s.rjust(3, '0')
while File.exists?("#{filename}-#{zero}")
appendix += 1
end
filename << "-#{zero}"
end
outfile = open(filename, "w")
outfile.write(line)
else
if outfile
outfile.write(line)
end
end
end
end
def splitByHunk
outfile = nil
stream = open(@filename)
filename = ""
counter = 0
header = ""
until (stream.eof?)
line = stream.readline
# we need to create a new file
if (line =~ /--- .*/) == 0
#find filename
tokens = line.split(" ")
tokens = tokens[1].split(":")
tokens = tokens[0].split("/")
filename = tokens[-1]
header = line
# next line is header too
line = stream.readline
header << line
counter = 0
elsif (line =~ /@@ .* @@/) == 0
if (outfile)
outfile.close_write
end
zero = counter.to_s.rjust(3, '0')
hunkfilename = "#{filename}-#{zero}.patch"
if File.exists?(hunkfilename)
puts "File #{hunkfilename} already exists. Renaming patch."
appendix = 0
zero = appendix.to_s.rjust(3, '0')
while File.exists?("#{hunkfilename}-#{zero}")
appendix += 1
end
hunkfilename << "-#{zero}"
end
outfile = open(hunkfilename, "w")
counter += 1
outfile.write(header)
outfile.write(line)
else
if outfile
outfile.write(line)
end
end
end
end
end
def help
puts <<EOF
SYNOPSIS
#{PROGRAM} [options] FILE.patch
OPTIONS
-h,--help
-H,--hunk
-V,--version
DESCRIPTION
Split the patch up into files or hunks
Divide a patch or diff file into pieces. The split can made by file
or by hunk basis. This makes is possible to separate changes that
might not be desireable or assemble the patch into more coherent set
of changes. See e.g. combinediff(1) from patchutils package.
EOF
end
def version
puts "#{VERSION} #{LICENSE} #{AUTHOR}"
end
######################## MAIN ########################
if ARGV.length < 1 or ARGV.length > 2
puts "Wrong parameter. Usage: splitpatch.rb [--hunks] <patchfile>"
exit 1
elsif ARGV[0] == "--help"
puts "splitpatch splits a patch that is supposed to patch multiple files"
puts "into a set of patches."
puts "Currently splits unified diff patches."
puts "If the --hunk option is given, a new file is created for each hunk."
exit 1
else
opt = ARGV[0]
if /^-h$|--help/.match(opt)
help
exit 0
elsif /^-H$|--hunks?/.match(opt)
hunk = 1
elsif /^-V$|--version/.match(opt)
version
exit 0
elsif /^-/.match(opt)
puts "ERROR: Unknonw option: #{opt}. See --help."
exit 1
end
file = ARGV[-1]
s = Splitter.new(file)
if s.validFile?
if hunk
s.splitByHunk
else
s.splitByFile
end
else
puts "File does not exist or is not readable: #{file}"
end
end
# End of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment