mirror of https://gitee.com/openkylin/quilt.git
Import Upstream version 0.66
This commit is contained in:
commit
4f66d04872
|
@ -0,0 +1,42 @@
|
|||
Quilt started as a series of scripts written by Andrew Morton
|
||||
(patch-scripts). Based on Andrew's ideas, Andreas Gruenbacher
|
||||
completely rewrote the scripts, with the help of several other
|
||||
contributors (see below).
|
||||
|
||||
Please report bugs to the quilt-dev mailing list,
|
||||
|
||||
<http://mail.nongnu.org/mailman/listinfo/quilt-dev>.
|
||||
|
||||
|
||||
Quilt
|
||||
=====
|
||||
|
||||
Andreas Gruenbacher <agruen@suse.de>
|
||||
Clean up, reorganize, speedups, documentation.
|
||||
Package up as RPM.
|
||||
|
||||
Gerd Knorr <kraxel@suse.de>
|
||||
Contributed spec2series (which is inspect now).
|
||||
|
||||
Martin Quinson (martin.quinson#debian.org)
|
||||
Several little patches and improvements.
|
||||
Internationalization.
|
||||
Debian packaging.
|
||||
|
||||
Peter Braam <braam@clusterfs.com>
|
||||
Tom Wang <wangdi@clusterfs.com>
|
||||
Fix pop logic if series file changes.
|
||||
|
||||
|
||||
Pre-quilt (patch-scripts)
|
||||
=========================
|
||||
|
||||
Andrew Morton <akpm@digeo.com>
|
||||
Collection of scripts for patch management (patch-scripts).
|
||||
|
||||
Stephen Cameron <steve.cameron@hp.com>
|
||||
Contributed pstatus.
|
||||
|
||||
Matt Reppert <arashi@arashi.yi.org>
|
||||
Jeremy Fitzhardinge <jeremy@digeo.com>
|
||||
Contributions to Andrew's scripts.
|
|
@ -0,0 +1,340 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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 of the License, 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,454 @@
|
|||
PACKAGE := @PACKAGE_NAME@
|
||||
VERSION := @PACKAGE_VERSION@
|
||||
RELEASE := @PACKAGE_RELEASE@
|
||||
PACKAGE_TARNAME := @PACKAGE_TARNAME@
|
||||
PACKAGE_BUGREPORT := @PACKAGE_BUGREPORT@
|
||||
|
||||
prefix := @prefix@
|
||||
exec_prefix := @exec_prefix@
|
||||
bindir := @bindir@
|
||||
datarootdir := @datarootdir@
|
||||
datadir := @datadir@
|
||||
docdir := @docdir@
|
||||
mandir := @mandir@
|
||||
localedir := $(datadir)/locale
|
||||
emacsdir := $(datadir)/emacs/site-lisp
|
||||
etcdir := @sysconfdir@
|
||||
|
||||
INSTALL := @INSTALL@
|
||||
POD2MAN := @POD2MAN@
|
||||
COLUMN := @COLUMN@
|
||||
GETOPT := @GETOPT@
|
||||
CP := @CP@
|
||||
DATE := @DATE@
|
||||
PERL := @PERL@
|
||||
BASH := @BASH@
|
||||
SHELL:= @BASH@ # It does not work if dash is used as a shell, for example
|
||||
GREP := @GREP@
|
||||
TAIL := @TAIL@
|
||||
TR := @TR@
|
||||
SED := @SED@
|
||||
AWK := @AWK@
|
||||
FIND := @FIND@
|
||||
XARGS := @XARGS@
|
||||
DIFF := @DIFF@
|
||||
PATCH := @PATCH@
|
||||
MKTEMP := @MKTEMP@
|
||||
MSGMERGE := @MSGMERGE@
|
||||
MSGFMT := @MSGFMT@
|
||||
XGETTEXT := @XGETTEXT@
|
||||
MSGUNIQ := @MSGUNIQ@
|
||||
MSGCAT := @MSGCAT@
|
||||
DIFFSTAT := @DIFFSTAT@
|
||||
RPMBUILD := @RPMBUILD@
|
||||
SENDMAIL := @SENDMAIL@
|
||||
MD5SUM := @MD5SUM@
|
||||
7Z := @P7ZIP@
|
||||
|
||||
USE_NLS := @USE_NLS@
|
||||
STAT_HARDLINK := @STAT_HARDLINK@
|
||||
PATCH_WRAPPER := @PATCH_WRAPPER@
|
||||
|
||||
COMPAT_SYMLINKS := @COMPAT_SYMLINKS@
|
||||
COMPAT_PROGRAMS := @COMPAT_PROGRAMS@
|
||||
|
||||
default: all
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
DIRT += $(shell $(FIND) . -name '*~')
|
||||
DIRT += $(shell $(FIND) . -name '.\#*')
|
||||
|
||||
SRC += COPYING AUTHORS TODO Makefile.in configure.ac \
|
||||
config/install-sh quilt.spec.in NEWS \
|
||||
bash_completion quilt.quiltrc aclocal.m4 git-desc
|
||||
DIRT += quilt.spec
|
||||
|
||||
DIRT += $(PACKAGE)-*.tar.gz
|
||||
DIRT += $(PACKAGE)-*.tar.gz.sig
|
||||
DIRT += $(PACKAGE)-*.tar.bz2
|
||||
|
||||
BIN_IN := quilt guards
|
||||
BIN_SRC := $(BIN_IN:%=%.in)
|
||||
BIN := $(BIN_IN)
|
||||
SRC += $(BIN_SRC:%=bin/%) bin/patch-wrapper.in
|
||||
DIRT += $(BIN_IN:%=bin/%) bin/patch-wrapper
|
||||
|
||||
QUILT_IN := $(patsubst quilt/%.in,%,$(wildcard quilt/*.in))
|
||||
QUILT_SRC := $(QUILT_IN:%=%.in)
|
||||
QUILT := $(QUILT_IN)
|
||||
SRC += $(QUILT_SRC:%=quilt/%)
|
||||
DIRT += $(QUILT_IN:%=quilt/%)
|
||||
|
||||
SCRIPTS_IN := patchfns inspect-wrapper dependency-graph edmail \
|
||||
remove-trailing-ws backup-files
|
||||
|
||||
SCRIPTS_SRC := $(SCRIPTS_IN:%=%.in)
|
||||
SCRIPTS := $(SCRIPTS_IN)
|
||||
SRC += $(SCRIPTS_SRC:%=quilt/scripts/%)
|
||||
SRC += quilt/scripts/utilfns
|
||||
DIRT += $(SCRIPTS_IN:%=quilt/scripts/%)
|
||||
|
||||
COMPAT := $(COMPAT_PROGRAMS:%=compat/%) $(COMPAT_SYMLINKS:%=compat/%)
|
||||
SRC += $(wildcard compat/*.in) $(wildcard compat/*.sh)
|
||||
DIRT += $(patsubst %.in,%,$(wildcard compat/*.in)) $(COMPAT_SYMLINKS:%=compat/%)
|
||||
|
||||
LIB_SRC := quilt.el
|
||||
SRC += $(LIB_SRC:%=lib/%)
|
||||
|
||||
DOC_IN := README quilt.1
|
||||
DOC_SRC := $(DOC_IN:%=doc/%.in)
|
||||
DOC := $(DOC_IN)
|
||||
SRC += $(DOC_SRC)
|
||||
SRC += doc/main.tex doc/quilt.pdf doc/Makefile \
|
||||
doc/README.MAIL doc/README.EMACS
|
||||
DIRT += $(DOC_IN:%=doc/%) doc/reference
|
||||
|
||||
MAN1 := doc/quilt.1
|
||||
ifneq ($(POD2MAN),)
|
||||
MAN1 += doc/guards.1
|
||||
DIRT += doc/guards.1
|
||||
endif
|
||||
|
||||
LINGUAS := fr de ja ru
|
||||
PO := quilt.pot $(LINGUAS:%=%.po)
|
||||
SRC += $(PO:%=po/%)
|
||||
DIRT += po/*.mo po/*~
|
||||
|
||||
SRC += $(wildcard test/*.test) test/run test/test.quiltrc
|
||||
|
||||
NON_EXEC_IN := doc/quilt.1 doc/README quilt/scripts/patchfns quilt/scripts/utilfns
|
||||
|
||||
GIT_DESC := $(shell ./git-desc | sed -e 's:^v::')
|
||||
|
||||
# Tests are sorted to make it easier to compare the results between runs
|
||||
TESTS := $(sort $(wildcard test/*.test))
|
||||
ifeq ($(PATCH_WRAPPER),)
|
||||
TESTS := $(filter-out test/patch-wrapper.test,$(TESTS))
|
||||
endif
|
||||
DIRT += test/.depend $(wildcard test/.*.ok)
|
||||
|
||||
# Settings for running the uninstalled version of quilt in the source tree:
|
||||
PATH := $(CURDIR)/bin:$(CURDIR)/compat:$(PATH)
|
||||
QUILT_DIR := $(CURDIR)/quilt
|
||||
QUILTRC := $(CURDIR)/test/test.quiltrc
|
||||
export QUILT_DIR QUILTRC
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
all : configure scripts compat $(DOC:%=doc/%) $(MAN1) mofiles
|
||||
|
||||
ifeq ($(USE_NLS),yes)
|
||||
mofiles : $(LINGUAS:%=po/%.mo)
|
||||
else
|
||||
mofiles :
|
||||
endif
|
||||
|
||||
%.mo : %.po
|
||||
$(MSGFMT) --statistics -o $@ $<
|
||||
|
||||
%.po : po/quilt.pot
|
||||
$(MSGMERGE) -o $@ $@ $^
|
||||
|
||||
updatepo : $(PO:%=po/%)
|
||||
|
||||
scripts : $(BIN:%=bin/%) $(QUILT:%=quilt/%) \
|
||||
$(SCRIPTS:%=quilt/scripts/%) \
|
||||
$(if $(PATCH_WRAPPER),bin/patch-wrapper)
|
||||
|
||||
dist : clean $(PACKAGE)-$(VERSION).tar.gz
|
||||
|
||||
publish : dist
|
||||
gpg --detach-sign --use-agent $(PACKAGE)-$(VERSION).tar.gz
|
||||
scp $(PACKAGE)-$(VERSION).tar.gz{,.sig} \
|
||||
dl.sv.nongnu.org:/releases/quilt/
|
||||
|
||||
snapshot : $(PACKAGE)-$(GIT_DESC).tar.bz2
|
||||
|
||||
rpm rpmbuild : $(PACKAGE)-$(VERSION).tar.gz
|
||||
$(RPMBUILD) -ta $<
|
||||
|
||||
po/quilt.pot: $(filter-out doc/quilt.1.in doc/README.in, \
|
||||
$(wildcard */*.in) $(wildcard */*/*.in))
|
||||
rm -f po/quilt.pot; touch po/quilt.pot
|
||||
for file in $+ ; do \
|
||||
if test -n "`$(SED) -ne '1{ /@BASH''@/p }' $$file`" \
|
||||
-o "$$file" = quilt/scripts/patchfns.in; then \
|
||||
$(BASH) --dump-po-strings $$file ; \
|
||||
elif test -n "`$(SED) -ne '1{ /@PERL''@/p }' $$file`"; then \
|
||||
$(XGETTEXT) --from-code=UTF-8 --omit-header --language=Perl \
|
||||
--keyword=_ -o - $$file; \
|
||||
else \
|
||||
echo "Don't know how to handle $$file" >&2 ; \
|
||||
exit 1; \
|
||||
fi \
|
||||
done \
|
||||
|$(MSGUNIQ) \
|
||||
|$(MSGCAT) --force-po -F - $@ -o $@
|
||||
|
||||
doc/README : doc/README.in doc/reference
|
||||
@echo "README.in -> README"
|
||||
@while read line; do \
|
||||
case "$$line" in \
|
||||
'@REFERENCE''@') \
|
||||
cat doc/reference \
|
||||
;; \
|
||||
*) \
|
||||
echo $$line \
|
||||
;; \
|
||||
esac ; \
|
||||
done 2>&1 < $< > $@
|
||||
|
||||
doc/quilt.1: doc/quilt.1.in doc/reference $(COMPAT)
|
||||
@echo "quilt.1.in -> quilt.1"
|
||||
@while read line; do \
|
||||
case "$$line" in \
|
||||
'@REFERENCE''@') \
|
||||
$(SED) -e 's/^quilt \([^ ]*\)\(.*\)/.IP "\\fB\1\\fP\2 " 4/' \
|
||||
-e $$'s/^ \\(-[^\t]*\\)\t\\?/.IP " \\1" 8\\\n/' \
|
||||
-e $$'s/^ \t\\?//' \
|
||||
< doc/reference \
|
||||
;; \
|
||||
*@DOCSUBDIR@*) \
|
||||
echo "$$line" | \
|
||||
$(SED) -e 's:@DOCSUBDIR''@:$(docdir):g' \
|
||||
;; \
|
||||
*) \
|
||||
echo "$$line" \
|
||||
;; \
|
||||
esac; \
|
||||
done < $< 2>&1 > $@
|
||||
|
||||
doc/reference : bin/quilt $(QUILT:%=quilt/%) quilt/scripts/patchfns quilt/scripts/utilfns $(COMPAT)
|
||||
@unset LANG LC_MESSAGES LC_CTYPE LC_ALL; \
|
||||
for i in $(sort $(QUILT)); \
|
||||
do \
|
||||
echo; \
|
||||
QUILT_PC=.fake_pc quilt $$i -h; \
|
||||
echo; \
|
||||
done | \
|
||||
$(SED) -e 's/\$$EDITOR ([^)]*)/$$EDITOR/' \
|
||||
-e '/^$$/!s/^/ /' \
|
||||
-e 's/^ Usage: *//' > $@
|
||||
|
||||
doc/guards.1 : bin/guards
|
||||
$(POD2MAN) $< > $@
|
||||
|
||||
$(PACKAGE)-$(VERSION).tar.gz : $(SRC) configure $(PACKAGE).spec
|
||||
rm -f $(PACKAGE)-$(VERSION) $@
|
||||
ln -s . $(PACKAGE)-$(VERSION)
|
||||
tar chf - $(+:%=$(PACKAGE)-$(VERSION)/%) | gzip -9 > $@
|
||||
rm -f $(PACKAGE)-$(VERSION)
|
||||
@echo "File $@ created."
|
||||
|
||||
$(PACKAGE)-$(GIT_DESC).tar.bz2 : $(SRC) configure $(PACKAGE).spec
|
||||
rm -f $(PACKAGE)-$(GIT_DESC) $@
|
||||
ln -s . $(PACKAGE)-$(GIT_DESC)
|
||||
tar chf - $(+:%=$(PACKAGE)-$(GIT_DESC)/%) | bzip2 -9 > $@
|
||||
rm -f $(PACKAGE)-$(GIT_DESC)
|
||||
@echo "File $@ created."
|
||||
|
||||
$(PACKAGE).spec : $(PACKAGE).spec.in NEWS Makefile
|
||||
@echo "Generating spec file" ; \
|
||||
set -e ; \
|
||||
changelog="`sed \
|
||||
-e 's/^Version \([0-9.]*\) (\(.*\))/* \2 - upstream\n- Update to version \1/' \
|
||||
-e 's/^ -/ +/' < NEWS`" ; \
|
||||
$(AWK) '{ gsub(/@VERSION''@/, "$(VERSION)") ; \
|
||||
gsub(/@RELEASE''@/, "$(RELEASE)") ; \
|
||||
gsub(/@CHANGELOG''@/, changelog) ; \
|
||||
print }' changelog="$$changelog" $< > $@
|
||||
|
||||
$(patsubst %.in,%,$(wildcard bin/*.in quilt/*.in quilt/scripts/*.in)) :: Makefile
|
||||
% :: %.in
|
||||
@echo "$< -> $@" >&2
|
||||
@$(SED) -e 's:@QUILT_DIR''@:$(datadir)/$(PACKAGE):g' \
|
||||
-e 's:@PERL''@:$(PERL):g' \
|
||||
-e 's:@BASH''@:$(BASH):g' \
|
||||
-e 's:@PATCH''@:$(PATCH):g' \
|
||||
-e 's:@STAT_HARDLINK''@:$(STAT_HARDLINK):g' \
|
||||
-e 's:@VERSION''@:$(VERSION):g' \
|
||||
-e 's:@ETCDIR''@:$(etcdir):g' \
|
||||
-e 's:@LOCALEDIR''@:$(localedir):g' \
|
||||
-e 's:@DOCSUBDIR''@:$(docdir):g' \
|
||||
-e '/^### Local Variables:/Q' \
|
||||
$< > $@
|
||||
@$(if $(filter $@,$(NON_EXEC_IN)),,chmod +x $@)
|
||||
|
||||
configure : configure.ac aclocal.m4
|
||||
autoconf
|
||||
@echo "Please run ./configure"
|
||||
@false
|
||||
|
||||
Makefile : Makefile.in configure
|
||||
@echo "Please run ./configure"
|
||||
@false
|
||||
|
||||
compat_leftover := $(filter-out $(COMPAT),$(shell $(FIND) compat -type f -perm -0100))
|
||||
|
||||
.PHONY :: compat
|
||||
compat :: $(COMPAT)
|
||||
$(if $(compat_leftover),rm -f $(compat_leftover))
|
||||
|
||||
# VIRTUAL_SYMLINKS creates a shell script that operates similar to
|
||||
# a symbolic link. It is used to workaround the way make treats
|
||||
# symlinks as targets.
|
||||
# Usage: $(call VIRTUAL_SYMLINK, source, target)
|
||||
define VIRTUAL_SYMLINK
|
||||
@echo "Generating $(strip $(1)) wrapper" >&2;
|
||||
@printf "#!%s\nexec %s "'"$$@"'"\n" $(BASH) $(strip $(1)) > $(2);
|
||||
endef
|
||||
|
||||
# Rule to create compat/<binary> for each binary in $(COMPAT_SYMLINKS)
|
||||
$(COMPAT_SYMLINKS:%=compat/%) :: Makefile
|
||||
$(call VIRTUAL_SYMLINK, \
|
||||
$($(shell echo $@ | $(AWK) '{split($$1, ar, "/"); print toupper(ar[2])}')), \
|
||||
$(strip $@))
|
||||
@chmod +x $(strip $@)
|
||||
|
||||
install-main :: scripts
|
||||
$(INSTALL) -d $(BUILD_ROOT)$(bindir)
|
||||
$(INSTALL) -m 755 $(BIN:%=bin/%) $(BUILD_ROOT)$(bindir)/
|
||||
|
||||
$(INSTALL) -d $(BUILD_ROOT)$(datadir)/$(PACKAGE)
|
||||
$(INSTALL) -m 755 $(QUILT:%=quilt/%) $(BUILD_ROOT)$(datadir)/$(PACKAGE)/
|
||||
|
||||
$(INSTALL) -d $(BUILD_ROOT)$(datadir)/$(PACKAGE)/scripts
|
||||
$(INSTALL) -m 755 $(patsubst %,quilt/scripts/%, \
|
||||
$(filter-out patchfns,$(SCRIPTS))) \
|
||||
$(BUILD_ROOT)$(datadir)/$(PACKAGE)/scripts
|
||||
$(INSTALL) -m 644 quilt/scripts/patchfns quilt/scripts/utilfns \
|
||||
$(BUILD_ROOT)$(datadir)/$(PACKAGE)/scripts
|
||||
ifneq ($(PATCH_WRAPPER),)
|
||||
$(INSTALL) -d $(BUILD_ROOT)$(datadir)/$(PACKAGE)/wrapper
|
||||
$(INSTALL) -m 755 bin/patch-wrapper \
|
||||
$(BUILD_ROOT)$(datadir)/$(PACKAGE)/wrapper/patch
|
||||
endif
|
||||
|
||||
$(INSTALL) -d $(BUILD_ROOT)$(docdir)/
|
||||
$(INSTALL) -m 644 doc/README \
|
||||
$(BUILD_ROOT)$(docdir)/
|
||||
$(INSTALL) -m 644 doc/quilt.pdf doc/README.MAIL \
|
||||
$(BUILD_ROOT)$(docdir)/
|
||||
|
||||
$(INSTALL) -d $(BUILD_ROOT)$(mandir)/man1
|
||||
$(INSTALL) -m 644 $(MAN1) $(BUILD_ROOT)$(mandir)/man1/
|
||||
|
||||
$(INSTALL) -d $(BUILD_ROOT)$(etcdir)
|
||||
$(INSTALL) -d $(BUILD_ROOT)$(etcdir)/bash_completion.d
|
||||
$(INSTALL) -m 644 bash_completion \
|
||||
$(BUILD_ROOT)$(etcdir)/bash_completion.d/quilt
|
||||
$(INSTALL) -m 644 quilt.quiltrc $(BUILD_ROOT)$(etcdir)/
|
||||
$(INSTALL) -d $(BUILD_ROOT)$(emacsdir)/
|
||||
$(INSTALL) -m 644 lib/quilt.el $(BUILD_ROOT)$(emacsdir)/
|
||||
|
||||
install-compat: install-compat1 $(COMPAT_SYMLINKS:%=install-compat-symlink-%)
|
||||
install-compat-symlink-% :: install-compat1
|
||||
ln -sf $($(shell echo $* | $(AWK) '{print toupper($$1)}')) \
|
||||
$(BUILD_ROOT)$(datadir)/$(PACKAGE)/compat/$*
|
||||
|
||||
install-compat1:
|
||||
rm -rf $(BUILD_ROOT)$(datadir)/$(PACKAGE)/compat
|
||||
ifneq ($(COMPAT_PROGRAMS)$(COMPAT_SYMLINKS),)
|
||||
$(INSTALL) -d $(BUILD_ROOT)$(datadir)/$(PACKAGE)/compat
|
||||
ifneq ($(COMPAT_PROGRAMS),)
|
||||
$(INSTALL) -m 755 $(COMPAT_PROGRAMS:%=compat/%) \
|
||||
$(BUILD_ROOT)$(datadir)/$(PACKAGE)/compat
|
||||
endif
|
||||
endif
|
||||
|
||||
install: install-main install-compat
|
||||
|
||||
uninstall ::
|
||||
rm -rf $(BIN:%=$(BUILD_ROOT)$(bindir)/%) \
|
||||
$(BUILD_ROOT)$(datadir)/$(PACKAGE) \
|
||||
$(patsubst %,$(BUILD_ROOT)$(mandir)/man1/%, \
|
||||
$(notdir $(MAN1))) \
|
||||
$(BUILD_ROOT)$(etcdir)/bash_completion.d/quilt \
|
||||
$(BUILD_ROOT)$(etcdir)/quilt.quiltrc \
|
||||
$(BUILD_ROOT)$(docdir)/ \
|
||||
$(BUILD_ROOT)$(emacsdir)/quilt.el
|
||||
|
||||
check: $(TESTS:test/%.test=test/.%.ok)
|
||||
check-all: $(TESTS:test/%.test=check-%)
|
||||
|
||||
check-% : test/.%.ok
|
||||
@/bin/true
|
||||
|
||||
# Only include the test suite dependencies when required
|
||||
ifneq ($(findstring test,$(MAKECMDGOALS))$(findstring check,$(MAKECMDGOALS)),)
|
||||
-include test/.depend
|
||||
endif # (test|check)
|
||||
|
||||
test/.patch-wrapper.ok : bin/patch-wrapper
|
||||
|
||||
# Include a run-time generated list of dependencies for each test case
|
||||
test/.depend : Makefile $(TESTS)
|
||||
@( printf "%s : bin/quilt quilt/scripts/patchfns quilt/scripts/utilfns quilt/scripts/backup-files $(COMPAT)\n" $(TESTS); \
|
||||
$(AWK) 'sub(/.*\$$ *quilt /, "") \
|
||||
{ print FILENAME, ":", "quilt/"$$1}' $(TESTS); \
|
||||
$(AWK) 'sub(/.*\<quilt_command /, "") && ($$1 !~ /[^a-z]/) \
|
||||
{ print FILENAME, ":", "quilt/"$$1 }' quilt/*.in; \
|
||||
$(AWK) 'sub(/.*\$$ *%{QUILT_DIR}\/scripts\//, "") \
|
||||
{ print FILENAME, ":", "quilt/scripts/"$$1 }' $(TESTS); \
|
||||
) | sort -u | $(SED) -re 's:^test/(.*)\.test:test/.\1.ok:' \
|
||||
-e 's:quilt/graph:quilt/graph quilt/scripts/dependency-graph:' \
|
||||
-e 's:quilt/mail:quilt/mail quilt/scripts/edmail:' \
|
||||
-e 's:quilt/refresh:quilt/refresh quilt/scripts/remove-trailing-ws:' \
|
||||
-e 's:quilt/setup:quilt/setup quilt/scripts/inspect-wrapper:' \
|
||||
> $@
|
||||
|
||||
ifneq ($(shell . $(QUILTRC) ; echo $$QUILT_PATCHES_PREFIX),)
|
||||
CHECK_ENV := P=patches/; _P=../patches/; export P _P;
|
||||
endif
|
||||
CHECK_ENV += QUILT_PC=.pc; export QUILT_PC;
|
||||
|
||||
# Each tests dependencies are stored in test/.depend
|
||||
ifneq ($(findstring check-,$(MAKECMDGOALS)),)
|
||||
test/.%.ok : test/%.test test/run test/test.quiltrc FORCE
|
||||
else
|
||||
test/.%.ok : test/%.test test/run test/test.quiltrc
|
||||
endif
|
||||
@LANG=C; LC_ALL=C; \
|
||||
export LANG LC_ALL; \
|
||||
unset POSIXLY_CORRECT; \
|
||||
$(CHECK_ENV) \
|
||||
cd $(@D); \
|
||||
./run -q $(<F)
|
||||
@touch $@
|
||||
|
||||
clean :
|
||||
rm -f $(DIRT)
|
||||
|
||||
distclean : clean
|
||||
rm -f config.log config.status Makefile
|
||||
rm -rf autom4te.cache/
|
||||
|
||||
ifeq ($(USE_NLS),yes)
|
||||
install-main ::
|
||||
for lang in $(LINGUAS) ; do \
|
||||
dir=$(BUILD_ROOT)$(localedir)/$$lang/LC_MESSAGES; \
|
||||
$(INSTALL) -d $$dir; \
|
||||
$(INSTALL) -m 644 po/$$lang.mo \
|
||||
$$dir/quilt.mo ; \
|
||||
done
|
||||
|
||||
uninstall ::
|
||||
for lang in $(LINGUAS) ; do \
|
||||
dir=$(BUILD_ROOT)$(localedir)/$$lang/LC_MESSAGES; \
|
||||
rm -f $$dir/quilt.mo ; \
|
||||
done
|
||||
endif
|
||||
|
||||
.PHONY :: all install uninstall clean distclean updatepo
|
||||
|
||||
# Clear the suffix list
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .in
|
||||
# Bad gmake, never *ever* try to get a file out of source control by yourself.
|
||||
%: %,v
|
||||
%: RCS/%,v
|
||||
%: RCS/%
|
||||
%: s.%
|
||||
%: SCCS/s.%
|
||||
|
||||
FORCE:
|
|
@ -0,0 +1,214 @@
|
|||
Version 0.66 (Thu Mar 28 2019)
|
||||
- Add support for lzip archives and patches (#54570)
|
||||
- Document QUILT_PC as user-settable
|
||||
- configure: Don't require md5sum
|
||||
- Test suite: Allow keeping the working directory on failure
|
||||
- Test suite: Fix regex for recent versions of perl
|
||||
- Test suite: Fix /bin/sh filtering
|
||||
- Test suite: Run tests again if test.quiltrc changes
|
||||
- Test suite: Handle alternative QUILT_PATCHES values
|
||||
- Test suite: Increase code path coverage
|
||||
- Test suite: Be verbose on directory error
|
||||
- Test suite: Clean up when interrupted
|
||||
- Test suite: Prevent test cases from escaping
|
||||
- fold: Fix German translation
|
||||
- diff: Add missing quotes in basename call (#50862)
|
||||
- header: Fix corruption when trailing newline is missing (#50841)
|
||||
- mail: Fix patch set threading (#50775)
|
||||
- mail: Fix French translation
|
||||
- mail: Remove Content-Disposition headers
|
||||
- mail: Complain when a patch doesn't exist
|
||||
- new: Fix corruption when trailing newline is missing (#54295)
|
||||
- refresh: Add missing quotes in basename call (#50862)
|
||||
- setup: Add basic support for p7zip (.7z) archives (#49754)
|
||||
- setup: Align --fast on --slow for series files
|
||||
- quilt.el: Define quilt-edit-top-only before it's used
|
||||
- quilt.el: Stop using deprecated toggle-read-only
|
||||
- quilt.el: Don't strip directory in quilt-top-patch
|
||||
- quilt.el: Fix emacs compatibility issue (#51977)
|
||||
- quilt.el: Read QUILT_PC from config file
|
||||
- quiltrc: Support all patch formats by default
|
||||
- guards: Mention it in quilt manual page
|
||||
- compat/getopt: Handle a second separator (#54772)
|
||||
- compat/getopt: Allow non-digit parameter embedded in short option (#54772)
|
||||
|
||||
Version 0.65 (Wed Oct 09 2016)
|
||||
- Translation fixes
|
||||
- Project settings have priority
|
||||
- Reject binary files in patches
|
||||
- Fix a race condition in diff_file
|
||||
- Performance: Optimizations to the setup command
|
||||
- Performance: Optimizations to the bash completion script
|
||||
- Test suite: Improve the edit test case
|
||||
- Test suite: Make the symlink test more robust
|
||||
- Test suite: Test backup failure
|
||||
- Test suite: Test the header command with hard links
|
||||
- diff: Report diff failures
|
||||
- edit: Fix a corner case bug
|
||||
- mail: Fix the help text
|
||||
- push: Fix the synopsis
|
||||
- refresh: Do not remove symlinks
|
||||
- refresh: Break links to read-only patch files
|
||||
- refresh: Always preserve modification time
|
||||
- setup: Report failed look-ups in inspect-wrapper
|
||||
- quilt.el: Fix quilt-editable when patches are stored in subdirs
|
||||
- bash_completion: Handle spaces in file names
|
||||
- bash_completion: Update the list of commands
|
||||
- bash_completion: Add new command options
|
||||
- bash_completion: Fix handling of mail, new, push options
|
||||
- guards: Simplify the help text
|
||||
- guards: Include the file name also in the "Not found" case
|
||||
- guards: Add support for an external filelist in --check mode
|
||||
- guards: Report which config file has problem in --check mode
|
||||
- guards: Documentation update
|
||||
- guards: Clarify a user message
|
||||
|
||||
Version 0.64 (Mon Feb 09 2015)
|
||||
- Check for series file consistency
|
||||
- Performance: Several optimizations
|
||||
- Test suite: Several fixes and coverage improvements
|
||||
- Test suite: Run the tests in predictable order
|
||||
- files: Add support for unapplied patches
|
||||
- graph: Check for graphviz availability
|
||||
- mail: Remove procmail dependency
|
||||
- mail: Don't include the release number in User-Agent
|
||||
- pop: Add --refresh option
|
||||
- push: Add --refresh option
|
||||
- push: Do not use interactive mode with -f
|
||||
- setup: Skip version check
|
||||
- setup: Check for rpmbuild availability
|
||||
- setup: Handle long options passed to tar
|
||||
- setup: Several cleanups and minor fixes
|
||||
- setup: Major performance optimizations
|
||||
- setup: Fix path to extra patches in series file
|
||||
- setup: Trace calls earlier
|
||||
- setup: Add --fast option
|
||||
- setup: Fix link creation
|
||||
- quilt.el: Fix tramp support
|
||||
- quilt.el: Fix patch select completion
|
||||
|
||||
Version 0.63 (Sun May 25 2014)
|
||||
- New NEWS file, containing a human-readable changelog
|
||||
- Option -E is no longer passed to patch by default
|
||||
- Huge performance improvement (e.g., for commands series, applied and
|
||||
unapplied)
|
||||
- configure: Add compat symlinks for md5sum
|
||||
- Return 2 when there is nothing to do, contrasting with errors (ret=1)
|
||||
- Exit with an error when diff's retcode=2 (error) on patch refresh
|
||||
- bash_completion: cleanups and performance improvement (Savannah's #27111)
|
||||
- test/run: Use perl module Text::ParseWords (+ performance improvement)
|
||||
- Add some tests to our testsuite, for a better coverage
|
||||
- Fix heuristic for unapplied patches with timestamps
|
||||
- Bug fix: Patches emptying files should work now
|
||||
- Bug fix: Check for duplicate patch in series (Savannah's #20628)
|
||||
- Portability fixes for older Bash and GNU patch
|
||||
|
||||
Version 0.62 (Wed May 07 2014)
|
||||
- Was a buggy release, with an incomplete tarfile
|
||||
|
||||
Version 0.61 (Sun Dec 08 2013)
|
||||
- Almost two years of fixes and minor improvements
|
||||
- Fix support for ./configure --with-xargs
|
||||
- Parameter quoting fixes to many commands
|
||||
- Various fixes to the pop, push, refresh and patches commands
|
||||
- Translation fixes
|
||||
- setup: Many fixes and improvements
|
||||
- remove-trailing-ws: Several fixes and improvements
|
||||
- remove-trailing-ws: Add a dedicated test case
|
||||
- quilt.el: Many fixes and improvements (emacs integration)
|
||||
|
||||
Version 0.60 (Wed Feb 29 2012)
|
||||
- BSD compatibility improvements
|
||||
- grep: Support file names which include spaces
|
||||
- import: Fix import of relative patches
|
||||
- mail: Several fixes
|
||||
- setup: Support directory and archive names which include spaces
|
||||
- backup-files: rewritten from C to bash
|
||||
- backup-files: Add a dedicated test case
|
||||
|
||||
Version 0.51 (Sat Jan 28 2012)
|
||||
- Fix support for ./configure --docdir
|
||||
- Various $TMPDIR fixes
|
||||
- mail: Fix delivery address checking
|
||||
- mail: CC people in more common patch headers
|
||||
- push: Fix bash completion
|
||||
- inspect: Complain if wrapper script can't be executed
|
||||
|
||||
Version 0.50 (Mon Dec 5 2011)
|
||||
- 34 months of fixes and improvements, too many to list them all
|
||||
- Fix detection of the patch version
|
||||
- Avoid error messages when building due to missing git-desc file
|
||||
- Add support for lzma and xz compression formats
|
||||
- import: Fix confusing French translation
|
||||
- mail: Stop using =~ for older versions of bash
|
||||
- mail: Fix a temporary directory leak
|
||||
- revert: Stop using cp -l
|
||||
- revert: Add bash completion support
|
||||
- setup: Add --fuzz parameter
|
||||
- setup: Add support for reverse patches
|
||||
- inspect: Fix shell syntax errors
|
||||
- Fix error in test case create-delete
|
||||
|
||||
Version 0.48 (Thu Jan 29 2009)
|
||||
- fold: Fix bash completion
|
||||
- mail: Don't use GNU awk extensions
|
||||
- mail: Check for formail
|
||||
- setup: Fix for rpm 4.6
|
||||
- Fix error in test case import
|
||||
|
||||
Version 0.47 (Thu Aug 21 2008)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.46 (Thu Oct 19 2006)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.45 (Mon Apr 24 2006)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.44 (Tue Feb 14 2006)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.43 (Wed Feb 01 2006)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.42 (Tue Jul 26 2005)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.40 (Fri Apr 29 2005)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.39 (Thu Feb 10 2005)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.37 (Sun Oct 17 2004)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.36 (Wed Sep 22 2004)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.35 (Thu Jul 15 2004)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.34 (Thu Jun 10 2004)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.33 (Sun Jun 06 2004)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.32 (Sat Mar 13 2004)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.30 (Wed Jan 28 2004)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.29 (Wed Nov 12 2003)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.28 (Fri Oct 31 2003)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.27 (Tue Oct 28 2003)
|
||||
- Change summary not available
|
||||
|
||||
Version 0.26 (Tue Oct 21 2003)
|
||||
- Change summary not available
|
|
@ -0,0 +1,126 @@
|
|||
General:
|
||||
|
||||
- Abstract backup operations to/from the .pc/ directory, so that
|
||||
optionally something like rcs can be used instead of
|
||||
scripts/backup-files?
|
||||
|
||||
- Add something similar to cvs diff, which scans all files for
|
||||
changes that have not been folded back into their patches,
|
||||
similar to:
|
||||
`for p in $(quilt series); do quilt diff -z $p; done'?
|
||||
|
||||
- Allow to add a directory? Then we could detect also new files
|
||||
in the directory, without having to add them individually.
|
||||
|
||||
- Support different diff/patch options for different patches.
|
||||
(By specifying them in the series file?)
|
||||
|
||||
- Add command that generates a summary (patch names + descriptions).
|
||||
|
||||
- Add more long-form options, and add some nagative options so that
|
||||
defaults from .quiltrc can easily be overruled.
|
||||
|
||||
- series.conf: Allow to specify options like -R, -u, -Unum, -c,
|
||||
-Cnum per patch.
|
||||
|
||||
- Whenever the contents of the QUILT_PATCHES directory change,
|
||||
optionally call a trigger so that another tool can keep track of
|
||||
the patches directory history (e.g., CVS, RCS). Also call the
|
||||
trigger when the series file changes?
|
||||
|
||||
- Check if we can somehow support -p0 style patches that are
|
||||
applied in subdirectories (patch -d option): There are problems
|
||||
with relative $QUILT_PATCHES, and likely with several commands.
|
||||
|
||||
- wrapper scripts: check with [ -ef ] if the wrapper is the same
|
||||
as the default binary found to avoid wrappers like awk -> gawk.
|
||||
|
||||
- Add some more colors.
|
||||
|
||||
- Add the same kind of (optional) pager handling that git has.
|
||||
|
||||
Documentation:
|
||||
|
||||
- How to import a complete directory before doing wild changes?
|
||||
|
||||
- Describe how to work with hard-linked trees
|
||||
|
||||
- /etc/quilt.quiltrc and ~/.quiltrc
|
||||
|
||||
- diff/refresh: C -c -N -n options
|
||||
|
||||
- Subdirectory support
|
||||
|
||||
quilt new:
|
||||
|
||||
- Prevent spaces in patch names.
|
||||
|
||||
quilt push:
|
||||
|
||||
- Add option to print the reject to stdout
|
||||
|
||||
- If push fails, check if patch can be reversed.
|
||||
|
||||
- Add -l option to ignore whitespace changes.
|
||||
|
||||
- Check if there are any .orig or .rej files and barf if so.
|
||||
|
||||
quilt pop:
|
||||
|
||||
- The timestamp comparison logic is broken; need to track
|
||||
last-known timestamps per file.
|
||||
|
||||
quilt diff:
|
||||
|
||||
- Error message when a file is specified that isn't in the
|
||||
patch(es).
|
||||
|
||||
- When a directory is specified, diff all files below it.
|
||||
|
||||
quilt refresh:
|
||||
|
||||
- Add an -m option similar to `cvs commit -m "..."' to simplify
|
||||
keeping a change log in the patch documentation?
|
||||
|
||||
- Add option to log the updates of each patch (e.g., append the
|
||||
output of ``quilt diff -zR'' to patch.log on each update).
|
||||
|
||||
- Remove existing diffstat if --diffstat is not specified?
|
||||
|
||||
- Improve whitespace stripping
|
||||
|
||||
quilt import:
|
||||
|
||||
- Add option to replace the currently applied patch with a new
|
||||
one, by backing out the topmost patch first.
|
||||
|
||||
quilt setup:
|
||||
|
||||
- Also recognize other uses of tar and patch (with options in the
|
||||
command line), etc.
|
||||
|
||||
quit edit:
|
||||
|
||||
- Check for actual changes, and remove files again that haven't been
|
||||
changed.
|
||||
|
||||
quilt files:
|
||||
|
||||
- Print filenames relative to the working directory.
|
||||
|
||||
quilt mail:
|
||||
|
||||
- Improve recipient handling (quote special characters automatically;
|
||||
encode 8-bit characters).
|
||||
|
||||
- Character set handling is missing, too.
|
||||
|
||||
- Too many passes of edmail make it a bit slow.
|
||||
- If someone adds a References header to the intro, the References
|
||||
header added to patch messages for threading do not append to that
|
||||
header. They probably should; not sure if duplicate References
|
||||
headers are valid.
|
||||
|
||||
quilt fold:
|
||||
|
||||
- Add an -R option for reverse-applying a patch.
|
|
@ -0,0 +1,119 @@
|
|||
dnl Allow configure to specify a specific binary
|
||||
dnl 1: Environment variable
|
||||
dnl 2: binary name
|
||||
dnl 3: optional list of alternative binary names
|
||||
dnl 4: optional list of additional search directories
|
||||
AC_DEFUN([QUILT_COMPAT_PROG_PATH],[
|
||||
m4_define([internal_$2_cmd],[esyscmd(ls compat/$2.in 2>/dev/null)])
|
||||
|
||||
AC_ARG_WITH($2, AC_HELP_STRING(
|
||||
[--with-$2], [name of the $2 executable to use]
|
||||
m4_if(internal_$2_cmd,[],[],[ (use --without-$2
|
||||
to use an internal mechanism)])),
|
||||
[
|
||||
if test x"$withval" = xnone; then
|
||||
AC_MSG_ERROR([Invalid configure argument. use --without-$2])
|
||||
fi
|
||||
if test x"$withval" != xno; then
|
||||
AC_MSG_CHECKING(for $2)
|
||||
$1="$withval"
|
||||
if test -e "$$1"; then
|
||||
if test ! -f "$$1" -a ! -h "$$1" || test ! -x "$$1"; then
|
||||
AC_MSG_ERROR([$$1 is not an executable file])
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT([$$1])
|
||||
if test ! -e "$$1"; then
|
||||
AC_MSG_WARN([$$1 does not exist])
|
||||
fi
|
||||
COMPAT_SYMLINKS="$COMPAT_SYMLINKS $2"
|
||||
fi
|
||||
],[
|
||||
m4_if([$3],[],[
|
||||
AC_PATH_PROG($1,$2,,$PATH:$4)
|
||||
],[
|
||||
AC_PATH_PROGS($1,$3,,$PATH:$4)
|
||||
if test -n "$$1" -a "`expr "$$1" : '.*/\([[^/]]*\)$'`" != "$2"; then
|
||||
COMPAT_SYMLINKS="$COMPAT_SYMLINKS $2"
|
||||
fi
|
||||
])
|
||||
m4_if([$4],[],[],[
|
||||
if test -n "$$1"; then
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for dir in "$4"; do
|
||||
if test "`dirname $$1`" = "$dir"; then
|
||||
COMPAT_SYMLINKS="$COMPAT_SYMLINKS $2"
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS="$as_save_IFS"
|
||||
fi
|
||||
])
|
||||
])
|
||||
if test -z "$$1"; then
|
||||
m4_if(internal_$2_cmd,[],[
|
||||
AC_MSG_ERROR([Please specify the location of $2 with the option '--with-$2'])
|
||||
],[
|
||||
AC_MSG_WARN([Using internal $2 mechanism. Use option '--with-$2' to override])
|
||||
COMPAT_PROGRAMS="$COMPAT_PROGRAMS $2"
|
||||
$1=$2
|
||||
INTERNAL_$1=1
|
||||
])
|
||||
fi
|
||||
AC_SUBST($1)
|
||||
])
|
||||
|
||||
dnl Allow configure to specify a specific binary
|
||||
dnl This variant is for optional binaries.
|
||||
dnl 1: Environment variable
|
||||
dnl 2: binary name
|
||||
dnl 3: optional list of alternative binary names
|
||||
dnl 4: optional list of additional search directories
|
||||
AC_DEFUN([QUILT_COMPAT_PROG_PATH_OPT],[
|
||||
AC_ARG_WITH($2, AC_HELP_STRING(
|
||||
[--with-$2], [name of the $2 executable to use]),
|
||||
[
|
||||
if test x"$withval" != xno; then
|
||||
AC_MSG_CHECKING(for $2)
|
||||
$1="$withval"
|
||||
if test -e "$$1"; then
|
||||
if test ! -f "$$1" -a ! -h "$$1" || test ! -x "$$1"; then
|
||||
AC_MSG_ERROR([$$1 is not an executable file])
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT([$$1])
|
||||
if test ! -e "$$1"; then
|
||||
AC_MSG_WARN([$$1 does not exist])
|
||||
fi
|
||||
COMPAT_SYMLINKS="$COMPAT_SYMLINKS $2"
|
||||
fi
|
||||
],[
|
||||
m4_if([$3],[],[
|
||||
AC_PATH_PROG($1,$2,,$PATH:$4)
|
||||
],[
|
||||
AC_PATH_PROGS($1,$3,,$PATH:$4)
|
||||
if test -n "$$1" -a "`expr "$$1" : '.*/\([[^/]]*\)$'`" != "$2"; then
|
||||
COMPAT_SYMLINKS="$COMPAT_SYMLINKS $2"
|
||||
fi
|
||||
])
|
||||
m4_if([$4],[],[],[
|
||||
if test -n "$$1"; then
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for dir in "$4"; do
|
||||
if test "`dirname $$1`" = "$dir"; then
|
||||
COMPAT_SYMLINKS="$COMPAT_SYMLINKS $2"
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS="$as_save_IFS"
|
||||
fi
|
||||
])
|
||||
if test -z "$$1"; then
|
||||
AC_MSG_WARN([$2 not found, some optional functionalities will be missing])
|
||||
fi
|
||||
])
|
||||
if test -z "$$1"; then
|
||||
$1=$2
|
||||
fi
|
||||
AC_SUBST($1)
|
||||
])
|
|
@ -0,0 +1,274 @@
|
|||
#-*- mode: shell-script;-*-
|
||||
|
||||
# Programmed completion for bash to use quilt
|
||||
# Copyright 2003-2004 Martin Quinson (martin quinson#debian org)
|
||||
|
||||
# This file is part of the distribution of quilt, and is distributed under
|
||||
# the same licence than quilt itself
|
||||
|
||||
# WARNING: This script doesn't read user or system quiltrc files, and assumes
|
||||
# that QUILT_PC is left unchanged. If you have changed QUILT_PC and want
|
||||
# completion to work then you must set QUILT_PC in your global environment
|
||||
# (for example in ~/.profile) and not just in your quiltrc file.
|
||||
|
||||
# Complete on files (by default) or directories (with -d)
|
||||
#
|
||||
_quilt_comfile()
|
||||
{
|
||||
local IFS=$'\t\n'
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen ${1:--f} -- "$cur" ) )
|
||||
}
|
||||
|
||||
_quilt_completion()
|
||||
{
|
||||
local cur prev cmds command_matches
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
# quilt sub commands
|
||||
cmds='add annotate applied delete diff edit files fold fork graph \
|
||||
grep header import mail new next patches pop previous push refresh \
|
||||
remove rename revert series setup snapshot top unapplied upgrade'
|
||||
|
||||
# if no command were given, complete on commands
|
||||
if [[ $COMP_CWORD -eq 1 ]] ; then
|
||||
COMPREPLY=( $( compgen -W "$cmds -h" -- $cur ) )
|
||||
return 0
|
||||
fi
|
||||
|
||||
# if we're completing for 'quilt -h', then just
|
||||
# complete on any valid command
|
||||
if [ ${COMP_WORDS[1]} == -h ] ; then
|
||||
COMPREPLY=( $( compgen -W "$cmds" -- $cur ) )
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Accept a partial command if it's unique, because quilt will accept it.
|
||||
command_matches=( $(compgen -W "$cmds" -- ${COMP_WORDS[1]}) )
|
||||
if [ ${#command_matches[@]} -ne 1 ] ; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Complete depending on options
|
||||
case ${command_matches[0]} in
|
||||
add)
|
||||
case $prev in
|
||||
-P)
|
||||
COMPREPLY=( $( compgen -W "$(quilt --quiltrc - applied 2>/dev/null)" -- $cur ) )
|
||||
;;
|
||||
*)
|
||||
_quilt_comfile
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "-P -h" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
annotate)
|
||||
case $prev in
|
||||
-P)
|
||||
COMPREPLY=( $( compgen -W "$(quilt --quiltrc - applied 2>/dev/null)" -- $cur ) )
|
||||
;;
|
||||
*)
|
||||
_quilt_comfile
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "-P -h" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
applied)
|
||||
COMPREPLY=( $( compgen -W "-h $(quilt --quiltrc - applied 2>/dev/null)" -- $cur ) )
|
||||
;;
|
||||
delete)
|
||||
COMPREPLY=( $( compgen -W "-n -r -h --backup $(quilt --quiltrc - series)" -- $cur ) )
|
||||
;;
|
||||
diff)
|
||||
case $prev in
|
||||
-p)
|
||||
COMPREPLY=( $( compgen -W "0 1 ab" -- $cur ) )
|
||||
;;
|
||||
-P|--combine)
|
||||
COMPREPLY=( $( compgen -W "$(quilt --quiltrc - applied 2>/dev/null)" -- $cur ) )
|
||||
;;
|
||||
--diff|-U|-C)
|
||||
;;
|
||||
*)
|
||||
_quilt_comfile
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "-p -P -u -U -c -C -R -z -h --snapshot --diff --no-timestamps --no-index --combine --color --sort" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
edit)
|
||||
_quilt_comfile
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "-h" -- $cur ) )
|
||||
;;
|
||||
files)
|
||||
case $prev in
|
||||
--combine)
|
||||
COMPREPLY=( $( compgen -W "$(quilt --quiltrc - applied 2>/dev/null)" -- $cur ) )
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -W "-a -l -v -h --combine $(quilt --quiltrc - applied 2>/dev/null)" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
fold)
|
||||
case $prev in
|
||||
-p)
|
||||
COMPREPLY=( $( compgen -W "0 1 2 3 4 5 6 7 8 9 10" -- $cur ) )
|
||||
;;
|
||||
*)
|
||||
_quilt_comfile
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "-R -q -f -p -h" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
graph)
|
||||
case $prev in
|
||||
-T)
|
||||
COMPREPLY=( $( compgen -W "ps" -- $cur ) )
|
||||
;;
|
||||
--edge-labels)
|
||||
COMPREPLY=( $( compgen -W "files" -- $cur ) )
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -W "-T -h --all --reduce --lines --edge-labels $(quilt --quiltrc - applied 2>/dev/null)" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
grep)
|
||||
type _longopt &> /dev/null && _longopt grep
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "-h" -- $cur ) )
|
||||
;;
|
||||
header)
|
||||
COMPREPLY=( $( compgen -W "-a -e -h -r --backup --strip-diffstat --strip-trailing-whitespace $(quilt --quiltrc - series)" -- $cur ) )
|
||||
;;
|
||||
import)
|
||||
case $prev in
|
||||
-p)
|
||||
COMPREPLY=( $( compgen -W "0 1 2 3 4 5 6 7 8 9 10" -- $cur ) )
|
||||
;;
|
||||
-P)
|
||||
;;
|
||||
-d)
|
||||
COMPREPLY=( $( compgen -W "o a n" -- $cur ) )
|
||||
;;
|
||||
*)
|
||||
_quilt_comfile
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "-p -R -P -f -d -h" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
mail)
|
||||
case $prev in
|
||||
--mbox|-M)
|
||||
_quilt_comfile
|
||||
;;
|
||||
--signature)
|
||||
_quilt_comfile
|
||||
COMPREPLY=( "${COMPREPLY[@]}" - )
|
||||
;;
|
||||
--prefix|--sender|--from|--subject|--to|--cc|--bcc|--charset|--reply-to)
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -W "-m -M --prefix --mbox --send --sender --from --subject --to --cc --bcc --charset --signature --reply-to -h" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
new)
|
||||
case $prev in
|
||||
-p)
|
||||
COMPREPLY=( $( compgen -W "0 1 ap" -- $cur ) )
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -W "-p -h" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
next|previous)
|
||||
COMPREPLY=( $( compgen -W "$(quilt --quiltrc - series) -h" -- $cur ) )
|
||||
;;
|
||||
patches)
|
||||
_quilt_comfile
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "-v --color -h" -- $cur ) )
|
||||
;;
|
||||
pop)
|
||||
COMPREPLY=( $( compgen -W "-a -f -R -q -v --refresh -h $(quilt --quiltrc - applied 2>/dev/null)" -- $cur ) )
|
||||
;;
|
||||
push)
|
||||
case $prev in
|
||||
--fuzz)
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -W "-a -f -q -v -h --fuzz -m --merge --leave-rejects --color --refresh $(quilt --quiltrc - unapplied 2>/dev/null)" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
refresh)
|
||||
case $prev in
|
||||
-p)
|
||||
COMPREPLY=( $( compgen -W "0 1 ap" -- $cur ) )
|
||||
;;
|
||||
-U|-C)
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -W "-p -u -U -c -C -z -f -h $(quilt --quiltrc - applied 2>/dev/null) --no-timestamps --no-index --diffstat --sort --backup --strip-trailing-whitespace" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
remove|revert)
|
||||
case $prev in
|
||||
-P)
|
||||
COMPREPLY=( $( compgen -W "$(quilt --quiltrc - applied 2>/dev/null)" -- $cur ) )
|
||||
;;
|
||||
*)
|
||||
_quilt_comfile
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "-P -h" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
rename)
|
||||
case $prev in
|
||||
-P)
|
||||
COMPREPLY=( $( compgen -W "$(quilt --quiltrc - series)" -- $cur ) )
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -W "-P -h" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
series)
|
||||
COMPREPLY=( $( compgen -W "-v -h --color" -- $cur ) )
|
||||
;;
|
||||
setup)
|
||||
case $prev in
|
||||
-d|--sourcedir)
|
||||
_quilt_comfile -d
|
||||
;;
|
||||
--fuzz)
|
||||
;;
|
||||
*)
|
||||
_quilt_comfile
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "-d -v -h --sourcedir --fuzz --slow --fast" -- $cur ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
snapshot)
|
||||
COMPREPLY=( $( compgen -W "-d -h" -- $cur ) )
|
||||
;;
|
||||
unapplied)
|
||||
COMPREPLY=( $( compgen -W "-h $(quilt --quiltrc - series)" -- $cur ) )
|
||||
;;
|
||||
fork|top|upgrade)
|
||||
;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
# With option "filenames", directories are shown in completion with their
|
||||
# trailing / so that the user can go in them.
|
||||
#
|
||||
[ ${BASH_VERSINFO[0]} '>' 2 -o \
|
||||
${BASH_VERSINFO[0]} = 2 -a ${BASH_VERSINFO[1]} '>' 04 ] \
|
||||
&& _quilt_complete_opt="-o filenames"
|
||||
complete -F _quilt_completion $_quilt_complete_opt quilt
|
||||
unset -v _quilt_complete_opt
|
|
@ -0,0 +1,301 @@
|
|||
#!@PERL@ -w
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
#
|
||||
# Guards:
|
||||
#
|
||||
# +xxx include if xxx is defined
|
||||
# -xxx exclude if xxx is defined
|
||||
# +!xxx include if xxx is not defined
|
||||
# -!xxx exclude if xxx is not defined
|
||||
#
|
||||
|
||||
use FileHandle;
|
||||
use Getopt::Long;
|
||||
use strict;
|
||||
|
||||
# Prototypes
|
||||
sub files_in($$);
|
||||
sub parse($$);
|
||||
sub help();
|
||||
|
||||
sub slashme($) {
|
||||
my ($dir) = @_;
|
||||
$dir =~ s#([^/])$#$&/#; # append a slash if necessary
|
||||
if ($dir eq './') {
|
||||
return '';
|
||||
} else {
|
||||
return $dir;
|
||||
}
|
||||
}
|
||||
|
||||
# Generate a list of files in a directory
|
||||
#
|
||||
sub files_in($$) {
|
||||
my ($dir, $path) = @_;
|
||||
my $dh = new FileHandle;
|
||||
my (@files, $file);
|
||||
|
||||
# @<file> syntax
|
||||
if ($path =~ s/^@//) {
|
||||
my $fh;
|
||||
open($fh, '<', $path) or die "$path: $!\n";
|
||||
@files = <$fh>;
|
||||
close($fh);
|
||||
chomp(@files);
|
||||
s:^$dir:: for @files;
|
||||
return @files;
|
||||
}
|
||||
|
||||
$path = slashme($path);
|
||||
opendir $dh, length("$dir$path") ? "$dir$path" : '.'
|
||||
or die "$dir$path: $!\n";
|
||||
while ($file = readdir($dh)) {
|
||||
next if $file =~ /^(\.|\.\.|\.#.*|CVS|.*~)$/;
|
||||
if (-d "$dir$path$file") {
|
||||
@files = (@files, files_in($dir, "$path$file/"));
|
||||
} else {
|
||||
#print "[$path$file]\n";
|
||||
push @files, "$path$file";
|
||||
}
|
||||
}
|
||||
closedir $dh;
|
||||
return @files;
|
||||
}
|
||||
|
||||
# Parse a configuration file
|
||||
# Callback called with ($patch, @guards) arguments
|
||||
#
|
||||
sub parse($$) {
|
||||
my ($fh, $callback) = @_;
|
||||
|
||||
my $line = "";
|
||||
|
||||
while (<$fh>) {
|
||||
chomp;
|
||||
s/(^|\s+)#.*//;
|
||||
if (s/\\$/ /) {
|
||||
$line .= $_;
|
||||
next;
|
||||
}
|
||||
$line .= $_;
|
||||
my @guards = ();
|
||||
foreach my $token (split /[\s\t\n]+/, $line) {
|
||||
next if $token eq "";
|
||||
if ($token =~ /^[-+]/) {
|
||||
push @guards, $token;
|
||||
} else {
|
||||
#print "[" . join(",", @guards) . "] $token\n";
|
||||
&$callback($token, @guards);
|
||||
}
|
||||
}
|
||||
$line = "";
|
||||
}
|
||||
}
|
||||
|
||||
# Command line options
|
||||
#
|
||||
my ($dir, $config, $default, $check, $list, $invert_match, $with_guards) =
|
||||
( '', '-', 1, 0, 0, 0, 0);
|
||||
my @path;
|
||||
|
||||
# Help text
|
||||
#
|
||||
sub help() {
|
||||
print "$0 - select from a list of files guarded by conditions\n";
|
||||
print "SYNOPSIS: $0 [--prefix=dir] [--path=dir1:dir2:...]\n" .
|
||||
" [--default=0|1] [--check|--list] [--invert-match]\n" .
|
||||
" [--with-guards] [--config=file] symbol ...\n\n" .
|
||||
" Defaults: --default=$default\n" .
|
||||
" Use --path=\@<file> to read the list of entries from <file>\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
# Parse command line options
|
||||
#
|
||||
Getopt::Long::Configure ("bundling");
|
||||
eval {
|
||||
unless (GetOptions (
|
||||
'd|prefix=s' => \$dir,
|
||||
'c|config=s' => \$config,
|
||||
'C|check' => \$check,
|
||||
'l|list' => \$list,
|
||||
'w|with-guards' => \$with_guards,
|
||||
'p|path=s' => \@path,
|
||||
'D|default=i' => \$default,
|
||||
'v|invert-match' => \$invert_match,
|
||||
'h|help' => sub { help(); exit 0; })) {
|
||||
help();
|
||||
exit 1;
|
||||
}
|
||||
};
|
||||
if ($@) {
|
||||
print "$@";
|
||||
help();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
@path = ('.')
|
||||
unless (@path);
|
||||
@path = split(/:/, join(':', @path));
|
||||
|
||||
my $fh = ($config eq '-') ? \*STDIN : new FileHandle($config)
|
||||
or die "$config: $!\n";
|
||||
|
||||
$dir = slashme($dir);
|
||||
|
||||
if ($check) {
|
||||
# Check for duplicate files, or for files that are not referenced by
|
||||
# the specification.
|
||||
|
||||
my $problems = 0;
|
||||
my @files;
|
||||
|
||||
foreach (@path) {
|
||||
@files = (@files, files_in($dir, $_));
|
||||
}
|
||||
my %files = map { $_ => 0 } @files;
|
||||
|
||||
parse($fh, sub {
|
||||
my ($patch, @guards) = @_;
|
||||
if (exists $files{$patch}) {
|
||||
$files{$patch}++;
|
||||
} else {
|
||||
if ($config eq '-') {
|
||||
print "Not found: $dir$patch\n";
|
||||
} else {
|
||||
print "In $config but not found: $dir$patch\n";
|
||||
}
|
||||
$problems++;
|
||||
}});
|
||||
|
||||
$fh->close();
|
||||
|
||||
my ($file, $ref);
|
||||
while (($file, $ref) = each %files) {
|
||||
next if $ref == 1;
|
||||
|
||||
if ($ref == 0) {
|
||||
if ($config eq '-') {
|
||||
print "Unused: $file\n";
|
||||
} else {
|
||||
print "Not in $config: $file\n";
|
||||
}
|
||||
$problems++;
|
||||
}
|
||||
if ($ref > 1) {
|
||||
print "Warning: multiple uses";
|
||||
print " in $config" if $config ne '-';
|
||||
print ": $file\n";
|
||||
# This is not an error if the entries are mutually exclusive...
|
||||
}
|
||||
}
|
||||
exit $problems ? 1 : 0;
|
||||
|
||||
} elsif ($list) {
|
||||
parse($fh, sub {
|
||||
my ($patch, @guards) = @_;
|
||||
print join(' ', @guards), ' '
|
||||
if (@guards && $with_guards);
|
||||
print "$dir$patch\n";
|
||||
});
|
||||
} else {
|
||||
# Generate a list of patches to apply.
|
||||
|
||||
my %symbols = map { $_ => 1 } @ARGV;
|
||||
|
||||
parse($fh, sub {
|
||||
my ($patch, @guards) = @_;
|
||||
|
||||
my $selected;
|
||||
if (@guards) {
|
||||
# If the first guard is -xxx, the patch is included by default;
|
||||
# if it is +xxx, the patch is excluded by default.
|
||||
$selected = ($guards[0] =~ /^-/);
|
||||
|
||||
foreach (@guards) {
|
||||
/^([-+])(!?)(.*)?/
|
||||
or die "Bad guard '$_'\n";
|
||||
|
||||
# Check if the guard matches
|
||||
if (($2 eq '!' && !exists $symbols{$3}) ||
|
||||
($2 eq '' && ( $3 eq '' || exists $symbols{$3}))) {
|
||||
# Include or exclude
|
||||
$selected = ($1 eq '+');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# If there are no guards, use the specified default result.
|
||||
$selected = $default;
|
||||
}
|
||||
|
||||
print "$dir$patch\n"
|
||||
if $selected ^ $invert_match;
|
||||
});
|
||||
|
||||
$fh->close();
|
||||
|
||||
exit 0;
|
||||
}
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
guards - select from a list of files guarded by conditions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
F<guards> [--prefix=F<dir>] [--path=F<dir1:dir2:...>] [--default=<0|1>]
|
||||
[--check|--list] [--invert-match] [--with-guards] [--config=<file>]
|
||||
I<symbol> ...
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The script reads a configuration file that may contain so-called guards, file
|
||||
names, and comments, and writes those file names that satisfy all guards to
|
||||
standard output. The script takes a list of symbols as its arguments. Each line
|
||||
in the configuration file is processed separately. Lines may start with a
|
||||
number of guards. The following guards are defined:
|
||||
|
||||
=over
|
||||
|
||||
+I<xxx> Include the file(s) on this line if the symbol I<xxx> is defined.
|
||||
|
||||
-I<xxx> Exclude the file(s) on this line if the symbol I<xxx> is defined.
|
||||
|
||||
+!I<xxx> Include the file(s) on this line if the symbol I<xxx> is not defined.
|
||||
|
||||
-!I<xxx> Exclude the file(s) on this line if the symbol I<xxx> is not defined.
|
||||
|
||||
- Exclude this file. Used to avoid spurious I<--check> messages.
|
||||
|
||||
=back
|
||||
|
||||
The guards are processed left to right. The last guard that matches determines
|
||||
if the file is included. If no guard is specified, the I<--default>
|
||||
setting determines if the file is included.
|
||||
|
||||
If no configuration file is specified, the script reads from standard input.
|
||||
|
||||
The I<--check> option is used to compare the specification file against the
|
||||
file system. If files are referenced in the specification that do not exist, or
|
||||
if files are not enlisted in the specification file warnings are printed. The
|
||||
I<--path> option can be used to specify which directory or directories to scan.
|
||||
Multiple directories are separated by a colon (C<:>) character. The
|
||||
I<--prefix> option specifies the location of the files. Alternatively, the
|
||||
I<--path=@E<lt>fileE<gt>> syntax can be used to specify a file from which the
|
||||
file names will be read.
|
||||
|
||||
Use I<--list> to list all files independent of any rules. Use I<--invert-match>
|
||||
to list only the excluded patches. Use I<--with-guards> to also include all
|
||||
inclusion and exclusion rules.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Andreas Gruenbacher <agruen@suse.de>, SUSE Labs
|
|
@ -0,0 +1,265 @@
|
|||
#! @BASH@
|
||||
|
||||
# This is a wrapper to GNU patch that recognizes the most common
|
||||
# options and mimics GNU patch's behavior and output, and creates the
|
||||
# quilt metadata as if quilt push was used to apply the patches. When
|
||||
# options are used that this wrapper does not recognize, GNU patch is
|
||||
# used directly, and no quilt metadata will get created.
|
||||
|
||||
PATCH=@PATCH@
|
||||
original_options=("$@")
|
||||
|
||||
# GNU patch recognizes these environment variables
|
||||
if [ -n "$SIMPLE_BACKUP_SUFFIX" ]
|
||||
then
|
||||
set -- --suffix "$SIMPLE_BACKUP_SUFFIX" "$@"
|
||||
fi
|
||||
if [ -n "$PATCH_VERSION_CONTROL" ]
|
||||
then
|
||||
set -- --version-control "$PATCH_VERSION_CONTROL" "$@"
|
||||
elif [ -n "$VERSION_CONTROL" ]
|
||||
then
|
||||
set -- --version-control "$VERSION_CONTROL" "$@"
|
||||
fi
|
||||
if [ -n "$POSIXLY_CORRECT" ]
|
||||
then
|
||||
set -- --posix "$@"
|
||||
fi
|
||||
|
||||
backup_files()
|
||||
{
|
||||
declare dir=${QUILT_PC:-.pc}/$name
|
||||
|
||||
if [ "$backup_mode" = --backup-if-mismatch ]
|
||||
then
|
||||
awk '
|
||||
/^patching file / \
|
||||
{ file=$0
|
||||
sub(/^patching file /, "", file)
|
||||
}
|
||||
/^Hunk #[0-9]* / \
|
||||
{ if (!(file in backup)) {
|
||||
backup[file] = 1
|
||||
#print "ln -f "dir"/"file" "prefix file suffix > "/dev/stderr"
|
||||
system("ln -f "dir"/"file" "prefix file suffix)
|
||||
}
|
||||
}
|
||||
{ if (!silent)
|
||||
print
|
||||
}
|
||||
' dir="${dir//\\/\\\\}" \
|
||||
prefix="${opt_prefix//\\/\\\\}" \
|
||||
suffix="${opt_suffix//\\/\\\\}" \
|
||||
silent="${opt_silent:+1}"
|
||||
elif [ -n "$opt_silent" ]; then
|
||||
cat > /dev/null
|
||||
fi
|
||||
if [ "$backup_mode" = --backup -a -d "$dir" ]
|
||||
then
|
||||
for file in $(find "$dir" -type f -a ! -path "$path/.timestamp")
|
||||
do
|
||||
dest=$opt_prefix${file#$dir/}$opt_suffix
|
||||
mkdir -p $(dirname "$dest")
|
||||
ln -f $file $dest
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
find_pipe_patch()
|
||||
{
|
||||
declare patch=$1
|
||||
patch=${patch//\[/\\[}
|
||||
patch=${patch//\]/\\]}
|
||||
set -- $(stat -c $'%a %N\n' /proc/*/fd/* 2>/dev/null \
|
||||
| sed -nre "s,^300 \`(/proc/.*/fd)/.*' -> \`$patch'$,\\1,p")
|
||||
set -- $(stat -c $'%a %N\n' $1/* 2>/dev/null \
|
||||
| sed -nre "s,^500 \`.*' -> \`(.*)',\\1,p")
|
||||
[ $# -eq 1 ] || set -- "$patch"
|
||||
echo "$1"
|
||||
}
|
||||
|
||||
options=`getopt -q -o bsB:z:i:p:d: \
|
||||
--long quiet,silent,backup,backup-if-mismatch \
|
||||
--long no-backup-if-mismatch,prefix: \
|
||||
--long suffix:,posix,input:,strip:,directory: -- "$@"`
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
cannot_handle=1
|
||||
else
|
||||
case "${LC_ALL:-${LC_MESSAGES:-${LANG}}}" in
|
||||
''|C|POSIX|en*)
|
||||
;;
|
||||
*) cannot_handle=1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ -z "$cannot_handle" ]; then
|
||||
eval set -- "$options"
|
||||
|
||||
backup_mode=--backup-if-mismatch
|
||||
opt_prefix=
|
||||
opt_suffix=
|
||||
opt_silent=
|
||||
opt_input=
|
||||
opt_strip=
|
||||
opt_directory=$PWD
|
||||
|
||||
while :
|
||||
do
|
||||
case "$1" in
|
||||
-b|--backup)
|
||||
backup_mode=--backup
|
||||
;;
|
||||
--backup-if-mismatch)
|
||||
backup_mode=--backup-if-mismatch
|
||||
;;
|
||||
-d|--directory)
|
||||
cd "$2" || exit 1
|
||||
shift
|
||||
;;
|
||||
-i|--input)
|
||||
opt_input=$2
|
||||
new_options[${#new_options[@]}]=$1
|
||||
new_options[${#new_options[@]}]=$2
|
||||
shift
|
||||
;;
|
||||
--no-backup-if-mismatch)
|
||||
backup_mode=--no-backup-if-mismatch
|
||||
;;
|
||||
-B|--prefix)
|
||||
opt_prefix=$2
|
||||
new_options[${#new_options[@]}]=$1
|
||||
new_options[${#new_options[@]}]=$2
|
||||
shift
|
||||
;;
|
||||
-s|--silent|--quiet)
|
||||
opt_silent=--silent
|
||||
;;
|
||||
-p|--strip)
|
||||
opt_strip=-p$2
|
||||
new_options[${#new_options[@]}]=-p$2
|
||||
shift
|
||||
;;
|
||||
-z|--suffix)
|
||||
opt_suffix=$2
|
||||
new_options[${#new_options[@]}]=$1
|
||||
new_options[${#new_options[@]}]=$2
|
||||
shift
|
||||
;;
|
||||
--posix)
|
||||
backup_mode=--no-backup-if-mismatch
|
||||
new_options[${#new_options[@]}]=$1
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
new_options[${#new_options[@]}]=$1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
[ -n "$opt_prefix$opt_suffix" ] || opt_suffix=.orig
|
||||
if [ -z "$opt_strip" -o $# -ne 0 ]
|
||||
then
|
||||
cannot_handle=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$cannot_handle" ]
|
||||
then
|
||||
if [ -n "$opt_input" ]
|
||||
then
|
||||
patch=$opt_input
|
||||
elif [ ! -e /proc/self ]
|
||||
then
|
||||
echo "patch-wrapper: /proc not mounted!" >&2
|
||||
exit 1
|
||||
elif [ -e /proc/self/fd/0 ]
|
||||
then
|
||||
patch=$(readlink /proc/self/fd/0)
|
||||
case "$patch" in
|
||||
pipe:*)
|
||||
patch=$(find_pipe_patch "$patch")
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
patch=${patch#$PWD/}
|
||||
|
||||
if [ ! -e "$patch" ]
|
||||
then
|
||||
cannot_handle=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$cannot_handle" ]
|
||||
then
|
||||
$PATCH "${original_options[@]}"
|
||||
exit
|
||||
fi
|
||||
|
||||
quilt_patches=${QUILT_PATCHES:-patches}
|
||||
|
||||
if [ "${patch#$RPM_SOURCE_DIR}" != "$patch" ]
|
||||
then
|
||||
name=SOURCES/${patch#$RPM_SOURCE_DIR/}
|
||||
if [ ! -e "$quilt_patches/SOURCES" ]
|
||||
then
|
||||
mkdir -p "$quilt_patches"
|
||||
ln -s $RPM_SOURCE_DIR "$quilt_patches/SOURCES"
|
||||
fi
|
||||
elif [ "${patch#$RPM_BUILD_DIR}" != "$patch" ]
|
||||
then
|
||||
name=BUILD/${patch#$RPM_BUILD_DIR/}
|
||||
if [ ! -e "$quilt_patches/BUILD" ]
|
||||
then
|
||||
mkdir -p "$quilt_patches"
|
||||
ln -s $RPM_BUILD_DIR "$quilt_patches/BUILD"
|
||||
fi
|
||||
else
|
||||
name=${patch#/}
|
||||
dir=$(dirname "$quilt_patches/$name")
|
||||
mkdir -p "$dir"
|
||||
|
||||
if [ "${patch:0:1}" = / ]
|
||||
then
|
||||
ln -s "$patch" "$quilt_patches/${name#/}"
|
||||
else
|
||||
while ! [ "$dir/$updir$name" -ef "$patch" ]
|
||||
do
|
||||
updir=$updir../
|
||||
[ ${#updir} -gt 96 ] && break
|
||||
done
|
||||
if [ "$dir/$updir$name" -ef "$patch" ]
|
||||
then
|
||||
ln -s "$updir$patch" "$quilt_patches/$name"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$opt_strip" = -p1 ]; then
|
||||
echo "$name"
|
||||
else
|
||||
echo "$name $opt_strip"
|
||||
fi >> $quilt_patches/series
|
||||
|
||||
$PATCH "${new_options[@]}" --backup --prefix "${QUILT_PC:-.pc}/$name/" \
|
||||
| backup_files
|
||||
status=${PIPESTATUS[0]}
|
||||
if [ $status -eq 0 ]
|
||||
then
|
||||
dir=${QUILT_PC:-.pc}/$name
|
||||
if [ ! -e "$dir" ]
|
||||
then
|
||||
mkdir -p "$dir"
|
||||
fi
|
||||
echo -n "" > $dir/.timestamp
|
||||
if [ ! -e ${QUILT_PC:-.pc}/.version ]
|
||||
then
|
||||
echo 2 > ${QUILT_PC:-.pc}/.version
|
||||
fi
|
||||
echo "$name" >> "${QUILT_PC:-.pc}/applied-patches"
|
||||
fi
|
||||
exit $status
|
|
@ -0,0 +1,157 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# unset posix strict conformance variable since patch cannot be run
|
||||
# non-interactively when it's set.
|
||||
unset POSIXLY_CORRECT
|
||||
|
||||
# unset GREP_OPTIONS as it's quite easy to break quilt with uncommon options
|
||||
# see http://bugs.debian.org/715563
|
||||
unset GREP_OPTIONS
|
||||
|
||||
export TEXTDOMAIN=quilt
|
||||
export TEXTDOMAINDIR=@LOCALEDIR@
|
||||
|
||||
: ${QUILT_DIR=@QUILT_DIR@}
|
||||
export QUILT_DIR
|
||||
|
||||
if [ -z "$QUILTRC" ]
|
||||
then
|
||||
for QUILTRC in $HOME/.quiltrc @ETCDIR@/quilt.quiltrc; do
|
||||
[ -e $QUILTRC ] && break
|
||||
done
|
||||
export QUILTRC
|
||||
fi
|
||||
|
||||
# Support compatibility layer
|
||||
if [ -d $QUILT_DIR/compat ]
|
||||
then
|
||||
export PATH="$QUILT_DIR/compat:$PATH"
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
|
||||
echo $"Usage: quilt [--trace[=verbose]] [--quiltrc=XX] command [-h] ..."
|
||||
echo $" quilt --version"
|
||||
|
||||
echo $"Commands are:"
|
||||
quilt_commands \
|
||||
| sort \
|
||||
| column | column -t \
|
||||
| sed -e $'s/^/\t/'
|
||||
printf $"
|
||||
Global options:
|
||||
|
||||
--trace
|
||||
Runs the command in bash trace mode (-x). For internal debugging.
|
||||
|
||||
--quiltrc file
|
||||
Use the specified configuration file instead of ~/.quiltrc (or
|
||||
%s/quilt.quiltrc if ~/.quiltrc does not exist). See the pdf
|
||||
documentation for details about its possible contents. The
|
||||
special value \"-\" causes quilt not to read any configuration
|
||||
file.
|
||||
|
||||
--version
|
||||
Print the version number and exit immediately.\n" "@ETCDIR@"
|
||||
exit 1
|
||||
}
|
||||
|
||||
quilt_commands()
|
||||
{
|
||||
local command
|
||||
for command in $QUILT_DIR/*
|
||||
do
|
||||
if [ -f "$command" -a -x "$command" ]
|
||||
then
|
||||
echo ${command##$QUILT_DIR/}
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
if [ $# -eq 1 -a "$1" == "--version" ]
|
||||
then
|
||||
echo '@VERSION@'
|
||||
exit
|
||||
fi
|
||||
|
||||
BASH_OPTS=
|
||||
while [ $# -ne 0 ]
|
||||
do
|
||||
case $1 in
|
||||
[^-]*)
|
||||
if [ -z "$command" ]
|
||||
then
|
||||
command=$1
|
||||
else
|
||||
args[${#args[@]}]=$1
|
||||
fi ;;
|
||||
# Use a resource file other than ~/.quiltrc
|
||||
--quiltrc=*)
|
||||
QUILTRC=${1#--quiltrc=}
|
||||
[ "$QUILTRC" = - ] && unset QUILTRC ;;
|
||||
--quiltrc)
|
||||
QUILTRC=$2
|
||||
[ "$QUILTRC" = - ] && unset QUILTRC
|
||||
shift ;;
|
||||
# Trace execution of commands
|
||||
--trace*)
|
||||
BASH_OPTS="${BASH_OPTS:+$BASH_OPTS }-x"
|
||||
case "${1:7}" in
|
||||
'')
|
||||
;;
|
||||
=verbose)
|
||||
BASH_OPTS="${BASH_OPTS:+$BASH_OPTS }-v" ;;
|
||||
*)
|
||||
command=
|
||||
break ;;
|
||||
esac ;;
|
||||
*)
|
||||
args[${#args[@]}]=$1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if ! [ -f "$QUILT_DIR/$command" -a -x "$QUILT_DIR/$command" ]
|
||||
then
|
||||
if [ -n "$command" ]
|
||||
then
|
||||
for arg in $(quilt_commands)
|
||||
do
|
||||
case "$arg" in
|
||||
$command*)
|
||||
commands[${#commands[@]}]=$arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
unset arg
|
||||
fi
|
||||
|
||||
if [ ${#commands[@]} -eq 0 ]
|
||||
then
|
||||
usage
|
||||
elif [ ${#commands[@]} -eq 1 ]
|
||||
then
|
||||
command=${commands[0]}
|
||||
unset commands
|
||||
else
|
||||
echo "$command :" "${commands[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
set -- "${args[@]}"
|
||||
unset args
|
||||
|
||||
export QUILT_COMMAND="${command##*/}"
|
||||
bash $BASH_OPTS -c ". $QUILT_DIR/$command" "quilt ${command##*/}" "$@"
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,3 @@
|
|||
#! @BASH@
|
||||
|
||||
cat
|
|
@ -0,0 +1,59 @@
|
|||
#! @PERL@ -w
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
use strict;
|
||||
use POSIX qw(strftime);
|
||||
use Getopt::Long qw(:config gnu_getopt prefix_pattern=(--|-));
|
||||
use Date::Parse;
|
||||
|
||||
my $spec = '%a %b %e %H:%M:%S %Z %Y';
|
||||
my $now = time();
|
||||
my $utc = 0;
|
||||
|
||||
sub usage() {
|
||||
print "Usage: date [OPTION]... [+FORMAT]
|
||||
Display the current time in the given FORMAT.
|
||||
|
||||
-d, --date=STRING display time described by STRING, not `now'
|
||||
-f, --file=DATEFILE like --date once for each line of DATEFILE
|
||||
-R, --rfc-822 output RFC-822 compliant date string
|
||||
-u, --utc, --universal print or set Coordinated Universal Time
|
||||
--help display this help and exit
|
||||
";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub parse_utc_secs($) {
|
||||
my ($now) = @_;
|
||||
|
||||
if ($now =~ / UTC ([0-9]+) seconds$/) {
|
||||
# This is an heuristic specifically for quilts mail.in invocation:
|
||||
# date --rfc-822 -d "1970/01/01 UTC nnnnnnnn seconds"
|
||||
return $1;
|
||||
}
|
||||
else {
|
||||
return str2time($now);
|
||||
}
|
||||
}
|
||||
|
||||
GetOptions('rfc-822|R' => sub() { $spec = '%a, %d %b %Y %H:%M:%S %z' },
|
||||
'utc|universal|u' => \$utc,
|
||||
'date|d=s' => sub() { $now = parse_utc_secs($_[1]) },
|
||||
'reference|r=s' => sub() { my @filestats = stat($_[1]); $now = parse_utc_secs('1970/01/01 UTC ' . $filestats[9] . ' seconds') },
|
||||
'help|h' => sub() { usage })
|
||||
or usage;
|
||||
|
||||
if (@ARGV == 1 && $ARGV[0] =~ /^\+/) {
|
||||
$spec = substr($ARGV[0], 1);
|
||||
} elsif (@ARGV > 1) {
|
||||
usage;
|
||||
}
|
||||
|
||||
my @now = $utc ? gmtime($now) : localtime($now);
|
||||
|
||||
print strftime($spec, @now) . "\n";
|
|
@ -0,0 +1,136 @@
|
|||
#! @PERL@ -w
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
use strict;
|
||||
|
||||
my $opts = '';
|
||||
my @words;
|
||||
my $found_sep = 0;
|
||||
|
||||
foreach my $arg (@ARGV) {
|
||||
if (!$found_sep && $arg eq '--') {
|
||||
$found_sep = 1;
|
||||
}
|
||||
else {
|
||||
if (!$found_sep) {
|
||||
$opts .= ' ' . $arg;
|
||||
}
|
||||
else {
|
||||
push @words, $arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# there is no reason to parse
|
||||
# the opts if there are no args.
|
||||
if (!@words) {
|
||||
print " --\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
my $short_opts = '';
|
||||
my @long_opts;
|
||||
|
||||
# nothing fancy to see here; this script provides minimal compatibility
|
||||
# with the getopt from util-linux until a cross platform binary exists.
|
||||
# We silently ignore option -q.
|
||||
if ($opts =~ /^\s*(?:-q\s+)?-o ([a-zA-Z:]*)?(\s+--long .*)*/) {
|
||||
$short_opts = $1;
|
||||
if ($2) {
|
||||
my $long_opts = $2;
|
||||
$long_opts =~ s/^\s*--long //g;
|
||||
$long_opts =~ s/ --long /,/g;
|
||||
@long_opts = split(/,/,$long_opts);
|
||||
}
|
||||
}
|
||||
|
||||
my @barewords = ('--');
|
||||
my @options;
|
||||
|
||||
# set the previous option name when a param is required
|
||||
my $need_param;
|
||||
|
||||
sub quote_word
|
||||
{
|
||||
my $word = shift;
|
||||
$word =~ s/'/'\\''/;
|
||||
return "'$word'";
|
||||
}
|
||||
|
||||
# there can be a second separator, to inhibit processing following arguments
|
||||
# as options
|
||||
$found_sep = 0;
|
||||
foreach my $word (@words) {
|
||||
if ($word eq '--') {
|
||||
$found_sep = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
# allow '-' to be an option value
|
||||
if ($found_sep || (!$need_param && $word !~ /^-./)) {
|
||||
push @barewords, quote_word($word);
|
||||
next;
|
||||
}
|
||||
if ($need_param) {
|
||||
die "expecting param for $need_param" if $word =~ /^-./;
|
||||
push @options, quote_word($word);
|
||||
$need_param = undef;
|
||||
next;
|
||||
}
|
||||
# process short options
|
||||
if ($word =~ s/^-([^-])/$1/) {
|
||||
my @letters = reverse(split(//,$word));
|
||||
while (@letters) {
|
||||
my $letter = pop @letters;
|
||||
my $found = grep(/$letter/, $short_opts);
|
||||
push @options, '-'.$letter;
|
||||
die "illegal option: $letter" if !$found;
|
||||
|
||||
# handle options with optional parameters
|
||||
if (grep(/${letter}::/, $short_opts)) {
|
||||
if (scalar(@letters) == 0) {
|
||||
push @options, quote_word('');
|
||||
} else {
|
||||
# what looked like more short options
|
||||
# are in fact the optional parameters
|
||||
push @options, quote_word(join('', reverse @letters));
|
||||
}
|
||||
last;
|
||||
}
|
||||
|
||||
# handle options with mandatory parameters
|
||||
if (grep(/$letter:/, $short_opts)) {
|
||||
if (scalar(@letters) == 0) {
|
||||
$need_param = $letter;
|
||||
} else {
|
||||
# short options can have args
|
||||
# embedded in the short option list
|
||||
push @options, quote_word(join('', reverse @letters));
|
||||
@letters = ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# process long options
|
||||
if ($word =~ s/^--//) {
|
||||
my $param = '';
|
||||
if ($word =~ /(.*)=(.*)/) {
|
||||
$word = $1;
|
||||
$param = $2;
|
||||
}
|
||||
my ($found) = grep(/^$word:{0,2}$/,@long_opts);
|
||||
die "illegal option: $word" if !$found;
|
||||
die "$word: unexpected paramater $param" if $found !~ /:$/ && $param ne '';
|
||||
|
||||
$need_param = $word if $found =~ /[^:]:$/ && $param eq '';
|
||||
push @options, "--$word";
|
||||
push @options, quote_word($param) if $param || $found =~ /::$/;
|
||||
}
|
||||
}
|
||||
|
||||
print " @options @barewords\n"
|
|
@ -0,0 +1,27 @@
|
|||
#! @BASH@
|
||||
|
||||
if [ x"$1" = x"-d" ]
|
||||
then
|
||||
for ((n=0 ; $n<100 ; n++))
|
||||
do
|
||||
try=${2%XXXXXX}$RANDOM
|
||||
mkdir -m 700 "$try" 2>/dev/null && break
|
||||
done
|
||||
else
|
||||
user_mask=$(umask)
|
||||
umask 077
|
||||
set -o noclobber
|
||||
for ((n=0 ; $n<100 ; n++))
|
||||
do
|
||||
try=${1%XXXXXX}$RANDOM
|
||||
echo -n "" 2> /dev/null > "$try" && break
|
||||
done
|
||||
set +o noclobber
|
||||
umask $user_mask
|
||||
fi
|
||||
if [ $n -lt 100 ]
|
||||
then
|
||||
echo "$try"
|
||||
else
|
||||
exit 1
|
||||
fi
|
|
@ -0,0 +1,4 @@
|
|||
#! @BASH@
|
||||
|
||||
echo "No mail transfer agent configured for \`quilt mail'" >&2
|
||||
exit 1
|
|
@ -0,0 +1,276 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd=$cpprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "$0: no input file specified" >&2
|
||||
exit 1
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d "$dst" ]; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
else
|
||||
instcmd=$mkdirprog
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f "$src" ] || [ -d "$src" ]
|
||||
then
|
||||
:
|
||||
else
|
||||
echo "$0: $src does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "$0: no destination specified" >&2
|
||||
exit 1
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d "$dst" ]
|
||||
then
|
||||
dst=$dst/`basename "$src"`
|
||||
else
|
||||
:
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-$defaultIFS}"
|
||||
|
||||
oIFS=$IFS
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS=$oIFS
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp=$pathcomp$1
|
||||
shift
|
||||
|
||||
if [ ! -d "$pathcomp" ] ;
|
||||
then
|
||||
$mkdirprog "$pathcomp"
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
pathcomp=$pathcomp/
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd "$dst" &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
|
||||
else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename "$dst"`
|
||||
else
|
||||
dstfile=`basename "$dst" $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename "$dst"`
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
rmtmp=$dstdir/#rm.$$#
|
||||
|
||||
# Trap to clean up temp files at exit.
|
||||
|
||||
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd "$src" "$dsttmp" &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
|
||||
|
||||
# Now remove or move aside any old file at destination location. We try this
|
||||
# two ways since rm can't unlink itself on some systems and the destination
|
||||
# file might be busy for other reasons. In this case, the final cleanup
|
||||
# might fail but the new file should still install successfully.
|
||||
|
||||
{
|
||||
if [ -f "$dstdir/$dstfile" ]
|
||||
then
|
||||
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
|
||||
$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
|
||||
{
|
||||
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
|
||||
(exit 1); exit
|
||||
}
|
||||
else
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||
|
||||
fi &&
|
||||
|
||||
# The final little trick to "correctly" pass the exit status to the exit trap.
|
||||
|
||||
{
|
||||
(exit 0); exit
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,429 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT([quilt],[0.66],[quilt-dev@nongnu.org])
|
||||
AC_CONFIG_AUX_DIR(config)
|
||||
AC_PREREQ(2.53)
|
||||
|
||||
PACKAGE_RELEASE=1
|
||||
AC_SUBST(PACKAGE_RELEASE)
|
||||
AC_SUBST(PACKAGE_TARNAME)
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
AC_SYS_INTERPRETER
|
||||
if test "$interpval" != yes ; then
|
||||
AC_MSG_WARN([no
|
||||
|
||||
bash/perl scripts may not be invoked correctly due to problems with your
|
||||
systems implementation of #! being either broken or non-existant.
|
||||
])
|
||||
fi
|
||||
|
||||
dnl Check for Bourne-Again Shell
|
||||
unset BASH # bash sets this itself!
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(BASH, bash)
|
||||
|
||||
# It would be nice not to have to use backticks, but too many retarded sh
|
||||
# implementations still don't support $( )
|
||||
# BEWARE: There is a distinct possibility that we are currently running under
|
||||
# bash in this configure script (/bin/sh being a symlink to /bin/bash). Even
|
||||
# though the result /could/ be available to us directly as $BASH_VERSION we
|
||||
# don't want to use, or trust it, incase the user is specifying a different
|
||||
# bash executable.
|
||||
if `$BASH -c '[[ "$BASH_VERSION" \< "3.0" ]]'` ; then
|
||||
AC_MSG_ERROR([
|
||||
$PACKAGE_NAME requires at least version 3.0 of bash, you can download a current
|
||||
version of bash from ftp.gnu.org
|
||||
])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(whether $BASH quoting works)
|
||||
if test `$BASH -c "echo \"\\\$(set -- \\\$'a b'; echo \\\$#)\"" 2>/dev/null` = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
You have a version of `bash' which suffers from a quoting bug.
|
||||
This is a known bug of bash 3.1, which was fixed by patch bash31-011.
|
||||
You can get this patch at ftp://ftp.gnu.org/gnu/bash/
|
||||
])
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(CP, cp, [gcp cp])
|
||||
QUILT_COMPAT_PROG_PATH(DATE, date, [gdate date])
|
||||
|
||||
if test -z "$INTERNAL_DATE"; then
|
||||
AC_MSG_CHECKING([whether $DATE --rfc-822 works])
|
||||
if $DATE --rfc-822 >/dev/null 2>/dev/null; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_ERROR([no
|
||||
|
||||
If you don't have a version of `date' that supports --rfc-822, you
|
||||
can specify '--without-date' and $PACKAGE_NAME will use its own
|
||||
internal date.
|
||||
])
|
||||
fi
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(PERL, perl, [perl perl5])
|
||||
QUILT_COMPAT_PROG_PATH(GREP, grep)
|
||||
|
||||
AC_MSG_CHECKING([whether $GREP -q works])
|
||||
if echo first | $GREP -q first 2>/dev/null; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
Sorry, you have a version of grep which doesn't understand -q.
|
||||
$PACKAGE_NAME needs it. If you have access to a version of grep which does
|
||||
understand -q, you can supply its path with the '--with-grep=' option.
|
||||
])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether $GREP understands (foo|bar)])
|
||||
if echo first | $GREP '^\(fir\|las\)' >/dev/null 2>&1; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
Sorry, you have a version of grep which doesn't understand constructs
|
||||
of the form (foo|bar). $PACKAGE_NAME needs it. If you have access to
|
||||
a version of grep which does understand such constructs, you can supply
|
||||
its path with the '--with-grep=' option.
|
||||
])
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(TAIL, tail)
|
||||
|
||||
# Solaris' /usr/bin/tail doesn't understand -n.
|
||||
AC_MSG_CHECKING([whether $TAIL -n works])
|
||||
if test "`(echo first; echo second) | $TAIL -n 1 2>/dev/null`" = "second"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
Sorry, you have a version of tail which doesn't understand -n.
|
||||
$PACKAGE_NAME needs it. If you have access to a version of tail which does
|
||||
understand -n, you can supply its path with the '--with-tail=' option.
|
||||
Solaris users can use /usr/xpg4/bin/tail.
|
||||
])
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(TR, tr)
|
||||
|
||||
AC_MSG_CHECKING([whether $TR understands a-z ])
|
||||
if test "`echo first | $TR a-z A-Z 2>/dev/null`" = "FIRST"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
Sorry, you have a version of tr which doesn't understand constructs
|
||||
of the form a-z. $PACKAGE_NAME needs it. If you have access to
|
||||
a version of tr which does understand such constructs, you can supply
|
||||
its path with the '--with-tr=' option.
|
||||
Solaris users can use /usr/xpg4/bin/tr.
|
||||
])
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(STAT, stat)
|
||||
|
||||
AC_MSG_CHECKING([whether $STAT -c '%h' works])
|
||||
if $STAT -c '%h' /dev/null >/dev/null 2>/dev/null; then
|
||||
AC_MSG_RESULT(yes)
|
||||
STAT_HARDLINK="-c '%h'"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_CHECKING([whether $STAT -f '%l' works])
|
||||
if $STAT -f '%l' /dev/null >/dev/null 2>/dev/null; then
|
||||
AC_MSG_RESULT(yes)
|
||||
STAT_HARDLINK="-f '%l'"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
Sorry, you have a version of stat which understands neither -c nor -f.
|
||||
$PACKAGE_NAME needs it. If you have access to a version of stat which does
|
||||
understand -c or -f, you can supply its path with the '--with-stat=' option.
|
||||
])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(STAT_HARDLINK)
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(SED, sed)
|
||||
|
||||
AC_MSG_CHECKING([whether $SED understands (foo|bar)])
|
||||
if test "`echo first | $SED -e 's/\(fir\|lo\)/la/' 2>/dev/null`" = "last"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
Sorry, you have a version of sed which doesn't understand constructs
|
||||
of the form (foo|bar). $PACKAGE_NAME needs it. If you have access to
|
||||
a version of sed which does understand such constructs, you can supply
|
||||
its path with the '--with-sed=' option.
|
||||
])
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(AWK, awk, [gawk awk])
|
||||
|
||||
AC_MSG_CHECKING([whether $AWK supports sub])
|
||||
if test "`echo first | $AWK 'sub(/first/, "last")' 2>/dev/null`" = "last"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
Sorry, you have a version of awk which doesn't understand sub( ).
|
||||
$PACKAGE_NAME needs it. If you have access to a version of awk
|
||||
which does understand such constructs, you can supply its path
|
||||
with the '--with-awk=' option.
|
||||
Solaris users can use /usr/xpg4/bin/awk.
|
||||
])
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(pod2man, AC_HELP_STRING(
|
||||
[--with-pod2man],
|
||||
[name of the pod2man executable to use (use --without-pod2man to disable)]),
|
||||
[
|
||||
if test x"$withval" = xno; then
|
||||
POD2MAN=
|
||||
else
|
||||
POD2MAN=$withval
|
||||
fi],[
|
||||
AC_PATH_PROG(POD2MAN, pod2man)
|
||||
]
|
||||
)
|
||||
AC_SUBST(POD2MAN)
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(COLUMN, column)
|
||||
QUILT_COMPAT_PROG_PATH(GETOPT, getopt)
|
||||
|
||||
if test -z "$INTERNAL_GETOPT"; then
|
||||
AC_MSG_CHECKING(for getopt --long syntax)
|
||||
dnl check GNU syntax
|
||||
$GETOPT -o t --long test -- --test | grep 'illegal option' >/dev/null
|
||||
getopt_long_errors=$?
|
||||
$GETOPT -o t --long test -- --test | grep '^ *--test *--' >/dev/null
|
||||
getopt_long_works=$?
|
||||
if test $getopt_long_errors -eq 1 -a $getopt_long_works -eq 0; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
$GETOPT does not support the --long option.
|
||||
If you don't have a version of getopt that supports long options, you
|
||||
can specify '--without-getopt' and $PACKAGE_NAME will use its own
|
||||
internal getopt.
|
||||
])
|
||||
fi
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(MKTEMP, mktemp)
|
||||
if test -z "$INTERNAL_MKTEMP" ; then
|
||||
AC_MSG_CHECKING(whether $MKTEMP -d works)
|
||||
if tempdir=`$MKTEMP -d ${TMPDIR:-/tmp}/$PACKAGE_NAME.XXXXXX 2>/dev/null` && \
|
||||
rmdir "$tempdir" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
'$MKTEMP -d' does not create temporary directories.
|
||||
If you don't have a version of mktemp that can create directories, you
|
||||
can specify '--without-mktemp' and $PACKAGE_NAME will use its own
|
||||
internal tempfile generation mechanism.
|
||||
])
|
||||
fi
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(DIFF, diff)
|
||||
QUILT_COMPAT_PROG_PATH(PATCH, patch)
|
||||
|
||||
# Sun diff and others will not work because GNU patch options are used.
|
||||
AC_MSG_CHECKING([the version of $DIFF])
|
||||
if $DIFF --version 2>/dev/null | grep GNU >/dev/null; then
|
||||
set -- `$DIFF --version 2>/dev/null | $AWK '{ print $NF; exit }'`
|
||||
diff_version=$1
|
||||
AC_MSG_RESULT($diff_version)
|
||||
saved_IFS=$IFS; IFS='.'
|
||||
set -- $diff_version
|
||||
IFS=$saved_IFS
|
||||
set -- `echo $1 | $TR -cd 0-9` `echo $2 | $TR -cd 0-9`
|
||||
if test 0$1 -lt 2 || test 0$1 -eq 2 -a 0$2 -lt 7 ; then
|
||||
diff_version=
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no GNU diff)
|
||||
fi
|
||||
if test -z "$diff_version" ; then
|
||||
AC_MSG_ERROR([
|
||||
$PACKAGE_NAME requires at least version 2.7 of GNU diffutils. You can
|
||||
download a current version of patch from ftp.gnu.org, or if you already
|
||||
have GNU diff then you can supply its path with the '--with-diff=' option.
|
||||
])
|
||||
fi
|
||||
|
||||
|
||||
# Sun's patch, and others, do not work because GNU patch options are used.
|
||||
AC_MSG_CHECKING([the version of $PATCH])
|
||||
if $PATCH --version 2> /dev/null | grep GNU >/dev/null; then
|
||||
set -- `$PATCH --version 2> /dev/null`
|
||||
if test x$1 = xGNU ; then
|
||||
patch_version=$3
|
||||
else
|
||||
patch_version=$2
|
||||
fi
|
||||
AC_MSG_RESULT($patch_version)
|
||||
saved_IFS=$IFS; IFS='.'
|
||||
set -- $patch_version
|
||||
IFS=$saved_IFS
|
||||
set -- `echo $1 | $TR -cd 0-9` `echo $2 | $TR -cd 0-9`
|
||||
if test 0$1 -lt 2 || test 0$1 -eq 2 -a 0$2 -lt 5 ; then
|
||||
patch_version=
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no GNU patch)
|
||||
fi
|
||||
if test -z "$patch_version" ; then
|
||||
AC_MSG_ERROR([
|
||||
$PACKAGE_NAME requires at least version 2.5 of GNU patch. You can download a
|
||||
current version of patch from ftp.gnu.org, or if you already have GNU patch
|
||||
then you can supply its path with the '--with-patch=' option.
|
||||
])
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(FIND, find)
|
||||
|
||||
AC_MSG_CHECKING([whether $FIND -path works])
|
||||
if $FIND . -path '*' >/dev/null 2>&1; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
Sorry, you have a version of find which doesn't understand -path.
|
||||
$PACKAGE_NAME needs it. If you have access to a version of find which
|
||||
does understand -path, you can supply its path with the
|
||||
'--with-find=' option.
|
||||
])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether $FIND -print0 works])
|
||||
if $FIND . -path '*' -print0 >/dev/null 2>&1; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
Sorry, you have a version of find which doesn't understand -print0.
|
||||
$PACKAGE_NAME needs it. If you have access to a version of find which
|
||||
does understand -print0, you can supply its path with the
|
||||
'--with-find=' option.
|
||||
])
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(XARGS, xargs)
|
||||
|
||||
AC_MSG_CHECKING([whether $XARGS -0 works])
|
||||
if echo | $XARGS -0 echo >/dev/null 2>&1; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([
|
||||
Sorry, you have a version of xargs which doesn't understand -0.
|
||||
$PACKAGE_NAME needs it. If you have access to a version of xargs which
|
||||
does understand -0, you can supply its path with the
|
||||
'--with-xargs=' option.
|
||||
])
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH_OPT(DIFFSTAT, diffstat)
|
||||
|
||||
if test "$DIFFSTAT" != "diffstat"; then
|
||||
# We need diffstat version 1.32 or better, else quilt refresh --diffstat
|
||||
# will show progress data we don't want to see. This is only a warning
|
||||
# and we continue even if version is older, as this is only a minor
|
||||
# annoyance.
|
||||
AC_MSG_CHECKING([for diffstat version])
|
||||
diffstat_version=`$DIFFSTAT -V 2>/dev/null | \
|
||||
sed 's/^[[^0-9]]*\([[0-9]]*\)\.\([[0-9]]*\).*/\1 \2/'`
|
||||
eval set -- "$diffstat_version"
|
||||
diffstat_major_version="$1"
|
||||
diffstat_minor_version="$2"
|
||||
if test -z "$diffstat_major_version" -o -z "$diffstat_minor_version"; then
|
||||
AC_MSG_RESULT(unknown)
|
||||
AC_MSG_WARN([
|
||||
diffstat utility version couldn't be checked; chances are good that the
|
||||
--diffstat option of the refresh command will not work properly.
|
||||
])
|
||||
else
|
||||
AC_MSG_RESULT($diffstat_major_version.$diffstat_minor_version)
|
||||
if test "$diffstat_major_version" -lt 1 \
|
||||
-o \( "$diffstat_major_version" -eq 1 -a "$diffstat_minor_version" -lt 32 \); then
|
||||
AC_MSG_WARN([
|
||||
diffstat utility is too old; the --diffstat option of the refresh command
|
||||
will not work correctly until a newer version (>= 1.32) is installed.
|
||||
])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
QUILT_COMPAT_PROG_PATH(SENDMAIL, sendmail, [], [/usr/sbin])
|
||||
|
||||
AC_PATH_PROG(MSGMERGE, [msgmerge])
|
||||
AC_PATH_PROG(MSGFMT, [msgfmt])
|
||||
AC_PATH_PROG(XGETTEXT, [xgettext])
|
||||
AC_PATH_PROG(MSGUNIQ, [msguniq])
|
||||
AC_PATH_PROG(MSGCAT, [msgcat])
|
||||
if test -n "$MSGFMT" -a -n "$MSGMERGE" -a -n "$XGETTEXT" -a -n "$MSGUNIQ" -a -n "$MSGCAT" ; then
|
||||
HAVE_NLS=yes
|
||||
else
|
||||
HAVE_NLS=no
|
||||
fi
|
||||
|
||||
USE_NLS=no
|
||||
AC_ARG_ENABLE(nls, AC_HELP_STRING(
|
||||
[--disable-nls], [exclude natural language support]),
|
||||
[USE_NLS=$enableval],[USE_NLS=$HAVE_NLS])
|
||||
|
||||
if test $USE_NLS = yes -a $HAVE_NLS = no ; then
|
||||
AC_MSG_ERROR([
|
||||
You do not appear to have msgfmt, which is part of the GNU Gettext package. It
|
||||
is a required package as you chose the '--enable-nls' option to configure.
|
||||
You can download GNU Gettext from ftp.gnu.org
|
||||
])
|
||||
fi
|
||||
|
||||
PATCH_WRAPPER=
|
||||
AC_ARG_WITH(patch-wrapper, AC_HELP_STRING(
|
||||
[--with-patch-wrapper], [include GNU patch wrapper]), [
|
||||
if test "$withval" = yes ; then
|
||||
PATCH_WRAPPER=$withval
|
||||
fi
|
||||
])
|
||||
AC_SUBST(PATCH_WRAPPER)
|
||||
|
||||
if test $USE_NLS = no ; then
|
||||
AC_MSG_NOTICE([Building without natural language support])
|
||||
fi
|
||||
AC_SUBST(USE_NLS)
|
||||
|
||||
AC_SUBST(docdir)
|
||||
|
||||
dnl Check for rpmbuild (v4) vs. rpm (v3)
|
||||
QUILT_COMPAT_PROG_PATH_OPT(RPMBUILD, rpmbuild, [rpmbuild rpm])
|
||||
|
||||
QUILT_COMPAT_PROG_PATH_OPT(MD5SUM, md5sum, [gmd5sum md5sum])
|
||||
|
||||
QUILT_COMPAT_PROG_PATH_OPT(P7ZIP, 7z, [7zr 7za 7z])
|
||||
|
||||
AC_SUBST(COMPAT_SYMLINKS)
|
||||
AC_SUBST(COMPAT_PROGRAMS)
|
||||
|
||||
AC_CONFIG_FILES(Makefile)
|
||||
AC_OUTPUT
|
||||
|
||||
dnl Print results
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([$PACKAGE_NAME version $PACKAGE_VERSION configured.])
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([Using '$prefix' for installation prefix.])
|
||||
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([Report bugs to $PACKAGE_BUGREPORT])
|
|
@ -0,0 +1,27 @@
|
|||
all : quilt.pdf quilt-rus.pdf
|
||||
|
||||
quilt.ps : quilt.dvi
|
||||
dvips -t letter -o $@ $<
|
||||
|
||||
quilt.pdf: main.tex
|
||||
pdflatex --jobname=quilt -t letter $<
|
||||
|
||||
quilt.dvi : main.tex
|
||||
latex $< && \
|
||||
mv main.dvi $@
|
||||
|
||||
quilt-rus.ps : quilt-rus.dvi
|
||||
dvips -t letter -o $@ $<
|
||||
|
||||
quilt-rus.pdf: main-rus.tex
|
||||
pdflatex --jobname=quilt-rus -t letter $<
|
||||
|
||||
quilt-rus.dvi : main-rus.tex
|
||||
latex $< && \
|
||||
mv main-rus.dvi $@
|
||||
|
||||
clean:
|
||||
rm -f {main,quilt}.{dvi,log,aux} {main,quilt}-rus.{dvi,log,aux}
|
||||
|
||||
distclean: clean
|
||||
rm -f quilt.{ps,pdf,dvi} quilt-rus.{ps,pdf,dvi}
|
|
@ -0,0 +1,19 @@
|
|||
Introduction
|
||||
============
|
||||
|
||||
quilt-el minor mode (lib/quilt.el) is toggled by `M-x quilt-mode'. It
|
||||
provides the following features:
|
||||
|
||||
- You can issue many quilt sub-commands by shortcut keys. By using
|
||||
these keys, quilt-el can also detect moving the patch stack and
|
||||
can refresh corresponding buffers automatically.
|
||||
|
||||
- If a buffer is associated with the file which is not included in
|
||||
the topmost patch, the buffer becomes read-only. So you can avoid
|
||||
editing wrong files accidentally.
|
||||
|
||||
- After quilt-el is once enabled, all files which you open are checked
|
||||
whether it is in a quilt hierarchy or not. If so, corresponding buffer
|
||||
becomes quilt-mode automatically.
|
||||
|
||||
-- Satoru Takeuchi <nqm08501@nifty.com>, Sun, 14 Jan 2007 23:57:29 +0900
|
|
@ -0,0 +1,82 @@
|
|||
QUILT MAIL COMMAND
|
||||
==================
|
||||
|
||||
The mail command starts up the system editor ($EDITOR, or vi if $EDITOR
|
||||
is undefined) with an template in Internet Message Format (RFC 2822).
|
||||
This template is used to generate an introduction, as well as one
|
||||
message for each patch in the selected range of the series file. The
|
||||
template is used as follows: The headers are used in each message
|
||||
generated, and modified as required. The template body is used only for
|
||||
the introduction.
|
||||
|
||||
In the template, the headers can be modified, additional headers added,
|
||||
and unneeeded headers can be removed. The template header also contains
|
||||
a special Subject-Prefix header which defines a prefix for each subject
|
||||
header. The @num@ and @total@ macros in the Subject-Prefix header are
|
||||
replaced with the patch number and the total number of patches,
|
||||
respectively. The patch number @num@ is zero-padded to the same width
|
||||
that @total@ has.
|
||||
|
||||
Each message is assigned a unique Message-Id header, and all messages
|
||||
other than the introduction are made to refer to the introduction (using
|
||||
a References header) for proper message threading in mail clients. The
|
||||
message timestamps in Date headers in each message is incremented by one
|
||||
second per message, starting with the timestamp of the introduction.
|
||||
|
||||
If a ~/.signature file exists, this file is appended to each message
|
||||
generated.
|
||||
|
||||
Recipients and headers can be added, and existing headers can be
|
||||
replaced, individually in each message based on the headers in the
|
||||
introduction. Quilt does not enforce a specific patch file format. The
|
||||
mail command has a built-in heuristic for extracting subjects from
|
||||
patches, though:
|
||||
|
||||
* if the patch starts with something that looks like a mail
|
||||
header, and there is a Subject header, use this as the subject,
|
||||
or else
|
||||
|
||||
* if the patch has DESC a line followed by an EDESC line, use
|
||||
the text in between as the subject, or else
|
||||
|
||||
* if the first paragraph is short enough to serve as a subject
|
||||
(150 characters or less), use the first paragraph as the
|
||||
subject.
|
||||
|
||||
All bracketed fields and Fwd:, Fw:, Re:, Aw: are stripped from subject
|
||||
headers as well.
|
||||
|
||||
If no subject can be extracted from a patch, or there are duplicate
|
||||
subjects, the mail command will print an error message and abort.
|
||||
|
||||
In case a patch header contains a line starting with `Cc:', `Acked-by:',
|
||||
or `Signed-off-by:', the email address specified is added to the
|
||||
CC header for this patch. If a patch header contains a line starting
|
||||
with `To:', the email address specified is added to To header for this
|
||||
patch.
|
||||
|
||||
If the user specified in `To:', `Cc:', `Acked-by:', or `Signed-off-by:'
|
||||
equals the current user's name ($LOGNAME or $(whoami) if LOGNAME is
|
||||
undefined), this does not add a recipient.
|
||||
|
||||
Each recipient will occur in the resulting message only once. Duplicates
|
||||
are filtered out. This happens as the headers are read, so the relative
|
||||
order of the To, Cc, and Bcc headers should not be changed.
|
||||
|
||||
Recipients are checked for RFC 2822 conformance (at least that is the
|
||||
intention; actually the checks are not perfect). This means that special
|
||||
characters must be quoted, and 8-bit characters must be encoded. In
|
||||
practice it probably makes little sense to use anything fancy right now;
|
||||
this area still needs some work. Character set recognition and proper
|
||||
qualifying is also still missing.
|
||||
|
||||
The heuristic can be overridden by defining a quilt_mail_patch_filter
|
||||
function in ~/.quiltrc or /etc/quilt.quiltrc. This function is passed
|
||||
the patch name as argument (without the $QUILT_PATCHES prefix). It
|
||||
shall read the patch from standard input, and write a RFC 2822 message
|
||||
header and the patch to standard output. Headers of the form
|
||||
``Recipient-$X: ...'' denote recipients to be added to the $X header
|
||||
(for example, ``Recipient-Cc: agruen@suse.de''). Headers of the form
|
||||
``Replace-$X: ...'' specify that header $X is to be replaced by this
|
||||
header (for eaxmple, ``Replace-Subject: Patch description''). All other
|
||||
headers are appended to the existing headers.
|
|
@ -0,0 +1,117 @@
|
|||
The scripts in this package simplify working with a series of patches.
|
||||
The usual tasks like applying, refreshing and reversing are supported.
|
||||
|
||||
Please see the paper "How To Survive With Many Patches /or/
|
||||
Introduction to Quilt" for an introduction.
|
||||
|
||||
|
||||
Command reference
|
||||
=================
|
||||
@REFERENCE@
|
||||
|
||||
|
||||
Typical Usages: New patches; Importing patches; Patch management
|
||||
======================================================================
|
||||
|
||||
Add new patches:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
1. create a new patch: quilt new {patchname, e.g., sysctl_fix.patch}
|
||||
|
||||
2. add/edit file(s): quilt edit filepath
|
||||
or:
|
||||
2a. add file(s) to patch: quilt add {filepath}
|
||||
2b. manual edit file(s) use your $editor
|
||||
|
||||
3. update the patch: quilt refresh
|
||||
3b. list the patch description: quilt header [patch]
|
||||
3c. update the patch description: quilt header -e [patch]
|
||||
|
||||
4. list files in the patch: quilt files
|
||||
|
||||
5. show current patch contents: quilt diff
|
||||
|
||||
6. apply current, ready for next: quilt push
|
||||
|
||||
7. remove file(s) from patch: quilt remove {filepath}
|
||||
|
||||
Importing patches:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
1. import a patch: quilt import patchfile
|
||||
|
||||
2. apply it: quilt push
|
||||
|
||||
3. update the patch: quilt refresh
|
||||
3b. list the patch description: quilt header [patch]
|
||||
3c. update the patch description: quilt header -e [patch]
|
||||
|
||||
4. list files in the patch: quilt files
|
||||
|
||||
5. show current patch contents: quilt diff
|
||||
|
||||
Import/Apply a series file + patches to a tree:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
1. cp(1) the patches directory ('series' file + all patch files) to
|
||||
the expected patches location (as specified in your .quiltrc file)
|
||||
|
||||
2. apply all of series: quilt push -a
|
||||
|
||||
Other patch management:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
1. remove files from a patch: quilt remove {filepath}
|
||||
|
||||
2. remove unapplied patch: quilt delete {patchname}
|
||||
|
||||
3. list all patch names: quilt series
|
||||
|
||||
4. list all applied/unapplied: quilt applied | unapplied
|
||||
|
||||
5. list top/previous/next patch name: quilt top | previous | next
|
||||
|
||||
6. list patches modifying file: quilt patches {filepath}
|
||||
|
||||
7. rename a patch: quilt rename {patchname}
|
||||
|
||||
8. duplicate a patch: quilt fork {patchname}
|
||||
|
||||
9. prepare or send mails: quilt mail ...
|
||||
|
||||
10. search in source files: quilt grep ...
|
||||
|
||||
11. create snapshot: quilt snapshot
|
||||
|
||||
12. init from RPM spec or series file: quilt setup
|
||||
|
||||
13. distribution of patches: quilt diff --combine
|
||||
and distribute the combined diff file,
|
||||
or distribute the patches/ directory content
|
||||
|
||||
|
||||
Helper files/scripts
|
||||
====================
|
||||
|
||||
backup-files
|
||||
A simple utility that creates / restores / removes
|
||||
backup files.
|
||||
|
||||
dependency-graph
|
||||
A utility to compute patch dependencies from the QUILT_PC
|
||||
metadata.
|
||||
|
||||
edmail
|
||||
A utility to manipulate the headers of an Internet mail message.
|
||||
|
||||
guards
|
||||
Convert a series file with conditional statements into a series
|
||||
file as expected; see the guards(1) manual page.
|
||||
|
||||
inspect
|
||||
A script to create a series file from an rpm spec file (including
|
||||
a list of tar files).
|
||||
|
||||
patchfns
|
||||
utilfns
|
||||
Collections of functions.
|
||||
|
||||
remove-trailing-ws
|
||||
A utility to report trailing whitespace, and remove trailing
|
||||
whitespace from files.
|
|
@ -0,0 +1,794 @@
|
|||
%\documentclass[a4paper]{article}
|
||||
\documentclass{article}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{subfigure}
|
||||
\usepackage{fancyvrb}
|
||||
%\usepackage{times}
|
||||
\usepackage[latin1]{inputenc}
|
||||
\usepackage{url}
|
||||
|
||||
%\usepackage{lineno}
|
||||
%\linenumbers
|
||||
%\renewcommand{\baselinestretch}{1.5}
|
||||
|
||||
% Change url font to textsf (and check what breaks in PDF/HTML/...)
|
||||
|
||||
\fvset{xleftmargin=3em,commandchars=\\\{\}}
|
||||
|
||||
\newcommand{\quilt}[1]{\textsf{quilt #1}}
|
||||
\newcommand{\sh}[1]{\textsl{#1}}
|
||||
\newcommand{\prog}[1]{\textit{#1}}
|
||||
|
||||
\title{How To Survive With Many Patches\\
|
||||
{\Large or}\\
|
||||
Introduction to Quilt\footnote{
|
||||
Quilt is a GPL licensed project hosted on GNU Savannah. Some ideas
|
||||
for this document were taken from \textit{docco.txt} in
|
||||
Andrew Morton's patch management scripts package~\cite{akpm02}.
|
||||
The text in the examples was taken from \textit{A Midsummer
|
||||
Night's Dream} by William Shakespeare.
|
||||
}}
|
||||
\author{Andreas Grünbacher, SuSE Labs \\
|
||||
%\em{SUSE Labs, SUSE LINUX AG} \\
|
||||
{\normalsize agruen@suse.de}
|
||||
}
|
||||
%\date{}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
|
||||
\thispagestyle{empty}
|
||||
|
||||
\begin{abstract}
|
||||
After looking at different strategies for dealing with software packages
|
||||
that consist of a base software package on top of which a number of
|
||||
patches are applied, this document introduces the script collection
|
||||
\textit{quilt,} which was specifically written to help deal with
|
||||
multiple patches and common patch management tasks.
|
||||
\end{abstract}
|
||||
|
||||
\section{Introduction}
|
||||
|
||||
% Prerequisites: UNIX, patches, using GNU diff and GNU patch.
|
||||
% Why patches in the first place?
|
||||
|
||||
In the old days, vendor specific software packages in the open source
|
||||
world consisted of a file with the official version of the software,
|
||||
plus a patch file with the additional changes needed to adapt the
|
||||
package to specific needs. The official software package was usually
|
||||
contained in a \textsf{package.tar.gz} file, while the patch was found
|
||||
in \textsf{package.diff.} Instead of modifying the official
|
||||
package sources, local changes were kept separate. When building the
|
||||
software package, the tar archive was extracted, and the patch was
|
||||
applied.
|
||||
|
||||
Over time, the patch file ended up containing several independent
|
||||
changes. Of those changes, some were integrated into later versions of
|
||||
the software, while other add-ons or adaptations remain external. Whenever
|
||||
a new official version was integrated, the patch needed to be revised:
|
||||
changes that were already integrated in the official version needed to
|
||||
be split from changes that were not.
|
||||
|
||||
A big improvement was to allow multiple patches in a vendor package,
|
||||
and this is also how patches are handled today: a number of
|
||||
patches is applied on top of each other. Each patch usually consists of
|
||||
a logically related set of changes. When some patches get integrated
|
||||
upstream, those patches can simply be removed from the vendor specific
|
||||
package. The remaining patches frequently continue to apply cleanly.
|
||||
Some of the remaining patches may have to be maintained across a range
|
||||
of upstream versions because they are too specific for the upstream
|
||||
software package, etc. These patches often get out of sync, and need to
|
||||
be updated.
|
||||
|
||||
For the majority of packages, the number of patches remains relatively
|
||||
low, so maintaining those patches without tools is feasible. A number of
|
||||
packages have dozens of patches, however. At the extreme end is the
|
||||
kernel source package (kernel-source-\textit{2.4.x}) with more than
|
||||
1\,000 patches. The difficulty of managing such a vast number of
|
||||
patches without tools can easily be imagined.
|
||||
|
||||
This document discusses different strategies of dealing with large sets
|
||||
of patches. Patches are usually generated by the \prog{diff} utility,
|
||||
and applied with the \prog{patch} utility. Different patch file formats are
|
||||
defined as part of the specification of the \prog{diff} utility in
|
||||
POSIX.1~\cite{posix-2001-diff}. The most commonly used format today,
|
||||
\textit{unified diff,} is not covered by POSIX.1, however. A good
|
||||
description of patch file formats is found in the \prog{GNU diff} info
|
||||
pages~\cite{info-diff}.
|
||||
|
||||
The question we try to answer in this document is how patches are best kept
|
||||
up to date in face of changes both to the upstream software package, and
|
||||
to the patches that precede them. After looking at some existing
|
||||
approaches, a collection of patch management scripts known as
|
||||
\textit{quilt} is described~\cite{quilt}, starting with basic concepts,
|
||||
and progressing towards more advanced tasks.
|
||||
|
||||
% - quilt
|
||||
% (wet people's mouths about the features)
|
||||
|
||||
% How exactly does this relate to many patches?
|
||||
|
||||
\section{Existing Approaches}
|
||||
\label{sec:existing}
|
||||
|
||||
The minimal solution for updating a patch is to apply all preceding
|
||||
patches.
|
||||
%\footnote{ In the kernel CVS, we have a a script called
|
||||
%\textit{sequence-patch} that simply applies all patches up to a
|
||||
%specified patch. }
|
||||
Then, a copy of the resulting source tree is created.\footnote{
|
||||
The two copies can also be hard-linked with each other, which
|
||||
significantly speeds up both the copying and the final
|
||||
``diffing''. If hard links are used, care must be taken that the
|
||||
tools used to update one copy of the source tree will create new
|
||||
files, and will not overwrite shared files. Editors like
|
||||
\prog{emacs} and \prog{vi}, and utilities like \prog{patch},
|
||||
support this.
|
||||
} The next patch in the sequence of patches (which is the one to be
|
||||
updated) is applied to only one of these source trees. This source tree
|
||||
is then modified until it reflects the desired result. The new version of
|
||||
the patch is distilled by comparing the two source trees with
|
||||
\prog{diff}, and writing the result into a file.
|
||||
|
||||
This simple approach is rather error prone, and leaves much to be
|
||||
desired. Several people have independently written scripts that
|
||||
automate and improve upon this process.
|
||||
|
||||
A version control system like \prog{CVS} or \prog{RCS} may be a
|
||||
reasonable alternative in some cases. The version control system is
|
||||
brought in the state of the working tree with a number of patches
|
||||
applied. Then the next patch is applied. After the working tree is
|
||||
updated as required, a diff between the repository copy and the working
|
||||
tree is created (with \prog{cvs diff}, etc). In this scenario the
|
||||
version control system is used to store and compare against the old
|
||||
repository version only. The full version control overhead is paid,
|
||||
while only a small fraction of its functionality is needed. Switching
|
||||
between different patches is not simplified.
|
||||
|
||||
% TODO: Mention some approaches here; RCS and CVS ...
|
||||
|
||||
One of the most advanced approaches is Andrew Morton's patch management
|
||||
scripts~\cite{akpm02}. The author of this document found that none of
|
||||
the available solutions would scale up to the specific requirements of
|
||||
the SUSE kernel-source package, and started to improve Andrew Morton's
|
||||
scripts until they became what they are now~\cite{quilt}.
|
||||
|
||||
% - Re and Rd scripts (Czech scripts using RCS, replaces the
|
||||
% now-obsolete rpmpatch that supports one .dif only).
|
||||
% - Werner's scripts
|
||||
|
||||
% What couldn't be done:
|
||||
% - Patches in sub-directories
|
||||
% - Many patches
|
||||
% - Retaining documentation (akpm's scripts do part of this)
|
||||
|
||||
% Actually merging rejects is not handled; use tools like:
|
||||
% - wiggle
|
||||
% - Other merge tools (e.g., graphical ones)
|
||||
|
||||
\section{Quilt: Basic Concepts and Operation}
|
||||
\label{sec:basic}
|
||||
|
||||
The remainder of this document discusses the script collection
|
||||
\textit{quilt.}
|
||||
|
||||
With quilt, all work occurs within a single directory tree. Since
|
||||
version 0.30, commands can be invoked from anywhere within the source
|
||||
tree (the directory tree is scanned upwards until either the
|
||||
\textsf{.pc} or the \textsf{patches} directory is found).
|
||||
Commands are of the form ``\quilt{cmd}'', similar to CVS
|
||||
commands. They can be abbreviated as long as the specified part of the
|
||||
command is unique. All commands print some help text with ``\quilt{cmd
|
||||
-h}''.
|
||||
|
||||
Quilt manages a stack of patches. Patches are applied incrementally on
|
||||
top of the base tree plus all preceding patches. They can be pushed
|
||||
on top of the stack (\quilt{push}), and popped off the stack
|
||||
(\quilt{pop}). Commands are available for querying the contents of the
|
||||
series file (\quilt{series}, see below), the contents of the stack
|
||||
(\quilt{applied}, \quilt{previous}, \quilt{top}), and the patches that
|
||||
are not applied at a particular moment (\quilt{next}, \quilt{unapplied}).
|
||||
By default, most commands apply to the topmost patch on the stack.
|
||||
|
||||
When files in the working directory are changed, those changes become
|
||||
part of the working state of the topmost patch, provided that those
|
||||
files are part of the patch. Files that are not part of a patch must be
|
||||
added before modifying them so that quilt is aware of the original
|
||||
versions of the files. The \quilt{refresh} command regenerates a patch.
|
||||
After the refresh, the patch and the working state are the same.
|
||||
|
||||
Patch files are located in the \textsf{patches} sub-directory of the
|
||||
source tree (see Figure~\ref{fig:dir-layout}). The \textsf{QUILT\_PATCHES}
|
||||
environment variable can be used to override this location and quilt
|
||||
will remember this location by storing its value in the
|
||||
\textsf{.pc/.quilt\_patches} file. The \textsf{patches} directory may contain
|
||||
sub-directories, which is useful for grouping related patches together.
|
||||
\textsf{patches} may also be a symbolic link instead of a directory.
|
||||
|
||||
A file called \textsf{series} contains a list of patch file names that
|
||||
defines the order in which patches are applied. Unless there are means
|
||||
by which series files can be generated automatically (see
|
||||
Section~\ref{sec:rpm}), they are usually provided along with a set of
|
||||
patches. In \textsf{series}, each patch file name is on a separate line.
|
||||
Patch files are identified by pathnames that are relative to the
|
||||
\textsf{patches} directory; patches may be in sub-directories below the
|
||||
\textsf{patches} directory. Lines in the series file that start with a
|
||||
hash character (\texttt{\#}) are ignored. When quilt adds, removes, or
|
||||
renames patches, it automatically updates the series file. Users of
|
||||
quilt can modify series files while some patches are applied, as long as
|
||||
the applied patches remain in their original order.
|
||||
|
||||
Different series files can be used to assemble patches in different ways,
|
||||
corresponding for example to different development branches.
|
||||
|
||||
\begin{figure}
|
||||
\begin{center}
|
||||
\begin{minipage}{6cm}
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
work/ -+- ...
|
||||
|- patches/ -+- series
|
||||
| |- patch2.diff
|
||||
| |- patch1.diff
|
||||
| +- ...
|
||||
+- .pc/ -+- applied-patches
|
||||
|- patch1.diff/ -+- ...
|
||||
|- patch2.diff/ -+- ...
|
||||
+- ...
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
\end{minipage}
|
||||
\caption{Quilt files in a source tree.}
|
||||
\label{fig:dir-layout}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
Before a patch is applied (or ``pushed on the stack''), copies of all
|
||||
files the patch modifies are saved to the \textsf{.pc/\textit{patch}}
|
||||
directory.\footnote{
|
||||
The patch name with extensions stripped is used as the name of
|
||||
the sub-directory below the \textsf{.pc} directory. \prog{GNU patch},
|
||||
which quilt uses internally to apply patches, creates backup
|
||||
files and applies the patch in one step.
|
||||
} The patch is added to the list of
|
||||
currently applied patches (\textsf{.pc/applied-patches}). Later when a patch is regenerated
|
||||
(\quilt{refresh}), the backup copies in \textsf{.pc/\textit{patch}} are
|
||||
compared with the current versions of the files in the source tree
|
||||
using \prog{GNU diff}.
|
||||
|
||||
Documentation related to a patch can be put at the beginning of a patch
|
||||
file. Quilt is careful to preserve all text that precedes the actual
|
||||
patch when doing a refresh.
|
||||
|
||||
The series file is looked up in the root of the source tree, in the
|
||||
patches directory, and in the \textsf{.pc} directory. The first series
|
||||
file that is found is used. This may also be a symbolic link, or a file
|
||||
with multiple hard links. Usually, only one series file is used for a
|
||||
set of patches, so the \textsf{patches} sub-directory is a convenient
|
||||
location.
|
||||
|
||||
While patches are applied to the source tree, the \textsf{.pc} directory
|
||||
is essential for many operations, including taking patches off the stack
|
||||
(\quilt{pop}), and refreshing patches (\quilt{refresh}). Files in the
|
||||
\textsf{.pc} directory are automatically removed when they are no longer
|
||||
needed, so usually there is no need to clean up manually. The
|
||||
\textsf{QUILT\_PC} environment variable can be used to override the
|
||||
location of the \textsf{.pc} directory.
|
||||
|
||||
\section{An Example}
|
||||
|
||||
This section demonstrates how new patches are created and updated, and
|
||||
how conflicts are resolved. Let's start with a short text file:
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
Yet mark'd I where the bolt of Cupid fell:
|
||||
It fell upon a little western flower,
|
||||
Before milk-white, now purple with love's wound,
|
||||
And girls call it love-in-idleness.
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
New patches are created with \quilt{new}. A new patch automatically
|
||||
becomes the topmost patch on the stack. Files must be added
|
||||
with \quilt{add} before they are modified. Note that this is slightly
|
||||
different from the CVS style of interaction: with CVS, files are in the
|
||||
repository, and adding them before committing (but after modifying them)
|
||||
is enough. Files are usually added and immediately modified. The
|
||||
command \quilt{edit} adds a file and loads it into the default editor.
|
||||
(The environment variable \textsf{EDITOR} specifies which is the default
|
||||
editor. If \textsf{EDITOR} is not set, \prog{vi} is used.)
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
\sh{$ quilt new flower.diff}
|
||||
Patch flower.diff is now on top
|
||||
\sh{$ quilt edit Oberon.txt}
|
||||
File Oberon.txt added to patch flower.diff
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
Let's assume that the following lines were added to \textsf{Oberon.txt}
|
||||
during editing:
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
The juice of it on sleeping eye-lids laid
|
||||
Will make a man or woman madly dote
|
||||
Upon the next live creature that it sees.
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
The actual patch file is created (and later updated) with
|
||||
\quilt{refresh}. The result is as follows:\footnote{
|
||||
Timestamps in patches are omitted from the output in the examples.
|
||||
}
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
\sh{$ quilt refresh}
|
||||
\sh{$ cat patches/flower.diff}
|
||||
Index: example1/Oberon.txt
|
||||
===================================================================
|
||||
--- example1.orig/Oberon.txt
|
||||
+++ example1/Oberon.txt
|
||||
@@ -2,3 +2,6 @@
|
||||
It fell upon a little western flower,
|
||||
Before milk-white, now purple with love's wound,
|
||||
And girls call it love-in-idleness.
|
||||
+The juice of it on sleeping eye-lids laid
|
||||
+Will make a man or woman madly dote
|
||||
+Upon the next live creature that it sees.
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
Now let's assume that a line in the text has been overlooked, and must
|
||||
be inserted. The file \textsf{Oberon.txt} is already part of the patch
|
||||
\textsf{flower.diff}, so it can immediately be modified in an editor.
|
||||
Alternatively, \quilt{edit} can be used; it simply opens up the default
|
||||
editor if the file is already part of the patch.
|
||||
|
||||
After the line is added, we use \quilt{diff -z} to see a diff of the
|
||||
changes we made:
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
\sh{$ quilt diff -z}
|
||||
Index: example1/Oberon.txt
|
||||
===================================================================
|
||||
--- example1.orig/Oberon.txt
|
||||
+++ example1/Oberon.txt
|
||||
@@ -2,6 +2,7 @@
|
||||
It fell upon a little western flower,
|
||||
Before milk-white, now purple with love's wound,
|
||||
And girls call it love-in-idleness.
|
||||
+Fetch me that flower; the herb I shew'd thee once:
|
||||
The juice of it on sleeping eye-lids laid
|
||||
Will make a man or woman madly dote
|
||||
Upon the next live creature that it sees.
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
A diff of the topmost patch can be generated with \quilt{diff} without
|
||||
arguments. This does not modify the actual patch file. The changes are
|
||||
only added to the patch file by updating it with \quilt{refresh}. Then
|
||||
we remove the patch from the stack with \quilt{pop}:
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
\sh{$ quilt refresh}
|
||||
Refreshed patch flower.diff
|
||||
\sh{$ quilt pop}
|
||||
Removing flower.diff
|
||||
Restoring Oberon.txt
|
||||
|
||||
No patches applied
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
Next, let's assume that \textsf{Oberon.txt} was modified ``upstream'':
|
||||
The word \textit{girl} did not fit very well, and so it was replaced
|
||||
with \textit{maiden.} \textsf{Oberon.txt} now contains:
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
Yet mark'd I where the bolt of Cupid fell:
|
||||
It fell upon a little western flower,
|
||||
Before milk-white, now purple with love's wound,
|
||||
And maidens call it love-in-idleness.
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
This causes \textsf{flower.diff} to no longer apply cleanly. When we
|
||||
try to push \textsf{flower.diff} on the stack with \quilt{push}, we get
|
||||
the following result:
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
\sh{$ quilt push}
|
||||
Applying flower.diff
|
||||
patching file Oberon.txt
|
||||
Hunk #1 FAILED at 2.
|
||||
1 out of 1 hunk FAILED -- rejects in file Oberon.txt
|
||||
Patch flower.diff does not apply (enforce with -f)
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
Quilt does not automatically apply patches that have rejects. Patches
|
||||
that do not apply cleanly can be ``force-applied'' with \quilt{push -f},
|
||||
which leaves reject files in the source tree for each file that has
|
||||
conflicts. Those conflicts must be resolved manually, after which the
|
||||
patch can be updated (\quilt{refresh}). Quilt remembers when a patch has
|
||||
been force-applied. It refuses to push further patches on top of such
|
||||
patches, and it does not remove them from the stack. A force-applied
|
||||
patch may be ``force-removed'' from the stack with \quilt{pop -f},
|
||||
however. Here is what happens when force-applying \textsf{flower.diff}:
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
\sh{$ quilt push -f}
|
||||
Applying flower.diff
|
||||
patching file Oberon.txt
|
||||
Hunk #1 FAILED at 2.
|
||||
1 out of 1 hunk FAILED -- saving rejects to file Oberon.txt.rej
|
||||
Applied flower.diff (forced; needs refresh)
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
After re-adding the lines of verse from \textsf{flower.diff} to
|
||||
\textsf{Oberon.txt}, we update the patch with \quilt{refresh}.
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
\sh{$ quilt edit Oberon.txt}
|
||||
\sh{$ quilt refresh}
|
||||
Refreshed patch flower.diff
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
Our final version of \textsf{Oberon.txt} contains:
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
Yet mark'd I where the bolt of Cupid fell:
|
||||
It fell upon a little western flower,
|
||||
Before milk-white, now purple with love's wound,
|
||||
And maidens call it love-in-idleness.
|
||||
Fetch me that flower; the herb I shew'd thee once:
|
||||
The juice of it on sleeping eye-lids laid
|
||||
Will make a man or woman madly dote
|
||||
Upon the next live creature that it sees.
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
\section{Further Commands and Concepts}
|
||||
|
||||
This section introduces a few more basic commands, and then describes
|
||||
additional concepts that may not be immediately obvious. We do not
|
||||
describe all of the features of quilt here since many quilt commands are
|
||||
quite intuitive; furthermore, help text that describes the available
|
||||
options for each command is available via \quilt{\textit{cmd} -h}.
|
||||
|
||||
The \quilt{top} command shows the name of the topmost patch. The
|
||||
\quilt{files} command shows which files a patch contains. The
|
||||
\quilt{patches} command shows which patches modify a specified file.
|
||||
With our previous example, we get the following results:
|
||||
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
\sh{$ quilt top}
|
||||
flower.diff
|
||||
\sh{$ quilt files}
|
||||
Oberon.txt
|
||||
\sh{$ quilt patches Oberon.txt}
|
||||
flower.diff
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
|
||||
The \quilt{push} and \quilt{pop} commands optionally take a number or
|
||||
a patch name as argument. If a number is given, the specified number of
|
||||
patches is added (\quilt{push}) or removed (\quilt{pop}). If a patch
|
||||
name is given, patches are added (\quilt{push}) or removed (\quilt{pop})
|
||||
until the specified patch is on top of the stack. With the \textsf{-a}
|
||||
option, all patches in the series file are added (\quilt{push}), or all
|
||||
applied patches are removed from the stack (\quilt{pop}).
|
||||
|
||||
\subsection{Patch Strip Levels}
|
||||
|
||||
Quilt assumes that patches are applied with a strip level of one (the
|
||||
\textsf{-p1} option of \prog{GNU patch}) by default: the topmost directory
|
||||
level of file names in patches is stripped off. Quilt remembers the
|
||||
strip level of each patch in the \textsf{series} file. When generating a
|
||||
diff (\quilt{diff}) or updating a patch (\quilt{refresh}), a different
|
||||
strip level can be specified, and the series file will be updated
|
||||
accordingly. Quilt can apply patches with an arbitrary strip level, and
|
||||
produces patches with a strip level of zero or one. With a strip level
|
||||
of one, the name of the directory that contains the working tree is used
|
||||
as the additional path component. (So in our example,
|
||||
\textsf{Oberon.txt} is contained in directory \textsf{example1}.)
|
||||
|
||||
\subsection{Importing Patches}
|
||||
|
||||
The \quilt{import} command automates the importing of patches into the
|
||||
quilt system. The command copies a patch into the \textsf{patches}
|
||||
directory and adds it to the \textsf{series} file. For patch strip
|
||||
levels other than one, the strip level is added after the patch file
|
||||
name. (An entry for \textsf{a.diff} with strip level zero might read
|
||||
``{\small \verb|a.diff -p0|}''.)
|
||||
|
||||
Another common operation is to incorporate a fix or similar that comes
|
||||
as a patch into the topmost patch. This can be done by hand by first
|
||||
adding all the files contained in the additional patch to the topmost
|
||||
patch with \quilt{add},\footnote{
|
||||
The \prog{lsdiff} utility, which is part of the \textit{patchutils}
|
||||
package, generates a list of files affected by a patch.
|
||||
} and then applying the patch to the working tree. The \quilt{fold}
|
||||
command combines these steps.
|
||||
|
||||
\subsection{Sharing patches with others}
|
||||
|
||||
For sharing a set of patches with someone else, the series file which
|
||||
contains the list of patches and how they are applied, and the patches
|
||||
themselves are all that's needed. The \textsl{.pc} directory only
|
||||
contains quilt's working state, and should not be distributed. Make sure
|
||||
that all the patches are up-to-date, and refresh patches when
|
||||
necessary. The \textsf{--combine} option of \quilt{diff} can be used for
|
||||
generating a single patch out of all the patches in the series file.
|
||||
|
||||
\subsection{Merging with upstream}
|
||||
|
||||
The concept of merging your patches with upstream is identical to applying
|
||||
your patches on a more recent version of the software.
|
||||
|
||||
Before merging, make sure to pop all your patches using \quilt{pop -a}.
|
||||
Then, update your codebase. Finally, remove obsoleted patches
|
||||
from the series file and \quilt{push} the remaining ones, resolve
|
||||
conflicts and refresh patches as needed.
|
||||
|
||||
\subsection{Forking}
|
||||
\label{sec:forking}
|
||||
|
||||
There are situations in which updating a patch in-place is not ideal:
|
||||
the same patch may be used in more than one series file. It may also
|
||||
serve as convenient documentation to retain old versions of patches, and
|
||||
create new ones under different names. This can be done by hand by
|
||||
creating a copy of a patch (which must not be applied), and updating the
|
||||
patch name in the series file.
|
||||
|
||||
The \quilt{fork} command simplifies this: it creates a copy of the
|
||||
topmost patch in the series, and updates the series file. Unless a patch
|
||||
name is explicitly specified, \quilt{fork} will generate the following
|
||||
sequence of patch names: \textsf{patch.diff}, \textsf{patch-2.diff},
|
||||
\textsf{patch-3.diff},\dots
|
||||
|
||||
\subsection{Dependencies}
|
||||
\label{sec:dependencies}
|
||||
|
||||
When the number of patches in a project grows large, it becomes
|
||||
increasingly difficult to find the right place for adding a new patch in
|
||||
the patch series. At a certain point, patches will get inserted at the
|
||||
end of the patch series, because finding the right place has become too
|
||||
complicated. In the long run, a mess accumulates.
|
||||
|
||||
To help avoid this by keeping the big picture, the \quilt{graph} command
|
||||
generates \textit{dot} graphs showing the dependencies between
|
||||
patches.\footnote{
|
||||
The \quilt{graph} command computes dependencies based on
|
||||
which patches modify which files, and optionally will also
|
||||
check for overlapping changes in the files. While the former
|
||||
approach will often result in false positives, the latter
|
||||
approach may result in false negatives (that is, \quilt{graph}
|
||||
may overlook dependencies).
|
||||
} The output of this command can be visualized using the tools from AT\&T
|
||||
Research's Graph Visualization Project (GraphViz,
|
||||
\url{http://www.graphviz.org/}). The \quilt{graph} command supports
|
||||
different kinds of graphs.
|
||||
|
||||
\subsection{Advanced Diffing}
|
||||
|
||||
Quilt allows us to diff and refresh patches that are applied, but are not
|
||||
on top of the stack (\quilt{diff -P \textit{patch}} and \quilt{refresh
|
||||
\textit{patch}}). This is useful in several cases, for example, when
|
||||
%\begin{itemize}
|
||||
%
|
||||
%\item When the topmost patch has been modified but the changes are not
|
||||
%yet completed, refreshing the patch would leave a patch file that is in
|
||||
%an inconsistent state. Without that, the patch cannot be removed from
|
||||
%the stack, or else the changes would be lost.
|
||||
%
|
||||
%\item Popping patches and then pushing them again results in modified
|
||||
%time stamps. This may trigger time consuming recompiles.
|
||||
%
|
||||
%\item It is simply convenient to be able to fix small bugs in patches
|
||||
%further down in the stack without much ado.
|
||||
%
|
||||
%\end{itemize}
|
||||
%
|
||||
patches applied higher on the stack modify some of the files that this
|
||||
patch modifies. We can picture this as a shadow which the patches higher
|
||||
on the stack throw on the files they modify. When refreshing a patch,
|
||||
changes to files that are not shadowed (and thus were last modified by
|
||||
the patch that is being refreshed) are taken into account. The
|
||||
modifications that the patch contains for shadowed files will not be
|
||||
updated.
|
||||
|
||||
The \quilt{diff} command allows us to merge multiple patches into one by
|
||||
optionally specifying the range of patches to include (see \quilt{diff
|
||||
-h}). The combined patch will only modify each file contained in these
|
||||
patches once. The result of applying the combined patch is the same as
|
||||
applying all the patches in the specified range in sequence.
|
||||
|
||||
Sometimes it is convenient to use a tool other than \prog{GNU diff} for
|
||||
comparing files (for example, a graphical diff replacement like
|
||||
\prog{tkdiff}). Quilt will not use tools other than \prog{GNU diff} when
|
||||
updating patches (\quilt{refresh}), but \quilt{diff} can be passed the
|
||||
\textsf{-{}-diff=\textit{utility}} argument. With this argument, the
|
||||
specified utility is invoked for each file that is being modified with
|
||||
the original file and new file as arguments. For new files, the first
|
||||
argument will be \textsf{/dev/null}. For removed files, the second
|
||||
argument will be \textsf{/dev/null}.
|
||||
|
||||
When \quilt{diff} is passed a list of file names, the diff will be
|
||||
limited to those files. With the \textsf{-R} parameter, the original and
|
||||
new files are swapped, which results in a reverse diff.
|
||||
|
||||
Sometimes it is useful to create a diff between an arbitrary state of
|
||||
the working tree and the current version. This can be used to create a
|
||||
diff between different versions of a patch (see
|
||||
Section~\ref{sec:forking}), etc. To this end, quilt allows us to take a
|
||||
snapshot of the working directory (\quilt{snapshot}). Later, a diff
|
||||
against this state of the working tree can be created with \quilt{diff
|
||||
-{}-snapshot}.
|
||||
|
||||
Currently, only a single snapshot is supported. It is stored in the
|
||||
\textsf{.pc/.snap} directory. To recover the disk space the snapshot
|
||||
occupies, it can be removed with \quilt{snapshot -d}, or by removing the
|
||||
\textsf{.pc/.snap} directory manually.
|
||||
|
||||
\subsection{Working with RPM Packages}
|
||||
\label{sec:rpm}
|
||||
|
||||
Several Linux distributions are based on the RPM Package
|
||||
Manager~\cite{max-rpm}. RPM packages consist of a spec that defines how
|
||||
packages are built, and a number of additional files like tar archives,
|
||||
patches, etc. Most RPM packages contain an official software package
|
||||
plus a number of patches. Before these patches can be manipulated with
|
||||
quilt, a series file must be created that lists the patches along with
|
||||
their strip levels.
|
||||
|
||||
The \quilt{setup} command automates this for most RPM packages. When
|
||||
given a spec file as its argument, it performs the \textsf{\%prep}
|
||||
section of the spec file, which is supposed to extract the official
|
||||
software package, and apply the patches. In this run, quilt remembers
|
||||
the tar archives and the patches that are applied, and creates a series
|
||||
file. Based on that series file, \quilt{setup} extracts the archives,
|
||||
and copies the patches into the \textsf{patches} sub-directory. Some
|
||||
meta-information like the archive names are stored as comments in the
|
||||
series file. \quilt{setup} also accepts a series file as argument (which
|
||||
must contain some meta-information), and sets up the working tree from
|
||||
the series file in this case.
|
||||
|
||||
\section{Customizing Quilt}
|
||||
|
||||
Upon startup, quilt evaluates the file \textsf{.quiltrc} in the user's
|
||||
home directory, or the file specified with the \textsf{--quiltrc} option.
|
||||
This file is a regular bash script. Default options can be passed to
|
||||
any command by defining a \textsf{QUILT\_\textit{COMMAND}\_ARGS} variable
|
||||
(for example, \textsf{QUILT\_DIFF\_ARGS="--color=auto"} causes the output
|
||||
of \quilt{diff} to be syntax colored when writing to a terminal).
|
||||
|
||||
In addition to that, quilt recognizes the following variables:
|
||||
|
||||
\begin{description}
|
||||
|
||||
\item[\textsf{QUILT\_DIFF\_OPTS}]
|
||||
Additional options that quilt shall pass to \prog{GNU diff} when
|
||||
generating patches. A useful setting for C source code is
|
||||
``\textsf{-p}'', which causes \prog{GNU diff} to show in the resulting
|
||||
patch which function a change is in.
|
||||
|
||||
\item[\textsf{QUILT\_PATCH\_OPTS}]
|
||||
Additional options that quilt shall pass to \prog{GNU patch} when
|
||||
applying patches. (For example, recent versions of \prog{GNU patch}
|
||||
support the ``\textsf{--reject-format=unified}'' option for generating
|
||||
reject files in unified diff style (older versions used
|
||||
``\textsf{--unified-reject-files}'' for that).
|
||||
|
||||
\item[\textsf{QUILT\_PATCHES}]
|
||||
The location of patch files (see Section~\ref{sec:basic}). This setting
|
||||
defaults to ``\textsf{patches}''.
|
||||
|
||||
\end{description}
|
||||
|
||||
\section{Pitfalls and Known Problems}
|
||||
|
||||
As mentioned earlier, files must be added to patches before they can be
|
||||
modified. If this step is overlooked, one of the following problems will
|
||||
occur: If the file is included in a patch further below on the stack,
|
||||
the changes will appear in that patch when it is refreshed, and for that
|
||||
patch the \quilt{pop} command will fail before it is refreshed. If the
|
||||
file is not included in any applied patch, the original file in the
|
||||
working tree is modified.
|
||||
|
||||
Patch files may modify the same file more than once. \prog{GNU patch}
|
||||
has a bug that corrupts backup files in this case. A fix is available,
|
||||
and will be integrated in a later version of \textit{GNU patch}. The fix has
|
||||
already been integrated into the SUSE version of \textit{GNU patch}.
|
||||
|
||||
There are some packages that assume that it's a good idea to remove all
|
||||
empty files throughout a working tree, including the \textsf{.pc}
|
||||
directory. The \textit{make clean} target in the linux kernel sources
|
||||
is an example. Quilt uses zero-length files in \textsf{.pc} to mark
|
||||
files added by patches, so such packages may corrupt the \textsf{.pc}
|
||||
directory. A workaround is to create a symbolic link \textsf{.pc} in the
|
||||
working tree that points to a directory outside.
|
||||
|
||||
It may happen that the files in the \textsf{patches} directory gets out of
|
||||
sync with the working tree (e.g., they may accidentally get updated by
|
||||
CVS or similar). Files in the \textsf{.pc} directory may also become
|
||||
inconsistent, particularly if files are not added before modifying them
|
||||
(\quilt{add} / \quilt{edit}). If this happens, it may be possible to
|
||||
repair the source tree, but often the best solution is to start over
|
||||
with a scratch working directory and the \textsf{patches} sub-directory.
|
||||
There is no need to keep any files from the \textsf{.pc} directory in
|
||||
this case.
|
||||
|
||||
% - Patches cannot automatically be reverse applied (?)
|
||||
% - Does not auto-detect is a patch has been cleanly integrated
|
||||
% - Speed
|
||||
|
||||
% - Push a patch that is not in the series file (after changing
|
||||
% applied-patches to include the full patch name)?
|
||||
|
||||
% - Other back-ends (RCS etc.)
|
||||
|
||||
% - Pop and push modify file timestamps, which causes recompiles.
|
||||
% Ccache ameliorates this.
|
||||
|
||||
% - patchutils: Very useful: lsdiff, filterdiff, etc.
|
||||
|
||||
\section{Summary}
|
||||
|
||||
We have shown how the script collection \textit{quilt} solves various
|
||||
problems that occur when dealing with patches to software packages.
|
||||
Quilt is an obvious improvement over directly using the underlying tools
|
||||
(\prog{GNU patch}, \prog{GNU diff}, etc.), and offers many features not
|
||||
available with competing solutions. Join the club!
|
||||
|
||||
The quilt project homepage is
|
||||
\url{http://savannah.nongnu.org/projects/quilt/}. There is a development
|
||||
mailing list at \url{http://mail.nongnu.org/mailman/listinfo/quilt-dev}.
|
||||
Additional features that fit into quilt's mode of operation are always
|
||||
welcome, of course.
|
||||
|
||||
\begin{thebibliography}{XX}
|
||||
|
||||
\bibitem{akpm02}
|
||||
Andrew Morton: Patch Management Scripts,
|
||||
\url{http://lwn.net/Articles/13518/} and
|
||||
\url{http://userweb.kernel.org/~akpm/stuff/patch-scripts.tar.gz}.
|
||||
|
||||
\bibitem{quilt}
|
||||
Andreas Grünbacher et al.: Patchwork Quilt,
|
||||
\url{http://savannah.nongnu.org/projects/quilt}.
|
||||
|
||||
\bibitem{posix-2001-diff}
|
||||
IEEE Std. 1003.1-2001: Standard for Information Technology, Portable
|
||||
Operating System Interface (POSIX), Shell and Utilities, diff
|
||||
command, pp.~317. Online version available from the The Austin Common
|
||||
Standards Revision Group, \url{http://www.opengroup.org/austin/}.
|
||||
|
||||
\bibitem{info-diff}
|
||||
\textit{GNU diff} info pages (\textsf{info Diff}), section \textit{Output
|
||||
Formats.}
|
||||
|
||||
\bibitem{max-rpm}
|
||||
Edward C. Bailey: Maximum RPM: Taking the Red Hat Package Manager to the
|
||||
Limit, \url{http://www.rpm.org/max-rpm/}.
|
||||
|
||||
\end{thebibliography}
|
||||
|
||||
% Add a "quick-reference card"?
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,351 @@
|
|||
.\\" Created by Martin Quinson from the tex documentation
|
||||
.\\"
|
||||
.TH quilt 1 "Dec 17, 2013" "quilt"
|
||||
|
||||
.SH NAME
|
||||
quilt \\- tool to manage series of patches
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B quilt
|
||||
[-h] command [options]
|
||||
|
||||
.SH DESCRIPTION
|
||||
Quilt is a tool to manage large sets of patches by keeping track of the
|
||||
changes each patch makes. Patches can be applied, un-applied, refreshed,
|
||||
etc. The key philosophical concept is that your primary output is patches.
|
||||
|
||||
With quilt, all work occurs within a single directory tree. Commands can be
|
||||
invoked from anywhere within the source tree. They are of the form
|
||||
.B quilt cmd
|
||||
similar to CVS, svn or git commands. They can be abbreviated as long as the specified
|
||||
part of the command is unique. All commands print some help text with
|
||||
.B quilt cmd -h.
|
||||
|
||||
Quilt manages a stack of patches. Patches are applied incrementally on top
|
||||
of the base tree plus all preceding patches. They can be pushed on top of
|
||||
the stack
|
||||
.RB ( "quilt push" ),
|
||||
and popped off the stack
|
||||
.RB ( "quilt pop" ).
|
||||
Commands are available for querying the contents of the series file
|
||||
.RB ( "quilt series" ,
|
||||
see below), the contents of the stack
|
||||
.RB ( "quilt applied" , " quilt previous" , " quilt top" ),
|
||||
and the patches that are not applied at a particular moment
|
||||
.RB ( "quilt next" , " quilt unapplied" ).
|
||||
By default, most commands apply to the topmost patch on the stack.
|
||||
|
||||
Patch files are located in the
|
||||
.I patches
|
||||
sub-directory of the source tree (see EXAMPLE OF WORKING TREE below). The
|
||||
.I QUILT_PATCHES
|
||||
environment variable can be used to override this location. When not
|
||||
found in the current directory, that subdirectory is searched
|
||||
recursively in the parent directories (this is similar to the way
|
||||
.I git
|
||||
searches for its configuration files). The
|
||||
.I patches
|
||||
directory may contain sub-directories. It may also be a symbolic link
|
||||
instead of a directory.
|
||||
|
||||
A file called
|
||||
.I series
|
||||
contains a list of patch file names that defines the order in which patches
|
||||
are applied. Unless there are means by which series files can be generated
|
||||
automatically, it is usually provided along with a set of patches. In this
|
||||
file, each patch file name is on a separate line. Patch files are identified
|
||||
by path names that are relative to the
|
||||
.I patches
|
||||
directory; patches may be in sub-directories below this directory. Lines
|
||||
in the series file that start with a hash character (#) are ignored.
|
||||
You can also add a comment after each patch file name, introduced by a
|
||||
space followed by a hash character. When
|
||||
quilt adds, removes, or renames patches, it automatically updates the series
|
||||
file. Users of quilt can modify series files while some patches are
|
||||
applied, as long as the applied patches remain in their original order.
|
||||
|
||||
Different series files can be used to assemble patches in different ways,
|
||||
corresponding for example to different development branches.
|
||||
|
||||
Before a patch is applied (or ``pushed on the stack''), copies of all files
|
||||
the patch modifies are saved to the
|
||||
.RI .pc/ patch
|
||||
directory. The patch is added to the list of currently applied patches
|
||||
(.pc/applied-patches). Later when a patch is regenerated
|
||||
.RB ( "quilt refresh" ),
|
||||
the backup copies in
|
||||
.RI .pc/ patch
|
||||
are compared with the current versions of the files in the source tree using
|
||||
GNU diff.
|
||||
|
||||
Documentation related to a patch can be put at the beginning of a patch
|
||||
file. Quilt is careful to preserve all text that precedes the actual patch
|
||||
when doing a refresh. (This is limited to patches in unified format; see
|
||||
.B diff
|
||||
documentation).
|
||||
|
||||
The series file is looked up in the .pc directory, in the root of the source
|
||||
tree, and in the patches directory. The first series file that is found is
|
||||
used. This may also be a symbolic link, or a file with multiple hard links.
|
||||
Usually, only one series file is used for a set of patches, so the
|
||||
patches sub-directory is a convenient location.
|
||||
|
||||
The .pc directory and its sub-directories cannot be relocated, but it can be
|
||||
a symbolic link. While patches are applied to the source tree, this
|
||||
directory is essential for many operations, including taking patches off the
|
||||
stack
|
||||
.RB ( "quilt pop" ),
|
||||
and refreshing patches
|
||||
.RB ( "quilt refresh" ).
|
||||
Files in the .pc directory are automatically removed when they are
|
||||
no longer needed, so there is no need to clean up manually.
|
||||
|
||||
.SH QUILT COMMANDS REFERENCE
|
||||
|
||||
@REFERENCE@
|
||||
|
||||
.SH COMMON OPTIONS TO ALL COMMANDS
|
||||
|
||||
.IP \"\\fB--trace\\fP\" 8
|
||||
|
||||
Runs the command in bash trace mode (-x). For internal debugging.
|
||||
|
||||
.IP \"\\fB--quiltrc\\fP file\" 8
|
||||
|
||||
Use the specified configuration file instead of ~/.quiltrc (or
|
||||
/etc/quilt.quiltrc if ~/.quiltrc does not exist). See the pdf
|
||||
documentation for details about its possible contents. The
|
||||
special value \"-\" causes quilt not to read any configuration
|
||||
file.
|
||||
|
||||
.IP \"\\fB--version\\fP\" 8
|
||||
|
||||
Print the version number and exit immediately.
|
||||
|
||||
.SH EXIT STATUS
|
||||
|
||||
The exit status is 0 if the sub-command was successfully executed, and
|
||||
1 in case of error.
|
||||
|
||||
An exit status of 2 denotes that quilt did not do anything to complete
|
||||
the command. This happens in particular when asking to push when the
|
||||
whole stack is already pushed, or asking to pop when the whole stack
|
||||
is already popped. This behavior is intended to ease the scripting
|
||||
around quilt.
|
||||
|
||||
.SH EXAMPLE OF WORKING TREE
|
||||
|
||||
.fam C
|
||||
.RS
|
||||
.nf
|
||||
work/
|
||||
├── patches/
|
||||
│ ├── series (list of patches to apply)
|
||||
│ ├── patch1.diff (one particular patch)
|
||||
│ ├── patch2.diff
|
||||
│ └── ...
|
||||
├── .pc/
|
||||
│ ├── .quilt_patches (content of QUILT_PATCHES)
|
||||
│ ├── .quilt_series (content of QUILT_SERIES)
|
||||
│ ├── patch1.diff/ (copy of patched files)
|
||||
│ │ └── ...
|
||||
│ ├── patch2.diff/
|
||||
│ │ └── ...
|
||||
│ └── ...
|
||||
└── ...
|
||||
.fi
|
||||
.RE
|
||||
.fam T
|
||||
|
||||
The patches/ directory is precious as it contains all your patches as
|
||||
well as the order in which it should be applied.
|
||||
|
||||
The .pc/ directory contains some metadata about the current state of
|
||||
your patch serie. Changing its content is not advised. This directory
|
||||
can usually be regenerated from the initial files and the
|
||||
content of the patches/ directory (provided that all patches were
|
||||
regenerated before the removal).
|
||||
|
||||
.SH EXAMPLE
|
||||
|
||||
Please refer to the pdf documentation for a full example of use.
|
||||
|
||||
.SH CONFIGURATION FILE
|
||||
|
||||
Upon startup, quilt evaluates the file .quiltrc in the user's home
|
||||
directory, or the file specified with the --quiltrc option. This file
|
||||
is a regular bash script. Default options can be passed to any COMMAND
|
||||
by defining a QUILT_${COMMAND}_ARGS variable. For example,
|
||||
QUILT_DIFF_ARGS="--color=auto" causes the output of quilt diff to be
|
||||
syntax colored when writing to a terminal.
|
||||
|
||||
In addition to that, quilt recognizes the following variables:
|
||||
|
||||
.IP EDITOR 4
|
||||
|
||||
The program to run to edit files. If it isn't redefined in the
|
||||
configuration file, $EDITOR as defined in the environment will be used.
|
||||
|
||||
.IP LESS 4
|
||||
|
||||
The arguments used to invoke the pager. Inherits the existing value
|
||||
of $LESS if LESS is already set in the environment, otherwise defaults
|
||||
to "-FRSX".
|
||||
|
||||
.IP QUILT_DIFF_OPTS 4
|
||||
|
||||
Additional options that quilt shall pass to GNU diff when generating
|
||||
patches. A useful setting for C source code is "-p", which causes GNU diff
|
||||
to show in the resulting patch which function a change is in.
|
||||
|
||||
.IP QUILT_PATCH_OPTS 4
|
||||
|
||||
Additional options that quilt shall pass to GNU patch when applying
|
||||
patches. For example, recent versions of GNU patch support the
|
||||
"--reject-format=unified" option for generating reject files in unified
|
||||
diff style (older patch versions used "--unified-reject-files" for that).
|
||||
|
||||
You may also want to add the "-E" option if you have issues with quilt
|
||||
not deleting empty files when you think it should. The documentation of
|
||||
GNU patch says that "normally this option is unnecessary", but when patch
|
||||
is in POSIX mode or if the patch format doesn't allow to distinguish
|
||||
empty files from deleted files, patch deletes empty files only if the
|
||||
-E option is given. Beware that when passing -E to patch, quilt will
|
||||
no longer be able to deal with empty files, which is why using -E is
|
||||
no longer the default.
|
||||
|
||||
.IP QUILT_DIFFSTAT_OPTS 4
|
||||
|
||||
Additional options that quilt shall pass to diffstat when generating
|
||||
patch statistics. For example, "-f0" can be used for an alternative output
|
||||
format. Recent versions of diffstat also support alternative rounding
|
||||
methods ("-r1", "-r2").
|
||||
|
||||
.IP QUILT_PC 4
|
||||
|
||||
The location of backup files and any other data relating to the current
|
||||
state of the working directory from quilt's perspective. Defaults to ".pc".
|
||||
|
||||
.IP QUILT_PATCHES 4
|
||||
|
||||
The location of patch files, defaulting to "patches".
|
||||
|
||||
.IP QUILT_SERIES 4
|
||||
|
||||
The name of the series file, defaulting to "series". Unless an absolute path
|
||||
is used, the search algorithm described above applies.
|
||||
|
||||
.IP QUILT_PATCHES_PREFIX 4
|
||||
|
||||
If set to anything, quilt will prefix patch names it prints with their
|
||||
directory (QUILT_PATCHES).
|
||||
|
||||
.IP QUILT_NO_DIFF_INDEX 4
|
||||
|
||||
By default, quilt prepends an Index: line to the patches it generates.
|
||||
If this variable is set to anything, no line is prepended. This is
|
||||
a shortcut to adding --no-index to both QUILT_DIFF_ARGS and
|
||||
QUILT_REFRESH_ARGS.
|
||||
|
||||
.IP QUILT_NO_DIFF_TIMESTAMPS 4
|
||||
|
||||
By default, quilt includes timestamps in headers when generating patches.
|
||||
If this variable is set to anything, no timestamp will be included. This
|
||||
is a shortcut to adding --no-timestamps to both QUILT_DIFF_ARGS and
|
||||
QUILT_REFRESH_ARGS.
|
||||
|
||||
.IP QUILT_PAGER 4
|
||||
|
||||
The pager quilt shall use for commands which produce paginated output. If
|
||||
unset, the values of GIT_PAGER or PAGER is used. If none of these variables
|
||||
is set, "less -R" is used. An empty value indicates that no pager should be
|
||||
used.
|
||||
|
||||
.IP QUILT_COLORS 4
|
||||
|
||||
By default, quilt uses its predefined color set in order to be more
|
||||
comprehensible when distiguishing various types of patches, eg.
|
||||
applied/unapplied, failed, etc.
|
||||
|
||||
To override one or more color settings, set the QUILT_COLORS variable in
|
||||
following syntax - colon (:) separated list of elements, each being of the
|
||||
form <format name>=<foreground color>[;<background color>]
|
||||
|
||||
Format names with their respective default values are listed below,
|
||||
along with their usage(s).
|
||||
Color codes(values) are standard bash coloring escape codes.
|
||||
See more at http://tldp.org/LDP/abs/html/colorizing.html#AEN20229
|
||||
|
||||
.RS 4
|
||||
.IP \\fBdiff_hdr\\fP 10
|
||||
Used in 'quilt diff' to color the index line. Defaults to 32 (green).
|
||||
|
||||
.IP \\fBdiff_add\\fP 10
|
||||
Used in 'quilt diff' to color added lines. Defaults to 36 (azure).
|
||||
|
||||
.IP \\fBdiff_mod\\fP 10
|
||||
Used in 'quilt diff' to color modified lines. Defaults to 35 (purple).
|
||||
|
||||
.IP \\fBdiff_rem\\fP 10
|
||||
Used in 'quilt diff' to color removed lines. Defaults to 35 (purple).
|
||||
|
||||
.IP \\fBdiff_hunk\\fP 10
|
||||
Used in 'quilt diff' to color hunk header. Defaults to 33 (brown/orange).
|
||||
|
||||
.IP \\fBdiff_ctx\\fP 10
|
||||
Used in 'quilt diff' to color the text after end of hunk header (diff --show-c-function generates this). Defaults to 35 (purple).
|
||||
|
||||
.IP \\fBdiff_cctx\\fP 10
|
||||
Used in 'quilt diff' to color the 15-asterisk sequence before or after a hunk. Defaults to 33 (brown/orange).
|
||||
|
||||
.IP \\fBpatch_fuzz\\fP 10
|
||||
Used in 'quilt push' to color the patch fuzz information. Defaults to 35 (purple).
|
||||
|
||||
.IP \\fBpatch_fail\\fP 10
|
||||
Used in 'quilt push' to color the fail message. Defaults to 31 (red).
|
||||
|
||||
.IP \\fBseries_app\\fP 10
|
||||
Used in 'quilt series' and 'quilt patches' to color the applied patch names. Defaults to 32 (green).
|
||||
|
||||
.IP \\fBseries_top\\fP 10
|
||||
Used in 'quilt series' and 'quilt patches' to color the top patch name. Defaults to 33 (brown/orange).
|
||||
|
||||
.IP \\fBseries_una\\fP 10
|
||||
Used in 'quilt series' and 'quilt patches' to color unapplied patch names. Defaults to 0 (no special color).
|
||||
|
||||
.RE
|
||||
.RS 4
|
||||
In addition, the \\fBclear\\fP format name is used to turn off special
|
||||
coloring. Its value is 0; it is not advised to modify it.
|
||||
|
||||
The content of QUILT_COLORS supersedes default values. So the value
|
||||
diff_hdr=35;44 will get you the diff headers in magenta over blue
|
||||
instead of the default green over unchanged background. For that, add
|
||||
the following content to ~/.quiltrc (or /etc/quilt.quiltrc):
|
||||
|
||||
.nf
|
||||
QUILT_DIFF_ARGS="--color"
|
||||
QUILT_COLORS='diff_hdr=35;44'
|
||||
.fi
|
||||
.RE 4
|
||||
|
||||
.SH AUTHORS
|
||||
|
||||
Quilt started as a series of scripts written by Andrew Morton
|
||||
(patch-scripts). Based on Andrew's ideas, Andreas Gruenbacher completely
|
||||
rewrote the scripts, with the help of several other contributors (see
|
||||
AUTHORS file in the distribution).
|
||||
|
||||
This man page was written by Martin Quinson, based on information found in
|
||||
the pdf documentation, and in the help messages of each commands.
|
||||
|
||||
.SH SEE ALSO
|
||||
|
||||
The pdf documentation, which should be under @DOCSUBDIR@/quilt.pdf.
|
||||
Note that some distributors compress this file.
|
||||
.BR zxpdf ( 1 )
|
||||
can be used to display compressed pdf files.
|
||||
|
||||
.BR diff ( 1 ),
|
||||
.BR patch ( 1 ),
|
||||
.BR guards ( 1 ).
|
Binary file not shown.
|
@ -0,0 +1,11 @@
|
|||
#! /bin/sh
|
||||
|
||||
if git rev-parse --show-cdup > /dev/null 2> /dev/null; then
|
||||
tag=$(git describe --tags HEAD 2> /dev/null || \
|
||||
git rev-parse --short HEAD)
|
||||
dirty=$(git update-index --refresh --unmerged > /dev/null
|
||||
if git diff-index --name-only HEAD | read dummy; then
|
||||
echo -dirty
|
||||
fi)
|
||||
echo $tag$dirty
|
||||
fi
|
|
@ -0,0 +1,591 @@
|
|||
;;; quilt.el --- a minor mode for working with files in quilt
|
||||
|
||||
;; Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
|
||||
;; Satoru Takeuchi <satoru.takeuchi@gmail.com> took over this package
|
||||
;; from Matt Mackall.
|
||||
|
||||
;; Author: Saotru takeuchi <satoru.takeuchi@gmail.com>
|
||||
;;
|
||||
;; This software may be used and distributed according to the terms
|
||||
;; of the GNU General Public License, incorporated herein by reference.
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
|
||||
;; Add (load "~/quilt.el") to your .emacs file
|
||||
|
||||
;;; History:
|
||||
;;
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defun quilt-buffer-file-name-safe ()
|
||||
"Return buffer file name. If buffer is not associated with any file, return nil."
|
||||
(let ((fn buffer-file-name))
|
||||
(if (and fn (file-exists-p fn))
|
||||
fn)))
|
||||
|
||||
(defun quilt-bottom-p ()
|
||||
"Return t if there is on the bottom of patch stack, return nil if otherwise."
|
||||
(if (> (call-process "quilt" nil nil nil "applied") 0) 1))
|
||||
|
||||
(defun quilt-patches-directory ()
|
||||
"Return the location of patch files."
|
||||
(or (with-current-buffer (generate-new-buffer " *cmd")
|
||||
(shell-command
|
||||
(concat "test -f ~/.quiltrc && . ~/.quiltrc ;"
|
||||
"echo -n $QUILT_PATCHES")
|
||||
t)
|
||||
(unwind-protect
|
||||
(let ((v (buffer-string)))
|
||||
(if (string= "" (buffer-string))
|
||||
nil
|
||||
v))
|
||||
(kill-buffer (current-buffer))))
|
||||
(or (getenv "QUILT_PATCHES")
|
||||
"patches")))
|
||||
|
||||
(defun quilt-pc-directory ()
|
||||
"Return the location of patch files."
|
||||
(or (with-current-buffer (generate-new-buffer " *cmd")
|
||||
(shell-command
|
||||
(concat "test -f ~/.quiltrc && . ~/.quiltrc ;"
|
||||
"echo -n $QUILT_PC")
|
||||
t)
|
||||
(unwind-protect
|
||||
(let ((v (buffer-string)))
|
||||
(if (string= "" (buffer-string))
|
||||
nil
|
||||
v))
|
||||
(kill-buffer (current-buffer))))
|
||||
(or (getenv "QUILT_PC")
|
||||
".pc")))
|
||||
|
||||
(defun quilt-find-dir (fn &optional prefn)
|
||||
"Return the top level dir of quilt from FN."
|
||||
(if (or (not fn) (equal fn "/") (equal fn prefn))
|
||||
nil
|
||||
(let ((d (file-name-directory fn)))
|
||||
(if (file-accessible-directory-p (concat d "/" (quilt-pc-directory)))
|
||||
d
|
||||
(quilt-find-dir (directory-file-name d) d)))))
|
||||
|
||||
(defun quilt-dir (&optional fn)
|
||||
"Return the top level dir of quilt from FN. FN is just a hint and find from other way if FN is nil."
|
||||
(quilt-find-dir (if fn fn
|
||||
(let ((fn2 (quilt-buffer-file-name-safe)))
|
||||
(if fn2 fn2
|
||||
(if default-directory
|
||||
(expand-file-name default-directory)))))))
|
||||
|
||||
(defun quilt-drop-dir (fn)
|
||||
"Return the relative path of FN based on quilt top directory."
|
||||
(let ((d (quilt-find-dir fn)))
|
||||
(substring fn (length d) (length fn))))
|
||||
|
||||
(defun quilt-p (&optional fn)
|
||||
"Check if FN is in a quilt tree."
|
||||
(if (quilt-dir fn) 't nil))
|
||||
|
||||
(defun quilt-save ()
|
||||
"Save all buffers associated with current quilt tree."
|
||||
(save-some-buffers nil 'quilt-p))
|
||||
|
||||
(defun quilt-owned-p (fn)
|
||||
"Check if FN is a file which quilt handles."
|
||||
(if (not fn)
|
||||
nil
|
||||
(let ((pd (file-name-nondirectory
|
||||
(directory-file-name (file-name-directory fn)))))
|
||||
(and
|
||||
(not (string-match "\\(~$\\|\\.rej$\\)" fn))
|
||||
(not (equal pd (quilt-patches-directory)))
|
||||
(not (equal pd (quilt-pc-directory)))
|
||||
(quilt-p fn)))))
|
||||
|
||||
(defun quilt-cmd (cmd &optional buf)
|
||||
"Execute CMD, a quilt subcommand, at the top of quilt tree associated with BUF."
|
||||
(let ((d default-directory)
|
||||
(qd (quilt-dir)))
|
||||
(if (not qd)
|
||||
(shell-command (concat "quilt " cmd) buf)
|
||||
(cd qd)
|
||||
(unwind-protect ; make sure to cd back even if an erro occurs.
|
||||
(shell-command (concat "quilt " cmd) buf)
|
||||
(cd d)))))
|
||||
|
||||
(defun quilt-cmd-to-string (cmd)
|
||||
"Execute CMD, a quilt subcommand, at the top of quilt tree associated with BUF and return its output string."
|
||||
(let ((d default-directory)
|
||||
(qd (quilt-dir)))
|
||||
(if (not qd)
|
||||
nil
|
||||
(cd qd)
|
||||
(unwind-protect ; make sure to cd back even if an error occurs.
|
||||
(shell-command-to-string (concat "quilt " cmd))
|
||||
(cd d)))))
|
||||
|
||||
(defun quilt-cmd-to-list (cmd)
|
||||
"Execute CMD, a quilt sumcommand at the top of quilt tree associated with BUF.."
|
||||
"Return the lines of the command output as elements of a list."
|
||||
(let ((s (quilt-cmd-to-string cmd)))
|
||||
(if s
|
||||
(split-string s "\n" t))))
|
||||
|
||||
(defun quilt-applied-list ()
|
||||
"Return the list of the applied patch names."
|
||||
(quilt-cmd-to-list "applied"))
|
||||
|
||||
(defun quilt-file-list ()
|
||||
"Return the list of the file names associated with current patch."
|
||||
(quilt-cmd-to-list "files"))
|
||||
|
||||
(defun quilt-patch-list ()
|
||||
"Return the list of the name of patches."
|
||||
(quilt-cmd-to-list "series"))
|
||||
|
||||
(defun quilt-files-affected (&optional first last)
|
||||
"Return the file names which modified from FIRST to LAST."
|
||||
"Omitted args are considered as current patch."
|
||||
(let ((qd (quilt-dir))
|
||||
files fp)
|
||||
(when qd
|
||||
(setq files (quilt-cmd-to-list
|
||||
(if last
|
||||
(if (equal first last)
|
||||
(concat "files " first)
|
||||
(concat "files --combine " first last))
|
||||
(if first
|
||||
(concat "files --combine " first)
|
||||
"files"))))
|
||||
(setq fp files)
|
||||
(while fp
|
||||
(setcar fp (concat qd (car fp)))
|
||||
(setq fp (cdr fp)))
|
||||
files)))
|
||||
|
||||
(defun quilt-top-patch ()
|
||||
"Return the top patch name. return nil if there is the bottom of patch stack."
|
||||
(if (quilt-bottom-p)
|
||||
nil
|
||||
(substring (quilt-cmd-to-string "top") 0 -1)))
|
||||
|
||||
(defun quilt-complete-list (p l)
|
||||
"Call 'completing-read' with prompt P and list L."
|
||||
"Convert L to an alist using indices as keys. Note that this function modifies L."
|
||||
(let ((list l)
|
||||
(n 0))
|
||||
(while list
|
||||
(setcar list (cons (car list) n))
|
||||
(setq list (cdr list))
|
||||
(setq n (1+ n))))
|
||||
(completing-read p l nil t))
|
||||
|
||||
(defvar quilt-edit-top-only 't)
|
||||
(defun quilt-editable (f)
|
||||
"Return t if F is editable in terms of current patch. Return nil if otherwise."
|
||||
(let ((qd (quilt-dir))
|
||||
(fn (quilt-drop-dir f))
|
||||
dirs result)
|
||||
(if qd
|
||||
(if (quilt-bottom-p)
|
||||
(quilt-cmd "applied") ; to print error message
|
||||
(setq dirs (if quilt-edit-top-only
|
||||
(list (substring (quilt-cmd-to-string "top") 0 -1))
|
||||
(cdr (cdr (directory-files (concat qd (quilt-pc-directory) "/"))))))
|
||||
(while (and (not result) dirs)
|
||||
(if (file-exists-p (concat qd (quilt-pc-directory) "/" (car dirs) "/" fn))
|
||||
(setq result t)
|
||||
(setq dirs (cdr dirs))))
|
||||
result))))
|
||||
|
||||
(defun quilt-short-patchname ()
|
||||
"Return shortened name of top patch. Return \"none\" when on the bottom patch stack."
|
||||
(let ((p (quilt-top-patch)))
|
||||
(if (not p)
|
||||
"none"
|
||||
(let ((p2 (file-name-sans-extension (file-name-nondirectory p))))
|
||||
(if (< (length p2) 10)
|
||||
p2
|
||||
(concat (substring p2 0 8) ".."))))))
|
||||
|
||||
(defvar quilt-mode-line nil)
|
||||
(make-variable-buffer-local 'quilt-mode-line)
|
||||
|
||||
(defun quilt-update-modeline ()
|
||||
"Update mode line."
|
||||
(interactive)
|
||||
(setq quilt-mode-line
|
||||
(concat " Q:" (quilt-short-patchname)))
|
||||
(force-mode-line-update))
|
||||
|
||||
(defun quilt-revert (filelist)
|
||||
"Refresh contents, editability and modeline of FILESIT.
|
||||
FILELIST won't be touched unless their file is a child of the
|
||||
current quilt directory. Each elements in FILELIST should be the absolute
|
||||
file names of those files affected by the latest quilt
|
||||
operation. Associated buffers get reverted to update their
|
||||
contents. Other buffers will only get their modeline and
|
||||
editability adjusted."
|
||||
(let ((qd (quilt-dir))
|
||||
fn)
|
||||
(dolist (buf (buffer-list))
|
||||
(if (not (string-match "^ " (buffer-name buf)))
|
||||
(with-current-buffer buf
|
||||
(setq fn (quilt-buffer-file-name-safe))
|
||||
(when (string-equal qd (quilt-dir))
|
||||
(quilt-update-modeline)
|
||||
(when (and (not (buffer-modified-p))
|
||||
(quilt-owned-p fn))
|
||||
;; If the file doesn't exist on disk it can't be reverted, but we
|
||||
;; need the revert hooks to run anyway so that the buffer's
|
||||
;; editability will update. Files not affected by the latest change
|
||||
;; (as listed in filelist) don't need to get reverted either.
|
||||
(if (and (file-exists-p buffer-file-name)
|
||||
(member fn filelist))
|
||||
(progn
|
||||
(revert-buffer t t t))
|
||||
(run-hooks 'after-revert-hook)))))))))
|
||||
|
||||
(defun quilt-push (arg)
|
||||
"Push next patch. It is forced if ARG is specified."
|
||||
(interactive "P")
|
||||
(quilt-save)
|
||||
(if arg
|
||||
(quilt-cmd "push -f" "*quilt*")
|
||||
(quilt-cmd "push -q"))
|
||||
(quilt-revert (quilt-files-affected)))
|
||||
|
||||
(defun quilt-pop (arg)
|
||||
"Pop top patch. It is forced if ARG is specified."
|
||||
(interactive "P")
|
||||
(quilt-save)
|
||||
(if arg
|
||||
(quilt-cmd "pop -f")
|
||||
(quilt-cmd "pop -q"))
|
||||
(quilt-revert (quilt-files-affected)))
|
||||
|
||||
(defun quilt-push-all (arg)
|
||||
"Push all remaining patches. It is forced if ARG is specified."
|
||||
(interactive "P")
|
||||
(quilt-save)
|
||||
(let ((next (car (quilt-cmd-to-list "next"))))
|
||||
(if arg
|
||||
(quilt-cmd "push -f" "*quilt*")
|
||||
(quilt-cmd "push -qa"))
|
||||
(quilt-revert (quilt-files-affected next))))
|
||||
|
||||
(defun quilt-pop-all (arg)
|
||||
"Pop all applied patches. It is forced if ARG is specified."
|
||||
(interactive "P")
|
||||
(quilt-save)
|
||||
(let ((fa (quilt-files-affected "-")))
|
||||
(if arg
|
||||
(quilt-cmd "pop -af")
|
||||
(quilt-cmd "pop -qa"))
|
||||
(quilt-revert fa)))
|
||||
|
||||
(defun quilt-goto ()
|
||||
"Go to a specified patch."
|
||||
(interactive)
|
||||
(let ((qd (quilt-dir)))
|
||||
(if (not qd)
|
||||
(quilt-cmd "push") ; to print error message
|
||||
(let ((arg (quilt-complete-list "Goto patch: " (quilt-patch-list))))
|
||||
(if (string-equal arg "")
|
||||
(message "no patch name is supplied")
|
||||
(quilt-save)
|
||||
(let (cmd first last)
|
||||
(if (file-exists-p (concat qd (quilt-pc-directory) "/" arg))
|
||||
(progn
|
||||
(setq cmd "pop")
|
||||
(setq first (car (quilt-cmd-to-list (concat "next " arg))))
|
||||
(setq last (quilt-top-patch)))
|
||||
(setq cmd "push")
|
||||
(setq last arg)
|
||||
(setq first (if (quilt-bottom-p)
|
||||
"-"
|
||||
(car (quilt-cmd-to-list "next")))))
|
||||
(quilt-cmd (concat cmd " -q " arg) "*quilt*")
|
||||
(quilt-revert (quilt-files-affected first last))))))))
|
||||
|
||||
(defun quilt-top ()
|
||||
"Display topmost patch."
|
||||
(interactive)
|
||||
(quilt-cmd "top"))
|
||||
|
||||
(defun quilt-find-file ()
|
||||
"Find a file in the topmost patch."
|
||||
(interactive)
|
||||
(let ((qd (quilt-dir)))
|
||||
(if (not qd)
|
||||
(quilt-cmd "push") ; to print error message
|
||||
(if (quilt-bottom-p)
|
||||
(quilt-cmd "applied") ; to print error message
|
||||
(let ((l (quilt-file-list)))
|
||||
(if (not l)
|
||||
(message "no file is existed in this patch")
|
||||
(let ((f (quilt-complete-list "File: " l)))
|
||||
(if (string-equal f "")
|
||||
(message "file name is not specified")
|
||||
(find-file (concat qd f))))))))))
|
||||
|
||||
(defun quilt-files ()
|
||||
"Display files in topmost patch."
|
||||
(interactive)
|
||||
(quilt-cmd "files"))
|
||||
|
||||
(defun quilt-import (fn pn)
|
||||
"Import external patch FN as PN.patch."
|
||||
(interactive "fPatch to import: \nsPatch name: ")
|
||||
(if (not pn)
|
||||
(message "no patch name supplied")
|
||||
(quilt-cmd (concat "import -p " pn ".patch " (if fn fn pn)))))
|
||||
|
||||
(defun quilt-diff ()
|
||||
"Display the diff of current change."
|
||||
(interactive)
|
||||
(quilt-save)
|
||||
(quilt-cmd "diff" "*diff*"))
|
||||
|
||||
(defun quilt-new (f)
|
||||
"Create a new patch F.patch."
|
||||
(interactive "sPatch name: ")
|
||||
(if (string-equal f "")
|
||||
(message "no patch name is supplied")
|
||||
(quilt-save)
|
||||
(quilt-cmd (concat "new " f ".patch"))
|
||||
(quilt-revert nil)))
|
||||
|
||||
(defun quilt-applied ()
|
||||
"Show applied patches."
|
||||
(interactive)
|
||||
(quilt-cmd "applied" "*quilt*"))
|
||||
|
||||
(defun quilt-add (arg)
|
||||
"Add ARG to the current patch."
|
||||
(interactive "b")
|
||||
(with-current-buffer arg
|
||||
(let ((fn (quilt-buffer-file-name-safe)))
|
||||
(cond
|
||||
((not fn)
|
||||
(message "buffer %s is not associated with any buffer" (buffer-name)))
|
||||
((not (quilt-dir))
|
||||
(quilt-cmd (concat "push"))) ; to print error message
|
||||
(t
|
||||
(quilt-cmd (concat "add " (quilt-drop-dir fn)))
|
||||
(quilt-revert (list fn)))))))
|
||||
|
||||
(defun quilt-edit-patch ()
|
||||
"Edit the topmost patch."
|
||||
(interactive)
|
||||
(let ((qd (quilt-dir)))
|
||||
(if (not qd)
|
||||
(quilt-cmd "push") ; to print error message
|
||||
(let ((patch (quilt-top-patch)))
|
||||
(if (not patch)
|
||||
(quilt-cmd "applied") ; to print error message
|
||||
(quilt-save)
|
||||
(let ((pf (concat qd
|
||||
(format "/%s/" (quilt-patches-directory))
|
||||
patch)))
|
||||
(if (file-exists-p pf)
|
||||
(progn (find-file pf)
|
||||
(read-only-mode 0))
|
||||
(message (format "%s doesn't exist yet." pf)))))))))
|
||||
|
||||
(defun quilt-patches ()
|
||||
"Show which patches modify the current buffer."
|
||||
(interactive)
|
||||
(let ((fn (quilt-buffer-file-name-safe)))
|
||||
(cond
|
||||
((not fn)
|
||||
(message "buffer %s is not associated with any buffer" (buffer-name)))
|
||||
((not (quilt-dir))
|
||||
(quilt-cmd "push")) ; to print error message
|
||||
(t
|
||||
(quilt-cmd (concat "patches " (quilt-drop-dir fn)))))))
|
||||
|
||||
(defun quilt-unapplied ()
|
||||
"Display unapplied patch list."
|
||||
(interactive)
|
||||
(quilt-cmd "unapplied" "*quilt*"))
|
||||
|
||||
(defun quilt-refresh ()
|
||||
"Refresh the current patch."
|
||||
(interactive)
|
||||
(quilt-save)
|
||||
(quilt-cmd "refresh"))
|
||||
|
||||
(defun quilt-remove ()
|
||||
"Remove a file from the current patch and revert it."
|
||||
(interactive)
|
||||
(let ((f (quilt-buffer-file-name-safe)))
|
||||
(cond
|
||||
((not f)
|
||||
(message "buffer %s is not associated with any patch" (buffer-name)))
|
||||
((not (quilt-dir))
|
||||
(quilt-cmd "push")) ; to print error message
|
||||
(t
|
||||
(if (quilt-bottom-p)
|
||||
(quilt-cmd "applied") ; to print error message
|
||||
(let ((dropped (quilt-drop-dir f)))
|
||||
(if (y-or-n-p (format "Really drop %s? " dropped))
|
||||
(progn
|
||||
(quilt-cmd (concat "remove " dropped))
|
||||
(quilt-revert (list f))))))))))
|
||||
|
||||
(defun quilt-edit-series ()
|
||||
"Edit the patch series file."
|
||||
(interactive)
|
||||
(let ((qd (quilt-dir)))
|
||||
(if (not qd)
|
||||
(quilt-cmd "push") ; to print error message
|
||||
(let ((series (concat qd
|
||||
(format "/%s/series" (quilt-patches-directory)))))
|
||||
(if (file-exists-p series)
|
||||
(find-file series)
|
||||
(message (quilt-top-patch)))))))
|
||||
|
||||
(defun quilt-header (arg)
|
||||
"Print the header of ARG."
|
||||
(interactive "P")
|
||||
(let ((qd (quilt-dir)))
|
||||
(if (not qd)
|
||||
(quilt-cmd "push") ; to print error message
|
||||
(if (not arg)
|
||||
(quilt-cmd "header")
|
||||
(let ((p (quilt-complete-list "Patch: " (quilt-patch-list))))
|
||||
(if (string-equal p "")
|
||||
(message "no patch name is supplied")
|
||||
(quilt-cmd (concat "header " p))))))))
|
||||
|
||||
(defun quilt-delete (arg)
|
||||
"Delete ARG from the series file."
|
||||
(interactive "P")
|
||||
(let ((qd (quilt-dir)))
|
||||
(if (not qd)
|
||||
(quilt-cmd "push") ; to print error message
|
||||
(let ((p (if arg
|
||||
(quilt-complete-list "Delete patch: " (quilt-patch-list))
|
||||
(quilt-top-patch))))
|
||||
(if (string-equal p "")
|
||||
(message "no patch name is supplied")
|
||||
(if (not p)
|
||||
(quilt-cmd "applied") ; to print error message
|
||||
(if (y-or-n-p (format "Really delete %s? " p))
|
||||
(let ((fa (quilt-files-affected p p)))
|
||||
(quilt-save)
|
||||
(quilt-cmd (concat "delete " p))
|
||||
(quilt-revert fa)))))))))
|
||||
|
||||
(defvar quilt-header-directory nil)
|
||||
|
||||
(defun quilt-header-commit ()
|
||||
"Commit to change patch header."
|
||||
(interactive)
|
||||
(let ((tmp (make-temp-file "quilt-header-")))
|
||||
(set-visited-file-name tmp)
|
||||
(basic-save-buffer)
|
||||
(cd quilt-header-directory)
|
||||
(shell-command (concat "EDITOR=cat quilt -r header <" tmp))
|
||||
(kill-buffer (current-buffer))
|
||||
(delete-file tmp)))
|
||||
|
||||
(defvar quilt-header-mode-map (make-keymap))
|
||||
(define-key quilt-header-mode-map "\C-c\C-c" 'quilt-header-commit)
|
||||
|
||||
(defun quilt-edit-header (arg)
|
||||
"Edit the header of ARG."
|
||||
(interactive "P")
|
||||
(let ((qd (quilt-dir)))
|
||||
(if (not qd)
|
||||
(quilt-cmd "push") ; to print error message
|
||||
(let ((p (if arg
|
||||
(quilt-complete-list "Edit patch: " (quilt-patch-list))
|
||||
(quilt-top-patch))))
|
||||
(if (string-equal p "")
|
||||
(message "no patch name is supplied")
|
||||
(if (not p)
|
||||
(quilt-cmd "applied") ; to print error message
|
||||
(let ((qb (get-buffer-create (format " *quilt-header(%s)*" p))))
|
||||
(switch-to-buffer-other-window qb)
|
||||
(erase-buffer)
|
||||
(kill-all-local-variables)
|
||||
(make-local-variable 'quilt-header-directory)
|
||||
(setq quilt-header-directory default-directory)
|
||||
(use-local-map quilt-header-mode-map)
|
||||
(setq major-mode 'quilt-header-mode)
|
||||
(call-process "quilt" nil qb nil "header" p)
|
||||
(goto-char 0))))))))
|
||||
|
||||
(defun quilt-series (arg)
|
||||
"Show patche series. It can be verbose mode if ARG is specified."
|
||||
(interactive "P")
|
||||
(if arg
|
||||
(quilt-cmd "series -v")
|
||||
(quilt-cmd "series")))
|
||||
|
||||
(defvar quilt-mode-map (make-sparse-keymap))
|
||||
(define-key quilt-mode-map "\C-c.t" 'quilt-top)
|
||||
(define-key quilt-mode-map "\C-c.f" 'quilt-find-file)
|
||||
(define-key quilt-mode-map "\C-c.F" 'quilt-files)
|
||||
(define-key quilt-mode-map "\C-c.d" 'quilt-diff)
|
||||
(define-key quilt-mode-map "\C-c.p" 'quilt-push)
|
||||
(define-key quilt-mode-map "\C-c.o" 'quilt-pop)
|
||||
(define-key quilt-mode-map "\C-c.P" 'quilt-push-all)
|
||||
(define-key quilt-mode-map "\C-c.O" 'quilt-pop-all)
|
||||
(define-key quilt-mode-map "\C-c.g" 'quilt-goto)
|
||||
(define-key quilt-mode-map "\C-c.A" 'quilt-applied)
|
||||
(define-key quilt-mode-map "\C-c.n" 'quilt-new)
|
||||
(define-key quilt-mode-map "\C-c.i" 'quilt-import)
|
||||
(define-key quilt-mode-map "\C-c.a" 'quilt-add)
|
||||
(define-key quilt-mode-map "\C-c.e" 'quilt-edit-patch)
|
||||
(define-key quilt-mode-map "\C-c.m" 'quilt-patches)
|
||||
(define-key quilt-mode-map "\C-c.u" 'quilt-unapplied)
|
||||
(define-key quilt-mode-map "\C-c.r" 'quilt-refresh)
|
||||
(define-key quilt-mode-map "\C-c.R" 'quilt-remove)
|
||||
(define-key quilt-mode-map "\C-c.s" 'quilt-series)
|
||||
(define-key quilt-mode-map "\C-c.S" 'quilt-edit-series)
|
||||
(define-key quilt-mode-map "\C-c.h" 'quilt-header)
|
||||
(define-key quilt-mode-map "\C-c.H" 'quilt-edit-header)
|
||||
(define-key quilt-mode-map "\C-c.D" 'quilt-delete)
|
||||
|
||||
(defvar quilt-mode nil)
|
||||
(make-variable-buffer-local 'quilt-mode)
|
||||
|
||||
(defun quilt-mode (&optional arg)
|
||||
"Toggle 'quilt-mode'. Enable 'quilt-mode' if ARG is positive.
|
||||
|
||||
\\{quilt-mode-map}"
|
||||
(interactive "P")
|
||||
(setq quilt-mode
|
||||
(if (null arg)
|
||||
(not quilt-mode)
|
||||
(> (prefix-numeric-value arg) 0)))
|
||||
(if quilt-mode
|
||||
(let ((f (quilt-buffer-file-name-safe)))
|
||||
(if (quilt-owned-p f)
|
||||
(if (not (quilt-editable f))
|
||||
(read-only-mode 1)
|
||||
(read-only-mode 0)))
|
||||
(quilt-update-modeline))))
|
||||
|
||||
(defun quilt-hook ()
|
||||
"Enable quilt mode for quilt-controlled files."
|
||||
(if (quilt-p) (quilt-mode 1)))
|
||||
|
||||
(add-hook 'find-file-hooks 'quilt-hook)
|
||||
(add-hook 'after-revert-hook 'quilt-hook)
|
||||
|
||||
(or (assq 'quilt-mode minor-mode-alist)
|
||||
(setq minor-mode-alist
|
||||
(cons '(quilt-mode quilt-mode-line) minor-mode-alist)))
|
||||
|
||||
(or (assq 'quilt-mode-map minor-mode-map-alist)
|
||||
(setq minor-mode-map-alist
|
||||
(cons (cons 'quilt-mode quilt-mode-map) minor-mode-map-alist)))
|
||||
|
||||
(provide 'quilt)
|
||||
|
||||
;;; quilt.el ends here
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,35 @@
|
|||
# Example /etc/quilt.quiltrc
|
||||
|
||||
# Options passed to GNU diff when generating patches
|
||||
QUILT_DIFF_OPTS="--show-c-function"
|
||||
|
||||
# Options passed to GNU patch when applying patches
|
||||
#QUILT_PATCH_OPTS="--ignore-whitespace"
|
||||
|
||||
# Options passed to diffstat when generating patch statistics
|
||||
#QUILT_DIFFSTAT_OPTS="-f0"
|
||||
|
||||
# Options to pass to commands (QUILT_${COMMAND}_ARGS)
|
||||
QUILT_PUSH_ARGS="--color=auto"
|
||||
QUILT_DIFF_ARGS="--no-timestamps --color=auto"
|
||||
QUILT_REFRESH_ARGS="--no-timestamps --backup"
|
||||
QUILT_SERIES_ARGS="--color=auto"
|
||||
QUILT_PATCHES_ARGS="--color=auto"
|
||||
|
||||
# When non-default less options are used, add the -R option so that less outputs
|
||||
# ANSI color escape codes "raw".
|
||||
[ -n "$LESS" -a -z "${QUILT_PAGER+x}" ] && QUILT_PAGER="less -FRX"
|
||||
|
||||
# (Add "-p ab" to QUILT_DIFF_ARGS and QUILT_REFRESH_ARGS to get
|
||||
# -p1 style diffs with a/file and b/file filenams in headers
|
||||
# instead of dir.orig/file and dir/file.)
|
||||
|
||||
# The directory in which patches are found (defaults to "patches").
|
||||
#QUILT_PATCHES=patches
|
||||
|
||||
# Prefix all patch names with the relative path to the patch?
|
||||
QUILT_PATCHES_PREFIX=yes
|
||||
|
||||
# Use a specific editor for quilt (defaults to the value of $EDITOR before
|
||||
# sourcing this configuration file, or vi if $EDITOR wasn't set).
|
||||
#EDITOR=nedit
|
|
@ -0,0 +1,304 @@
|
|||
#
|
||||
# spec file for quilt - patch management scripts
|
||||
#
|
||||
|
||||
Name: quilt
|
||||
Summary: Scripts for working with series of patches
|
||||
License: GPL
|
||||
Group: Productivity/Text/Utilities
|
||||
Version: 0.66
|
||||
Release: 1
|
||||
Requires: coreutils diffutils findutils patch gzip bzip2 perl mktemp gettext
|
||||
Autoreqprov: off
|
||||
Source: quilt-%{version}.tar.gz
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
|
||||
%description
|
||||
The scripts allow to manage a series of patches by keeping
|
||||
track of the changes each patch makes. Patches can be
|
||||
applied, un-applied, refreshed, etc.
|
||||
|
||||
The scripts are heavily based on Andrew Morton's patch scripts
|
||||
found at http://userweb.kernel.org/~akpm/stuff/patch-scripts.tar.gz.
|
||||
|
||||
Authors:
|
||||
--------
|
||||
Andrew Morton <akpm@digeo.com>
|
||||
Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
CFLAGS="$RPM_OPT_FLAGS" \
|
||||
./configure --prefix=/usr \
|
||||
--mandir=%_mandir \
|
||||
--docdir=%_docdir/%{name}-%{version}
|
||||
make RELEASE=%release
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
make install prefix=/usr BUILD_ROOT=$RPM_BUILD_ROOT
|
||||
%{find_lang} %{name}
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files -f %{name}.lang
|
||||
%defattr(-, root, root)
|
||||
/usr/bin/guards
|
||||
/usr/bin/quilt
|
||||
/usr/share/quilt/
|
||||
/usr/share/emacs/
|
||||
/etc/bash_completion.d/quilt
|
||||
%config(noreplace) /etc/quilt.quiltrc
|
||||
%doc %{_mandir}/man1/guards.1*
|
||||
%doc %{_mandir}/man1/quilt.1*
|
||||
%doc %{_docdir}/%{name}-%{version}/README
|
||||
%doc %{_docdir}/%{name}-%{version}/README.MAIL
|
||||
%doc %{_docdir}/%{name}-%{version}/quilt.pdf
|
||||
|
||||
%changelog
|
||||
* Thu Mar 28 2019 - upstream
|
||||
- Update to version 0.66
|
||||
+ Add support for lzip archives and patches (#54570)
|
||||
+ Document QUILT_PC as user-settable
|
||||
+ configure: Don't require md5sum
|
||||
+ Test suite: Allow keeping the working directory on failure
|
||||
+ Test suite: Fix regex for recent versions of perl
|
||||
+ Test suite: Fix /bin/sh filtering
|
||||
+ Test suite: Run tests again if test.quiltrc changes
|
||||
+ Test suite: Handle alternative QUILT_PATCHES values
|
||||
+ Test suite: Increase code path coverage
|
||||
+ Test suite: Be verbose on directory error
|
||||
+ Test suite: Clean up when interrupted
|
||||
+ Test suite: Prevent test cases from escaping
|
||||
+ fold: Fix German translation
|
||||
+ diff: Add missing quotes in basename call (#50862)
|
||||
+ header: Fix corruption when trailing newline is missing (#50841)
|
||||
+ mail: Fix patch set threading (#50775)
|
||||
+ mail: Fix French translation
|
||||
+ mail: Remove Content-Disposition headers
|
||||
+ mail: Complain when a patch doesn't exist
|
||||
+ new: Fix corruption when trailing newline is missing (#54295)
|
||||
+ refresh: Add missing quotes in basename call (#50862)
|
||||
+ setup: Add basic support for p7zip (.7z) archives (#49754)
|
||||
+ setup: Align --fast on --slow for series files
|
||||
+ quilt.el: Define quilt-edit-top-only before it's used
|
||||
+ quilt.el: Stop using deprecated toggle-read-only
|
||||
+ quilt.el: Don't strip directory in quilt-top-patch
|
||||
+ quilt.el: Fix emacs compatibility issue (#51977)
|
||||
+ quilt.el: Read QUILT_PC from config file
|
||||
+ quiltrc: Support all patch formats by default
|
||||
+ guards: Mention it in quilt manual page
|
||||
+ compat/getopt: Handle a second separator (#54772)
|
||||
+ compat/getopt: Allow non-digit parameter embedded in short option (#54772)
|
||||
|
||||
* Wed Oct 09 2016 - upstream
|
||||
- Update to version 0.65
|
||||
+ Translation fixes
|
||||
+ Project settings have priority
|
||||
+ Reject binary files in patches
|
||||
+ Fix a race condition in diff_file
|
||||
+ Performance: Optimizations to the setup command
|
||||
+ Performance: Optimizations to the bash completion script
|
||||
+ Test suite: Improve the edit test case
|
||||
+ Test suite: Make the symlink test more robust
|
||||
+ Test suite: Test backup failure
|
||||
+ Test suite: Test the header command with hard links
|
||||
+ diff: Report diff failures
|
||||
+ edit: Fix a corner case bug
|
||||
+ mail: Fix the help text
|
||||
+ push: Fix the synopsis
|
||||
+ refresh: Do not remove symlinks
|
||||
+ refresh: Break links to read-only patch files
|
||||
+ refresh: Always preserve modification time
|
||||
+ setup: Report failed look-ups in inspect-wrapper
|
||||
+ quilt.el: Fix quilt-editable when patches are stored in subdirs
|
||||
+ bash_completion: Handle spaces in file names
|
||||
+ bash_completion: Update the list of commands
|
||||
+ bash_completion: Add new command options
|
||||
+ bash_completion: Fix handling of mail, new, push options
|
||||
+ guards: Simplify the help text
|
||||
+ guards: Include the file name also in the "Not found" case
|
||||
+ guards: Add support for an external filelist in --check mode
|
||||
+ guards: Report which config file has problem in --check mode
|
||||
+ guards: Documentation update
|
||||
+ guards: Clarify a user message
|
||||
|
||||
* Mon Feb 09 2015 - upstream
|
||||
- Update to version 0.64
|
||||
+ Check for series file consistency
|
||||
+ Performance: Several optimizations
|
||||
+ Test suite: Several fixes and coverage improvements
|
||||
+ Test suite: Run the tests in predictable order
|
||||
+ files: Add support for unapplied patches
|
||||
+ graph: Check for graphviz availability
|
||||
+ mail: Remove procmail dependency
|
||||
+ mail: Don't include the release number in User-Agent
|
||||
+ pop: Add --refresh option
|
||||
+ push: Add --refresh option
|
||||
+ push: Do not use interactive mode with -f
|
||||
+ setup: Skip version check
|
||||
+ setup: Check for rpmbuild availability
|
||||
+ setup: Handle long options passed to tar
|
||||
+ setup: Several cleanups and minor fixes
|
||||
+ setup: Major performance optimizations
|
||||
+ setup: Fix path to extra patches in series file
|
||||
+ setup: Trace calls earlier
|
||||
+ setup: Add --fast option
|
||||
+ setup: Fix link creation
|
||||
+ quilt.el: Fix tramp support
|
||||
+ quilt.el: Fix patch select completion
|
||||
|
||||
* Sun May 25 2014 - upstream
|
||||
- Update to version 0.63
|
||||
+ New NEWS file, containing a human-readable changelog
|
||||
+ Option -E is no longer passed to patch by default
|
||||
+ Huge performance improvement (e.g., for commands series, applied and
|
||||
unapplied)
|
||||
+ configure: Add compat symlinks for md5sum
|
||||
+ Return 2 when there is nothing to do, contrasting with errors (ret=1)
|
||||
+ Exit with an error when diff's retcode=2 (error) on patch refresh
|
||||
+ bash_completion: cleanups and performance improvement (Savannah's #27111)
|
||||
+ test/run: Use perl module Text::ParseWords (+ performance improvement)
|
||||
+ Add some tests to our testsuite, for a better coverage
|
||||
+ Fix heuristic for unapplied patches with timestamps
|
||||
+ Bug fix: Patches emptying files should work now
|
||||
+ Bug fix: Check for duplicate patch in series (Savannah's #20628)
|
||||
+ Portability fixes for older Bash and GNU patch
|
||||
|
||||
* Wed May 07 2014 - upstream
|
||||
- Update to version 0.62
|
||||
+ Was a buggy release, with an incomplete tarfile
|
||||
|
||||
* Sun Dec 08 2013 - upstream
|
||||
- Update to version 0.61
|
||||
+ Almost two years of fixes and minor improvements
|
||||
+ Fix support for ./configure --with-xargs
|
||||
+ Parameter quoting fixes to many commands
|
||||
+ Various fixes to the pop, push, refresh and patches commands
|
||||
+ Translation fixes
|
||||
+ setup: Many fixes and improvements
|
||||
+ remove-trailing-ws: Several fixes and improvements
|
||||
+ remove-trailing-ws: Add a dedicated test case
|
||||
+ quilt.el: Many fixes and improvements (emacs integration)
|
||||
|
||||
* Wed Feb 29 2012 - upstream
|
||||
- Update to version 0.60
|
||||
+ BSD compatibility improvements
|
||||
+ grep: Support file names which include spaces
|
||||
+ import: Fix import of relative patches
|
||||
+ mail: Several fixes
|
||||
+ setup: Support directory and archive names which include spaces
|
||||
+ backup-files: rewritten from C to bash
|
||||
+ backup-files: Add a dedicated test case
|
||||
|
||||
* Sat Jan 28 2012 - upstream
|
||||
- Update to version 0.51
|
||||
+ Fix support for ./configure --docdir
|
||||
+ Various $TMPDIR fixes
|
||||
+ mail: Fix delivery address checking
|
||||
+ mail: CC people in more common patch headers
|
||||
+ push: Fix bash completion
|
||||
+ inspect: Complain if wrapper script can't be executed
|
||||
|
||||
* Mon Dec 5 2011 - upstream
|
||||
- Update to version 0.50
|
||||
+ 34 months of fixes and improvements, too many to list them all
|
||||
+ Fix detection of the patch version
|
||||
+ Avoid error messages when building due to missing git-desc file
|
||||
+ Add support for lzma and xz compression formats
|
||||
+ import: Fix confusing French translation
|
||||
+ mail: Stop using =~ for older versions of bash
|
||||
+ mail: Fix a temporary directory leak
|
||||
+ revert: Stop using cp -l
|
||||
+ revert: Add bash completion support
|
||||
+ setup: Add --fuzz parameter
|
||||
+ setup: Add support for reverse patches
|
||||
+ inspect: Fix shell syntax errors
|
||||
+ Fix error in test case create-delete
|
||||
|
||||
* Thu Jan 29 2009 - upstream
|
||||
- Update to version 0.48
|
||||
+ fold: Fix bash completion
|
||||
+ mail: Don't use GNU awk extensions
|
||||
+ mail: Check for formail
|
||||
+ setup: Fix for rpm 4.6
|
||||
+ Fix error in test case import
|
||||
|
||||
* Thu Aug 21 2008 - upstream
|
||||
- Update to version 0.47
|
||||
+ Change summary not available
|
||||
|
||||
* Thu Oct 19 2006 - upstream
|
||||
- Update to version 0.46
|
||||
+ Change summary not available
|
||||
|
||||
* Mon Apr 24 2006 - upstream
|
||||
- Update to version 0.45
|
||||
+ Change summary not available
|
||||
|
||||
* Tue Feb 14 2006 - upstream
|
||||
- Update to version 0.44
|
||||
+ Change summary not available
|
||||
|
||||
* Wed Feb 01 2006 - upstream
|
||||
- Update to version 0.43
|
||||
+ Change summary not available
|
||||
|
||||
* Tue Jul 26 2005 - upstream
|
||||
- Update to version 0.42
|
||||
+ Change summary not available
|
||||
|
||||
* Fri Apr 29 2005 - upstream
|
||||
- Update to version 0.40
|
||||
+ Change summary not available
|
||||
|
||||
* Thu Feb 10 2005 - upstream
|
||||
- Update to version 0.39
|
||||
+ Change summary not available
|
||||
|
||||
* Sun Oct 17 2004 - upstream
|
||||
- Update to version 0.37
|
||||
+ Change summary not available
|
||||
|
||||
* Wed Sep 22 2004 - upstream
|
||||
- Update to version 0.36
|
||||
+ Change summary not available
|
||||
|
||||
* Thu Jul 15 2004 - upstream
|
||||
- Update to version 0.35
|
||||
+ Change summary not available
|
||||
|
||||
* Thu Jun 10 2004 - upstream
|
||||
- Update to version 0.34
|
||||
+ Change summary not available
|
||||
|
||||
* Sun Jun 06 2004 - upstream
|
||||
- Update to version 0.33
|
||||
+ Change summary not available
|
||||
|
||||
* Sat Mar 13 2004 - upstream
|
||||
- Update to version 0.32
|
||||
+ Change summary not available
|
||||
|
||||
* Wed Jan 28 2004 - upstream
|
||||
- Update to version 0.30
|
||||
+ Change summary not available
|
||||
|
||||
* Wed Nov 12 2003 - upstream
|
||||
- Update to version 0.29
|
||||
+ Change summary not available
|
||||
|
||||
* Fri Oct 31 2003 - upstream
|
||||
- Update to version 0.28
|
||||
+ Change summary not available
|
||||
|
||||
* Tue Oct 28 2003 - upstream
|
||||
- Update to version 0.27
|
||||
+ Change summary not available
|
||||
|
||||
* Tue Oct 21 2003 - upstream
|
||||
- Update to version 0.26
|
||||
+ Change summary not available
|
|
@ -0,0 +1,62 @@
|
|||
#
|
||||
# spec file for quilt - patch management scripts
|
||||
#
|
||||
|
||||
Name: quilt
|
||||
Summary: Scripts for working with series of patches
|
||||
License: GPL
|
||||
Group: Productivity/Text/Utilities
|
||||
Version: @VERSION@
|
||||
Release: @RELEASE@
|
||||
Requires: coreutils diffutils findutils patch gzip bzip2 perl mktemp gettext
|
||||
Autoreqprov: off
|
||||
Source: quilt-%{version}.tar.gz
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
|
||||
%description
|
||||
The scripts allow to manage a series of patches by keeping
|
||||
track of the changes each patch makes. Patches can be
|
||||
applied, un-applied, refreshed, etc.
|
||||
|
||||
The scripts are heavily based on Andrew Morton's patch scripts
|
||||
found at http://userweb.kernel.org/~akpm/stuff/patch-scripts.tar.gz.
|
||||
|
||||
Authors:
|
||||
--------
|
||||
Andrew Morton <akpm@digeo.com>
|
||||
Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
CFLAGS="$RPM_OPT_FLAGS" \
|
||||
./configure --prefix=/usr \
|
||||
--mandir=%_mandir \
|
||||
--docdir=%_docdir/%{name}-%{version}
|
||||
make RELEASE=%release
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
make install prefix=/usr BUILD_ROOT=$RPM_BUILD_ROOT
|
||||
%{find_lang} %{name}
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files -f %{name}.lang
|
||||
%defattr(-, root, root)
|
||||
/usr/bin/guards
|
||||
/usr/bin/quilt
|
||||
/usr/share/quilt/
|
||||
/usr/share/emacs/
|
||||
/etc/bash_completion.d/quilt
|
||||
%config(noreplace) /etc/quilt.quiltrc
|
||||
%doc %{_mandir}/man1/guards.1*
|
||||
%doc %{_mandir}/man1/quilt.1*
|
||||
%doc %{_docdir}/%{name}-%{version}/README
|
||||
%doc %{_docdir}/%{name}-%{version}/README.MAIL
|
||||
%doc %{_docdir}/%{name}-%{version}/quilt.pdf
|
||||
|
||||
%changelog
|
||||
@CHANGELOG@
|
|
@ -0,0 +1,144 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt add [-P patch] {file} ...\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Add one or more files to the topmost or named patch. Files must be
|
||||
added to the patch before being modified. Files that are modified by
|
||||
patches already applied on top of the specified patch cannot be added.
|
||||
|
||||
-P patch
|
||||
Patch to add files to.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
in_valid_dir()
|
||||
{
|
||||
local p=$1 path
|
||||
|
||||
path=${p%/*}
|
||||
while [ "$p" != "$path" ]
|
||||
do
|
||||
if [ "$path" -ef "$QUILT_PATCHES" ]
|
||||
then
|
||||
printf $"File %s is located below %s\n" \
|
||||
"$1" "$QUILT_PATCHES/"
|
||||
return 1
|
||||
fi
|
||||
if [ "$path" -ef "$QUILT_PC" ]
|
||||
then
|
||||
printf $"File %s is located below %s\n" \
|
||||
"$1" "$QUILT_PC/"
|
||||
return 1
|
||||
fi
|
||||
p=$path
|
||||
path=${path%/*}
|
||||
done
|
||||
}
|
||||
|
||||
options=`getopt -o P:h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-P)
|
||||
opt_patch="$2"
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
patch=$(find_applied_patch "$opt_patch") || exit 1
|
||||
|
||||
status=0
|
||||
for file in "$@"
|
||||
do
|
||||
if ! in_valid_dir "$SUBDIR$file"
|
||||
then
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
if file_in_patch "$SUBDIR$file" $patch
|
||||
then
|
||||
printf $"File %s is already in patch %s\n" \
|
||||
"$SUBDIR$file" "$(print_patch $patch)" >&2
|
||||
[ $status -ne 1 ] && status=2
|
||||
continue
|
||||
fi
|
||||
next_patch=$(next_patch_for_file $patch "$SUBDIR$file")
|
||||
if [ -n "$next_patch" ]
|
||||
then
|
||||
printf $"File %s modified by patch %s\n" \
|
||||
"$SUBDIR$file" "$(print_patch $next_patch)" >&2
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -L "$SUBDIR$file" ]
|
||||
then
|
||||
printf $"Cannot add symbolic link %s\n" "$SUBDIR$file" >&2
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
|
||||
if ! $QUILT_DIR/scripts/backup-files -b -s -L -B $QUILT_PC/$patch/ "$SUBDIR$file"
|
||||
then
|
||||
printf $"Failed to back up file %s\n" "$SUBDIR$file" >&2
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -e "$SUBDIR$file" ]
|
||||
then
|
||||
# The original tree may be read-only.
|
||||
chmod u+w "$SUBDIR$file"
|
||||
fi
|
||||
|
||||
printf $"File %s added to patch %s\n" \
|
||||
"$SUBDIR$file" "$(print_patch $patch)"
|
||||
done
|
||||
exit $status
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,182 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt annotate [-P patch] {file}\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Print an annotated listing of the specified file showing which
|
||||
patches modify which lines. Only applied patches are included.
|
||||
|
||||
-P patch
|
||||
Stop checking for changes at the specified rather than the
|
||||
topmost patch.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
empty_file()
|
||||
{
|
||||
local file=$1
|
||||
[ -s "$file" ] \
|
||||
&& sed -e 's:.*::' "$file"
|
||||
}
|
||||
|
||||
annotation_for()
|
||||
{
|
||||
local old_file=$1 new_file=$2 annotation=$3
|
||||
[ -s "$old_file" ] || old_file=/dev/null
|
||||
[ -s "$new_file" ] || new_file=/dev/null
|
||||
diff -e "$old_file" "$new_file" \
|
||||
| perl -e '
|
||||
while (<>) {
|
||||
if (/^\d+(?:,\d+)?[ac]$/) {
|
||||
print;
|
||||
while (<>) {
|
||||
last if /^\.$/;
|
||||
print "'"$annotation"'\n";
|
||||
}
|
||||
print;
|
||||
next;
|
||||
}
|
||||
print;
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
merge_files()
|
||||
{
|
||||
local a b saved_IFS="$IFS"
|
||||
local template=$1 file=$2
|
||||
|
||||
[ -e "$file" ] || file=/dev/null
|
||||
|
||||
exec 3< "$template"
|
||||
exec 4< "$file"
|
||||
IFS=
|
||||
while read -r a <&3
|
||||
do
|
||||
read -r b <&4
|
||||
echo "$a"$'\t'"$b"
|
||||
done
|
||||
IFS="$saved_IFS"
|
||||
exec 3<&-
|
||||
exec 4<&-
|
||||
}
|
||||
|
||||
options=`getopt -o P:h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-P)
|
||||
opt_patch="$2"
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -ne 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
opt_file="$SUBDIR$1"
|
||||
|
||||
opt_patch=$(find_applied_patch "$opt_patch") || exit 1
|
||||
|
||||
for patch in $(applied_patches); do
|
||||
old_file="$(backup_file_name "$patch" "$opt_file")"
|
||||
if [ -f "$old_file" ]
|
||||
then
|
||||
patches[${#patches[@]}]="$patch"
|
||||
files[${#files[@]}]="$old_file"
|
||||
fi
|
||||
if [ "$opt_patch" = "$patch" ]
|
||||
then
|
||||
# We also need to know the next patch, if any
|
||||
next_patch="$(next_patch_for_file "$opt_patch" "$opt_file")"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$next_patch" ]
|
||||
then
|
||||
files[${#files[@]}]="$opt_file"
|
||||
else
|
||||
files[${#files[@]}]="$(backup_file_name "$next_patch" "$opt_file")"
|
||||
fi
|
||||
|
||||
if [ ${#patches[@]} = 0 ]
|
||||
then
|
||||
sed -e 's:^:'$'\t'':' "${files[${#files[@]}-1]}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
template=$(gen_tempfile)
|
||||
|
||||
add_exit_handler "rm -f $template"
|
||||
|
||||
# The annotated listing is generated as follows: A file of annotations
|
||||
# is created based on a file that contains the same number of lines as
|
||||
# the source file, but all lines are empty.
|
||||
#
|
||||
# Then, for each patch that modifies the source file, an ed-style diff
|
||||
# (which has no context, and removes lines that are removed without
|
||||
# caring for the line's contents) is generated. In that diff, all line
|
||||
# additions are replaced with the identifier of the patch (1, 2, ...).
|
||||
# These patches are then applied to the empty file.
|
||||
#
|
||||
# Finally, the annotations listing is merged with the source file line
|
||||
# by line.
|
||||
|
||||
setup_pager
|
||||
|
||||
empty_file ${files[0]} > $template
|
||||
for ((n = 0; n < ${#patches[@]}; n++))
|
||||
do
|
||||
annotation_for "${files[n]}" "${files[n+1]}" $((n+1))
|
||||
done \
|
||||
| patch $template
|
||||
merge_files $template "${files[${#files[@]}-1]}"
|
||||
|
||||
echo
|
||||
for ((n = 0; n < ${#patches[@]}; n++))
|
||||
do
|
||||
echo "$((n+1))"$'\t'"$(print_patch ${patches[n]})"
|
||||
done
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,68 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt applied [patch]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Print a list of applied patches, or all patches up to and including the
|
||||
specified patch in the file series.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o nh -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
patch=$(find_applied_patch "$1") || exit 1
|
||||
|
||||
setup_pager
|
||||
|
||||
printf "$(patch_format)\n" $(applied_before "$patch") "$patch"
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,143 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt delete [-r] [--backup] [patch|-n]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Remove the specified or topmost patch from the series file. If the
|
||||
patch is applied, quilt will attempt to remove it first. (Only the
|
||||
topmost patch can be removed right now.)
|
||||
|
||||
-n Delete the next patch after topmost, rather than the specified
|
||||
or topmost patch.
|
||||
|
||||
-r Remove the deleted patch file from the patches directory as well.
|
||||
|
||||
--backup
|
||||
Rename the patch file to patch~ rather than deleting it.
|
||||
Ignored if not used with \`-r'.
|
||||
"
|
||||
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o nrh --long backup -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-n)
|
||||
opt_next=1
|
||||
shift ;;
|
||||
-r)
|
||||
opt_remove=1
|
||||
shift ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--backup)
|
||||
QUILT_BACKUP=1
|
||||
shift ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 -o \( -n "$opt_next" -a $# -gt 0 \) ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
patch=$(find_patch "$1") || exit 1
|
||||
else
|
||||
patch=$(top_patch)
|
||||
fi
|
||||
if [ -n "$opt_next" ]
|
||||
then
|
||||
if ! patch=$(patch_after "$patch")
|
||||
then
|
||||
printf $"No next patch\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ -z "$patch" ]
|
||||
then
|
||||
# find_top_patch will display the proper error message for us
|
||||
find_top_patch > /dev/null
|
||||
exit 1
|
||||
fi
|
||||
if is_applied "$patch"; then
|
||||
if [ "$patch" != "$(top_patch)" ]
|
||||
then
|
||||
printf $"Patch %s is currently applied\n" \
|
||||
"$(print_patch "$patch")" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! quilt_command pop -fq
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if remove_from_series "$patch"
|
||||
then
|
||||
printf $"Removed patch %s\n" "$(print_patch "$patch")"
|
||||
else
|
||||
printf $"Failed to remove patch %s\n" "$(print_patch "$patch")" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
patch_file=$(patch_file_name "$patch")
|
||||
if [ "$opt_remove" -a -e "$patch_file" ]
|
||||
then
|
||||
if [ "$QUILT_BACKUP" ]
|
||||
then
|
||||
if ! mv -f "$patch_file" "$patch_file~"
|
||||
then
|
||||
printf $"Failed to backup patch file %s\n" \
|
||||
"$patch_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if ! rm -f "$patch_file"
|
||||
then
|
||||
printf $"Failed to remove patch file %s\n" \
|
||||
"$patch_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,384 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
setup_colors
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt diff [-p n|-p ab] [-u|-U num|-c|-C num] [--combine patch|-z] [-R] [-P patch] [--snapshot] [--diff=utility] [--no-timestamps] [--no-index] [--sort] [--color[=always|auto|never]] [file ...]\n"
|
||||
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Produces a diff of the specified file(s) in the topmost or specified
|
||||
patch. If no files are specified, all files that are modified are
|
||||
included.
|
||||
|
||||
-p n Create a -p n style patch (-p0 or -p1 are supported).
|
||||
|
||||
-p ab Create a -p1 style patch, but use a/file and b/file as the
|
||||
original and new filenames instead of the default
|
||||
dir.orig/file and dir/file names.
|
||||
|
||||
-u, -U num, -c, -C num
|
||||
Create a unified diff (-u, -U) with num lines of context. Create
|
||||
a context diff (-c, -C) with num lines of context. The number of
|
||||
context lines defaults to 3.
|
||||
|
||||
--no-timestamps
|
||||
Do not include file timestamps in patch headers.
|
||||
|
||||
--no-index
|
||||
Do not output Index: lines.
|
||||
|
||||
-z Write to standard output the changes that have been made
|
||||
relative to the topmost or specified patch.
|
||||
|
||||
-R Create a reverse diff.
|
||||
|
||||
-P patch
|
||||
Create a diff for the specified patch. (Defaults to the topmost
|
||||
patch.)
|
||||
|
||||
--combine patch
|
||||
Create a combined diff for all patches between this patch and
|
||||
the patch specified with -P. A patch name of \`-' is equivalent
|
||||
to specifying the first applied patch.
|
||||
|
||||
--snapshot
|
||||
Diff against snapshot (see \`quilt snapshot -h').
|
||||
|
||||
--diff=utility
|
||||
Use the specified utility for generating the diff. The utility
|
||||
is invoked with the original and new file name as arguments.
|
||||
|
||||
--color[=always|auto|never]
|
||||
Use syntax coloring (auto activates it only if the output is a tty).
|
||||
|
||||
--sort Sort files by their name instead of preserving the original order.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
colorize()
|
||||
{
|
||||
if [ -n "$opt_color" ]
|
||||
then
|
||||
sed -e '
|
||||
s/^\(Index:\|---\|+++\|\*\*\*\) .*/'$color_diff_hdr'&'$color_clear'/
|
||||
t ; s/^+.*/'$color_diff_add'&'$color_clear'/
|
||||
t ; s/^-.*/'$color_diff_rem'&'$color_clear'/
|
||||
t ; s/^!.*/'$color_diff_mod'&'$color_clear'/
|
||||
t ; s/^\(@@ \-[0-9]\+\(,[0-9]\+\)\? +[0-9]\+\(,[0-9]\+\)\? @@\)\([ \t]*\)\(.*\)/'$color_diff_hunk'\1'$color_clear'\4'$color_diff_ctx'\5'$color_clear'/
|
||||
t ; s/^\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*.*/'$color_diff_cctx'&'$color_clear'/
|
||||
'
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
|
||||
do_diff()
|
||||
{
|
||||
local file=$1 old_file=$2 new_file=$3 status
|
||||
|
||||
if [ -n "$opt_reverse" ]
|
||||
then
|
||||
local f=$new_file
|
||||
new_file=$old_file
|
||||
old_file=$f
|
||||
fi
|
||||
|
||||
if [ -n "$opt_diff" ]
|
||||
then
|
||||
[ -s "$old_file" ] || old_file=/dev/null
|
||||
[ -s "$new_file" ] || new_file=/dev/null
|
||||
if ! diff -q "$old_file" "$new_file" >/dev/null
|
||||
then
|
||||
export LANG=$ORIGINAL_LANG
|
||||
$opt_diff "$old_file" "$new_file"
|
||||
export LANG=POSIX
|
||||
true
|
||||
fi
|
||||
else
|
||||
diff_file "$file" "$old_file" "$new_file" | colorize
|
||||
|
||||
# Test the return value of diff, and propagate the error if any
|
||||
status=${PIPESTATUS[0]}
|
||||
if [ $status != 0 ]
|
||||
then
|
||||
die $status
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
die()
|
||||
{
|
||||
local status=$1
|
||||
[ -e "$tmp_files" ] && rm -f $tmp_files
|
||||
[ -n "$workdir" ] && rm -rf $workdir
|
||||
exit $status
|
||||
}
|
||||
|
||||
options=`getopt -o p:P:RuU:cC:zh --long diff:,snapshot,no-timestamps \
|
||||
--long no-index,combine:,color:: \
|
||||
--long sort -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
opt_format=-u
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-p)
|
||||
opt_strip_level=$2
|
||||
shift 2 ;;
|
||||
-P)
|
||||
last_patch=$2
|
||||
shift 2 ;;
|
||||
--combine)
|
||||
opt_combine=1
|
||||
if [ "$2" = - ]
|
||||
then
|
||||
first_patch=-
|
||||
else
|
||||
first_patch=$(find_applied_patch "$2") || exit 1
|
||||
fi
|
||||
shift 2 ;;
|
||||
-R)
|
||||
opt_reverse=1
|
||||
shift ;;
|
||||
-z)
|
||||
opt_relative=1
|
||||
shift ;;
|
||||
-u|-c)
|
||||
opt_format=$1
|
||||
shift ;;
|
||||
-U|-C)
|
||||
opt_format="$1 $2"
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--snapshot)
|
||||
opt_snapshot=1
|
||||
snap_subdir=.snap
|
||||
shift ;;
|
||||
--diff)
|
||||
opt_diff=$2
|
||||
shift 2 ;;
|
||||
--no-timestamps)
|
||||
QUILT_NO_DIFF_TIMESTAMPS=1
|
||||
shift ;;
|
||||
--no-index)
|
||||
QUILT_NO_DIFF_INDEX=1
|
||||
shift ;;
|
||||
--sort)
|
||||
opt_sort=1
|
||||
shift ;;
|
||||
--color)
|
||||
case "$2" in
|
||||
"" | always)
|
||||
opt_color=1 ;;
|
||||
auto | tty)
|
||||
opt_color=
|
||||
[ -t 1 ] && opt_color=1 ;;
|
||||
never)
|
||||
opt_color= ;;
|
||||
*)
|
||||
usage ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
QUILT_DIFF_OPTS="$QUILT_DIFF_OPTS $opt_format"
|
||||
|
||||
opt_files=( $(for file in "$@"; do echo "$SUBDIR${file#./}" ; done) )
|
||||
|
||||
if [ $[0$opt_combine + 0$opt_snapshot + 0$opt_relative] -gt 1 ]
|
||||
then
|
||||
printf $"Options \`--combine', \`--snapshot', and \`-z' cannot be combined.\n" >&2
|
||||
die 1
|
||||
fi
|
||||
|
||||
last_patch=$(find_applied_patch "$last_patch") || exit 1
|
||||
|
||||
if [ -z "$opt_strip_level" ]
|
||||
then
|
||||
opt_strip_level=$(patch_strip_level "$last_patch")
|
||||
fi
|
||||
case "$opt_strip_level" in
|
||||
0 | 1 | ab)
|
||||
;;
|
||||
*)
|
||||
printf $"Cannot diff patches with -p%s, please specify -p0, -p1, or -pab instead\n" \
|
||||
"$opt_strip_level" >&2
|
||||
die 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# If diffing against snapshot, ensure that snapshot is actually present
|
||||
if [ -n "$opt_snapshot" ] && [ ! -d "$QUILT_PC/$snap_subdir" ]
|
||||
then
|
||||
printf $"No snapshot to diff against\n" >&2
|
||||
die 1
|
||||
fi
|
||||
|
||||
trap "die 1" SIGTERM
|
||||
|
||||
tmp_files=$(gen_tempfile)
|
||||
exec 4> $tmp_files # open $tmp_files
|
||||
|
||||
if [ -n "$opt_snapshot" -a ${#opt_files[@]} -eq 0 ]
|
||||
then
|
||||
# Add all files in the snapshot into the file list (they may all
|
||||
# have changed).
|
||||
files=( $(find $QUILT_PC/$snap_subdir -type f \
|
||||
| sed -e "s/^$(quote_bre $QUILT_PC/$snap_subdir/)//" \
|
||||
| sort) )
|
||||
printf "%s\n" "${files[@]}" >&4
|
||||
unset files
|
||||
# Also look at all patches that are currently applied.
|
||||
opt_combine=1
|
||||
first_patch=$(applied_patches | head -n 1)
|
||||
fi
|
||||
|
||||
if [ -n "$opt_combine" ]
|
||||
then
|
||||
set -- $(patches_before "$last_patch") "$last_patch"
|
||||
if [ "$first_patch" != "-" ]
|
||||
then
|
||||
while [ $# -ge 1 -a "$1" != "$first_patch" ]
|
||||
do
|
||||
shift
|
||||
done
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
printf $"Patch %s not applied before patch %s\n" \
|
||||
"$(print_patch "$first_patch")" \
|
||||
"$(print_patch "$last_patch")" >&2
|
||||
die 1
|
||||
fi
|
||||
fi
|
||||
patches=( "$@" )
|
||||
else
|
||||
patches=( "$last_patch" )
|
||||
fi
|
||||
|
||||
# Properly handle spaces in file names
|
||||
saved_IFS=$IFS
|
||||
IFS=$'\n'
|
||||
|
||||
for patch in ${patches[@]}
|
||||
do
|
||||
for file in $(files_in_patch_ordered "$patch")
|
||||
do
|
||||
if [ ${#opt_files[@]} -gt 0 ] && \
|
||||
! in_array "$file" "${opt_files[@]}"
|
||||
then
|
||||
continue
|
||||
fi
|
||||
echo "$file" >&4
|
||||
done
|
||||
done
|
||||
|
||||
exec 4>&- # close $tmp_files
|
||||
|
||||
if [ -z "$opt_sort" ]
|
||||
then
|
||||
files=( $(
|
||||
awk '
|
||||
{ if ($0 in seen)
|
||||
next
|
||||
seen[$0]=1
|
||||
print
|
||||
}
|
||||
' $tmp_files) )
|
||||
else
|
||||
files=( $(sort -u $tmp_files) )
|
||||
fi
|
||||
|
||||
IFS=$saved_IFS
|
||||
|
||||
if [ -n "$opt_relative" ]
|
||||
then
|
||||
workdir=$(gen_tempfile -d $PWD/quilt)
|
||||
apply_patch_temporarily "$workdir" "$last_patch" "${files[@]}" \
|
||||
|| die 1
|
||||
fi
|
||||
|
||||
setup_pager
|
||||
|
||||
for file in "${files[@]}"
|
||||
do
|
||||
if [ -n "$opt_snapshot" -a -e "$QUILT_PC/$snap_subdir/$file" ]
|
||||
then
|
||||
old_file="$QUILT_PC/$snap_subdir/$file"
|
||||
elif [ -n "$opt_relative" ]
|
||||
then
|
||||
old_file="$workdir/$file"
|
||||
else
|
||||
patch=$(first_modified_by "$file" "${patches[@]}")
|
||||
if [ -z "$patch" ]
|
||||
then
|
||||
[ -z "$opt_snapshot" ] \
|
||||
&& printf $"File %s is not being modified\n" "$file" >&2
|
||||
continue
|
||||
fi
|
||||
old_file=$(backup_file_name "$patch" "$file")
|
||||
fi
|
||||
|
||||
next_patch=$(next_patch_for_file "$last_patch" "$file")
|
||||
if [ -z "$next_patch" ]
|
||||
then
|
||||
new_file=$file
|
||||
else
|
||||
new_file=$(backup_file_name "$next_patch" "$file")
|
||||
files_were_shadowed=1
|
||||
fi
|
||||
|
||||
do_diff "$file" "$old_file" "$new_file"
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
printf $"Diff failed, aborting\n" >&2
|
||||
die 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$files_were_shadowed" ]
|
||||
then
|
||||
printf $"Warning: more recent patches modify files in patch %s\n" \
|
||||
"$(print_patch "$last_patch")" >&2
|
||||
fi
|
||||
die 0
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,85 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
: ${EDITOR:=vi}
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt edit file ...\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Edit the specified file(s) in \$EDITOR (%s) after adding it (them) to
|
||||
the topmost patch.
|
||||
" "$EDITOR"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
quilt_command add "$@"
|
||||
status=$?
|
||||
if [ $status -ne 0 -a $status -ne 2 ]
|
||||
then
|
||||
exit $status
|
||||
fi
|
||||
LANG=$ORIGINAL_LANG $EDITOR "${@/#/$SUBDIR}"
|
||||
status=$?
|
||||
|
||||
patch=$(top_patch)
|
||||
for file in "$@"
|
||||
do
|
||||
if [ ! -e "$SUBDIR$file" -a ! -s "$QUILT_PC/$patch/$file" ]
|
||||
then
|
||||
quilt_command remove "$file"
|
||||
status=1
|
||||
fi
|
||||
done
|
||||
|
||||
exit $status
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,181 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt files [-v] [-a] [-l] [--combine patch] [patch]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Print the list of files that the topmost or specified patch changes.
|
||||
|
||||
-a List all files in all applied patches.
|
||||
|
||||
-l Add patch name to output.
|
||||
|
||||
-v Verbose, more user friendly output.
|
||||
|
||||
--combine patch
|
||||
Create a listing for all patches between this patch and
|
||||
the topmost or specified patch. A patch name of \`-' is
|
||||
equivalent to specifying the first applied patch.
|
||||
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o vhal --long combine: -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-v)
|
||||
opt_verbose=1
|
||||
shift ;;
|
||||
-a)
|
||||
opt_all=1
|
||||
shift ;;
|
||||
-l)
|
||||
opt_labels=1
|
||||
shift ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--combine)
|
||||
opt_all=1
|
||||
if [ "$2" = - ]
|
||||
then
|
||||
:
|
||||
else
|
||||
first_patch=$(find_patch_in_series "$2") || exit 1
|
||||
fi
|
||||
shift 2 ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
last_patch=$(find_patch_in_series "$1") || exit 1
|
||||
|
||||
if [ -n "$opt_all" -a -z "$first_patch" ]
|
||||
then
|
||||
first_patch=$(applied_patches | head -n 1)
|
||||
fi
|
||||
|
||||
if [ -n "$opt_all" ]
|
||||
then
|
||||
set -- $(patches_before "$last_patch") "$last_patch"
|
||||
while [ $# -ge 1 -a "$1" != "$first_patch" ]
|
||||
do
|
||||
shift
|
||||
done
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
printf $"Patch %s not applied before patch %s\n" \
|
||||
"$(print_patch "$first_patch")" \
|
||||
"$(print_patch "$last_patch")" >&2
|
||||
exit 1
|
||||
fi
|
||||
patches=( "$@" )
|
||||
else
|
||||
patches=( "$last_patch" )
|
||||
fi
|
||||
|
||||
list_files_in_patch()
|
||||
{
|
||||
local patch=$1
|
||||
local status
|
||||
local saved_IFS=$IFS
|
||||
|
||||
if [ -n "$opt_all" ] && [ -n "$opt_verbose" ] && [ -z "$opt_labels" ]
|
||||
then
|
||||
echo "$patch"
|
||||
fi
|
||||
if [ -n "$opt_verbose" ] && [ -z "$opt_labels" ]
|
||||
then
|
||||
use_status=yes
|
||||
fi
|
||||
# Note: If opt_labels is set, then use_status is not set.
|
||||
IFS=
|
||||
if is_applied "$patch"
|
||||
then
|
||||
files_in_patch "$patch"
|
||||
else
|
||||
filenames_in_patch "$patch"
|
||||
fi |
|
||||
sort |
|
||||
while read file
|
||||
do
|
||||
if [ -n "$opt_labels" ]
|
||||
then
|
||||
if [ -n "$opt_verbose" ]
|
||||
then
|
||||
echo -n "[$patch] "
|
||||
else
|
||||
echo -n "$patch "
|
||||
fi
|
||||
fi
|
||||
if [ -z "$use_status" ]
|
||||
then
|
||||
echo "$file"
|
||||
else
|
||||
status=" "
|
||||
if [ -s $(backup_file_name "$patch" "$file") ]
|
||||
then
|
||||
if ! [ -s "$file" ]
|
||||
then
|
||||
status="-"
|
||||
fi
|
||||
else
|
||||
if [ -s "$file" ]
|
||||
then
|
||||
status="+"
|
||||
fi
|
||||
fi
|
||||
echo "$status $file"
|
||||
fi
|
||||
done
|
||||
IFS=$saved_IFS
|
||||
}
|
||||
|
||||
setup_pager
|
||||
|
||||
for patch in "${patches[@]}"
|
||||
do
|
||||
list_files_in_patch "$patch"
|
||||
done
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,144 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt fold [-R] [-q] [-f] [-p strip-level]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Integrate the patch read from standard input into the topmost patch:
|
||||
After making sure that all files modified are part of the topmost
|
||||
patch, the patch is applied with the specified strip level (which
|
||||
defaults to 1).
|
||||
|
||||
-R Apply patch in reverse.
|
||||
|
||||
-q Quiet operation.
|
||||
|
||||
-f Force apply, even if the patch has rejects. Unless in quiet mode,
|
||||
apply the patch interactively: the patch utility may ask questions.
|
||||
|
||||
-p strip-level
|
||||
The number of pathname components to strip from file names
|
||||
when applying patchfile.
|
||||
"
|
||||
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o Rp:qfh -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-R)
|
||||
opt_reverse=1
|
||||
shift ;;
|
||||
-f)
|
||||
opt_force=1
|
||||
shift ;;
|
||||
-p)
|
||||
opt_strip_level=$2
|
||||
shift 2 ;;
|
||||
-q)
|
||||
opt_quiet=1
|
||||
shift ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
: ${opt_strip_level:=1}
|
||||
[ -n "$opt_quiet" ] && patch_args="$patch_args -s"
|
||||
[ -z "$opt_force" -o -n "$opt_quiet" ] && patch_args="$patch_args -f"
|
||||
[ -n "$opt_reverse" ] && patch_args="$patch_args -R"
|
||||
|
||||
top=$(find_top_patch) || exit 1
|
||||
|
||||
trap "failed=1" SIGINT
|
||||
|
||||
workdir=$(gen_tempfile -d $PWD)
|
||||
patch -d ${SUBDIR:-.} $QUILT_PATCH_OPTS -p$opt_strip_level \
|
||||
--backup --prefix="$workdir/$SUBDIR" $patch_args \
|
||||
|| failed=1
|
||||
|
||||
[ -n "$opt_force" ] && failed=
|
||||
|
||||
saved_IFS=$IFS
|
||||
IFS=$'\n'
|
||||
if [ -z "$failed" ]
|
||||
then
|
||||
# Copy additional files from workdir to the backup directory
|
||||
# For this patch
|
||||
for file in $(find $workdir -type f -a ! -path "$workdir/.timestamp")
|
||||
do
|
||||
file="${file:${#workdir}+1}"
|
||||
backup_file="$(backup_file_name $top "$file")"
|
||||
if ! [ -e "$backup_file" ]
|
||||
then
|
||||
if ! mkdir -p "$(dirname "$backup_file")" ||
|
||||
! ln "$workdir/$file" "$backup_file"
|
||||
then
|
||||
failed=1
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ -n "$failed" ]
|
||||
then
|
||||
# Restore all files to the state from before applying the patch
|
||||
for file in $(find $workdir -type f -a ! -path "$workdir/.timestamp")
|
||||
do
|
||||
file="${file:${#workdir}+1}"
|
||||
if ! mv -f "$workdir/$file" "$file"
|
||||
then
|
||||
printf $"File %s may be corrupted\n" "$file" >&2
|
||||
fi
|
||||
done
|
||||
rm -rf $workdir
|
||||
exit 1
|
||||
fi
|
||||
IFS=$saved_IFS
|
||||
|
||||
rm -rf $workdir
|
||||
exit 0
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,108 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt fork [new_name]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Fork the topmost patch. Forking a patch means creating a verbatim copy
|
||||
of it under a new name, and use that new name instead of the original
|
||||
one in the current series. This is useful when a patch has to be
|
||||
modified, but the original version of it should be preserved, e.g.
|
||||
because it is used in another series, or for the history. A typical
|
||||
sequence of commands would be: fork, edit, refresh.
|
||||
|
||||
If new_name is missing, the name of the forked patch will be the current
|
||||
patch name, followed by \`-2'. If the patch name already ends in a
|
||||
dash-and-number, the number is further incremented (e.g., patch.diff,
|
||||
patch-2.diff, patch-3.diff).
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
top_patch=$(find_top_patch) || exit 1
|
||||
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
new_patch="$1"
|
||||
else
|
||||
new_patch="$(next_filename "$top_patch")"
|
||||
fi
|
||||
|
||||
new_patch=${new_patch#$QUILT_PATCHES/}
|
||||
|
||||
if patch_in_series $new_patch || \
|
||||
[ -d "$QUILT_PC/$new_patch" ] || \
|
||||
[ -e "$(patch_file_name $new_patch)" ]
|
||||
then
|
||||
printf $"Patch %s exists already, please choose a new name\n" \
|
||||
"$(print_patch $new_patch)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! rename_in_db "$top_patch" "$new_patch" || \
|
||||
! rename_in_series "$top_patch" "$new_patch" || \
|
||||
! mv "$QUILT_PC/$top_patch" "$QUILT_PC/$new_patch" || \
|
||||
( [ -e "$(patch_file_name $top_patch)" ] && \
|
||||
! cp -p "$(patch_file_name $top_patch)" \
|
||||
"$(patch_file_name $new_patch)" )
|
||||
then
|
||||
printf $"Fork of patch %s to patch %s failed\n" \
|
||||
"$(print_patch $top_patch)" \
|
||||
"$(print_patch $new_patch)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf $"Fork of patch %s created as %s\n" \
|
||||
"$(print_patch $top_patch)" \
|
||||
"$(print_patch $new_patch)"
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,135 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt graph [--all] [--reduce] [--lines[=num]] [--edge-labels=files] [-T ps] [patch]\n"
|
||||
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Generate a dot(1) directed graph showing the dependencies between
|
||||
applied patches. A patch depends on another patch if both touch the same
|
||||
file or, with the --lines option, if their modifications overlap. Unless
|
||||
otherwise specified, the graph includes all patches that the topmost
|
||||
patch depends on.
|
||||
When a patch name is specified, instead of the topmost patch, create a
|
||||
graph for the specified patch. The graph will include all other patches
|
||||
that this patch depends on, as well as all patches that depend on this
|
||||
patch.
|
||||
|
||||
--all Generate a graph including all applied patches and their
|
||||
dependencies. (Unapplied patches are not included.)
|
||||
|
||||
--reduce
|
||||
Eliminate transitive edges from the graph.
|
||||
|
||||
--lines[=num]
|
||||
Compute dependencies by looking at the lines the patches modify.
|
||||
Unless a different num is specified, two lines of context are
|
||||
included.
|
||||
|
||||
--edge-labels=files
|
||||
Label graph edges with the file names that the adjacent patches
|
||||
modify.
|
||||
|
||||
-T ps Directly produce a PostScript output file.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o T:h --long all,reduce,lines::,edge-labels: -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-T) if [ "$2" != ps ]; then
|
||||
usage
|
||||
fi
|
||||
opt_format=ps
|
||||
shift 2 ;;
|
||||
|
||||
--all)
|
||||
opt_all=1
|
||||
shift ;;
|
||||
|
||||
--reduce)
|
||||
opt_reduce=1
|
||||
shift ;;
|
||||
|
||||
--lines)
|
||||
opt_lines=${2:-2}
|
||||
shift 2 ;;
|
||||
|
||||
--edge-labels)
|
||||
if [ "$2" != files ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
opt_edge_labels=$2
|
||||
shift 2 ;;
|
||||
|
||||
-h)
|
||||
usage -h ;;
|
||||
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 -o \( $# -ne 0 -a -n "$opt_all" \) ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
[ "$opt_format" = "ps" ] && check_external_tool dot graphviz -T
|
||||
[ -n "$opt_reduce" ] && check_external_tool tred graphviz --reduce
|
||||
|
||||
if [ -z "$opt_all" ]
|
||||
then
|
||||
patch=$(find_applied_patch "$1") || exit 1
|
||||
fi
|
||||
|
||||
options=
|
||||
[ -n "$patch" ] && options="--select-patch $patch"
|
||||
[ -n "$opt_reduce" ] && options="$options --reduce"
|
||||
[ "$opt_edge_labels" = files ] && options="$options --edge-files"
|
||||
[ -n "$opt_lines" ] && options="$options --lines=$opt_lines"
|
||||
|
||||
pipe=
|
||||
[ -n "$opt_format" ] && pipe="| dot -T$opt_format"
|
||||
|
||||
export QUILT_PC
|
||||
applied_patches \
|
||||
| eval $QUILT_DIR/scripts/dependency-graph $options - $pipe
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,133 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt grep [-h|options] {pattern}\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Grep through the source files, recursively, skipping patches and quilt
|
||||
meta-information. If no filename argument is given, the whole source
|
||||
tree is searched. Please see the grep(1) manual page for options.
|
||||
|
||||
-h Print this help. The grep -h option can be passed after a
|
||||
double-dash (--). Search expressions that start with a dash
|
||||
can be passed after a second double-dash (-- --).
|
||||
"
|
||||
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
get_options()
|
||||
{
|
||||
getopt -o EFGPe:f:iwxzsvVm:bHnhqoaId:D:RrlLcB:ZA:C:Uu \
|
||||
--long extended-regexp,fixed-strings,basic-regexp,perl-regexp \
|
||||
--long regexp:,file:,ignore-case,word-regexp \
|
||||
--long line-regexp,null-data,no-messages,invert-match,version \
|
||||
--long help,mmap,max-count:,byte-offset,line-number \
|
||||
--long line-buffered,with-filename,no-filename,label: \
|
||||
--long only-matching,quiet,silent,binary-files:,text, \
|
||||
--long directories:,devices:,recursive,include:,exclude: \
|
||||
--long exclude-from:,files-without-match,files-with-matches \
|
||||
--long count,null,before-context:,after-context:,context: \
|
||||
--long color::,colour::,binary,unix-byte-offsets \
|
||||
-- "$@"
|
||||
}
|
||||
|
||||
shift_myargs()
|
||||
{
|
||||
set -- "${myargs[@]}"
|
||||
shift
|
||||
myargs=( "$@" )
|
||||
}
|
||||
|
||||
shift_args()
|
||||
{
|
||||
while true
|
||||
do
|
||||
case "${myargs[0]}" in
|
||||
--)
|
||||
shift_myargs
|
||||
return ;;
|
||||
-h)
|
||||
opt_h=1 ;;
|
||||
-e|-f|--regexp|--file)
|
||||
has_pattern=1
|
||||
args=( "${args[@]}" "${myargs[0]}" )
|
||||
shift_myargs ;;
|
||||
-m|-d|-D|-B|-A|-C|\
|
||||
--max-count|--label|--binary-files|\
|
||||
--directories|--devices|--include|--exclude|--exclude-from|\
|
||||
--before-context|--after-context|--context|--color|--colour)
|
||||
args=( "${args[@]}" "${myargs[0]}" )
|
||||
shift_myargs ;;
|
||||
esac
|
||||
args=( "${args[@]}" "${myargs[0]}" )
|
||||
shift_myargs
|
||||
done
|
||||
}
|
||||
|
||||
options=$(get_options "$@")
|
||||
[ $? -ne 0 ] && usage
|
||||
eval set -- "$options"
|
||||
myargs=( "$@" )
|
||||
|
||||
args=()
|
||||
opt_h=
|
||||
has_pattern=
|
||||
shift_args
|
||||
[ -n "$opt_h" ] && usage -h
|
||||
case "${myargs[0]}" in
|
||||
-*)
|
||||
options=$(get_options "${myargs[@]}")
|
||||
[ $? -ne 0 ] && usage
|
||||
eval set -- "$options"
|
||||
myargs=( "$@" )
|
||||
shift_args ;;
|
||||
esac
|
||||
|
||||
if [ -z "$has_pattern" ]
|
||||
then
|
||||
[ ${#myargs[@]} -eq 0 ] && usage
|
||||
args=( "${args[@]}" -- "${myargs[0]}" )
|
||||
shift_myargs
|
||||
fi
|
||||
|
||||
# Print the filename for each match, unless -h is given. Otherwise, xargs
|
||||
# may pass a single filename to grep and cause it to omit the file name.
|
||||
[ -z "$opt_h" ] && opt_H=-H
|
||||
|
||||
find "${myargs[@]:-.}" \( \
|
||||
-path "./$QUILT_PATCHES/*" -o \
|
||||
-path "./$QUILT_PC/*" \) -prune -o \
|
||||
-type f -print0 \
|
||||
| xargs -0 grep $opt_H "${args[@]}" \
|
||||
| if [ ${#myargs[@]} -eq 0 ]; then
|
||||
sed -e 's,^./,,'
|
||||
else
|
||||
cat
|
||||
fi
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,182 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
: ${EDITOR:=vi}
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt header [-a|-r|-e] [--backup] [--strip-diffstat] [--strip-trailing-whitespace] [patch]\n"
|
||||
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Print or change the header of the topmost or specified patch.
|
||||
|
||||
-a, -r, -e
|
||||
Append to (-a) or replace (-r) the exiting patch header, or
|
||||
edit (-e) the header in \$EDITOR (%s). If none of these options is
|
||||
given, print the patch header.
|
||||
|
||||
--strip-diffstat
|
||||
Strip diffstat output from the header.
|
||||
|
||||
--strip-trailing-whitespace
|
||||
Strip trailing whitespace at the end of lines of the header.
|
||||
|
||||
--backup
|
||||
Create a backup copy of the old version of a patch as patch~.
|
||||
" "$EDITOR"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
maybe_strip_trailing_whitespace()
|
||||
{
|
||||
if [ -n "$opt_strip_trailing_whitespace" ]
|
||||
then
|
||||
sed -e 's:[ '$'\t'']*$::'
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
|
||||
maybe_strip_diffstat()
|
||||
{
|
||||
if [ -n "$opt_strip_diffstat" ]
|
||||
then
|
||||
strip_diffstat
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o areh --long backup,strip-trailing-whitespace,strip-diffstat -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-a)
|
||||
opt_append=1
|
||||
shift ;;
|
||||
-r)
|
||||
opt_replace=1
|
||||
shift ;;
|
||||
-e)
|
||||
opt_edit=1
|
||||
shift ;;
|
||||
--backup)
|
||||
QUILT_BACKUP=1
|
||||
shift ;;
|
||||
--strip-diffstat)
|
||||
opt_strip_diffstat=1
|
||||
shift ;;
|
||||
--strip-trailing-whitespace)
|
||||
opt_strip_trailing_whitespace=1
|
||||
shift ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$opt_append$opt_replace$opt_edit"
|
||||
in
|
||||
''|1) ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
|
||||
if [ $# -gt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
patch=$(find_patch_in_series "$1") || exit 1
|
||||
|
||||
patch_file=$(patch_file_name $patch)
|
||||
|
||||
if [ -z "$opt_replace" -a -z "$opt_append" -a -z "$opt_edit" ]
|
||||
then
|
||||
[ -e "$patch_file" ] || exit 0
|
||||
|
||||
setup_pager
|
||||
|
||||
cat_file "$patch_file" \
|
||||
| patch_header \
|
||||
| maybe_strip_diffstat \
|
||||
| maybe_strip_trailing_whitespace
|
||||
else
|
||||
patch_file_or_null=/dev/null
|
||||
[ -e "$patch_file" ] && patch_file_or_null=$patch_file
|
||||
|
||||
tmp=$(gen_tempfile) || exit 1
|
||||
tmp2=$(gen_tempfile) || exit 1
|
||||
add_exit_handler "rm -f $tmp $tmp2"
|
||||
|
||||
( if [ -z "$opt_replace" ]
|
||||
then
|
||||
cat_file $patch_file_or_null | patch_header
|
||||
fi
|
||||
if [ -n "$opt_append" -o -n "$opt_replace" ]
|
||||
then
|
||||
cat
|
||||
fi
|
||||
) > $tmp
|
||||
|
||||
if [ -n "$opt_edit" ]
|
||||
then
|
||||
LANG=$ORIGINAL_LANG $EDITOR "$tmp" || exit 1
|
||||
fi
|
||||
|
||||
# Ensure there is a trailing newline before we append the rest
|
||||
ensure_trailing_newline $tmp
|
||||
|
||||
maybe_strip_diffstat < $tmp \
|
||||
| maybe_strip_trailing_whitespace > $tmp2
|
||||
|
||||
cat_file "$patch_file_or_null" | patch_body >> $tmp2 || exit 1
|
||||
|
||||
if cat_to_new_file $patch_file $QUILT_BACKUP < $tmp2
|
||||
then
|
||||
if [ -z "$opt_append" ]
|
||||
then
|
||||
printf \
|
||||
$"Replaced header of patch %s\n" "$(print_patch $patch)"
|
||||
else
|
||||
printf \
|
||||
$"Appended text to header of patch %s\n" "$(print_patch $patch)"
|
||||
fi
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,258 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt import [-p num] [-R] [-P patch] [-f] [-d {o|a|n}] patchfile ...\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Import external patches. The patches will be inserted following the
|
||||
current top patch, and must be pushed after import to apply them.
|
||||
|
||||
-p num
|
||||
Number of directory levels to strip when applying (default=1)
|
||||
|
||||
-R
|
||||
Apply patch in reverse.
|
||||
|
||||
-P patch
|
||||
Patch filename to use inside quilt. This option can only be
|
||||
used when importing a single patch.
|
||||
|
||||
-f Overwrite/update existing patches.
|
||||
|
||||
-d {o|a|n}
|
||||
When overwriting in existing patch, keep the old (o), all (a), or
|
||||
new (n) patch header. If both patches include headers, this option
|
||||
must be specified. This option is only effective when -f is used.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
find_patch_file()
|
||||
{
|
||||
local name="$1"
|
||||
|
||||
if [ ${name:0:1} = / ]
|
||||
then
|
||||
# Patch has absolute path
|
||||
if [ -r "$name" ]
|
||||
then
|
||||
echo "$name"
|
||||
return
|
||||
fi
|
||||
else
|
||||
# Patch has a relative path
|
||||
if [ -r "$SUBDIR$name" ]
|
||||
then
|
||||
echo "$SUBDIR$name"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
printf $"Patch %s does not exist\n" "$name" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
merge_patches()
|
||||
{
|
||||
local old="$1" new="$2"
|
||||
local old_desc=$(gen_tempfile) new_desc=$(gen_tempfile)
|
||||
|
||||
cat_file "$old" | patch_header | strip_diffstat > $old_desc
|
||||
cat_file "$new" | patch_header | strip_diffstat > $new_desc
|
||||
|
||||
if [ -z "$opt_desc" ]
|
||||
then
|
||||
[ -s $old_desc ] || opt_desc=n
|
||||
[ -z "$opt_desc" -a ! -s $new_desc ] && opt_desc=o
|
||||
|
||||
if [ -z "$opt_desc" ]
|
||||
then
|
||||
local diff=$(diff -u $old_desc $new_desc \
|
||||
| sed -e '1,2d')
|
||||
if [ -n "$diff" ]
|
||||
then
|
||||
printf $"Patch headers differ:\n" >&2
|
||||
echo "$diff" >&2
|
||||
printf \
|
||||
$"Please use -d {o|a|n} to specify which patch header(s) to keep.\n" >&2
|
||||
rm -f $old_desc $new_desc
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
[ "$opt_desc" = n ] || cat "$old_desc"
|
||||
[ "$opt_desc" = a ] && echo '---'
|
||||
if [ "$opt_desc" = o ]
|
||||
then
|
||||
cat_file "$new" | patch_body
|
||||
else
|
||||
cat_file "$new"
|
||||
fi
|
||||
rm -f $old_desc $new_desc
|
||||
}
|
||||
|
||||
die()
|
||||
{
|
||||
local status=$1
|
||||
[ "$merged_patch_file" != "$patch_file" ] && rm -f "$merged_patch_file"
|
||||
exit $status
|
||||
}
|
||||
|
||||
options=`getopt -o P:d:fp:Rh -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-P)
|
||||
opt_patch=${2#$QUILT_PATCHES/}
|
||||
shift 2 ;;
|
||||
-p)
|
||||
opt_strip=$2
|
||||
shift 2 ;;
|
||||
-R)
|
||||
opt_reverse=1
|
||||
shift ;;
|
||||
-d)
|
||||
case "$2" in
|
||||
o|n|a) opt_desc=$2 ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
-f)
|
||||
opt_force=1
|
||||
shift ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 -a -n "$opt_patch" ]
|
||||
then
|
||||
printf $"Option \`-P' can only be used when importing a single patch\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ -n "$opt_strip" ] && patch_args="-p$opt_strip"
|
||||
if [ -n "$opt_reverse" ]
|
||||
then
|
||||
if [ -n "$patch_args" ]
|
||||
then
|
||||
patch_args="$patch_args -R"
|
||||
else
|
||||
patch_args="-R"
|
||||
fi
|
||||
fi
|
||||
|
||||
before=$(patch_after "$(top_patch)")
|
||||
for orig_patch_file in "$@"
|
||||
do
|
||||
if [ -n "$opt_patch" ]
|
||||
then
|
||||
patch=$opt_patch
|
||||
else
|
||||
patch=${orig_patch_file##*/}
|
||||
fi
|
||||
|
||||
patch_file=$(find_patch_file "$orig_patch_file") || exit 1
|
||||
merged_patch_file="$patch_file"
|
||||
|
||||
if is_applied $patch
|
||||
then
|
||||
printf $"Patch %s is applied\n" "$(print_patch $patch)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dest=$(patch_file_name $patch)
|
||||
if patch_in_series "$patch"
|
||||
then
|
||||
if [ "$patch_file" = "$dest" ]
|
||||
then
|
||||
printf $"Patch %s already exists in series.\n" \
|
||||
"$(print_patch $patch)" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$opt_force" ]
|
||||
then
|
||||
printf $"Patch %s exists. Replace with -f.\n" \
|
||||
"$(print_patch $patch)" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$opt_desc" != n ]
|
||||
then
|
||||
merged_patch_file=$(gen_tempfile)
|
||||
merge_patches "$dest" "$patch_file" \
|
||||
> $merged_patch_file \
|
||||
|| die 1
|
||||
fi
|
||||
printf $"Replacing patch %s with new version\n" \
|
||||
"$(print_patch $patch)" >&2
|
||||
elif [ -e "$dest" ]
|
||||
then
|
||||
printf $"Importing patch %s\n" "$(print_patch $patch)"
|
||||
else
|
||||
printf $"Importing patch %s (stored as %s)\n" \
|
||||
"$orig_patch_file" \
|
||||
"$(print_patch $patch)"
|
||||
|
||||
mkdir -p "${dest%/*}"
|
||||
fi
|
||||
|
||||
if [ "$merged_patch_file" != "$dest" ] && \
|
||||
(( [ "$merged_patch_file" != "$patch_file" ] && \
|
||||
! cat_to_new_file "$dest" < "$merged_patch_file" ) || \
|
||||
( [ "$merged_patch_file" = "$patch_file" ] && \
|
||||
! cp "$merged_patch_file" "$dest" ))
|
||||
then
|
||||
printf $"Failed to import patch %s\n" "$(print_patch $patch)" >&2
|
||||
die 1
|
||||
fi
|
||||
|
||||
[ "$merged_patch_file" != "$patch_file" ] && rm -f "$merged_patch_file"
|
||||
|
||||
if ! patch_in_series $patch &&
|
||||
! insert_in_series $patch "$patch_args" "$before"
|
||||
then
|
||||
printf $"Failed to insert patch %s into file series\n" \
|
||||
"$(print_patch $patch)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf $QUILT_PC/$patch
|
||||
done
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,700 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
: ${EDITOR:=vi}
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt mail {--mbox file|--send} [-m text] [-M file] [--prefix prefix] [--sender ...] [--from ...] [--to ...] [--cc ...] [--bcc ...] [--subject ...] [--reply-to message] [--charset ...] [--signature file] [first_patch [last_patch]]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Create mail messages from a specified range of patches, or all patches in
|
||||
the series file, and either store them in a mailbox file, or send them
|
||||
immediately. The editor is opened with a template for the introduction.
|
||||
Please see %s for details.
|
||||
When specifying a range of patches, a first patch name of \`-' denotes the
|
||||
first, and a last patch name of \`-' denotes the last patch in the series.
|
||||
|
||||
-m text
|
||||
Text to use as the text in the introduction. When this option is
|
||||
used, the editor will not be invoked, and the patches will be
|
||||
processed immediately.
|
||||
|
||||
-M file
|
||||
Like the -m option, but read the introduction from file.
|
||||
|
||||
--prefix prefix
|
||||
Use an alternate prefix in the bracketed part of the subjects
|
||||
generated. Defaults to \`patch'.
|
||||
|
||||
--mbox file
|
||||
Store all messages in the specified file in mbox format. The mbox
|
||||
can later be sent using formail, for example.
|
||||
|
||||
--send
|
||||
Send the messages directly.
|
||||
|
||||
--sender
|
||||
The envelope sender address to use. The address must be of the form
|
||||
\`user@domain.name'. No display name is allowed.
|
||||
|
||||
--from, --subject
|
||||
The values for the From and Subject headers to use. If no --from
|
||||
option is given, the value of the --sender option is used.
|
||||
|
||||
--to, --cc, --bcc
|
||||
Append a recipient to the To, Cc, or Bcc header.
|
||||
|
||||
--charset
|
||||
Specify a particular message encoding on systems which don't use
|
||||
UTF-8 or ISO-8859-15. This character encoding must match the one
|
||||
used in the patches.
|
||||
|
||||
--signature file
|
||||
Append the specified signature to messages (defaults to ~/.signature
|
||||
if found; use \`-' for no signature).
|
||||
|
||||
--reply-to message
|
||||
Add the appropriate headers to reply to the specified message.
|
||||
" "@DOCSUBDIR@/README.MAIL"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
msgid()
|
||||
{
|
||||
local timestamp=$(date --utc "+%Y%m%d%H%M%S.%N")
|
||||
echo "$timestamp@${opt_sender_address#*@}"
|
||||
}
|
||||
|
||||
# Extract RFC 2822 compliant header values, including Long Header Fields,
|
||||
# from messages
|
||||
|
||||
extract_header_value()
|
||||
{
|
||||
local header=$1
|
||||
|
||||
# Long Header Fields may span multiple lines, in which case CRLF
|
||||
# is followed by space or tab (RFC 2822)
|
||||
sed -ne "/^${header}/I,/^[^[:blank:]]/ { /^${header}/I { s/^${header}//I; p; n; }; /^[^[:blank:]]/q; /^$/q; p; }"
|
||||
}
|
||||
|
||||
# See RFC 2822 Internet Message Format for how the In-Reply-To and
|
||||
# References headers are generated...
|
||||
|
||||
in_reply_to_header()
|
||||
{
|
||||
local message=$1 message_id
|
||||
|
||||
message_id=$(extract_header_value Message-ID: < "$message")
|
||||
message_id=${message_id# }
|
||||
[ -n "$message_id" ] && echo "In-Reply-To: $message_id"
|
||||
}
|
||||
|
||||
references_header()
|
||||
{
|
||||
local message=$1 message_id references in_reply_to
|
||||
|
||||
message_id=$(extract_header_value Message-ID: < "$message")
|
||||
message_id=${message_id# }
|
||||
|
||||
references=$(extract_header_value References: < "$message")
|
||||
references=${references# }
|
||||
if [ -z "$references" ]
|
||||
then
|
||||
in_reply_to=$(extract_header_value In-Reply-To: < "$message")
|
||||
in_reply_to=${in_reply_to# }
|
||||
if [ -n "$in_reply_to" ]
|
||||
then
|
||||
case "$in_reply_to" in
|
||||
*@*@*)
|
||||
;;
|
||||
*) references=$in_reply_to
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
if [ -z "$references" ]
|
||||
then
|
||||
references=$message_id
|
||||
elif [ -n "$message_id" ]
|
||||
then
|
||||
references="$references"$'\n '"$message_id"
|
||||
fi
|
||||
[ -n "$references" ] && echo "References: $references"
|
||||
}
|
||||
|
||||
process_mail()
|
||||
{
|
||||
local tmpfile=$(gen_tempfile)
|
||||
|
||||
cat > $tmpfile
|
||||
|
||||
set -- $($QUILT_DIR/scripts/edmail --charset $opt_charset \
|
||||
--extract-recipients To \
|
||||
--extract-recipients Cc \
|
||||
--extract-recipients Bcc \
|
||||
< $tmpfile)
|
||||
if [ -n "$opt_send" ]
|
||||
then
|
||||
echo ${QUILT_SENDMAIL:-sendmail} \
|
||||
${QUILT_SENDMAIL_ARGS--f "$opt_sender"} "$@"
|
||||
$QUILT_DIR/scripts/edmail --charset $opt_charset \
|
||||
--remove-header Bcc < $tmpfile \
|
||||
| ${QUILT_SENDMAIL:-sendmail} \
|
||||
${QUILT_SENDMAIL_ARGS--f "$opt_sender"} "$@"
|
||||
else
|
||||
local from_date=$(LC_ALL=POSIX date "+%a %b %e %H:%M:%S %Y")
|
||||
echo "From $opt_sender_address $from_date"
|
||||
sed -e 's/^From />From /' $tmpfile
|
||||
echo
|
||||
fi
|
||||
rm -f $tmpfile
|
||||
}
|
||||
|
||||
join_lines()
|
||||
{
|
||||
awk '
|
||||
BEGIN { RS="\n\n" }
|
||||
{ gsub(/[ \t\n]+/, " ")
|
||||
sub(/ $/, "")
|
||||
sub(/^ /, "")
|
||||
print }
|
||||
'
|
||||
}
|
||||
|
||||
options=`getopt -o m:M:h \
|
||||
--long from:,to:,cc:,bcc:,subject: \
|
||||
--long send,mbox:,charset:,sender: \
|
||||
--long prefix:,reply-to:,signature: -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
opt_prefix=patch
|
||||
if [ -r $HOME/.signature ]
|
||||
then
|
||||
opt_signature="$(< $HOME/.signature)"
|
||||
fi
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-m)
|
||||
if [ -n "$opt_message" ]
|
||||
then
|
||||
echo $"Introduction message already specified" >&2
|
||||
exit 1
|
||||
fi
|
||||
opt_message=$2
|
||||
shift 2 ;;
|
||||
-M)
|
||||
if [ -n "$opt_message" ]
|
||||
then
|
||||
echo $"Introduction message already specified" >&2
|
||||
exit 1
|
||||
fi
|
||||
opt_message=$(< "$2")
|
||||
shift 2 ;;
|
||||
--sender)
|
||||
opt_sender=$2
|
||||
shift 2 ;;
|
||||
--from)
|
||||
opt_from=$2
|
||||
shift 2 ;;
|
||||
--to)
|
||||
opt_to[${#opt_to[@]}]=$2
|
||||
shift 2 ;;
|
||||
--cc)
|
||||
opt_cc[${#opt_cc[@]}]=$2
|
||||
shift 2 ;;
|
||||
--bcc)
|
||||
opt_bcc[${#opt_bcc[@]}]=$2
|
||||
shift 2 ;;
|
||||
--subject)
|
||||
opt_subject=$2
|
||||
shift 2 ;;
|
||||
--prefix)
|
||||
opt_prefix=$2
|
||||
shift 2 ;;
|
||||
--send)
|
||||
opt_send=1
|
||||
shift ;;
|
||||
--mbox)
|
||||
opt_mbox=$2
|
||||
shift 2 ;;
|
||||
--charset)
|
||||
opt_charset=$2
|
||||
shift 2 ;;
|
||||
--reply-to)
|
||||
opt_reply_to=$2
|
||||
shift 2 ;;
|
||||
--signature)
|
||||
if [ "$2" = - ]
|
||||
then
|
||||
opt_signature=
|
||||
else
|
||||
opt_signature=$(< "$2")
|
||||
fi
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 2 -o \( -z "$opt_send" -a -z "$opt_mbox" \) ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ $# -ge 1 ]
|
||||
then
|
||||
if [ "$1" = - ]
|
||||
then
|
||||
first_patch="$(find_first_patch)" || exit 1
|
||||
else
|
||||
first_patch="$(find_patch "$1")" || exit 1
|
||||
fi
|
||||
|
||||
if [ $# -ge 2 ]
|
||||
then
|
||||
if [ "$2" = - ]
|
||||
then
|
||||
last_patch="$(find_last_patch)" || exit 1
|
||||
else
|
||||
last_patch="$(find_patch "$2")" || exit 1
|
||||
fi
|
||||
else
|
||||
last_patch=$first_patch
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$opt_sender" ]
|
||||
then
|
||||
if [ -e /etc/mailname ]
|
||||
then
|
||||
hostname=$(< /etc/mailname)
|
||||
else
|
||||
hostname=$(hostname -f 2>/dev/null)
|
||||
fi
|
||||
|
||||
if [ "$hostname" = "${hostname/.}" ]
|
||||
then
|
||||
hostname=$(hostname)
|
||||
fi
|
||||
opt_sender="${LOGNAME:-$(whoami)}@$hostname"
|
||||
case "$opt_sender" in
|
||||
*@*.*) ;;
|
||||
*)
|
||||
echo $"\
|
||||
Could not determine the envelope sender address. Please use --sender." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
opt_sender_address=$(echo "$opt_sender" | sed -re 's:.*<([^<>]+)>.*:\1:')
|
||||
|
||||
if [ -z "$opt_charset" ]
|
||||
then
|
||||
case "${LC_ALL:-$ORIGINAL_LANG}" in
|
||||
*.UTF-8)
|
||||
opt_charset=UTF-8
|
||||
;;
|
||||
*)
|
||||
opt_charset=ISO-8859-15
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$(type -t quilt_mail_patch_filter 2> /dev/null)" != function ]
|
||||
then
|
||||
quilt_mail_patch_filter()
|
||||
{
|
||||
local tmpdir=$(gen_tempfile -d)
|
||||
cat > $tmpdir/patch
|
||||
patch_header < $tmpdir/patch > $tmpdir/header
|
||||
local subject
|
||||
local -a mh
|
||||
|
||||
# Does this patch have a Subject: line?
|
||||
subject=$(extract_header_value Subject: < $tmpdir/header)
|
||||
if [ -n "$subject" ]
|
||||
then
|
||||
awk '
|
||||
in_body { print }
|
||||
/^$/ { in_body = 1 }
|
||||
' $tmpdir/patch > $tmpdir/body
|
||||
fi
|
||||
|
||||
# Does this patch have DESC // subject // EDESC?
|
||||
if [ -z "$subject" ]
|
||||
then
|
||||
local desc=$(awk '
|
||||
/^EDESC/ { desc = 0 }
|
||||
desc { print }
|
||||
/^DESC/ { desc = 1 }
|
||||
' $tmpdir/header)
|
||||
if [ -n "$desc" ]
|
||||
then
|
||||
subject=$(echo "$desc" | join_lines)
|
||||
awk '
|
||||
/^DESC/ { desc = 1 }
|
||||
! desc { print }
|
||||
/^EDESC/ { desc = 0 }
|
||||
' $tmpdir/patch > $tmpdir/body
|
||||
fi
|
||||
fi
|
||||
|
||||
# Is the first paragraph short enough to be used as the subject?
|
||||
if [ -z "$subject" ]
|
||||
then
|
||||
local para=$(sed -e $'/^[ \t]*$/q' $tmpdir/header)
|
||||
if [ ${#para} -gt 0 -a ${#para} -lt 150 ]
|
||||
then
|
||||
subject=$(echo "$para" | join_lines)
|
||||
awk '
|
||||
in_body { print }
|
||||
/^[ \t]*$/ { in_body = 1 }
|
||||
' $tmpdir/patch > $tmpdir/body
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$subject" ]
|
||||
then
|
||||
rm -rf $tmpdir
|
||||
return 1
|
||||
fi
|
||||
|
||||
subject=$(echo "$subject" \
|
||||
| sed -e $'s/^\\(\\(\\[[^]]*\\]\\|fwd:\\|fw:\\|re:\\|aw:\\|tr:\\)[ \t]*\\)*//i')
|
||||
echo "Replace-Subject: $subject"
|
||||
|
||||
# Add recipients defined by some recognized keywords
|
||||
|
||||
# In Signed-off-by: and Acked-by: lines, try to recognize email
|
||||
# addresses that contain commas and add quotes, e.g.,
|
||||
# Last, First <email> => "Last, First" <email>
|
||||
|
||||
set -- Signed-off-by Acked-by Suggested-by Reviewed-by Requested-by Reported-by Tested-by Cc
|
||||
set -- "$*"
|
||||
set -- ${*// /\\|}
|
||||
|
||||
sed -n -e "/\<${LOGNAME:-$(whoami)}@/d" \
|
||||
-e 's/^\(\(To\|'"$*"'\):[ '$'\t'']*\)\([^"]*\(,[^"]*\)\+[^" '$'\t'']\)\([ '$'\t'']*<.*>\)/\1"\3"\5/I' \
|
||||
-e 's/^To:\(.*@.*\)/Recipient-To:\1/Ip' \
|
||||
-e 's/^\('"$*"'\):\(.*@.*\)/Recipient-Cc:\2/Ip' \
|
||||
$tmpdir/header
|
||||
|
||||
echo
|
||||
cat $tmpdir/body
|
||||
rm -rf $tmpdir
|
||||
}
|
||||
fi
|
||||
|
||||
if [ -n "$first_patch" ]
|
||||
then
|
||||
if [ -n "$last_patch" ]
|
||||
then
|
||||
set -- $(patches_before "$last_patch") "$last_patch"
|
||||
while [ $# -ne 0 ]
|
||||
do
|
||||
[ "$1" = "$first_patch" ] && break
|
||||
shift
|
||||
done
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
printf $"Patch %s not applied before patch %s\n" \
|
||||
"$(print_patch $first_patch)" \
|
||||
"$(print_patch $last_patch)" >&2
|
||||
exit 1
|
||||
fi
|
||||
patches=( "$@" )
|
||||
else
|
||||
patches=( "$first_patch" $(patches_after "$first_patch") )
|
||||
fi
|
||||
else
|
||||
patches=( $(cat_series) )
|
||||
fi
|
||||
total=${#patches[@]}
|
||||
|
||||
tmpdir=$(gen_tempfile -d)
|
||||
add_exit_handler "rm -rf $tmpdir"
|
||||
|
||||
for patch in "${patches[@]}"
|
||||
do
|
||||
patch_file="$(patch_file_name "$patch")"
|
||||
mkdir -p "$tmpdir/$(dirname "$patch")"
|
||||
cat_file "$patch_file" \
|
||||
| quilt_mail_patch_filter "$patch" > "$tmpdir/$patch"
|
||||
status=${PIPESTATUS[1]}
|
||||
|
||||
subject=$(extract_header_value Replace-Subject: < "$tmpdir/$patch" | join_lines)
|
||||
if [ $status -ne 0 -o -z "$subject" ]
|
||||
then
|
||||
if [ ! -r "$patch_file" ]
|
||||
then
|
||||
printf \
|
||||
$"Patch %s does not exist\n" "$(print_patch "$patch")" >&2
|
||||
else
|
||||
printf \
|
||||
$"Unable to extract a subject header from %s\n" "$(print_patch "$patch")" >&2
|
||||
fi
|
||||
|
||||
rm -rf $tmpdir
|
||||
exit 1
|
||||
fi
|
||||
subjects[${#subjects[@]}]="$patch"$'\t'"$subject"
|
||||
done
|
||||
|
||||
dup_subjects=( $(
|
||||
printf "%s\n" "${subjects[@]}" \
|
||||
| sort -k2 \
|
||||
| awk '{ patch = $1 ; sub(/^[^\t]+\t/, "");
|
||||
if ($0 in subjects) {
|
||||
if (subjects[$0] != "")
|
||||
print subjects[$0];
|
||||
print patch;
|
||||
subjects[$0] = "";
|
||||
}
|
||||
else subjects[$0] = patch }' \
|
||||
| while read patch; do
|
||||
print_patch $patch
|
||||
done
|
||||
) )
|
||||
if [ ${#dup_subjects[@]} -ne 0 ]
|
||||
then
|
||||
printf $"Patches %s have duplicate subject headers.\n" \
|
||||
"$(array_join ", " "${dup_subjects[@]}")"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$opt_reply_to" ]
|
||||
then
|
||||
if [ ! -e "$opt_reply_to" ]
|
||||
then
|
||||
printf $"File %s does not exist\n" "$opt_reply_to"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$opt_subject" ]
|
||||
then
|
||||
opt_subject="Re: $(extract_header_value Subject: < "$opt_reply_to" \
|
||||
| sed -e 's/^ *\([rR][eE]: *\)*//')"
|
||||
fi
|
||||
fi
|
||||
|
||||
introduction="$(gen_tempfile)"
|
||||
(
|
||||
cat <<-EOF
|
||||
Message-ID: <$(msgid)>
|
||||
User-Agent: quilt/@VERSION@
|
||||
Date: $(date --rfc-822)
|
||||
From: ${opt_from:-$opt_sender}
|
||||
To: $(IFS=,; echo "${opt_to[*]}")
|
||||
Cc: $(IFS=,; echo "${opt_cc[*]}")
|
||||
Bcc: $(IFS=,; echo "${opt_bcc[*]}")
|
||||
EOF
|
||||
|
||||
if [ -n "$opt_reply_to" ]
|
||||
then
|
||||
in_reply_to_header "$opt_reply_to"
|
||||
references_header "$opt_reply_to"
|
||||
fi
|
||||
|
||||
cat <<-EOF
|
||||
Subject-Prefix: [$opt_prefix @num@/@total@]
|
||||
Subject: $opt_subject
|
||||
|
||||
EOF
|
||||
if [ -n "$opt_message" ]
|
||||
then
|
||||
echo "$opt_message"
|
||||
echo
|
||||
fi
|
||||
if [ -n "$opt_signature" ]
|
||||
then
|
||||
echo "-- "
|
||||
echo "$opt_signature"
|
||||
fi
|
||||
) | $QUILT_DIR/scripts/edmail --charset $opt_charset > $introduction
|
||||
|
||||
if [ -z "$opt_message" ]
|
||||
then
|
||||
if ! LANG=$ORIGINAL_LANG $EDITOR $introduction
|
||||
then
|
||||
rm -f $introduction
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
subject=$(extract_header_value Subject: < $introduction | join_lines)
|
||||
if [ -z "$subject" ]
|
||||
then
|
||||
if [ -z "$opt_message" ]
|
||||
then
|
||||
printf $"Introduction has no subject header (saved as %s)\n" \
|
||||
"$introduction" >&2
|
||||
else
|
||||
printf $"Introduction has no subject header\n"
|
||||
rm -f $introduction
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$opt_mbox" ]
|
||||
then
|
||||
exec 1> $opt_mbox
|
||||
fi
|
||||
|
||||
subject_prefix=$(extract_header_value Subject-Prefix: < $introduction | join_lines)
|
||||
[ -n "$subject_prefix" ] && subject_prefix="$subject_prefix "
|
||||
|
||||
subject_prefix=${subject_prefix//\'/\'\'}
|
||||
subject_prefix=${subject_prefix//\//\\\/}
|
||||
p=${subject_prefix//@num@/$(printf %0*d ${#total} 0)}
|
||||
p=${p//@total@/$total}
|
||||
sed -e $'s/^\\(Subject:[ \t]\\)/\\1'"$p"'/' \
|
||||
-e '/^Subject-Prefix:/d' \
|
||||
$introduction \
|
||||
| $QUILT_DIR/scripts/edmail --charset $opt_charset \
|
||||
--remove-empty-headers To Cc Bcc \
|
||||
| process_mail
|
||||
|
||||
if [ -n "$opt_mbox" ]
|
||||
then
|
||||
exec 1>> $opt_mbox
|
||||
fi
|
||||
|
||||
# Remember the timestamp of the last message sent. For each message,
|
||||
# increment the timestamp by one second and wait with sending until
|
||||
# that time has arrived. This allows MUAs to show the messages in the
|
||||
# correct order.
|
||||
last_ts=$(date '+%s' -d "$(sed -ne $'s/^Date:[ \t]*//p' $introduction)")
|
||||
|
||||
num=1
|
||||
for patch in "${patches[@]}"; do
|
||||
body=$tmpdir/$patch
|
||||
#echo -n '.' >&2
|
||||
# Timestamps that are a few seconds in the future don't hurt usually
|
||||
#while [ $(date '+%s') -le $last_ts ]; do
|
||||
# sleep 1
|
||||
#done
|
||||
((last_ts++))
|
||||
new_date="$(date --rfc-822 -d "1970/01/01 UTC $last_ts seconds")"
|
||||
|
||||
modify="$(awk '
|
||||
in_header { if (/^[ \t]/) {
|
||||
headers[n] = headers[n] "\n" $0
|
||||
next }
|
||||
in_header = 0 }
|
||||
sub(/^Recipient-/, "") { headers[++n] = $0
|
||||
options[n] = "--add-good-recipient"
|
||||
in_header = 1
|
||||
next }
|
||||
sub(/^Replace-/, "") { headers[++n] = $0
|
||||
options[n] = "--replace-header"
|
||||
in_header = 1
|
||||
next }
|
||||
END { for(n = 1; n in headers; n++) {
|
||||
r = headers[n]
|
||||
sub(/:.*/, "", r)
|
||||
s = headers[n]
|
||||
sub(/^[^:]*:[ \t]*/, "", s)
|
||||
gsub(/'\''/, "'\'\''", s)
|
||||
print options[n] " " r "='\''" s "'\'' \\" } }
|
||||
' $body)"
|
||||
# echo "$modify" | sed -e 's/^/>> /' >&2
|
||||
p=${subject_prefix//@num@/$(printf %0*d ${#total} $num)}
|
||||
p=${p//@total@/$total}
|
||||
|
||||
# Make pipes fail if any of their commands fail (requires bash 3):
|
||||
set -o pipefail
|
||||
|
||||
( ( echo "Message-ID: <$(msgid)>"
|
||||
awk '
|
||||
/^$/ { exit }
|
||||
tolower($0) !~ /^(message-id|references|in-reply-to):/ \
|
||||
{ print }
|
||||
' $introduction
|
||||
references_header $introduction
|
||||
echo "MIME-Version: 1.0"
|
||||
echo "Content-Type: text/plain; charset=$opt_charset"
|
||||
awk '
|
||||
kill_header { if (/^[ \t]/) next ; kill_header = 0 }
|
||||
!in_body && tolower($0) ~ /^(recipient|replace)-.*:/ \
|
||||
{ kill_header = 1 ; next }
|
||||
/^$/ { in_body = 1 }
|
||||
{ print }
|
||||
' $body
|
||||
echo
|
||||
#if [ -n "$opt_signature" ]
|
||||
#then
|
||||
# echo '-- '
|
||||
# echo "$opt_signature"
|
||||
#fi
|
||||
) | eval $QUILT_DIR/scripts/edmail --charset $opt_charset \
|
||||
--replace-header Date="\"$new_date\"" \
|
||||
To Cc Bcc \
|
||||
"$modify" \
|
||||
| sed -e $'s/^\\(Subject:[ \t]\\)/\\1'"$p"'/' \
|
||||
-e '/^Subject-Prefix:/d' \
|
||||
| $QUILT_DIR/scripts/edmail --remove-empty-headers \
|
||||
| process_mail ) 2> $tmpdir/err
|
||||
|
||||
status=$?
|
||||
if [ -s $tmpdir/err ]
|
||||
then
|
||||
sed -e "s/^/${patch//\//\\/}: /" < $tmpdir/err >&2
|
||||
fi
|
||||
if [ $status -ne 0 ]
|
||||
then
|
||||
printf $"Introduction saved as %s\n" "$introduction" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If the character set is UTF-8, check for invalid byte
|
||||
# sequences.
|
||||
|
||||
#content_length=${#body}
|
||||
#if [ -n "$(echo "$body" | tr -d '\0-\177')" ]
|
||||
#then
|
||||
# charset=UTF-8
|
||||
#fi
|
||||
# Content-Transfer-Encoding: 7bit
|
||||
# Content-Transfer-Encoding: 8bit
|
||||
# Content-Type: text/plain; charset=ISO-8859-1
|
||||
# Content-Type: text/plain; charset=UTF-8
|
||||
|
||||
((num++))
|
||||
done
|
||||
rm -f $introduction
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,116 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt new [-p n|-p ab] {patchname}\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Create a new patch with the specified file name, and insert it after the
|
||||
topmost patch. The name can be prefixed with a sub-directory name, allowing
|
||||
for grouping related patches together.
|
||||
|
||||
-p n Create a -p n style patch (-p0 or -p1 are supported).
|
||||
|
||||
-p ab Create a -p1 style patch, but use a/file and b/file as the
|
||||
original and new filenames instead of the default
|
||||
dir.orig/file and dir/file names.
|
||||
|
||||
Quilt can be used in sub-directories of a source tree. It determines the
|
||||
root of a source tree by searching for a %s directory above the
|
||||
current working directory. Create a %s directory in the intended root
|
||||
directory if quilt chooses a top-level directory that is too high up
|
||||
in the directory tree.
|
||||
" "$QUILT_PATCHES" "$QUILT_PATCHES"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o p:h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-p) opt_strip_level=$2
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$opt_strip_level" in
|
||||
'' | 1)
|
||||
opt_strip_level= ;;
|
||||
0 | ab)
|
||||
;;
|
||||
*)
|
||||
printf $"Cannot create patches with -p%s, please specify -p0, p1, or -pab instead\n" \
|
||||
"$opt_strip_level" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $# -ne 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ "$QUILT_PATCHES" = "$QUILT_PC" ]
|
||||
then
|
||||
printf $"QUILT_PATCHES(%s) must differ from QUILT_PC(%s)\n" "$QUILT_PATCHES" "$QUILT_PC"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
patch=${1#$QUILT_PATCHES/}
|
||||
|
||||
if patch_in_series $patch
|
||||
then
|
||||
printf $"Patch %s exists already\n" "$(print_patch $patch)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
create_db
|
||||
rm -rf "$QUILT_PC/$patch"
|
||||
mkdir -p "$QUILT_PC/$patch"
|
||||
|
||||
if insert_in_series $patch ${opt_strip_level:+-p$opt_strip_level} && \
|
||||
add_to_db $patch
|
||||
then
|
||||
printf $"Patch %s is now on top\n" "$(print_patch $patch)"
|
||||
else
|
||||
printf $"Failed to create patch %s\n" "$(print_patch $patch)" >&2
|
||||
exit 1
|
||||
fi
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,71 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt next [patch]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Print the name of the next patch after the specified or topmost patch in
|
||||
the series file.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
next=$(find_unapplied_patch "$1") || exit
|
||||
|
||||
if [ -n "$next" ]
|
||||
then
|
||||
print_patch $next
|
||||
else
|
||||
exit 2
|
||||
fi
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,163 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
declare -a opt_files=()
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt patches [-v] [--color[=always|auto|never]] {file} [files...]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Print the list of patches that modify any of the specified files. (Uses a
|
||||
heuristic to determine which files are modified by unapplied patches.
|
||||
Note that this heuristic is much slower than scanning applied patches.)
|
||||
|
||||
-v Verbose, more user friendly output.
|
||||
|
||||
--color[=always|auto|never]
|
||||
Use syntax coloring (auto activates it only if the output is a tty).
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Uses global variable opt_files
|
||||
scan_applied()
|
||||
{
|
||||
local color=$1 prefix=$2
|
||||
shift 2
|
||||
local patch file
|
||||
|
||||
for patch in "$@"
|
||||
do
|
||||
for file in "${opt_files[@]}"
|
||||
do
|
||||
if file_in_patch "$file" $patch
|
||||
then
|
||||
echo "$color$prefix$(print_patch $patch)$color_clear"
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
# Uses global variable opt_files
|
||||
scan_unapplied()
|
||||
{
|
||||
local color=$1 prefix=$2
|
||||
shift 2
|
||||
local patch file
|
||||
local -a files_bre
|
||||
|
||||
# Quote each file name only once
|
||||
for file in "${opt_files[@]}"
|
||||
do
|
||||
files_bre[${#files_bre[@]}]=$(quote_bre "$file")
|
||||
done
|
||||
|
||||
# "Or" all files in a single pattern
|
||||
file=\\\($(array_join \\\| "${files_bre[@]}")\\\)
|
||||
|
||||
for patch in "$@"
|
||||
do
|
||||
if filenames_in_patch "$patch" \
|
||||
| grep -q "^$file\$"
|
||||
then
|
||||
echo "$color$prefix$(print_patch $patch)$color_clear"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
options=`getopt -o vh --long color:: -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-v)
|
||||
opt_verbose=1
|
||||
shift ;;
|
||||
--color)
|
||||
case "$2" in
|
||||
"" | always)
|
||||
opt_color=1 ;;
|
||||
auto | tty)
|
||||
opt_color=
|
||||
[ -t 1 ] && opt_color=1 ;;
|
||||
never)
|
||||
opt_color= ;;
|
||||
*)
|
||||
usage ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
while [ $# -ge 1 ]
|
||||
do
|
||||
opt_files[${#opt_files[@]}]="$SUBDIR$1"
|
||||
shift
|
||||
done
|
||||
|
||||
top=$(top_patch)
|
||||
|
||||
if [ -n "$opt_verbose" ]
|
||||
then
|
||||
applied="+ "
|
||||
current="= "
|
||||
unapplied=" "
|
||||
else
|
||||
applied=""
|
||||
current=""
|
||||
unapplied=""
|
||||
fi
|
||||
|
||||
[ -n "$opt_color" ] && setup_colors
|
||||
|
||||
setup_pager
|
||||
|
||||
scan_applied "$color_series_app" "$applied" \
|
||||
$(patches_before $top)
|
||||
[ -n "$top" ] && \
|
||||
scan_applied "$color_series_top" "$current" \
|
||||
$top
|
||||
scan_unapplied "$color_series_una" "$unapplied" \
|
||||
$(patches_after $top)
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,286 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt pop [-afRqv] [--refresh] [num|patch]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Remove patch(es) from the stack of applied patches. Without options,
|
||||
the topmost patch is removed. When a number is specified, remove the
|
||||
specified number of patches. When a patch name is specified, remove
|
||||
patches until the specified patch end up on top of the stack. Patch
|
||||
names may include the patches/ prefix, which means that filename
|
||||
completion can be used.
|
||||
|
||||
-a Remove all applied patches.
|
||||
|
||||
-f Force remove. The state before the patch(es) were applied will
|
||||
be restored from backup files.
|
||||
|
||||
-R Always verify if the patch removes cleanly; don't rely on
|
||||
timestamp checks.
|
||||
|
||||
-q Quiet operation.
|
||||
|
||||
-v Verbose operation.
|
||||
|
||||
--refresh
|
||||
Automatically refresh every patch before it gets unapplied.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
list_patches()
|
||||
{
|
||||
local n patches
|
||||
patches=( $(applied_patches) )
|
||||
for ((n=${#patches[@]}-1; n>=0; n--))
|
||||
do
|
||||
if [ -n "$number" ]
|
||||
then
|
||||
(( number-- > 0 )) || break
|
||||
fi
|
||||
[ "${patches[n]}" = "$stop_at_patch" ] && break
|
||||
echo "${patches[n]}"
|
||||
done
|
||||
}
|
||||
|
||||
files_may_have_changed()
|
||||
{
|
||||
local patch=$1 file
|
||||
local patch_file=$(patch_file_name "$patch")
|
||||
|
||||
if [ $? -ne 0 -o ! -e "$patch_file" \
|
||||
-o ! -e "$QUILT_PC/$patch/.timestamp" \
|
||||
-o ! "$QUILT_PC/$patch/.timestamp" -nt "$patch_file" ]
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
|
||||
for file in $(files_in_patch "$patch")
|
||||
do
|
||||
[ ! "$QUILT_PC/$patch/.timestamp" -nt "$file" ] && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check if all changes have been folded back into the patch (quilt refresh),
|
||||
# and report any pending changes.
|
||||
check_for_pending_changes()
|
||||
{
|
||||
local patch=$1
|
||||
local patch_file=$(patch_file_name "$patch")
|
||||
local workdir=$(gen_tempfile -d quilt) status=0
|
||||
|
||||
if [ -d "$QUILT_PC/$patch" ]
|
||||
then
|
||||
local prefix=$QUILT_PC/$patch/
|
||||
[ ${prefix:0:1} == / ] || prefix=$PWD/$prefix
|
||||
if ! ( cd $workdir && \
|
||||
$QUILT_DIR/scripts/backup-files -B "$prefix" -r -k -s - )
|
||||
then
|
||||
printf $"Failed to copy files to temporary directory\n" >&2
|
||||
rm -rf $workdir
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -s "$patch_file" ]
|
||||
then
|
||||
cat_file "$patch_file" \
|
||||
| patch -d $workdir $QUILT_PATCH_OPTS \
|
||||
$(patch_args "$patch") --no-backup-if-mismatch \
|
||||
-f >/dev/null 2>/dev/null
|
||||
fi
|
||||
|
||||
local file file2 failed
|
||||
for file2 in $(files_in_patch "$patch")
|
||||
do
|
||||
file=$workdir/$file2
|
||||
[ -e "$file" ] || file=/dev/null
|
||||
[ -e "$file2" ] || file2=/dev/null
|
||||
diff -q "$file" "$file2" > /dev/null || failed=1
|
||||
done
|
||||
|
||||
if [ -n "$failed" ]
|
||||
then
|
||||
printf $"Patch %s does not remove cleanly (refresh it or enforce with -f)\n" \
|
||||
"$(print_patch "$patch")" >&2
|
||||
status=1
|
||||
fi
|
||||
rm -rf $workdir
|
||||
|
||||
return $status
|
||||
}
|
||||
|
||||
remove_patch()
|
||||
{
|
||||
local patch=$1 status=0
|
||||
|
||||
trap "status=1" SIGINT
|
||||
if [ -z "$opt_force" ] && \
|
||||
( [ -n "$opt_remove" ] || files_may_have_changed "$patch" )
|
||||
then
|
||||
check_for_pending_changes "$patch" || status=1
|
||||
fi
|
||||
|
||||
if [ $status -eq 0 ]
|
||||
then
|
||||
rm -f "$QUILT_PC/$patch/.timestamp"
|
||||
if [ -z "$(shopt -s nullglob ; echo "$QUILT_PC/$patch/"*)" ]
|
||||
then
|
||||
printf $"Patch %s appears to be empty, removing\n" \
|
||||
"$(print_patch "$patch")"
|
||||
rmdir "$QUILT_PC/$patch"
|
||||
status=$?
|
||||
else
|
||||
printf $"Removing patch %s\n" "$(print_patch "$patch")"
|
||||
$QUILT_DIR/scripts/backup-files $silent -r -t -B "$QUILT_PC/$patch/" -
|
||||
status=$?
|
||||
fi
|
||||
remove_from_db "$patch"
|
||||
rm -f "$QUILT_PC/$patch~refresh"
|
||||
fi
|
||||
trap - SIGINT
|
||||
return $status
|
||||
}
|
||||
|
||||
options=`getopt -o fRqvah --long refresh -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-f)
|
||||
opt_force=1
|
||||
unset opt_remove
|
||||
shift ;;
|
||||
-R)
|
||||
opt_remove=1
|
||||
unset opt_force
|
||||
shift ;;
|
||||
-q)
|
||||
opt_quiet=1
|
||||
shift ;;
|
||||
-v)
|
||||
opt_verbose=1
|
||||
shift ;;
|
||||
-a)
|
||||
opt_all=1
|
||||
shift ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--refresh)
|
||||
opt_refresh=1
|
||||
shift ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 -o \( -n "$opt_all" -a $# -ne 0 \) ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ -n "$opt_force" -a -n "$opt_refresh" ]
|
||||
then
|
||||
printf $"Options %s and %s are mutually exclusive\n" "-f" "--refresh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
if is_numeric "$1"
|
||||
then
|
||||
number=$1
|
||||
else
|
||||
stop_at_patch=$(find_applied_patch "$1") || exit 1
|
||||
fi
|
||||
else
|
||||
[ -n "$opt_all" ] || number=1
|
||||
fi
|
||||
|
||||
[ -n "$opt_quiet" ] && silent=-s
|
||||
[ -z "$opt_verbose" ] && silent_unless_verbose=-s
|
||||
|
||||
top=$(top_patch)
|
||||
if [ -n "$top" -a -e "$QUILT_PC/$top~refresh" -a -z "$opt_force" ]
|
||||
then
|
||||
printf $"Patch %s needs to be refreshed first.\n" \
|
||||
"$(print_patch "$top")" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! patches=$(list_patches) 2>&1
|
||||
then
|
||||
exit 1
|
||||
elif [ -z "$patches" ]
|
||||
then
|
||||
printf $"No patch removed\n" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# We will update the list of applied patches, which in turn will disable the
|
||||
# consistency check. Enable it again if needed.
|
||||
if [ -z "$opt_all" -a ! "$DB" -nt "$SERIES" ] && ! consistency_check
|
||||
then
|
||||
rearm_check=1
|
||||
fi
|
||||
|
||||
for patch in $patches
|
||||
do
|
||||
[ -z "$opt_refresh" ] || quilt_command refresh $QUILT_REFRESH_ARGS
|
||||
if ! remove_patch "$patch"
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
[ -z "$opt_quiet" ] && echo
|
||||
done
|
||||
|
||||
patch="$(top_patch)"
|
||||
if [ -z "$patch" ]
|
||||
then
|
||||
printf $"No patches applied\n"
|
||||
else
|
||||
# Ensure that the files in the topmost patch have a link count
|
||||
# of one: This will automatically be the case in the usual
|
||||
# situations, but we don't want to risk file corruption in weird
|
||||
# corner cases such as files added to a patch but not modified.
|
||||
$QUILT_DIR/scripts/backup-files -L -s -B "$QUILT_PC/$patch/" -
|
||||
printf $"Now at patch %s\n" "$(print_patch "$patch")"
|
||||
|
||||
[ -z "$rearm_check" ] || touch "$SERIES"
|
||||
fi
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,72 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt previous [patch]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Print the name of the previous patch before the specified or topmost
|
||||
patch in the series file.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
patch=$(find_patch_in_series "$1") || exit 1
|
||||
|
||||
previous=$(applied_before "$patch" | tail -n 1)
|
||||
if [ -n "$previous" ]
|
||||
then
|
||||
print_patch $previous
|
||||
else
|
||||
exit 2
|
||||
fi
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,447 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
setup_colors
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt push [-afqvm] [--fuzz=N] [--merge[=merge|diff3]] [--leave-rejects] [--color[=always|auto|never]] [--refresh] [num|patch]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Apply patch(es) from the series file. Without options, the next patch
|
||||
in the series file is applied. When a number is specified, apply the
|
||||
specified number of patches. When a patch name is specified, apply
|
||||
all patches up to and including the specified patch. Patch names may
|
||||
include the patches/ prefix, which means that filename completion can
|
||||
be used.
|
||||
|
||||
-a Apply all patches in the series file.
|
||||
|
||||
-q Quiet operation.
|
||||
|
||||
-f Force apply, even if the patch has rejects.
|
||||
|
||||
-v Verbose operation.
|
||||
|
||||
--fuzz=N
|
||||
Set the maximum fuzz factor (default: 2).
|
||||
|
||||
-m, --merge[=merge|diff3]
|
||||
Merge the patch file into the original files (see patch(1)).
|
||||
|
||||
--leave-rejects
|
||||
Leave around the reject files patch produced, even if the patch
|
||||
is not actually applied.
|
||||
|
||||
--color[=always|auto|never]
|
||||
Use syntax coloring (auto activates it only if the output is a tty).
|
||||
|
||||
--refresh
|
||||
Automatically refresh every patch after it was successfully applied.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
interrupt()
|
||||
{
|
||||
local patch=$1
|
||||
|
||||
rollback_patch "$patch"
|
||||
printf $"Interrupted by user; patch %s was not applied.\n" \
|
||||
"$(print_patch "$patch")" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
colorize()
|
||||
{
|
||||
if [ -n "$opt_color" ]; then
|
||||
awk '
|
||||
{ if (/FAILED|hunks? ignored|can'\''t find file|file .* already exists|NOT MERGED/)
|
||||
print "'$color_patch_fail'" $0 "'$color_clear'"
|
||||
else if (/already applied$/)
|
||||
print "'$color_patch_fuzz'" $0 "'$color_clear'"
|
||||
else if (/^Hunk/) {
|
||||
sub(/^Hunk .* with fuzz [0-9]*/,
|
||||
"'$color_patch_fuzz'&'$color_clear'")
|
||||
sub(/offset -?[0-9]* lines?/,
|
||||
"'$color_patch_offs'&'$color_clear'")
|
||||
print
|
||||
} else
|
||||
print
|
||||
}'
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
|
||||
push_patch_args()
|
||||
{
|
||||
local patch=$1
|
||||
|
||||
if [ -z "$opt_reverse" ]
|
||||
then
|
||||
patch_args "$patch"
|
||||
else
|
||||
set -- $(patch_args "$patch")
|
||||
if [ "${*#-R}" != "$*" ]
|
||||
then
|
||||
echo "${*#-R}"
|
||||
else
|
||||
echo "$*" -R
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
apply_patch()
|
||||
{
|
||||
local patch=$1 patch_file=$2
|
||||
local output
|
||||
|
||||
[ -s "$patch_file" ] || return 0
|
||||
|
||||
set -- patch $QUILT_PATCH_OPTS $(push_patch_args "$patch") \
|
||||
--backup --prefix="$QUILT_PC/$patch/" -f \
|
||||
$no_reject_files $more_patch_args
|
||||
|
||||
if [ "${patch_file:(-3)}" = ".gz" ]
|
||||
then
|
||||
gzip -cd "$patch_file" | "$@" 2>&1
|
||||
elif [ "${patch_file:(-4)}" = ".bz2" ]
|
||||
then
|
||||
bzip2 -cd "$patch_file" | "$@" 2>&1
|
||||
elif [ "${patch_file:(-3)}" = ".xz" ]
|
||||
then
|
||||
xz -cd "$patch_file" | "$@" 2>&1
|
||||
elif [ "${patch_file:(-5)}" = ".lzma" ]
|
||||
then
|
||||
lzma -cd "$patch_file" | "$@" 2>&1
|
||||
elif [ "${patch_file:(-3)}" = ".lz" ]
|
||||
then
|
||||
lzip -cd "$patch_file" | "$@" 2>&1
|
||||
else
|
||||
"$@" -i "$patch_file" 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
rollback_patch()
|
||||
{
|
||||
local patch=$1
|
||||
|
||||
$QUILT_DIR/scripts/backup-files $silent_unless_verbose -r -B "$QUILT_PC/$patch/" -
|
||||
}
|
||||
|
||||
cleanup_patch_output()
|
||||
{
|
||||
if [ -z "$opt_leave_rejects" ]
|
||||
then
|
||||
if [ -n "$opt_quiet" ]; then
|
||||
# In this case, patch does not allow us to find out
|
||||
# which file contains the rejects; it only tells us
|
||||
# which reject file is used. We use a single temporary
|
||||
# reject file, so this does not help us.
|
||||
|
||||
awk '
|
||||
{ gsub(/ -- saving rejects to (file )?.*/, "") }
|
||||
{ print }
|
||||
'
|
||||
else
|
||||
awk '
|
||||
/^patching file / { filename = substr($0, 15) }
|
||||
{ gsub(/ -- saving rejects to (file )?.*/,
|
||||
" -- rejects in file " filename) }
|
||||
{ print }
|
||||
'
|
||||
fi
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
|
||||
add_patch()
|
||||
{
|
||||
local patch=$1
|
||||
local patch_file=$(patch_file_name "$patch")
|
||||
local file status tmp
|
||||
|
||||
printf $"Applying patch %s\n" "$(print_patch "$patch")"
|
||||
trap "interrupt $patch" SIGINT
|
||||
|
||||
no_reject_files=
|
||||
if [ -z "$opt_leave_rejects" ]; then
|
||||
tmp=$(gen_tempfile)
|
||||
no_reject_files="-r $tmp"
|
||||
fi
|
||||
|
||||
apply_patch "$patch" "$patch_file"
|
||||
status=$?
|
||||
trap "" SIGINT
|
||||
|
||||
[ -n "$tmp" ] && rm -f $tmp
|
||||
|
||||
if [ $status -eq 0 -o -n "$opt_force" ]
|
||||
then
|
||||
add_to_db "$patch"
|
||||
if [ $status -eq 0 ]
|
||||
then
|
||||
rm -f "$QUILT_PC/$patch~refresh"
|
||||
else
|
||||
touch "$QUILT_PC/$patch~refresh"
|
||||
fi
|
||||
|
||||
if [ -e "$QUILT_PC/$patch" ]
|
||||
then
|
||||
touch "$QUILT_PC/$patch/.timestamp"
|
||||
else
|
||||
mkdir "$QUILT_PC/$patch"
|
||||
fi
|
||||
|
||||
if ! [ -e "$patch_file" ]
|
||||
then
|
||||
printf $"Patch %s does not exist; applied empty patch\n" \
|
||||
"$(print_patch "$patch")"
|
||||
elif [ -z "$(shopt -s nullglob ; echo "$QUILT_PC/$patch/"*)" ]
|
||||
then
|
||||
printf $"Patch %s appears to be empty; applied\n" \
|
||||
"$(print_patch "$patch")"
|
||||
elif [ $status -ne 0 ]
|
||||
then
|
||||
printf $"Applied patch %s (forced; needs refresh)\n" \
|
||||
"$(print_patch "$patch")"
|
||||
fi
|
||||
else
|
||||
rollback_patch "$patch"
|
||||
tmp=$(gen_tempfile)
|
||||
no_reject_files="-r $tmp"
|
||||
opt_reverse=1
|
||||
if apply_patch "$patch" "$patch_file" > /dev/null 2> /dev/null
|
||||
then
|
||||
printf $"Patch %s can be reverse-applied\n" \
|
||||
"$(print_patch "$patch")"
|
||||
else
|
||||
printf $"Patch %s does not apply (enforce with -f)\n" \
|
||||
"$(print_patch "$patch")"
|
||||
fi
|
||||
rollback_patch "$patch"
|
||||
rm -f $tmp
|
||||
status=1
|
||||
fi
|
||||
trap - SIGINT
|
||||
return $status
|
||||
}
|
||||
|
||||
list_patches()
|
||||
{
|
||||
local top=$(top_patch) n=0 patch
|
||||
if [ -n "$top" ]
|
||||
then
|
||||
patches_after "$top"
|
||||
else
|
||||
cat_series
|
||||
fi \
|
||||
| if [ -n "$opt_all" ]
|
||||
then
|
||||
cat
|
||||
else
|
||||
while read patch
|
||||
do
|
||||
if [ -n "$number" ]
|
||||
then
|
||||
if [ $n -eq $number ]
|
||||
then
|
||||
break
|
||||
fi
|
||||
n=$[$n+1]
|
||||
fi
|
||||
echo "$patch"
|
||||
if [ -z "$number" -a "$patch" = "$stop_at_patch" ]
|
||||
then
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
check_duplicate_patches()
|
||||
{
|
||||
local IFS=$'\n'
|
||||
local -a duplicates
|
||||
local patch
|
||||
|
||||
duplicates=($((applied_patches ; printf $'%s\n' "${patches[@]}") \
|
||||
| awk '{ if (lines[$0]++ == 1) print }'))
|
||||
[ ${#duplicates[@]} -ge 1 ] || return 0
|
||||
|
||||
for patch in "${duplicates[@]}"
|
||||
do
|
||||
printf $"Patch %s is already applied; check your series file\n" \
|
||||
"$(print_patch "$patch")"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
options=`getopt -o fqvam::h --long fuzz:,merge::,leave-rejects,color::,refresh -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-f)
|
||||
opt_force=1
|
||||
shift ;;
|
||||
-q)
|
||||
opt_quiet=1
|
||||
shift ;;
|
||||
-v)
|
||||
opt_verbose=1
|
||||
shift ;;
|
||||
-a)
|
||||
opt_all=1
|
||||
shift ;;
|
||||
-h)
|
||||
usage -h
|
||||
;;
|
||||
--fuzz)
|
||||
opt_fuzz=$2
|
||||
shift 2 ;;
|
||||
-m | --merge)
|
||||
case "$2" in
|
||||
"" | merge)
|
||||
opt_merge=1
|
||||
opt_merge_arg= ;;
|
||||
diff3)
|
||||
opt_merge=1
|
||||
opt_merge_arg="=diff3" ;;
|
||||
*)
|
||||
usage ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
--leave-rejects)
|
||||
opt_leave_rejects=1
|
||||
shift ;;
|
||||
--color)
|
||||
case "$2" in
|
||||
"" | always)
|
||||
opt_color=1 ;;
|
||||
auto | tty)
|
||||
opt_color=
|
||||
[ -t 1 ] && opt_color=1 ;;
|
||||
never)
|
||||
opt_color= ;;
|
||||
*)
|
||||
usage ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
--refresh)
|
||||
opt_refresh=1
|
||||
shift ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 -o \( -n "$opt_all" -a $# -ne 0 \) ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ -n "$opt_force" -a -n "$opt_refresh" ]
|
||||
then
|
||||
printf $"Options %s and %s are mutually exclusive\n" "-f" "--refresh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
if is_numeric "$1"
|
||||
then
|
||||
number=$1
|
||||
else
|
||||
stop_at_patch=$1
|
||||
fi
|
||||
else
|
||||
[ -z "$opt_all" ] && number=1
|
||||
fi
|
||||
|
||||
stop_at_patch=$(find_unapplied_patch "$stop_at_patch") || exit
|
||||
|
||||
[ -z "$opt_verbose" ] && silent_unless_verbose=-s
|
||||
[ -n "$opt_force" ] && opt_leave_rejects=1
|
||||
|
||||
more_patch_args=
|
||||
[ -n "$opt_quiet" ] && more_patch_args="$more_patch_args -s"
|
||||
if [ -n "$opt_merge" ]
|
||||
then
|
||||
more_patch_args="$more_patch_args --merge$opt_merge_arg"
|
||||
fi
|
||||
[ -n "$opt_fuzz" ] && more_patch_args="$more_patch_args -F$opt_fuzz"
|
||||
|
||||
top=$(top_patch)
|
||||
if [ -n "$top" -a -e "$QUILT_PC/$top~refresh" ]
|
||||
then
|
||||
printf $"The topmost patch %s needs to be refreshed first.\n" \
|
||||
"$(print_patch "$top")"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
patches=$(list_patches)
|
||||
if [ -z "$patches" ]
|
||||
then
|
||||
printf $"No patch applied\n" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# In theory, these patches can't be already applied. However in the case
|
||||
# of a generated or manually tweaked series file, this could happen and
|
||||
# cause havoc, so play it safe and check.
|
||||
check_duplicate_patches || exit 1
|
||||
|
||||
create_db
|
||||
for patch in $patches
|
||||
do
|
||||
if ! add_patch "$patch"
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
[ -z "$opt_refresh" ] || quilt_command refresh $QUILT_REFRESH_ARGS
|
||||
[ -n "$opt_quiet" ] || echo
|
||||
done \
|
||||
| cleanup_patch_output \
|
||||
| colorize
|
||||
|
||||
if [ ${PIPESTATUS[0]} -eq 0 ]; then
|
||||
set -- $patches
|
||||
printf $"Now at patch %s\n" "$(print_patch ${!#})"
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,369 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt refresh [-p n|-p ab] [-u|-U num|-c|-C num] [-z[new_name]] [-f] [--no-timestamps] [--no-index] [--diffstat] [--sort] [--backup] [--strip-trailing-whitespace] [patch]\n"
|
||||
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Refreshes the specified patch, or the topmost patch by default.
|
||||
Documentation that comes before the actual patch in the patch file is
|
||||
retained.
|
||||
|
||||
It is possible to refresh patches that are not on top. If any patches
|
||||
on top of the patch to refresh modify the same files, the script aborts
|
||||
by default. Patches can still be refreshed with -f. In that case this
|
||||
script will print a warning for each shadowed file, changes by more
|
||||
recent patches will be ignored, and only changes in files that have not
|
||||
been modified by any more recent patches will end up in the specified
|
||||
patch.
|
||||
|
||||
-p n Create a -p n style patch (-p0 or -p1 supported).
|
||||
|
||||
-p ab Create a -p1 style patch, but use a/file and b/file as the
|
||||
original and new filenames instead of the default
|
||||
dir.orig/file and dir/file names.
|
||||
|
||||
-u, -U num, -c, -C num
|
||||
Create a unified diff (-u, -U) with num lines of context. Create
|
||||
a context diff (-c, -C) with num lines of context. The number of
|
||||
context lines defaults to 3.
|
||||
|
||||
-z[new_name]
|
||||
Create a new patch containing the changes instead of refreshing the
|
||||
topmost patch. If no new name is specified, \`-2' is added to the
|
||||
original patch name, etc. (See the fork command.)
|
||||
|
||||
--no-timestamps
|
||||
Do not include file timestamps in patch headers.
|
||||
|
||||
--no-index
|
||||
Do not output Index: lines.
|
||||
|
||||
--diffstat
|
||||
Add a diffstat section to the patch header, or replace the
|
||||
existing diffstat section.
|
||||
|
||||
-f Enforce refreshing of a patch that is not on top.
|
||||
|
||||
--backup
|
||||
Create a backup copy of the old version of a patch as patch~.
|
||||
|
||||
--sort Sort files by their name instead of preserving the original order.
|
||||
|
||||
--strip-trailing-whitespace
|
||||
Strip trailing whitespace at the end of lines.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
die()
|
||||
{
|
||||
local status=$1
|
||||
[ -n "$tmp_patch" ] && rm -f $tmp_patch
|
||||
[ -n "$tmp_result" ] && rm -f $tmp_result
|
||||
[ -n "$workdir" ] && rm -rf $workdir
|
||||
exit $status
|
||||
}
|
||||
|
||||
options=`getopt -o p:uU:cC:fz::h --long no-timestamps,diffstat,backup,sort \
|
||||
--long no-index \
|
||||
--long strip-trailing-whitespace -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
opt_format=-u
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-p)
|
||||
opt_strip_level=$2
|
||||
shift 2 ;;
|
||||
-f)
|
||||
opt_force=1
|
||||
shift ;;
|
||||
-u|-c)
|
||||
opt_format=$1
|
||||
shift ;;
|
||||
-U|-C)
|
||||
opt_format="$1 $2"
|
||||
shift 2 ;;
|
||||
-z)
|
||||
opt_fork=1
|
||||
opt_new_name=$2
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--no-timestamps)
|
||||
QUILT_NO_DIFF_TIMESTAMPS=1
|
||||
shift ;;
|
||||
--no-index)
|
||||
QUILT_NO_DIFF_INDEX=1
|
||||
shift ;;
|
||||
--diffstat)
|
||||
opt_diffstat=1
|
||||
shift ;;
|
||||
--backup)
|
||||
QUILT_BACKUP=1
|
||||
shift ;;
|
||||
--sort)
|
||||
opt_sort=1
|
||||
shift ;;
|
||||
--strip-trailing-whitespace)
|
||||
opt_strip_whitespace=1
|
||||
shift ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
QUILT_DIFF_OPTS="$QUILT_DIFF_OPTS $opt_format"
|
||||
|
||||
patch=$(find_applied_patch "$1") || exit 1
|
||||
|
||||
# Properly handle spaces in file names
|
||||
saved_IFS=$IFS
|
||||
IFS=$'\n'
|
||||
|
||||
if [ -z "$opt_sort" ]
|
||||
then
|
||||
files=( $(files_in_patch_ordered $patch) )
|
||||
else
|
||||
files=( $(files_in_patch $patch | sort) )
|
||||
fi
|
||||
|
||||
IFS=$saved_IFS
|
||||
|
||||
if [ -n "$opt_fork" -a $# -ne 0 ]
|
||||
then
|
||||
printf $"Can only refresh the topmost patch with -z currently\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$opt_fork" ]; then
|
||||
old_patch=$patch
|
||||
old_patch_args=$(patch_args "$old_patch")
|
||||
if [ -n "$opt_new_name" ]
|
||||
then
|
||||
patch=$opt_new_name
|
||||
else
|
||||
patch=$(next_filename "$patch")
|
||||
fi
|
||||
if [ -e "$(patch_file_name "$patch")" ]; then
|
||||
printf $"Patch %s exists already\n" "$(print_patch "$patch")" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$opt_strip_level" ]
|
||||
then
|
||||
opt_strip_level=$(patch_strip_level "$patch")
|
||||
fi
|
||||
case "$opt_strip_level" in
|
||||
0 | 1)
|
||||
num_strip_level=$opt_strip_level
|
||||
;;
|
||||
ab)
|
||||
num_strip_level=1
|
||||
;;
|
||||
*)
|
||||
printf $"Cannot refresh patches with -p%s, please specify -p0, -p1, or -pab instead\n" \
|
||||
"$opt_strip_level" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
trap "die 1" SIGTERM
|
||||
|
||||
if [ -n "$opt_fork" ]; then
|
||||
workdir=$(gen_tempfile -d $PWD/quilt)
|
||||
apply_patch_temporarily "$workdir" "$old_patch" || exit 1
|
||||
fi
|
||||
|
||||
tmp_patch=$(gen_tempfile)
|
||||
|
||||
for file in "${files[@]}"
|
||||
do
|
||||
if [ -n "$opt_fork" ]; then
|
||||
old_file=$workdir/$file
|
||||
new_file=$file
|
||||
else
|
||||
old_file=$(backup_file_name "$patch" "$file")
|
||||
next_patch=$(next_patch_for_file "$patch" "$file")
|
||||
if [ -z "$next_patch" ]
|
||||
then
|
||||
new_file=$file
|
||||
else
|
||||
new_file=$(backup_file_name "$next_patch" "$file")
|
||||
files_were_shadowed=1
|
||||
fi
|
||||
fi
|
||||
if ! diff_file "$file" "$old_file" "$new_file"
|
||||
then
|
||||
die 1
|
||||
fi
|
||||
|
||||
if [ -n "$files_were_shadowed" -a -z "$opt_force" ]
|
||||
then
|
||||
printf $"More recent patches modify files in patch %s. Enforce refresh with -f.\n" "$(print_patch "$patch")" >&2
|
||||
die 1
|
||||
fi
|
||||
|
||||
if [ -n "$files_were_shadowed" -a -n "$opt_strip_whitespace" ]
|
||||
then
|
||||
printf $"Cannot use --strip-trailing-whitespace on a patch that has shadowed files.\n" >&2
|
||||
fi
|
||||
done >> $tmp_patch
|
||||
|
||||
if [ -n "$opt_fork" -a ! -s $tmp_patch ]
|
||||
then
|
||||
printf $"Nothing in patch %s\n" "$(print_patch "$patch")" >&2
|
||||
die 1
|
||||
fi
|
||||
|
||||
# Check for trailing whitespace
|
||||
if [ -z "$opt_strip_whitespace" ]
|
||||
then
|
||||
$QUILT_DIR/scripts/remove-trailing-ws -n -p$num_strip_level \
|
||||
< $tmp_patch
|
||||
else
|
||||
tmp_patch2=$(gen_tempfile)
|
||||
if $QUILT_DIR/scripts/remove-trailing-ws -p$num_strip_level \
|
||||
< $tmp_patch > $tmp_patch2
|
||||
then
|
||||
rm -f $tmp_patch
|
||||
tmp_patch=$tmp_patch2
|
||||
fi
|
||||
fi
|
||||
# FIXME: no stripping of non-topmost patch !!!
|
||||
|
||||
patch_file=$(patch_file_name "$patch")
|
||||
|
||||
trap "" SIGINT
|
||||
|
||||
tmp_result=$(gen_tempfile) || die 1
|
||||
|
||||
prev_patch_file=$patch_file
|
||||
[ -e "$prev_patch_file" ] || prev_patch_file=/dev/null
|
||||
|
||||
if [ -n "$opt_diffstat" ]
|
||||
then
|
||||
cat_file "$prev_patch_file" | patch_header \
|
||||
| awk '
|
||||
function print_diffstat(arr, i) {
|
||||
if (system("diffstat '"$QUILT_DIFFSTAT_OPTS \
|
||||
-p$num_strip_level \
|
||||
$tmp_patch | sed -e s:^:"'" prefix ":"))
|
||||
exit 1
|
||||
}
|
||||
{ prefix=""
|
||||
if (index($0, "#") == 1)
|
||||
prefix="#"
|
||||
}
|
||||
/^#? .* \| *[1-9][0-9]* / { eat = eat $0 "\n"
|
||||
next }
|
||||
/^#? .* files? changed(, .* insertions?\(\+\))?(, .* deletions?\(-\))?/ \
|
||||
{ print_diffstat()
|
||||
diffstat_printed=1
|
||||
eat = ""
|
||||
next }
|
||||
{ print eat $0
|
||||
eat = "" }
|
||||
END { printf "%s", eat
|
||||
if (!diffstat_printed) {
|
||||
print "---"
|
||||
print_diffstat()
|
||||
print prefix
|
||||
}
|
||||
}
|
||||
' > $tmp_result
|
||||
else
|
||||
cat_file "$prev_patch_file" | patch_header \
|
||||
> $tmp_result
|
||||
fi
|
||||
|
||||
cat $tmp_patch >> $tmp_result
|
||||
|
||||
mkdir -p $(dirname "$patch_file")
|
||||
|
||||
if [ -e "$patch_file" ] && \
|
||||
diff -q "$patch_file" $tmp_result > /dev/null
|
||||
then
|
||||
printf $"Patch %s is unchanged\n" "$(print_patch "$patch")"
|
||||
elif cat_to_new_file "$patch_file" $QUILT_BACKUP < $tmp_result
|
||||
then
|
||||
if [ -n "$opt_fork" ]
|
||||
then
|
||||
if ! insert_in_series "$patch" "$old_patch_args"
|
||||
then
|
||||
printf $"Failed to insert patch %s into file series\n" \
|
||||
"$(print_patch "$patch")" >&2
|
||||
rm -f "$patch_file"
|
||||
exit 1
|
||||
fi
|
||||
if ! rm -rf "$QUILT_PC/$patch" || \
|
||||
! mv "$workdir" "$QUILT_PC/$patch" || \
|
||||
! echo "$patch" >> $QUILT_PC/applied-patches
|
||||
then
|
||||
printf $"Failed to create patch %s\n" \
|
||||
"$(print_patch "$patch")" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf $"Fork of patch %s created as %s\n" \
|
||||
"$(print_patch "$old_patch")" \
|
||||
"$(print_patch "$patch")"
|
||||
else
|
||||
if [ -s $tmp_patch ]
|
||||
then
|
||||
printf $"Refreshed patch %s\n" "$(print_patch "$patch")"
|
||||
else
|
||||
printf $"Nothing in patch %s\n" "$(print_patch "$patch")"
|
||||
fi
|
||||
fi
|
||||
touch "$QUILT_PC/$patch/.timestamp"
|
||||
else
|
||||
die 1
|
||||
fi
|
||||
|
||||
rm -f "$QUILT_PC/$patch~refresh"
|
||||
if ! change_db_strip_level -p$num_strip_level "$patch"
|
||||
then
|
||||
die 1
|
||||
fi
|
||||
die 0
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,112 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt remove [-P patch] {file} ...\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Remove one or more files from the topmost or named patch. Files that
|
||||
are modified by patches on top of the specified patch cannot be removed.
|
||||
|
||||
-P patch
|
||||
Remove named files from the named patch.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o P:h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-P)
|
||||
opt_patch=$2
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
patch=$(find_applied_patch "$opt_patch") || exit 1
|
||||
|
||||
status=0
|
||||
for file in "$@"
|
||||
do
|
||||
if ! file_in_patch "$SUBDIR$file" "$patch"
|
||||
then
|
||||
printf $"File %s is not in patch %s\n" \
|
||||
"$SUBDIR$file" "$(print_patch "$patch")" >&2
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
|
||||
next_patch=$(next_patch_for_file "$patch" "$SUBDIR$file")
|
||||
if [ -n "$next_patch" ]
|
||||
then
|
||||
printf $"File %s modified by patch %s\n" \
|
||||
"$SUBDIR$file" "$(print_patch "$next_patch")"
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
|
||||
# Restore file from backup
|
||||
if ! $QUILT_DIR/scripts/backup-files -r -t -s -B "$QUILT_PC/$patch/" "$SUBDIR$file"
|
||||
then
|
||||
printf $"Failed to remove file %s from patch %s\n" \
|
||||
"$SUBDIR$file" "$(print_patch "$patch")" >&2
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -e "$(dirname "$QUILT_PC/$patch~refresh")" -a \
|
||||
-e "$(patch_file_name "$patch")" ]
|
||||
then
|
||||
# The patch must be refreshed in order to get rid of the
|
||||
# patch permanently.
|
||||
touch "$QUILT_PC/$patch~refresh"
|
||||
fi
|
||||
|
||||
printf $"File %s removed from patch %s\n" \
|
||||
"$SUBDIR$file" "$(print_patch $patch)"
|
||||
done
|
||||
exit $status
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,110 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt rename [-P patch] new_name\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Rename the topmost or named patch.
|
||||
|
||||
-P patch
|
||||
Patch to rename.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
move_file()
|
||||
{
|
||||
local old=$1 new=$2 newdir=$(dirname "$2")
|
||||
|
||||
[ -d "$newdir" ] || mkdir -p "$newdir" || return 1
|
||||
mv "$old" "$new" || return 1
|
||||
rmdir -p "$(dirname "$old")" 2> /dev/null
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
options=`getopt -o P:h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-P)
|
||||
opt_patch=$2
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -ne 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
patch=$(find_patch_in_series "$opt_patch") || exit 1
|
||||
|
||||
new_patch=${1#$QUILT_PATCHES/}
|
||||
|
||||
if patch_in_series "$new_patch" || \
|
||||
[ -d "$QUILT_PC/$new_patch" ] || \
|
||||
[ -e "$(patch_file_name "$new_patch")" ]
|
||||
then
|
||||
printf $"Patch %s exists already, please choose a different name\n" \
|
||||
"$(print_patch "$new_patch")" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ( is_applied "$patch" && \
|
||||
( ! rename_in_db "$patch" "$new_patch" || \
|
||||
! move_file "$QUILT_PC/$patch" \
|
||||
"$QUILT_PC/$new_patch" ) ) || \
|
||||
! rename_in_series "$patch" "$new_patch" || \
|
||||
( [ -e "$(patch_file_name "$patch")" ] && \
|
||||
! move_file "$(patch_file_name "$patch")" \
|
||||
"$(patch_file_name "$new_patch")" )
|
||||
then
|
||||
printf $"Renaming of patch %s to %s failed\n" \
|
||||
"$(print_patch "$patch")" \
|
||||
"$(print_patch "$new_patch")" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf $"Patch %s renamed to %s\n" \
|
||||
"$(print_patch "$patch")" \
|
||||
"$(print_patch "$new_patch")"
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,132 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt revert [-P patch] {file} ...\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Revert uncommitted changes to the topmost or named patch for the specified
|
||||
file(s): after the revert, 'quilt diff -z' will show no differences for those
|
||||
files. Changes to files that are modified by patches on top of the specified
|
||||
patch cannot be reverted.
|
||||
|
||||
-P patch
|
||||
Revert changes in the named patch.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o P:h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-P)
|
||||
opt_patch="$2"
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
patch=$(find_applied_patch "$opt_patch") || exit 1
|
||||
|
||||
status=0
|
||||
for file in "${@/#/$SUBDIR}"
|
||||
do
|
||||
if ! file_in_patch "$file" $patch
|
||||
then
|
||||
printf $"File %s is not in patch %s\n" \
|
||||
"$file" "$(print_patch $patch)" >&2
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
|
||||
next_patch=$(next_patch_for_file $patch "$file")
|
||||
if [ -n "$next_patch" ]
|
||||
then
|
||||
printf $"File %s modified by patch %s\n" \
|
||||
"$file" "$(print_patch $next_patch)"
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
done
|
||||
[ $status -eq 0 ] || exit $status
|
||||
|
||||
workdir=$(gen_tempfile -d $PWD)
|
||||
add_exit_handler "rm -rf $workdir"
|
||||
apply_patch_temporarily $workdir $patch "${@/#/$SUBDIR}" || exit 1
|
||||
|
||||
for file in ${*/#/$SUBDIR}
|
||||
do
|
||||
if [ -s "$workdir/$file" ]
|
||||
then
|
||||
if [ -e "$file" ] &&
|
||||
diff -q "$workdir/$file" "$file" > /dev/null
|
||||
then
|
||||
printf $"File %s is unchanged\n" "$file"
|
||||
continue
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$file")"
|
||||
cp -p "$workdir/$file" "$file"
|
||||
else
|
||||
if [ ! -e "$file" ]
|
||||
then
|
||||
printf $"File %s is unchanged\n" "$file"
|
||||
continue
|
||||
fi
|
||||
|
||||
rm -f "$file"
|
||||
fi
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
printf $"Failed to revert changes to %s in patch %s\n" \
|
||||
"$file" "$(print_patch $patch)" >&2
|
||||
status=1
|
||||
else
|
||||
printf $"Changes to %s in patch %s reverted\n" \
|
||||
"$file" "$(print_patch $patch)"
|
||||
fi
|
||||
done
|
||||
exit $status
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,370 @@
|
|||
#! @BASH@
|
||||
|
||||
set -e
|
||||
# Keep /dev/null opened as we will need it repeatedly
|
||||
exec 4> /dev/null
|
||||
|
||||
# Copyright (C) 2006 Steve Langasek <vorlon@debian.org>
|
||||
# Copyright (C) 2011 Jean Delvare <jdelvare@suse.de>
|
||||
# Loosely based on C implementation by Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
# 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; version 2 dated June, 1991.
|
||||
|
||||
# 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, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
|
||||
usage ()
|
||||
{
|
||||
echo "Usage: $0 -B prefix {-b|-r|-c|-L} [-s] [-k] [-t] [-L] {-f {file|-}|-|file ...}
|
||||
|
||||
Create or restore backup copies of a list of files.
|
||||
|
||||
Mandatory parameters:
|
||||
-B Path name prefix for backup files
|
||||
|
||||
Action parameters:
|
||||
-b Create backup (preserve links)
|
||||
-r Restore the backup
|
||||
-c Create simple copy
|
||||
-L Ensure that source files have a link count of 1
|
||||
|
||||
Common options:
|
||||
-s Silent operation; only print error messages
|
||||
|
||||
Restore options:
|
||||
-k Keep backup files
|
||||
-t Touch original files after restore (update their mtimes)
|
||||
|
||||
Backup options:
|
||||
-L Ensure that source files have a link count of 1
|
||||
|
||||
File list parameters:
|
||||
-f Read the filenames to process from file (- = standard input)
|
||||
- Read the filenames to process from backup
|
||||
"
|
||||
}
|
||||
|
||||
: ${QUILT_DIR=@QUILT_DIR@}
|
||||
. $QUILT_DIR/scripts/utilfns
|
||||
|
||||
ensure_nolinks()
|
||||
{
|
||||
local filename=$1
|
||||
local link_count tmpname
|
||||
|
||||
link_count=$(stat @STAT_HARDLINK@ "$filename")
|
||||
if [ $link_count -gt 1 ]; then
|
||||
tmpname=$(mktemp "$filename.XXXXXX")
|
||||
cp -p "$filename" "$tmpname"
|
||||
mv "$tmpname" "$filename"
|
||||
fi
|
||||
}
|
||||
|
||||
notify_action()
|
||||
{
|
||||
[ $ECHO != : ] || return 0
|
||||
local action=$1 filename=$2
|
||||
|
||||
while read -d $'\0' -r
|
||||
do
|
||||
$ECHO "$action ${REPLY#./}"
|
||||
done < "$filename"
|
||||
}
|
||||
|
||||
backup()
|
||||
{
|
||||
local file=$1
|
||||
local backup=$OPT_PREFIX$file
|
||||
local dir
|
||||
|
||||
dir=$(dirname "$backup")
|
||||
[ -d "$dir" ] || mkdir -p "$dir"
|
||||
|
||||
if [ -e "$file" ]; then
|
||||
$ECHO "Copying $file"
|
||||
if [ -n "$OPT_NOLINKS" -a "$(stat @STAT_HARDLINK@ "$file")" = 1 ]; then
|
||||
cp -p "$file" "$backup"
|
||||
else
|
||||
ln "$file" "$backup" 2>&4 || cp -p "$file" "$backup"
|
||||
if [ -n "$OPT_NOLINKS" ]; then
|
||||
ensure_nolinks "$file"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
$ECHO "New file $file"
|
||||
: > "$backup"
|
||||
fi
|
||||
}
|
||||
|
||||
restore()
|
||||
{
|
||||
local file=$1
|
||||
local backup=$OPT_PREFIX$file
|
||||
|
||||
if [ ! -e "$backup" ]; then
|
||||
return 1
|
||||
fi
|
||||
if [ -s "$backup" ]; then
|
||||
$ECHO "Restoring $file"
|
||||
if [ -e "$file" ]; then
|
||||
rm "$file"
|
||||
else
|
||||
mkdir -p "$(dirname "$file")"
|
||||
fi
|
||||
ln "$backup" "$file" 2>&4 || cp -p "$backup" "$file"
|
||||
|
||||
if [ -n "$OPT_TOUCH" ]; then
|
||||
touch "$file"
|
||||
fi
|
||||
else
|
||||
$ECHO "Removing $file"
|
||||
if [ -e "$file" ]; then
|
||||
rm "$file"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$OPT_KEEP_BACKUP" ]; then
|
||||
rm "$backup"
|
||||
rmdir -p "${backup%/*}" 2>&4 || true
|
||||
fi
|
||||
}
|
||||
|
||||
restore_all()
|
||||
{
|
||||
local EMPTY_FILES NONEMPTY_FILES
|
||||
|
||||
# Store the list of files to process
|
||||
EMPTY_FILES=$(gen_tempfile)
|
||||
NONEMPTY_FILES=$(gen_tempfile)
|
||||
trap "rm -f \"$EMPTY_FILES\" \"$NONEMPTY_FILES\"" EXIT
|
||||
|
||||
cd "$OPT_PREFIX"
|
||||
find . -type f -size 0 -print0 > "$EMPTY_FILES"
|
||||
find . -type f -size +0 -print0 > "$NONEMPTY_FILES"
|
||||
cd "$OLDPWD"
|
||||
|
||||
if [ -s "$EMPTY_FILES" ]; then
|
||||
xargs -0 rm -f < "$EMPTY_FILES"
|
||||
notify_action Removing "$EMPTY_FILES"
|
||||
fi
|
||||
|
||||
if [ -s "$NONEMPTY_FILES" ]; then
|
||||
# Try a mass link (or copy) first, as it is much faster.
|
||||
# It is however not portable and may thus fail. If it fails,
|
||||
# fallback to per-file processing, which always works.
|
||||
local target_dir=$PWD
|
||||
|
||||
if (cd "$OPT_PREFIX" && \
|
||||
xargs -0 cp -l --parents --remove-destination \
|
||||
--target-directory="$target_dir" \
|
||||
< "$NONEMPTY_FILES" 2>&4); then
|
||||
notify_action Restoring "$NONEMPTY_FILES"
|
||||
else
|
||||
(cd "$OPT_PREFIX" && find . -type d -print0) \
|
||||
| xargs -0 mkdir -p
|
||||
|
||||
xargs -0 rm -f < "$NONEMPTY_FILES"
|
||||
|
||||
while read -d $'\0' -r
|
||||
do
|
||||
local file=${REPLY#./}
|
||||
local backup=$OPT_PREFIX$file
|
||||
|
||||
$ECHO "Restoring $file"
|
||||
ln "$backup" "$file" 2>&4 || cp -p "$backup" "$file"
|
||||
done < "$NONEMPTY_FILES"
|
||||
fi
|
||||
|
||||
if [ -n "$OPT_TOUCH" ]; then
|
||||
xargs -0 touch -c < "$NONEMPTY_FILES"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$OPT_KEEP_BACKUP" ]; then
|
||||
rm -rf "$OPT_PREFIX"
|
||||
fi
|
||||
}
|
||||
|
||||
noop_nolinks()
|
||||
{
|
||||
local file=$1
|
||||
|
||||
if [ -e "$file" ]; then
|
||||
ensure_nolinks "$file"
|
||||
fi
|
||||
}
|
||||
|
||||
copy()
|
||||
{
|
||||
local file=$1
|
||||
local backup=$OPT_PREFIX$file
|
||||
local dir
|
||||
|
||||
dir=$(dirname "$backup")
|
||||
[ -d "$dir" ] || mkdir -p "$dir"
|
||||
|
||||
if [ -e "$file" ]; then
|
||||
$ECHO "Copying $file"
|
||||
cp -p "$file" "$backup"
|
||||
else
|
||||
$ECHO "New file $file"
|
||||
: > "$backup"
|
||||
fi
|
||||
}
|
||||
|
||||
copy_many()
|
||||
{
|
||||
local NONEMPTY_FILES
|
||||
|
||||
# Store the list of non-empty files to process
|
||||
NONEMPTY_FILES=$(gen_tempfile)
|
||||
trap "rm -f \"$NONEMPTY_FILES\"" EXIT
|
||||
|
||||
# Keep the temporary file opened to speed up the loop
|
||||
exec 3> "$NONEMPTY_FILES"
|
||||
cat "$OPT_FILE" \
|
||||
| while read
|
||||
do
|
||||
if [ -e "$REPLY" ]; then
|
||||
printf '%s\0' "$REPLY" >&3
|
||||
else
|
||||
# This is a rare case, not worth optimizing
|
||||
copy "$REPLY"
|
||||
fi
|
||||
done
|
||||
exec 3>&-
|
||||
|
||||
if [ -s "$NONEMPTY_FILES" ]; then
|
||||
# Try a mass copy first, as it is much faster.
|
||||
# It is however not portable and may thus fail. If it fails,
|
||||
# fallback to per-file processing, which always works.
|
||||
|
||||
if xargs -0 cp -p --parents --target-directory="$OPT_PREFIX" \
|
||||
< "$NONEMPTY_FILES" 2>&4; then
|
||||
notify_action Copying "$NONEMPTY_FILES"
|
||||
else
|
||||
while read -d $'\0' -r
|
||||
do
|
||||
copy "$REPLY"
|
||||
done < "$NONEMPTY_FILES"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Test if some backed up files have a link count greater than 1
|
||||
some_files_have_links()
|
||||
{
|
||||
(cd "$OPT_PREFIX" && find . -type f -print0) \
|
||||
| xargs -0 stat @STAT_HARDLINK@ 2>&4 | grep -qv '^1$'
|
||||
}
|
||||
|
||||
|
||||
ECHO=echo
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-b) OPT_WHAT=backup
|
||||
;;
|
||||
-r) OPT_WHAT=restore
|
||||
;;
|
||||
-c) OPT_WHAT=copy
|
||||
;;
|
||||
-B) OPT_PREFIX=$2
|
||||
shift
|
||||
;;
|
||||
-f) OPT_FILE=$2
|
||||
shift
|
||||
;;
|
||||
-s) ECHO=:
|
||||
;;
|
||||
-k) OPT_KEEP_BACKUP=1
|
||||
;;
|
||||
-L) OPT_NOLINKS=1
|
||||
;;
|
||||
-t) OPT_TOUCH=1
|
||||
;;
|
||||
-?*) usage
|
||||
exit 0
|
||||
;;
|
||||
*) break
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -z "$OPT_PREFIX" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${OPT_PREFIX:(-1)}" != / ]; then
|
||||
echo "Prefix must be a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$OPT_WHAT" ]; then
|
||||
if [ -n "$OPT_NOLINKS" ]; then
|
||||
OPT_WHAT=noop_nolinks
|
||||
else
|
||||
echo "Please specify an action" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$OPT_FILE" ]; then
|
||||
if [ "$OPT_WHAT" = copy ]; then
|
||||
copy_many
|
||||
exit
|
||||
fi
|
||||
|
||||
cat "$OPT_FILE" \
|
||||
| while read nextfile; do
|
||||
$OPT_WHAT "$nextfile"
|
||||
done
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$1" = - ]; then
|
||||
# No backup directory? We're done
|
||||
[ -d "$OPT_PREFIX" ] || exit 0
|
||||
|
||||
if [ "$OPT_WHAT" = restore ]; then
|
||||
restore_all
|
||||
exit
|
||||
fi
|
||||
|
||||
# We typically expect the link count of backed up files to be 1
|
||||
# already, so check quickly that this is the case, and only if not,
|
||||
# take the slow path and walk the file list in search of files to fix.
|
||||
if [ "$OPT_WHAT" = noop_nolinks ] && ! some_files_have_links; then
|
||||
exit
|
||||
fi
|
||||
|
||||
find "$OPT_PREFIX" -type f -print \
|
||||
| while read
|
||||
do
|
||||
$OPT_WHAT "${REPLY#$OPT_PREFIX}"
|
||||
done
|
||||
if [ ${PIPESTATUS[0]} != 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
$OPT_WHAT "$1"
|
||||
shift
|
||||
done
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,470 @@
|
|||
#!@PERL@ -w
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Generate a dot-style graph of dependencies between patches.
|
||||
|
||||
use Getopt::Long;
|
||||
use FileHandle;
|
||||
use strict;
|
||||
|
||||
# Constants
|
||||
my $short_edge_style = "color=grey";
|
||||
my $close_node_style = "color=grey";
|
||||
my $highlighted_node_style = "style=bold";
|
||||
|
||||
# Command line arguments
|
||||
my $help = 0;
|
||||
my $use_patcher = 0; # Assume patcher format for metadata
|
||||
my $short_edge_thresh = 0; # threshold for coloring as "short", 0 = disable
|
||||
my $long_edge_thresh = 0; # threshold for coloring as "long",0 = disable
|
||||
my $edge_labels; # label all edges with filenames
|
||||
my $short_edge_labels; # label short edges with filenames
|
||||
my $long_edge_labels; # label long edges with filenames
|
||||
my $edge_length_labels; # distance between patches as edge labels
|
||||
my $node_numbers; # include sequence numbers
|
||||
my $show_isolated_nodes; # also include isolated nodes
|
||||
my $reduce; # remove transitive edges
|
||||
my $filter_patchnames; # filter for compacting filenames
|
||||
my $selected_patch; # only include patches related on this patch
|
||||
my $selected_distance = -1; # infinity
|
||||
my @highlight_patches; # a list of patches to highlight
|
||||
my $lines; # check ranges with this number of context
|
||||
# lines.
|
||||
|
||||
unless (GetOptions(
|
||||
"h|help" => \$help,
|
||||
"patcher" => \$use_patcher,
|
||||
"short-edge=i" => \$short_edge_thresh,
|
||||
"long-edge=i" => \$long_edge_thresh,
|
||||
"edge-files" => \$edge_labels,
|
||||
"short-edge-files" => \$short_edge_labels,
|
||||
"long-edge-files" => \$long_edge_labels,
|
||||
"edge-length" => \$edge_length_labels,
|
||||
"node-numbers" => \$node_numbers,
|
||||
"isolated" => \$show_isolated_nodes,
|
||||
"reduce" => \$reduce,
|
||||
"filter-patchnames=s" => \$filter_patchnames,
|
||||
"select-patch=s" => \$selected_patch,
|
||||
"select-distance=i" => \$selected_distance,
|
||||
"highlight=s" => \@highlight_patches,
|
||||
"lines=i" => \$lines) && !$help) {
|
||||
my $basename = $0;
|
||||
$basename =~ s:.*/::;
|
||||
my $fd = $help ? *STDOUT : *STDERR;
|
||||
print $fd <<EOF;
|
||||
SYNOPSIS: $basename [-h] [--patcher] [--short-edge=num] [--long-edge=num]
|
||||
[--short-edge-files] [--long-edge-files] [--edge-length]
|
||||
[--node-numbers] [--isolated] [--reduce] [--filter-patchnames=filter]
|
||||
[--select-patch=patch] [--select-distance=num] [--highlight=patch]
|
||||
[--lines=num]
|
||||
|
||||
--patcher
|
||||
Assume patch manager is Holger Schurig's patcher script instead
|
||||
of the default quilt.
|
||||
|
||||
--short-edge=num, --long-edge=num
|
||||
Define the maximum edge length of short edges, and minimum edge
|
||||
length of long edges. Short edges are de-emphasized, and long
|
||||
edges are emphasized. The default is to treat all edges equally.
|
||||
|
||||
-edge-files, --short-edge-files, --long-edge-files
|
||||
Include conflicting filenames on all edges, short edges, or long
|
||||
edges.
|
||||
|
||||
--edge-length
|
||||
Use the edge lengths as edge labels. Cannot be used together with
|
||||
filename labels.
|
||||
|
||||
--node-numbers
|
||||
Include the sequence numbers of patches in the patch series in
|
||||
node labels.
|
||||
|
||||
--isolated
|
||||
Do not suppress isolated nodes.
|
||||
|
||||
--reduce
|
||||
Remove transitive edges.
|
||||
|
||||
--filter-patchnames=filter
|
||||
Define a filter command for transforming patch names into node
|
||||
labels. The filter is passed each patch name on a separate line,
|
||||
and must return the edge label for each patch on a separate line
|
||||
(example: sed -e 's/^prefix//').
|
||||
|
||||
--select-patch=patch
|
||||
Reduce the graph to nodes that depend on the specified patch,
|
||||
and nodes that the specified patch depends on (recursively).
|
||||
|
||||
--select-distance=num
|
||||
Limit the depth of recusion for --select-patch. The default is
|
||||
to recurse exhaustively.
|
||||
|
||||
--highlight=patch
|
||||
Highlight the specified patch. This option can be specified more
|
||||
than once.
|
||||
|
||||
--lines=num
|
||||
Check the ranges of lines that the patches modify for computing
|
||||
dependencies. Include up to num lines of context.
|
||||
EOF
|
||||
exit $help ? 0 : 1;
|
||||
}
|
||||
|
||||
my @nodes;
|
||||
|
||||
sub next_patch_for_file($$)
|
||||
{
|
||||
my ($n, $file) = @_;
|
||||
|
||||
for (my $i = $n + 1; $i < @nodes; $i++) {
|
||||
return $i
|
||||
if (exists $nodes[$i]{files}{$file});
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Compute the ranges of lines that a patch modifies: The patch should
|
||||
# have no context lines. The return value is a list of pairs of line
|
||||
# numbers, alternatingly marking the start and end of a modification.
|
||||
sub ranges($) {
|
||||
my ($fd) = @_;
|
||||
my (@left, @right);
|
||||
while (<$fd>) {
|
||||
if (/^\@\@ -(\d+)(?:,(\d+)?) \+(\d+)(?:,(\d+)?) \@\@/) {
|
||||
push @left, ($3, $3 + $4);
|
||||
push @right, ($1, $1 + $2);
|
||||
}
|
||||
}
|
||||
return [ [ @left ], [ @right ] ];
|
||||
}
|
||||
|
||||
sub backup_file_name($$) {
|
||||
my ($patch, $file) = @_;
|
||||
|
||||
if ($use_patcher) {
|
||||
return $file . "~" . $patch;
|
||||
} else {
|
||||
return $ENV{QUILT_PC} . "/" . $patch . "/" . $file;
|
||||
}
|
||||
}
|
||||
|
||||
# Compute the lists of lines that a patch changes in a file.
|
||||
sub compute_ranges($$) {
|
||||
my ($n, $file) = @_;
|
||||
my $file1 = backup_file_name($nodes[$n]{file}, $file);
|
||||
my $file2;
|
||||
my $n2 = next_patch_for_file($n, $file);
|
||||
if (defined $n2) {
|
||||
$file2 = backup_file_name($nodes[$n2]{file}, $file);
|
||||
} else {
|
||||
$file2 = $file;
|
||||
}
|
||||
|
||||
#print STDERR "diff -U$lines \"$file1\" \"$file2\"\n";
|
||||
if (-z $file1) {
|
||||
$file1="/dev/null";
|
||||
return [[], []]
|
||||
if (-z $file2);
|
||||
} else {
|
||||
$file2="/dev/null"
|
||||
if (-z $file2);
|
||||
}
|
||||
my $fd = new FileHandle("diff -U$lines \"$file1\" \"$file2\" |");
|
||||
my $ranges = ranges($fd);
|
||||
$fd->close();
|
||||
return $ranges;
|
||||
}
|
||||
|
||||
sub is_a_conflict($$$) {
|
||||
my ($from, $to, $filename) = @_;
|
||||
|
||||
$nodes[$from]{files}{$filename} = compute_ranges($from, $filename)
|
||||
unless @{$nodes[$from]{files}{$filename}};
|
||||
$nodes[$to]{files}{$filename} = compute_ranges($to, $filename)
|
||||
unless @{$nodes[$to]{files}{$filename}};
|
||||
|
||||
my @a = @{$nodes[$from]{files}{$filename}[1]};
|
||||
my @b = @{$nodes[$to ]{files}{$filename}[0]};
|
||||
|
||||
while (@a && @b) {
|
||||
if ($a[0] < $b[0]) {
|
||||
return 1 if @b % 2;
|
||||
shift @a;
|
||||
} elsif ($a[0] > $b[0]) {
|
||||
return 1 if @a % 2;
|
||||
shift @b;
|
||||
} else {
|
||||
return 1 if (@a % 2) == (@b % 2);
|
||||
shift @a;
|
||||
shift @b;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Fetch the list of patches (all of them must be applied)
|
||||
my @patches;
|
||||
if (@ARGV) {
|
||||
if (@ARGV == 1 && $ARGV[0] eq "-") {
|
||||
@patches = map { chomp ; $_ } <STDIN>;
|
||||
} else {
|
||||
@patches = @ARGV;
|
||||
}
|
||||
} elsif ($use_patcher) {
|
||||
my $fh = new FileHandle("< .patches/applied")
|
||||
or die ".patches/applied: $!\n";
|
||||
@patches = map { chomp; $_ } <$fh>;
|
||||
$fh->close();
|
||||
} else {
|
||||
my $fh = new FileHandle("< $ENV{QUILT_PC}/applied-patches")
|
||||
or die ".$ENV{QUILT_PC}/applied-patches: $!\n";
|
||||
@patches = map { chomp; $_ } <$fh>;
|
||||
$fh->close();
|
||||
}
|
||||
|
||||
# Fetch the list of files
|
||||
my $n = 0;
|
||||
foreach my $patch (@patches) {
|
||||
my @files;
|
||||
if ($use_patcher) {
|
||||
my $fh = new FileHandle("< .patches/$patch.files")
|
||||
or die ".patches/$patch.files: $!\n";
|
||||
@files = map { chomp; $_ } <$fh>;
|
||||
$fh->close();
|
||||
} else {
|
||||
if (! -d "$ENV{QUILT_PC}/$patch") {
|
||||
print STDERR "$ENV{QUILT_PC}/$patch does not exist; skipping\n";
|
||||
next;
|
||||
}
|
||||
@files = split(/\n/, `cd $ENV{QUILT_PC}/$patch ; find . -type f ! -name .timestamp`);
|
||||
@files = map { s:\./::; $_ } @files;
|
||||
}
|
||||
push @nodes, {number=>$n++, name=>$patch, file=>$patch,
|
||||
files=>{ map {$_ => []} @files } };
|
||||
}
|
||||
|
||||
my %used_nodes; # nodes to which at least one edge is attached
|
||||
|
||||
# If a patch is selected, limit the graph to nodes that depend on this patch,
|
||||
# and nodes that are dependent on this patch.
|
||||
if ($selected_patch) {
|
||||
for ($n = 0; $n < @nodes; $n++) {
|
||||
last if $nodes[$n]{file} eq $selected_patch;
|
||||
}
|
||||
die "Patch $selected_patch not included\n"
|
||||
if ($n == @nodes);
|
||||
|
||||
$used_nodes{$n} = 1;
|
||||
my $selected_node = $nodes[$n];
|
||||
push @{$selected_node->{attrs}}, $highlighted_node_style;
|
||||
|
||||
my %sel;
|
||||
map { $sel{$_} = 1 } keys %{$selected_node->{files}};
|
||||
foreach my $node (@nodes) {
|
||||
foreach my $file (keys %{$node->{files}}) {
|
||||
unless (exists $sel{$file}) {
|
||||
delete $node->{files}{$file};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Optionally highlight a list of patches
|
||||
foreach my $patch (@highlight_patches) {
|
||||
for ($n = 0; $n < @nodes; $n++) {
|
||||
last if $nodes[$n]{file} eq $patch;
|
||||
}
|
||||
die "Patch $patch not included\n"
|
||||
if ($n == @nodes);
|
||||
|
||||
my $node = $nodes[$n];
|
||||
push @{$node->{attrs}}, $highlighted_node_style;
|
||||
$node->{colorized} = 1;
|
||||
}
|
||||
|
||||
# If a patchname filter is selected, pipe all patchnames through
|
||||
# it.
|
||||
if ($filter_patchnames) {
|
||||
local *PIPE;
|
||||
my $pid = open(PIPE, "- |"); # fork a child to read from
|
||||
die "fork: $!\n"
|
||||
unless defined $pid;
|
||||
unless ($pid) { # child
|
||||
# open a second pipe to the actual filter
|
||||
open(PIPE, "| $filter_patchnames")
|
||||
or die "$filter_patchnames: $!\n";
|
||||
map { print PIPE "$_\n" } @patches;
|
||||
close(PIPE);
|
||||
exit;
|
||||
} else { # parent
|
||||
$n = 0;
|
||||
foreach my $name (<PIPE>) {
|
||||
last unless $n < @nodes;
|
||||
chomp $name;
|
||||
if ($name eq "") {
|
||||
delete $nodes[$n++]{name};
|
||||
} else {
|
||||
$nodes[$n++]{name} = $name;
|
||||
}
|
||||
}
|
||||
close(PIPE)
|
||||
or die "patchname filter failed.\n";
|
||||
die "patchname filter returned too few lines\n"
|
||||
if $n != @nodes;
|
||||
}
|
||||
}
|
||||
|
||||
my %files_seen; # remember the last patch that touched each file
|
||||
my %edges;
|
||||
|
||||
foreach my $node (@nodes) {
|
||||
my $number = $node->{number};
|
||||
foreach my $file (keys %{$node->{files}}) {
|
||||
if (exists $files_seen{$file}) {
|
||||
my $patches = $files_seen{$file};
|
||||
my $patch;
|
||||
# Optionally look at the line ranges the patches touch
|
||||
if (defined $lines) {
|
||||
for (my $n = $#$patches; $n >= 0; $n--) {
|
||||
if (is_a_conflict($number, $patches->[$n], $file)) {
|
||||
$patch = $patches->[$n];
|
||||
last;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$patch = $patches->[$#$patches];
|
||||
}
|
||||
if (defined $patch) {
|
||||
push @{$edges{"$number:$patch"}{names}}, $file;
|
||||
$used_nodes{$number} = 1;
|
||||
$used_nodes{$patch} = 1;
|
||||
}
|
||||
}
|
||||
push @{$files_seen{$file}}, $number;
|
||||
}
|
||||
}
|
||||
|
||||
# Create adjacency lists
|
||||
foreach my $node (@nodes) {
|
||||
@{$node->{to}} = ();
|
||||
@{$node->{from}} = ();
|
||||
}
|
||||
foreach my $key (keys %edges) {
|
||||
my ($from, $to) = split /:/, $key;
|
||||
push @{$nodes[$from]{to}}, $to;
|
||||
push @{$nodes[$to]{from}}, $from;
|
||||
}
|
||||
|
||||
# Colorize nodes that are close to each other
|
||||
foreach my $node (@nodes) {
|
||||
if (!exists $node->{colorized} && !exists $used_nodes{$node->{number}}) {
|
||||
$node->{colorized} = 1;
|
||||
push @{$node->{attrs}}, $close_node_style;
|
||||
}
|
||||
}
|
||||
|
||||
# Colorize short and long edges
|
||||
foreach my $node (@nodes) {
|
||||
my $close = 1;
|
||||
foreach my $node2 (map {$nodes[$_]} @{$node->{to}}) {
|
||||
if (abs($node2->{number} - $node->{number}) > $short_edge_thresh) {
|
||||
$close = 0
|
||||
}
|
||||
}
|
||||
foreach my $node2 (map {$nodes[$_]} @{$node->{from}}) {
|
||||
if (abs($node2->{number} - $node->{number}) > $short_edge_thresh) {
|
||||
$close = 0
|
||||
}
|
||||
}
|
||||
if (!exists $node->{colorized} && $close) {
|
||||
$node->{colorized} = 1;
|
||||
push @{$node->{attrs}}, $close_node_style;
|
||||
}
|
||||
}
|
||||
|
||||
# Add node labels
|
||||
foreach my $node (@nodes) {
|
||||
my @label = ();
|
||||
push @label, $node->{number} + 1
|
||||
if ($node_numbers);
|
||||
push @label, $node->{name}
|
||||
if exists $node->{name};
|
||||
push @{$node->{attrs}}, "label=\"" . join(": ", @label) . "\"";
|
||||
}
|
||||
|
||||
# Add edge labels
|
||||
foreach my $key (keys %edges) {
|
||||
my ($from, $to) = split /:/, $key;
|
||||
if ($edge_length_labels) {
|
||||
push @{$edges{$key}->{attrs}}, "label=\"" . abs($to - $from) . "\""
|
||||
if abs($to - $from) > 1;
|
||||
} elsif (abs($to - $from) < $short_edge_thresh) {
|
||||
push @{$edges{$key}->{attrs}}, $short_edge_style;
|
||||
if ($edge_labels || $short_edge_labels) {
|
||||
push @{$edges{$key}->{attrs}},
|
||||
"label=\"" . join("\\n", @{$edges{$key}{names}}) . "\"";
|
||||
}
|
||||
} else {
|
||||
if ($long_edge_thresh && abs($to - $from) > $long_edge_thresh) {
|
||||
push @{$edges{$key}->{attrs}}, "style=bold";
|
||||
if ($edge_labels || $long_edge_labels) {
|
||||
push @{$edges{$key}->{attrs}},
|
||||
"label=\"" . join("\\n", @{$edges{$key}{names}}) . "\"";
|
||||
}
|
||||
} else {
|
||||
if ($edge_labels) {
|
||||
push @{$edges{$key}->{attrs}},
|
||||
"label=\"" . join("\\n", @{$edges{$key}{names}}) . "\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
# Compute a pseudo edge length so that neato works acceptably.
|
||||
push @{$edges{$key}{attrs}}, "len=\"" .
|
||||
sprintf("%.2f", log(abs($to - $from) + 3)) . "\"";
|
||||
}
|
||||
|
||||
#foreach my $node (@nodes) {
|
||||
# push @{$node->{attrs}}, "shape=box";
|
||||
#}
|
||||
|
||||
# Open output file / pipe
|
||||
my $out;
|
||||
if ($reduce) {
|
||||
$out = new FileHandle("| tred")
|
||||
or die "tred: $!\n";
|
||||
} else {
|
||||
$out = new FileHandle("> /dev/stdout")
|
||||
or die "$!\n";
|
||||
}
|
||||
|
||||
# Write graph
|
||||
print $out "digraph dependencies {\n";
|
||||
#print "\tsize=\"11,8\"\n";
|
||||
foreach my $node (@nodes) {
|
||||
next unless $show_isolated_nodes || exists $used_nodes{$node->{number}};
|
||||
print $out "\tn$node->{number}";
|
||||
if (exists $node->{attrs}) {
|
||||
print $out " [" .
|
||||
join(",", @{$node->{attrs}}) . "]";
|
||||
}
|
||||
print $out ";\n";
|
||||
}
|
||||
|
||||
sub w($) {
|
||||
my @n = split /:/, shift;
|
||||
return $n[0] * 10000 + $n[1];
|
||||
}
|
||||
foreach my $key (sort { w($a) <=> w($b) } keys %edges) {
|
||||
my ($from, $to) = split /:/, $key;
|
||||
print $out "\tn$to -> n$from";
|
||||
if (exists $edges{$key}{attrs}) {
|
||||
print $out " [" . join(",", @{$edges{$key}{attrs}}) . "]";
|
||||
}
|
||||
print $out ";\n";
|
||||
}
|
||||
print $out "}\n";
|
|
@ -0,0 +1,233 @@
|
|||
#! @PERL@ -w
|
||||
|
||||
# RFCs important for this script:
|
||||
#
|
||||
# RFC 2822 - Internet Message Format
|
||||
# RFC 2047 - MIME (Multipurpose Internet Mail Extensions) Part Three:
|
||||
# Message Header Extensions for Non-ASCII Text
|
||||
|
||||
use Getopt::Long;
|
||||
use strict;
|
||||
|
||||
# This ugly trick lets the script work even if gettext support is missing.
|
||||
# We did so because Locale::gettext doesn't ship with the standard perl
|
||||
# distribution.
|
||||
BEGIN {
|
||||
if (eval { require Locale::gettext }) {
|
||||
import Locale::gettext;
|
||||
require POSIX;
|
||||
import POSIX, qw(setlocale);
|
||||
} else {
|
||||
eval '
|
||||
use constant LC_MESSAGES => 0;
|
||||
sub setlocale($$) { }
|
||||
sub bindtextdomain($$) { }
|
||||
sub textdomain($) { }
|
||||
sub gettext($) { shift }
|
||||
'
|
||||
}
|
||||
}
|
||||
|
||||
setlocale(LC_MESSAGES, "");
|
||||
bindtextdomain("quilt", "@LOCALEDIR@");
|
||||
textdomain("quilt");
|
||||
|
||||
sub _($) {
|
||||
return gettext(shift);
|
||||
}
|
||||
|
||||
my $special = '()<>\[\]:;@\\,"'; # special characters
|
||||
my $special_dot = "$special."; # special characters + dot
|
||||
|
||||
sub check_recipient($);
|
||||
|
||||
my (%append_name, %append_value, $remove_empty_headers, %remove_header,
|
||||
%extract_recipients_from, %replace_name, %replace_value, $charset);
|
||||
GetOptions('add-recipient=s%' =>
|
||||
sub {
|
||||
$append_name{lc $_[1]} = $_[1];
|
||||
$append_value{lc $_[1]} .= ",\n " . $_[2];
|
||||
},
|
||||
'add-good-recipient=s%' =>
|
||||
sub {
|
||||
eval { check_recipient($_[2]) };
|
||||
if ($@) {
|
||||
chomp $@;
|
||||
print STDERR "$@; skipping\n";
|
||||
} else {
|
||||
$append_name{lc $_[1]} = $_[1];
|
||||
$append_value{lc $_[1]} .= ",\n " . $_[2];
|
||||
}
|
||||
},
|
||||
'remove-header=s' => sub { $remove_header{lc $_[1]}++ },
|
||||
'remove-empty-headers' => \$remove_empty_headers,
|
||||
'replace-header=s%' =>
|
||||
sub {
|
||||
$replace_name{lc $_[1]} = $_[1];
|
||||
$replace_value{lc $_[1]} = $_[2];
|
||||
},
|
||||
'extract-recipients=s' => sub { $extract_recipients_from{lc $_[1]} = 1 },
|
||||
'charset=s' => \$charset)
|
||||
or exit 1;
|
||||
my %recipient_headers = map {lc $_ => 1} (@ARGV, keys %append_name);
|
||||
|
||||
sub encode_header($) {
|
||||
my ($word) = @_;
|
||||
$word =~ s{[^\t\41-\76\100-\176]}{sprintf "=%02X", ord($&)}ge;
|
||||
return "=?$charset?q?$word?=";
|
||||
}
|
||||
|
||||
# Check for a valid display name
|
||||
sub check_display_name($) {
|
||||
my ($display) = @_;
|
||||
|
||||
if ($display =~ /^"((?:[^"\\]|\\[^\n\r])*)"/) {
|
||||
my $quoted = $1;
|
||||
if ($quoted =~ /[^\t\40-\176]/) {
|
||||
$display = $quoted;
|
||||
$display =~ s/\\//;
|
||||
return encode_header($display);
|
||||
}
|
||||
} else {
|
||||
local $_ = $display;
|
||||
# The value is not (properly) quoted. Check for invalid characters.
|
||||
while (/\(/ or /\)/) {
|
||||
die sprintf(
|
||||
_("Display name `%s' contains unpaired parentheses\n"), $display)
|
||||
unless s/\(([^()]*)\)/$1/;
|
||||
}
|
||||
if ($display =~ /[^\t\40-\176]/ || $display =~ /[$special_dot]/) {
|
||||
if ($display =~ /[^\1-\10\13\14\16-\37\40\41\43-\133\135-\177]/) {
|
||||
return encode_header($display);
|
||||
} elsif ($display =~ /[$special_dot]/) {
|
||||
return "\"$display\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
return $display;
|
||||
}
|
||||
|
||||
# Check for a valid delivery address
|
||||
sub check_delivery_address($) {
|
||||
my ($deliver) = @_;
|
||||
|
||||
die sprintf(_("Delivery address `%s' is invalid\n"), $deliver)
|
||||
if $deliver =~ /[ \t]/ or
|
||||
$deliver =~ /[^ \t\40-\176]/ or
|
||||
$deliver !~ /^[^$special]+@(\[?)[^$special_dot]+(?:\.[^$special_dot]+)*(\]?)$/ or
|
||||
(!$1) != (!$2);
|
||||
return $deliver;
|
||||
}
|
||||
|
||||
sub check_recipient($) {
|
||||
my ($recipient) = @_;
|
||||
|
||||
if ($recipient =~ /^(.*?)\s*<(.+)>$/) {
|
||||
my $deliver = check_delivery_address($2);
|
||||
return ( check_display_name($1) . " <" . $deliver . ">", $deliver );
|
||||
} elsif ($recipient =~ /^(\S*)\s*\((.*)\)$/) {
|
||||
my $deliver = check_delivery_address($1);
|
||||
return ( $deliver . " (" . check_display_name($2) . ")", $deliver );
|
||||
} else {
|
||||
my $deliver = check_delivery_address($recipient);
|
||||
return ( $deliver, $deliver );
|
||||
}
|
||||
}
|
||||
|
||||
sub split_recipients($) {
|
||||
my ($recipients) = @_;
|
||||
my @list = ();
|
||||
|
||||
while ($recipients !~ /^\s*$/) {
|
||||
my $recipient;
|
||||
if ($recipients =~ s/^\s*,?\s*((?:"(?:[^"]+)"|[^",])*)//) {
|
||||
$recipient = $1;
|
||||
} else {
|
||||
$recipient = $recipients;
|
||||
$recipients = "";
|
||||
}
|
||||
$recipient =~ s/\s*$//;
|
||||
push @list, $recipient;
|
||||
}
|
||||
return @list;
|
||||
}
|
||||
|
||||
my %recipients;
|
||||
sub process_header($) {
|
||||
local ($_) = @_;
|
||||
my ($name, $value);
|
||||
|
||||
return unless defined $_;
|
||||
unless (($name, $value) = /^([\41-\176]+):\s*(.*)/s) {
|
||||
print;
|
||||
return
|
||||
}
|
||||
if (%extract_recipients_from) {
|
||||
if (exists $extract_recipients_from{lc $name}) {
|
||||
$value =~ s/^\s*//; $value =~ s/\s*$//;
|
||||
foreach my $recipient (split_recipients($value)) {
|
||||
my $deliver;
|
||||
($recipient, $deliver) = check_recipient($recipient);
|
||||
print "$deliver\n";
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
return if exists $remove_header{lc $name};
|
||||
if (exists $replace_name{lc $name}) {
|
||||
if (exists $replace_value{lc $name}) {
|
||||
print "$replace_name{lc $name}: $replace_value{lc $name}\n";
|
||||
delete $replace_value{lc $name};
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (exists $recipient_headers{lc $1}) {
|
||||
if (exists $append_name{lc $name}) {
|
||||
$value .= $append_value{lc $name};
|
||||
delete $append_name{lc $name};
|
||||
}
|
||||
my @recipients;
|
||||
# This is a recipients field. Split out all the recipients and
|
||||
# check the addresses. Suppress duplicate recipients.
|
||||
foreach my $recipient (split_recipients($value)) {
|
||||
my $deliver;
|
||||
($recipient, $deliver) = check_recipient($recipient);
|
||||
unless (exists $recipients{$deliver}) {
|
||||
push @recipients, $recipient;
|
||||
$recipients{$deliver} = $deliver;
|
||||
}
|
||||
}
|
||||
print "$name: ", join(",\n ", @recipients), "\n"
|
||||
if @recipients || !$remove_empty_headers;
|
||||
} else {
|
||||
print if $value ne "" || !$remove_empty_headers;
|
||||
}
|
||||
}
|
||||
|
||||
my $header;
|
||||
while (<STDIN>) {
|
||||
last if (/^$/);
|
||||
if (/^\S/) {
|
||||
process_header $header;
|
||||
undef $header;
|
||||
}
|
||||
$header .= $_;
|
||||
}
|
||||
process_header $header;
|
||||
foreach my $name (keys %append_name) {
|
||||
process_header $append_name{$name} . ': ' . $append_value{$name};
|
||||
}
|
||||
unless (%extract_recipients_from) {
|
||||
# Copy the message body to standard output
|
||||
# FIXME check for 7-bit clean, else assume $charset
|
||||
# FIXME if UTF-8, check for invalid characters!
|
||||
# FIXME must make sure that all messages are written in
|
||||
# either 7-bit or $charset => mbox !!!
|
||||
|
||||
# Content-Transfer-Encoding: 7bit
|
||||
# Content-Transfer-Encoding: 8bit
|
||||
# Content-Type: text/plain; charset=ISO-8859-15
|
||||
# Content-Type: text/plain; charset=UTF-8
|
||||
undef $/;
|
||||
print "\n", <STDIN>;
|
||||
}
|
|
@ -0,0 +1,339 @@
|
|||
#! @BASH@
|
||||
|
||||
# find original data file by md5sum
|
||||
original_file()
|
||||
{
|
||||
local md5sum=$1
|
||||
|
||||
if ! [ -e $tmpdir/md5sums ]
|
||||
then
|
||||
echo >&4
|
||||
create_md5sums "$RPM_SOURCE_DIR" $tmpdir/md5sums
|
||||
echo -n "### rpmbuild: " >&4
|
||||
fi
|
||||
|
||||
while read md5sum_ file_
|
||||
do
|
||||
if [ "$md5sum" = "$md5sum_" ]
|
||||
then
|
||||
echo ${file_#\*}
|
||||
return 0
|
||||
fi
|
||||
done < $tmpdir/md5sums
|
||||
|
||||
# Try harder
|
||||
if ! [ -e $tmpdir/more-md5sums ]
|
||||
then
|
||||
( cd $RPM_BUILD_DIR
|
||||
find . -type f \
|
||||
| sed -e 's:^.\/::' \
|
||||
| xargs md5sum \
|
||||
) > $tmpdir/more-md5sums
|
||||
fi
|
||||
|
||||
while read md5sum_ file_
|
||||
do
|
||||
if [ "$md5sum" = "$md5sum_" ]
|
||||
then
|
||||
echo $QUILT_SETUP_PREFIX${file_#\*}
|
||||
return 0
|
||||
fi
|
||||
done < $tmpdir/more-md5sums
|
||||
|
||||
# Return md5sum and error if we can't match the file
|
||||
echo $md5sum
|
||||
return 1
|
||||
}
|
||||
|
||||
# Extract a command line option with or without argument
|
||||
cmdline_option()
|
||||
{
|
||||
local letter=$1 no_arg=$2
|
||||
shift
|
||||
|
||||
while [ $# -ne 0 ]
|
||||
do
|
||||
if [ "${1:0:2}" = -$letter ]
|
||||
then
|
||||
if [ -z "$no_arg" ]
|
||||
then
|
||||
[ "$1" = -$letter ] && set -- "$1$2"
|
||||
fi
|
||||
echo $1
|
||||
break
|
||||
fi
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
# Extract the -p option from the command line
|
||||
strip_option()
|
||||
{
|
||||
set -- $(cmdline_option p "$@")
|
||||
[ "$1" != -p1 ] && echo $1
|
||||
}
|
||||
|
||||
# Extract the -R option from the command line
|
||||
reverse_option()
|
||||
{
|
||||
set -- $(cmdline_option R no_arg "$@")
|
||||
echo $1
|
||||
}
|
||||
|
||||
patch_opt_d()
|
||||
{
|
||||
local subdir=$(cmdline_option d "$@")
|
||||
[ -z "$subdir" ] || echo "${subdir:2}"
|
||||
|
||||
}
|
||||
|
||||
patch_input_file()
|
||||
{
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
-i|--input)
|
||||
if [ $# -ge 2 ]
|
||||
then
|
||||
echo "$2"
|
||||
return
|
||||
fi
|
||||
;;
|
||||
-i*)
|
||||
echo "${1#-i}"
|
||||
return
|
||||
;;
|
||||
--input=*)
|
||||
echo "${1#--input=}"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
tar_input_file()
|
||||
{
|
||||
case "$1" in
|
||||
# Modern option format
|
||||
-*)
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
# Extract the file name (long option)
|
||||
--file)
|
||||
echo "$2"
|
||||
return
|
||||
;;
|
||||
--file=*)
|
||||
echo "${1#--file=}"
|
||||
return
|
||||
;;
|
||||
# Skip other long options
|
||||
--*)
|
||||
shift
|
||||
;;
|
||||
# Extract the file name (short option)
|
||||
-*f)
|
||||
echo "$2"
|
||||
return
|
||||
;;
|
||||
-f*)
|
||||
echo "${1#-f}"
|
||||
return
|
||||
;;
|
||||
# Skip other short options and parameters
|
||||
*)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
;;
|
||||
# Legacy option format (must always come first)
|
||||
*C*f*)
|
||||
echo "$3"
|
||||
return
|
||||
;;
|
||||
*f*)
|
||||
echo "$2"
|
||||
return
|
||||
;;
|
||||
?*)
|
||||
# Eat legacy options and try again
|
||||
until [ $# -eq 0 -o "${1:0:1}" = "-" ]
|
||||
do
|
||||
shift
|
||||
done
|
||||
tar_input_file "$@"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
unzip_input_file()
|
||||
{
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
-*)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "$1"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
_7z_input_file()
|
||||
{
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
-*|e|x)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "$1"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
tar_opt_C()
|
||||
{
|
||||
case "$1" in
|
||||
*C*f*)
|
||||
echo "$2"
|
||||
return ;;
|
||||
esac
|
||||
}
|
||||
|
||||
pwd_to_dir()
|
||||
{
|
||||
local subdir=$1 dir
|
||||
|
||||
if [ -n "$subdir" ]
|
||||
then
|
||||
dir=$(cd "$subdir" && echo $PWD)
|
||||
else
|
||||
dir=$PWD
|
||||
fi
|
||||
dir=${dir/$RPM_BUILD_DIR}
|
||||
dir=${dir##/}
|
||||
dir=${dir// /\\ }
|
||||
|
||||
echo "$dir"
|
||||
}
|
||||
|
||||
# Who were we called as?
|
||||
command=${0##*/}
|
||||
|
||||
PATH=${PATH#*:}
|
||||
# If we are called too early, pass through without processing
|
||||
[ -n "$RPM_BUILD_DIR" ] || exec $command "$@"
|
||||
|
||||
tmpdir=${RPM_BUILD_DIR%/*}
|
||||
case $command in
|
||||
patch)
|
||||
echo -n p >&4
|
||||
inputfile=$(patch_input_file "$@")
|
||||
;;
|
||||
tar)
|
||||
echo -n t >&4
|
||||
[ -n "$QUILT_SETUP_FAST" ] && exec tar "$@"
|
||||
inputfile=$(tar_input_file "$@")
|
||||
# For tar, file - means read from stdin
|
||||
[ "$inputfile" = "-" ] && inputfile=
|
||||
;;
|
||||
unzip)
|
||||
echo -n Z >&4
|
||||
[ -n "$QUILT_SETUP_FAST" ] && exec unzip "$@"
|
||||
inputfile=$(unzip_input_file "$@")
|
||||
;;
|
||||
7z)
|
||||
echo -n 7 >&4
|
||||
[ -n "$QUILT_SETUP_FAST" ] && exec 7z "$@"
|
||||
inputfile=$(_7z_input_file "$@")
|
||||
;;
|
||||
esac
|
||||
|
||||
# If the file was not passed as a parameter, try to identify stdin
|
||||
if [ -n "$QUILT_SETUP_FAST" -a -z "$inputfile" ]
|
||||
then
|
||||
inputfile=$(readlink /proc/self/fd/0)
|
||||
[ "${inputfile:0:1}" = / -a -f "$inputfile" ] || inputfile=
|
||||
fi
|
||||
|
||||
if [ -n "$inputfile" ]
|
||||
then
|
||||
if [ "${inputfile:0:1}" = / ]
|
||||
then
|
||||
unpackfile=${inputfile/$RPM_SOURCE_DIR}
|
||||
else
|
||||
unpackfile=$QUILT_SETUP_PREFIX$(dir_to_dir "$RPM_BUILD_DIR" "$inputfile")
|
||||
fi
|
||||
else
|
||||
if [ -n "$QUILT_SETUP_FAST" ]
|
||||
then
|
||||
# In fast mode we can read from stdin directly, we won't let
|
||||
# patch apply the patch anyway
|
||||
md5sum=$(md5sum)
|
||||
else
|
||||
# put data from stdin into tmpfile
|
||||
cat > $tmpdir/data
|
||||
md5sum=$(md5sum < $tmpdir/data)
|
||||
fi
|
||||
|
||||
unpackfile=$(original_file $md5sum)
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
# Report problem to the caller
|
||||
echo -n "?" >&4
|
||||
printf "Warning: no match for file with md5sum %s\n" \
|
||||
$unpackfile >&2
|
||||
unpackfile="#$unpackfile"
|
||||
fi
|
||||
fi
|
||||
|
||||
case $command in
|
||||
patch)
|
||||
subdir=$(patch_opt_d "$@")
|
||||
dir=$(pwd_to_dir $subdir)
|
||||
echo "patch ${dir:-.} $unpackfile" \
|
||||
$(strip_option "$@") $(reverse_option "$@") >&3
|
||||
;;
|
||||
tar)
|
||||
subdir=$(tar_opt_C "$@")
|
||||
dir=$(pwd_to_dir $subdir)
|
||||
echo "tar ${dir:-.} $unpackfile" >&3
|
||||
;;
|
||||
unzip)
|
||||
dir=$(pwd_to_dir)
|
||||
echo "unzip ${dir:-.} $unpackfile" >&3
|
||||
;;
|
||||
7z)
|
||||
dir=$(pwd_to_dir)
|
||||
echo "7z ${dir:-.} $unpackfile" >&3
|
||||
;;
|
||||
esac
|
||||
|
||||
# In fast mode, we don't actually apply patches
|
||||
[ -n "$QUILT_SETUP_FAST" ] && exit 0
|
||||
|
||||
if [ -n "$inputfile" ]
|
||||
then
|
||||
exec $command "$@"
|
||||
else
|
||||
exec $command "$@" < $tmpdir/data
|
||||
fi
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,146 @@
|
|||
#! @PERL@ -w
|
||||
|
||||
# Remove trailing whitespace from modified lines in working files.
|
||||
#
|
||||
# Input: diff between original and working files (unified or context
|
||||
# format).
|
||||
|
||||
use strict;
|
||||
use FileHandle;
|
||||
use File::Temp qw( :mktemp );
|
||||
use Getopt::Std;
|
||||
use vars qw($opt_p $opt_n);
|
||||
|
||||
# This ugly trick lets the script work even if gettext support is missing.
|
||||
# We did so because Locale::gettext doesn't ship with the standard perl
|
||||
# distribution.
|
||||
BEGIN {
|
||||
if (eval { require Locale::gettext }) {
|
||||
import Locale::gettext;
|
||||
require POSIX;
|
||||
import POSIX, qw(setlocale);
|
||||
} else {
|
||||
eval '
|
||||
use constant LC_MESSAGES => 0;
|
||||
sub setlocale($$) { }
|
||||
sub bindtextdomain($$) { }
|
||||
sub textdomain($) { }
|
||||
sub gettext($) { shift }
|
||||
'
|
||||
}
|
||||
}
|
||||
|
||||
setlocale(LC_MESSAGES, "");
|
||||
bindtextdomain("quilt", "@LOCALEDIR@");
|
||||
textdomain("quilt");
|
||||
|
||||
sub _($) {
|
||||
return gettext(shift);
|
||||
}
|
||||
|
||||
$opt_p = 0;
|
||||
getopts('np:')
|
||||
or die sprintf(_("SYNOPSIS: %s [-p num] [-n] [patch]\n"), $0);
|
||||
|
||||
my %files;
|
||||
my $file;
|
||||
while (<>) {
|
||||
print unless $opt_n;
|
||||
if (/^--- ./) {
|
||||
# unified diff
|
||||
$file = undef;
|
||||
while (<>) {
|
||||
print unless $opt_n;
|
||||
if (/^\+\+\+ (.+?)(?:[ \t][^\t]*)?$/) {
|
||||
$file = $1;
|
||||
$file =~ s<^([^/]+/+){$opt_p}><>;
|
||||
#print STDERR "[$file]\n";
|
||||
} elsif ($file && /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/) {
|
||||
my $removed = defined $2 ? $2 : 1;
|
||||
my $added = defined $4 ? $4 : 1;
|
||||
my $line_number = $3;
|
||||
|
||||
while ($removed || $added) {
|
||||
$_ = <>;
|
||||
defined $_
|
||||
or die sprintf(_("%s: I'm confused.\n"), $0);
|
||||
if (/^\+/) {
|
||||
push @{$files{$file}}, $line_number
|
||||
if s/(^\+.*?)[ \t]+$/$1/;
|
||||
$added--;
|
||||
$line_number++;
|
||||
} elsif (/^-/) {
|
||||
$removed--;
|
||||
} elsif (/^ / || /^$/) {
|
||||
$removed--;
|
||||
$added--;
|
||||
$line_number++;
|
||||
}
|
||||
print unless $opt_n;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elsif (/^\*\*\* ./) {
|
||||
# context diff
|
||||
$file = undef;
|
||||
while (<>) {
|
||||
print unless $opt_n;
|
||||
if ($file && /^--- (\d+)(?:,(\d+))? ----$/) {
|
||||
my $line_number = $1;
|
||||
my $last_line = defined $2 ? $2 : $1;
|
||||
while ($line_number <= $last_line) {
|
||||
$_ = <>;
|
||||
defined $_ or last;
|
||||
if (s/(^[+!] .*?)[ \t]+$/$1/) {
|
||||
push @{$files{$file}}, $line_number;
|
||||
}
|
||||
$line_number++;
|
||||
print unless $opt_n;
|
||||
last if (/^\*\*\*[* ]/);
|
||||
}
|
||||
} elsif (/^--- (.+?)(?:[ \t][^\t]*)?$/) {
|
||||
$file = $1;
|
||||
$file =~ s<^([^/]+/+){$opt_p}><>;
|
||||
#print STDERR "[$file]\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $file (sort keys %files) {
|
||||
my @lines = @{$files{$file}};
|
||||
if ($opt_n) {
|
||||
print STDERR sprintf(
|
||||
_("Warning: trailing whitespace in line %s of %s\n"), $lines[0], $file)
|
||||
if @lines == 1;
|
||||
print STDERR sprintf(
|
||||
_("Warning: trailing whitespace in lines %s of %s\n"), join(',', @lines), $file)
|
||||
if @lines > 1;
|
||||
} else {
|
||||
print STDERR sprintf(
|
||||
_("Removing trailing whitespace from line %s of %s\n"), $lines[0], $file)
|
||||
if @lines == 1;
|
||||
print STDERR sprintf(
|
||||
_("Removing trailing whitespace from lines %s of %s\n"), join(',', @lines), $file)
|
||||
if @lines > 1;
|
||||
}
|
||||
|
||||
unless ($opt_n) {
|
||||
my $fh = new FileHandle("< $file")
|
||||
or die "$file: $!\n";
|
||||
my ($tmp, $tmpname) = mkstemp("$file.XXXXXX")
|
||||
or die "$file.*: $!\n";
|
||||
while (<$fh>) {
|
||||
if (@lines && $lines[0] == $.) {
|
||||
s/[ \t]+$//;
|
||||
shift @lines;
|
||||
}
|
||||
print $tmp $_;
|
||||
}
|
||||
$fh->close;
|
||||
$tmp->close
|
||||
or die "$tmpname: $!\n";
|
||||
rename $tmpname, $file
|
||||
or die sprintf(_("Renaming %s to %s: %s\n"), $tmpname, $file, $!);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
# This file contains the common functions used by patchfns and backup-files.
|
||||
# It is meant to be sourced by bash scripts.
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
basename()
|
||||
{
|
||||
local path=$1
|
||||
while [ "${path:(-1)}" = "/" ]
|
||||
do
|
||||
path=${path%/}
|
||||
done
|
||||
echo "${path##*/}"
|
||||
}
|
||||
|
||||
dirname()
|
||||
{
|
||||
local path=$1
|
||||
while [ "${path:(-1)}" = "/" ]
|
||||
do
|
||||
path=${path%/}
|
||||
done
|
||||
local basename="${path##*/}"
|
||||
path="${path:0:${#path}-${#basename}}"
|
||||
while [ "${path:(-1)}" = "/" ]
|
||||
do
|
||||
path=${path%/}
|
||||
done
|
||||
if [ -n "$path" ]
|
||||
then
|
||||
echo "$path"
|
||||
else
|
||||
if [ ${1:0:1} = "/" ]
|
||||
then
|
||||
echo "/"
|
||||
else
|
||||
echo "."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
gen_tempfile()
|
||||
{
|
||||
if [ "$1" = -d ]
|
||||
then
|
||||
mktemp -d ${2:-${TMPDIR:-/tmp}/quilt.}XXXXXX
|
||||
else
|
||||
mktemp ${1:-${TMPDIR:-/tmp}/quilt.}XXXXXX
|
||||
fi
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt series [--color[=always|auto|never]] [-v]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Print the names of all patches in the series file.
|
||||
|
||||
--color[=always|auto|never]
|
||||
Use syntax coloring (auto activates it only if the output is a tty).
|
||||
|
||||
-v Verbose, more user friendly output.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
cat_patches()
|
||||
{
|
||||
local color=$1 prefix=$2
|
||||
shift 2
|
||||
|
||||
if [ $# -ge 1 ]
|
||||
then
|
||||
printf "$color$prefix$(patch_format)$color_clear\n" "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o vh --long color:: -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-v)
|
||||
opt_verbose=1
|
||||
shift ;;
|
||||
--color)
|
||||
case "$2" in
|
||||
"" | always)
|
||||
opt_color=1 ;;
|
||||
auto | tty)
|
||||
opt_color=
|
||||
[ -t 1 ] && opt_color=1 ;;
|
||||
never)
|
||||
opt_color= ;;
|
||||
*)
|
||||
usage ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
setup_pager
|
||||
|
||||
if [ -n "$opt_verbose$opt_color" ]
|
||||
then
|
||||
[ -n "$opt_color" ] && setup_colors
|
||||
|
||||
top=$(top_patch)
|
||||
cat_patches "$color_series_app" \
|
||||
"${opt_verbose:++ }" $(patches_before $top)
|
||||
[ -n "$top" ] && cat_patches "$color_series_top" \
|
||||
"${opt_verbose:+= }" $top
|
||||
cat_patches "$color_series_una" \
|
||||
"${opt_verbose:+ }" $(patches_after $top)
|
||||
else
|
||||
cat_patches "" "" $(cat_series)
|
||||
fi
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,531 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Version check is irrelevant to this command.
|
||||
skip_version_check=1
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
if [ -n "$SUBDIR" ]
|
||||
then
|
||||
cd $SUBDIR
|
||||
unset SUBDIR
|
||||
fi
|
||||
fi
|
||||
|
||||
check_for_existing_directories()
|
||||
{
|
||||
local tag dir last_dir arg status=0
|
||||
|
||||
while read tag dir arg
|
||||
do
|
||||
[ "$dir" != "." -a "$dir" != "$last_dir" ] || continue
|
||||
|
||||
if [ -e "$prefix$dir" ]
|
||||
then
|
||||
printf $"Directory %s exists\n" \
|
||||
"$prefix$dir" >&2
|
||||
status=1
|
||||
fi
|
||||
last_dir=$dir
|
||||
done < $tmpfile
|
||||
|
||||
return $status
|
||||
}
|
||||
|
||||
check_for_existing_files()
|
||||
{
|
||||
local tag dir last_dir arg status=0
|
||||
|
||||
while read tag dir arg
|
||||
do
|
||||
[ "$tag" = "patch" -a "$dir" != "$last_dir" ] || continue
|
||||
|
||||
if [ -e "$prefix$dir/$QUILT_PATCHES" ]
|
||||
then
|
||||
printf $"Directory %s exists\n" \
|
||||
"$prefix$dir/$QUILT_PATCHES" >&2
|
||||
status=1
|
||||
fi
|
||||
if [ -e "$prefix$dir/$QUILT_SERIES" ]
|
||||
then
|
||||
printf $"File %s exists\n" \
|
||||
"$prefix$dir/$QUILT_SERIES" >&2
|
||||
status=1
|
||||
fi
|
||||
last_dir=$dir
|
||||
done < $tmpfile
|
||||
|
||||
return $status
|
||||
}
|
||||
|
||||
# Resolve ".." in path and clean up double slashes and "."
|
||||
normalize_path()
|
||||
{
|
||||
echo "$1" | sed -r -e 's://:/:g' \
|
||||
-e 's:/\.(/\.)*(/|$):\2:g' \
|
||||
-e ':again' \
|
||||
-e 's:/[^/]+/\.\.(/|$):\1:g' \
|
||||
-e 'tagain'
|
||||
}
|
||||
|
||||
create_symlink()
|
||||
{
|
||||
local target=$1 link=$2 up
|
||||
if [ "${target:0:1}" = / -o "${link:0:1}" = / ]
|
||||
then
|
||||
[ "${target:0:1}" = / ] || target=$PWD/$target
|
||||
ln -s "$target" "$link"
|
||||
return
|
||||
fi
|
||||
|
||||
set -- "$(normalize_path "$PWD/$target")" \
|
||||
"$(normalize_path "$PWD/$link")"
|
||||
while [ "${1%%/*}" = "${2%%/*}" ]
|
||||
do
|
||||
set -- "${1#*/}" "${2#*/}"
|
||||
done
|
||||
up=$(echo "$2" | sed -r -e 's:(^|/)[^/]*$::' -e 's:[^/]+:..:g')
|
||||
set -- "${up:+$up/}$1"
|
||||
set -- "${1%/}"
|
||||
ln -s "${1:-.}" "$link"
|
||||
}
|
||||
|
||||
dir_to_dir()
|
||||
{
|
||||
local from=$1 to=$2
|
||||
|
||||
[ "${from:0:1}" = / ] || from=$PWD/$from
|
||||
from=$(normalize_path "$from")
|
||||
|
||||
[ "${to:0:1}" = / ] || to=$PWD/$to
|
||||
to=$(normalize_path "$to")
|
||||
|
||||
# If the target is a subdirectory of the origin, we can express the path
|
||||
# in a relative way. Otherwise, return the absolute path.
|
||||
if [ "${to:0:${#from}}" = "$from" ]
|
||||
then
|
||||
to=${to:${#from}}
|
||||
to=${to#/}
|
||||
fi
|
||||
|
||||
echo "$to"
|
||||
}
|
||||
|
||||
# create md5 sums, also for uncompressed files
|
||||
create_md5sums()
|
||||
{
|
||||
local sourcedir=$1 output=$2
|
||||
local file basename filetype
|
||||
|
||||
echo -n "### md5sum: " >&4
|
||||
shopt -s nullglob
|
||||
for file in "$sourcedir"*
|
||||
do
|
||||
basename=${file##*/}
|
||||
case "$basename" in
|
||||
ready|bigpack|_constraints|_service|baselibs.conf|MD5SUMS|MD5SUMS.meta|*.spec|*.changes|*.sig|*.sign|*rpmlintrc)
|
||||
continue
|
||||
;;
|
||||
# In fast mode, we are only interested in patches, so filter out
|
||||
# archives
|
||||
*.tar|*.tar.Z|*.tar.gz|*.tgz|*.tar.bz2|*.tar.xz|*.tar.lz|*.zip|*.7z)
|
||||
[ -n "$QUILT_SETUP_FAST" ] && continue
|
||||
;;
|
||||
esac
|
||||
[ -f "$file" ] || continue
|
||||
echo -n "." >&4
|
||||
echo "md5sum < $file" >&5
|
||||
set -- $(md5sum < "$file")
|
||||
echo "$1 $basename"
|
||||
|
||||
case "$file" in
|
||||
*.lzma)
|
||||
# file doesn't reliably recognize lzma-compressed files
|
||||
filetype="lzma"
|
||||
;;
|
||||
*.xz)
|
||||
# old versions of file don't know about xz-compressed
|
||||
# files
|
||||
filetype="xz"
|
||||
;;
|
||||
*)
|
||||
filetype=$(file -b "$file")
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$filetype" in
|
||||
compress*|gzip*)
|
||||
echo -n "g" >&4
|
||||
echo "gzip -cd $file | md5sum" >&5
|
||||
set -- $(gzip -cd "$file" | md5sum)
|
||||
echo "$1 $basename"
|
||||
;;
|
||||
bzip2*)
|
||||
echo -n "b" >&4
|
||||
echo "bzip2 -cd $file | md5sum" >&5
|
||||
set -- $(bzip2 -cd "$file" | md5sum)
|
||||
echo "$1 $basename"
|
||||
;;
|
||||
xz*|XZ*)
|
||||
echo -n "x" >&4
|
||||
echo "xz -cd $file | md5sum" >&5
|
||||
set -- $(xz -cd "$file" | md5sum)
|
||||
echo "$1 $basename"
|
||||
;;
|
||||
lzma*)
|
||||
echo -n "l" >&4
|
||||
echo "lzma -cd $file | md5sum" >&5
|
||||
set -- $(lzma -cd "$file" | md5sum)
|
||||
echo "$1 $basename"
|
||||
;;
|
||||
lzip*)
|
||||
echo -n "l" >&4
|
||||
echo "lzip -cd $file | md5sum" >&5
|
||||
set -- $(lzip -cd "$file" | md5sum)
|
||||
echo "$1 $basename"
|
||||
;;
|
||||
esac
|
||||
done > $output
|
||||
echo >&4
|
||||
shopt -u nullglob
|
||||
}
|
||||
|
||||
# Uses global variables: verbose, sourcedir, targetdir
|
||||
inspect()
|
||||
{
|
||||
local specfile=$1 specdir
|
||||
local abs_sourcedir=$sourcedir tmpdir
|
||||
|
||||
[ "${abs_sourcedir:0:1}" = / ] || abs_sourcedir=$PWD/$abs_sourcedir
|
||||
|
||||
if [ "${specfile:0:1}" = / ]
|
||||
then
|
||||
specdir=$(dirname "$specfile")
|
||||
specfile=${spec_file##*/}
|
||||
else
|
||||
specdir=$PWD
|
||||
fi
|
||||
|
||||
tmpdir=$(gen_tempfile -d ${VARTMPDIR:-/var/tmp}/${0##*/})
|
||||
mkdir -p $tmpdir || exit 1
|
||||
add_exit_handler "rm -rf $tmpdir"
|
||||
mkdir -p $tmpdir/bin
|
||||
ln -s $QUILT_DIR/scripts/inspect-wrapper $tmpdir/bin/patch
|
||||
ln -s $QUILT_DIR/scripts/inspect-wrapper $tmpdir/bin/tar
|
||||
ln -s $QUILT_DIR/scripts/inspect-wrapper $tmpdir/bin/unzip
|
||||
ln -s $QUILT_DIR/scripts/inspect-wrapper $tmpdir/bin/7z
|
||||
|
||||
# Redirect file descriptors
|
||||
# 5 is used in verbose mode, 4 in non-verbose mode, and 2 for both (real errors)
|
||||
if [ -n "$verbose" ]
|
||||
then
|
||||
exec 3>&1 5>&2 4>/dev/null
|
||||
else
|
||||
exec 3>&1 4>&2 5>/dev/null
|
||||
fi
|
||||
|
||||
if [ -n "$QUILT_SETUP_FAST" ]
|
||||
then
|
||||
# Fast mode
|
||||
[ -d "$targetdir" ] || mkdir -p "$targetdir" || exit 1
|
||||
ln -s "$targetdir" $tmpdir/build
|
||||
export -f create_md5sums
|
||||
else
|
||||
# Standard mode
|
||||
mkdir -p $tmpdir/build
|
||||
create_md5sums "$sourcedir" $tmpdir/md5sums
|
||||
fi
|
||||
export -f normalize_path dir_to_dir
|
||||
|
||||
# let rpm do all the dirty specfile stuff ...
|
||||
echo -n "### rpmbuild: " >&4
|
||||
|
||||
PATH="$tmpdir/bin:$PATH" \
|
||||
rpmbuild --eval "%define _sourcedir $abs_sourcedir" \
|
||||
--eval "%define _specdir $specdir" \
|
||||
--eval "%define _builddir $tmpdir/build" \
|
||||
--eval "%define __patch $tmpdir/bin/patch" \
|
||||
--eval "%define __tar $tmpdir/bin/tar" \
|
||||
--eval "%define __unzip $tmpdir/bin/unzip" \
|
||||
--eval "%define __7zip $tmpdir/bin/7z" \
|
||||
--eval "$DEFINE_FUZZ" \
|
||||
--nodeps \
|
||||
-bp "$specdir/$specfile" < /dev/null >&5 2>&5
|
||||
status=$?
|
||||
echo >&4
|
||||
return $status
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt setup [-d path-prefix] [-v] [--sourcedir dir] [--fuzz=N] [--slow|--fast] {specfile|seriesfile}\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Initializes a source tree from an rpm spec file or a quilt series file.
|
||||
|
||||
-d Optional path prefix for the resulting source tree.
|
||||
|
||||
--sourcedir
|
||||
Directory that contains the package sources. Defaults to \`.'.
|
||||
|
||||
-v Verbose debug output.
|
||||
|
||||
--fuzz=N
|
||||
Set the maximum fuzz factor (needs rpm 4.6 or later).
|
||||
|
||||
--slow Use the original, slow method to process the spec file. This is the
|
||||
default for now, but that might change in the future. In this mode,
|
||||
rpmbuild generates a working tree in a temporary directory while all
|
||||
its actions are recorded, and then everything is replayed from scratch
|
||||
in the target directory.
|
||||
|
||||
--fast Use an alternative, faster method to process the spec file. In this
|
||||
mode, rpmbuild is told to generate a working tree directly in the
|
||||
target directory.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o d:vh --long sourcedir:,fuzz:,slow,fast -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
prefix=
|
||||
sourcedir=
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-d)
|
||||
prefix=${2%/}/
|
||||
shift 2 ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
-v)
|
||||
verbose=1
|
||||
shift ;;
|
||||
--sourcedir)
|
||||
sourcedir=${2%/}/
|
||||
shift 2 ;;
|
||||
--fuzz)
|
||||
# Only works with rpm 4.6 and later
|
||||
DEFINE_FUZZ="%define _default_patch_fuzz $2"
|
||||
shift 2 ;;
|
||||
--slow)
|
||||
QUILT_SETUP_FAST=
|
||||
shift ;;
|
||||
--fast)
|
||||
export QUILT_SETUP_FAST=1
|
||||
shift ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -ne 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
tmpfile=$(gen_tempfile)
|
||||
add_exit_handler "rm -f $tmpfile"
|
||||
|
||||
# The patches link will point to the source directory, while extra patches
|
||||
# may be available under $prefix. If the latter is a subdirectory of the former,
|
||||
# a prefix can be added to fix up the path to the extra patches.
|
||||
export QUILT_SETUP_PREFIX=$(dir_to_dir "$sourcedir" "$prefix")
|
||||
|
||||
case "$1" in
|
||||
*.spec)
|
||||
spec_file=$1
|
||||
|
||||
# check if rpmbuild is installed before running inspect
|
||||
check_external_tool rpmbuild rpm-build
|
||||
|
||||
if [ -n "$QUILT_SETUP_FAST" ]
|
||||
then
|
||||
if [ "${prefix:0:1}" = / ]
|
||||
then
|
||||
targetdir=$prefix
|
||||
else
|
||||
targetdir=$PWD/$prefix
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! inspect "$spec_file" 2>&1 > $tmpfile
|
||||
then
|
||||
printf $"The %%prep section of %s failed; results may be incomplete\n" "$spec_file"
|
||||
if [ -z "$verbose" ]
|
||||
then
|
||||
printf $"The -v option will show rpm's output\n"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
series_file=$1
|
||||
# parse series file
|
||||
while read line; do
|
||||
set -- $line
|
||||
case "$@" in
|
||||
"# Sourcedir: "*)
|
||||
shift 2
|
||||
tar_dir="$@"
|
||||
tar_dir=${tar_dir// /\\ }
|
||||
;;
|
||||
"# Source: "*)
|
||||
shift 2
|
||||
source="$@"
|
||||
filetype=$(file -b "$source")
|
||||
case "$filetype" in
|
||||
Zip*)
|
||||
echo "unzip ${tar_dir:-.} ${source// /\\ }"
|
||||
;;
|
||||
7z*)
|
||||
echo "7z ${tar_dir:-.} ${source// /\\ }"
|
||||
;;
|
||||
*)
|
||||
echo "tar ${tar_dir:-.} ${source// /\\ }"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
"# Patchdir: "*)
|
||||
shift 2
|
||||
patch_dir="$@"
|
||||
patch_dir=${patch_dir// /\\ }
|
||||
;;
|
||||
''|'#'*)
|
||||
;;
|
||||
*)
|
||||
echo "patch ${patch_dir:-.} $@" ;;
|
||||
esac
|
||||
done < "$series_file" > $tmpfile
|
||||
;;
|
||||
esac
|
||||
|
||||
# If running on a spec file in fast mode, the source tree is already unpacked;
|
||||
# in all other cases, we must prepare the source tree now
|
||||
if [ -z "$QUILT_SETUP_FAST" -o -n "$series_file" ]
|
||||
then
|
||||
# Make sure that unpacking will not overwrite anything
|
||||
check_for_existing_directories || exit 1
|
||||
|
||||
while read tag dir arg1 arg2
|
||||
do
|
||||
[ "${arg1:0:1}" != '#' ] || continue
|
||||
|
||||
case "$tag" in
|
||||
tar)
|
||||
tarball=$sourcedir$arg1
|
||||
if [ ! -e "$tarball" ]
|
||||
then
|
||||
printf $"File %s not found\n" "$tarball" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf $"Unpacking archive %s\n" "$tarball"
|
||||
mkdir -p "${prefix:-.}" "$prefix$dir"
|
||||
cat_file "$tarball" \
|
||||
| tar xf - -C "$prefix$dir"
|
||||
;;
|
||||
unzip)
|
||||
tarball=$sourcedir$arg1
|
||||
if [ ! -e "$tarball" ]
|
||||
then
|
||||
printf $"File %s not found\n" "$tarball" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf $"Unpacking archive %s\n" "$tarball"
|
||||
mkdir -p "${prefix:-.}" "$prefix$dir"
|
||||
unzip -qqo "$tarball" -d "$prefix$dir"
|
||||
;;
|
||||
7z)
|
||||
tarball=$sourcedir$arg1
|
||||
if [ ! -e "$tarball" ]
|
||||
then
|
||||
printf $"File %s not found\n" "$tarball" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf $"Unpacking archive %s\n" "$tarball"
|
||||
mkdir -p "${prefix:-.}" "$prefix$dir"
|
||||
7z x -bd "$tarball" -o"$prefix$dir"
|
||||
;;
|
||||
esac
|
||||
done < $tmpfile
|
||||
fi
|
||||
|
||||
if ! check_for_existing_files
|
||||
then
|
||||
echo $"Trying alternative patches and series names..." >&2
|
||||
QUILT_PATCHES=quilt_patches
|
||||
QUILT_SERIES=quilt_series
|
||||
check_for_existing_files || exit 1
|
||||
fi
|
||||
|
||||
series_header()
|
||||
{
|
||||
local tar_dir=$1 tar_file=$2 dir=$3
|
||||
|
||||
echo "# Patch series file for quilt, created by ${0##*/}"
|
||||
[ -n "$tar_dir" ] && echo "# Sourcedir: $tar_dir"
|
||||
[ -n "$tar_file" ] && echo "# Source: $tar_file"
|
||||
echo "# Patchdir: $dir"
|
||||
echo "#"
|
||||
}
|
||||
|
||||
while read tag dir arg1 arg2
|
||||
do
|
||||
case "$tag" in
|
||||
tar|unzip|7z)
|
||||
tar_dir=$dir
|
||||
[ "$tar_dir" = . ] && tar_dir=
|
||||
tar_file=$arg1
|
||||
;;
|
||||
patch)
|
||||
if [ ! -e "$prefix$dir/$QUILT_PATCHES" ]
|
||||
then
|
||||
create_symlink "$sourcedir" "$prefix$dir/$QUILT_PATCHES"
|
||||
(cd "$prefix$dir" && create_db)
|
||||
fi
|
||||
|
||||
if [ -n "$series_file" ]
|
||||
then
|
||||
[ -e "$prefix$dir/$QUILT_SERIES" ] \
|
||||
|| create_symlink "$series_file" \
|
||||
"$prefix$dir/$QUILT_SERIES"
|
||||
else
|
||||
if ! [ -e "$prefix$dir/$QUILT_SERIES" ]
|
||||
then
|
||||
series_header "$tar_dir" "$tar_file" "$dir" \
|
||||
> "$prefix$dir/$QUILT_SERIES"
|
||||
fi
|
||||
echo "$arg1" $arg2 >> "$prefix$dir/$QUILT_SERIES"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done < $tmpfile
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,93 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt snapshot [-d]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Take a snapshot of the current working state. After taking the snapshot,
|
||||
the tree can be modified in the usual ways, including pushing and
|
||||
popping patches. A diff against the tree at the moment of the
|
||||
snapshot can be generated with \`quilt diff --snapshot'.
|
||||
|
||||
-d Only remove current snapshot.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o dh -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-d)
|
||||
opt_remove=1
|
||||
shift ;;
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
snap_subdir=.snap
|
||||
|
||||
# Clean up from previous snapshot
|
||||
rm -rf $QUILT_PC/$snap_subdir
|
||||
if [ -n "$opt_remove" ]
|
||||
then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Save current working state
|
||||
create_db
|
||||
mkdir -p $QUILT_PC/$snap_subdir
|
||||
for patch in $(applied_patches); do
|
||||
files_in_patch $patch
|
||||
done \
|
||||
| awk ' # filter out duplicates
|
||||
{ if (seen[$0])
|
||||
next
|
||||
seen[$0] = 1
|
||||
}
|
||||
{ print }
|
||||
' \
|
||||
| $QUILT_DIR/scripts/backup-files -c -s -f - -B "$QUILT_PC/$snap_subdir/"
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,65 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt top\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Print the name of the topmost patch on the current stack of applied
|
||||
patches.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
top=$(find_top_patch) || exit 2
|
||||
print_patch $top
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,74 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt unapplied [patch]\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Print a list of patches that are not applied, or all patches that follow
|
||||
the specified patch in the series file.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 ]
|
||||
then
|
||||
usage
|
||||
elif [ $# -eq 1 ]
|
||||
then
|
||||
start=$(find_patch_in_series "$1") || exit 1
|
||||
patch=$(patch_after "$start")
|
||||
|
||||
[ -n "$start" -a -z "$patch" ] && exit
|
||||
else
|
||||
patch=$(find_unapplied_patch) || exit 1
|
||||
fi
|
||||
|
||||
setup_pager
|
||||
|
||||
printf "$(patch_format)\n" "$patch" $(patches_after "$patch")
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,111 @@
|
|||
#! @BASH@
|
||||
|
||||
# This script is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# See the COPYING and AUTHORS files for more details.
|
||||
|
||||
# Don't abort in version check.
|
||||
skip_version_check=1
|
||||
|
||||
# Read in library functions
|
||||
if [ "$(type -t patch_file_name)" != function ]
|
||||
then
|
||||
if ! [ -r $QUILT_DIR/scripts/patchfns ]
|
||||
then
|
||||
echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
|
||||
exit 1
|
||||
fi
|
||||
. $QUILT_DIR/scripts/patchfns
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
printf $"Usage: quilt upgrade\n"
|
||||
if [ x$1 = x-h ]
|
||||
then
|
||||
printf $"
|
||||
Upgrade the meta-data in a working tree from an old version of quilt to the
|
||||
current version. This command is only needed when the quilt meta-data format
|
||||
has changed, and the working tree still contains old-format meta-data. In that
|
||||
case, quilt will request to run \`quilt upgrade'.
|
||||
"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
options=`getopt -o h -- "$@"`
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-h)
|
||||
usage -h ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
if version_check
|
||||
then
|
||||
printf $"The quilt meta-data in %s are already in the version %s format; nothing to do\n" "$QUILT_PC/" "$DB_VERSION"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf $"Converting meta-data to version %s\n" "$DB_VERSION"
|
||||
|
||||
# Previously we have stripped standard patch extensions (.dif .diff
|
||||
# .patch .gz .bz2) of patch names; we have used the mangled names in
|
||||
# .pc/applied-patches, .pc/$patch/, but not in the series file.
|
||||
|
||||
for patch in $(applied_patches)
|
||||
do
|
||||
proper_name="$(grep "^$(quote_bre $patch)"'\(\|\.patch\|\.diff?\)\(\|\.gz\|\.bz2\)\([ \t]\|$\)' $SERIES)"
|
||||
proper_name=${proper_name#$QUILT_PATCHES/}
|
||||
proper_name=${proper_name%% *}
|
||||
if [ -z "$proper_name" ]
|
||||
then
|
||||
failed=1
|
||||
break
|
||||
fi
|
||||
|
||||
if [ "$patch" != "$proper_name" -a -d $QUILT_PC/$patch ] \
|
||||
&& grep -q "^$(quote_bre $patch)\$" \
|
||||
$QUILT_PC/applied-patches
|
||||
then
|
||||
mv $QUILT_PC/$patch $QUILT_PC/$proper_name \
|
||||
|| failed=1
|
||||
rename_in_db $patch $proper_name \
|
||||
|| failed=1
|
||||
[ -z "$failed" ] || break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$failed" ]
|
||||
then
|
||||
printf $"Conversion failed\n" >&2
|
||||
printf $"
|
||||
Please remove all patches using \`quilt pop -a' from the quilt version used to create this working tree, or remove the %s directory and apply the patches from scratch.\n" "$QUILT_PC" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo $DB_VERSION > $QUILT_PC/.version
|
||||
### Local Variables:
|
||||
### mode: shell-script
|
||||
### End:
|
||||
# vim:filetype=sh
|
|
@ -0,0 +1,14 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ quilt new test.diff
|
||||
> Patch %{P}test.diff is now on top
|
||||
|
||||
$ echo foo > foo
|
||||
$ quilt add foo
|
||||
> File foo added to patch %{P}test.diff
|
||||
|
||||
$ quilt add patches/bar
|
||||
> File patches/bar is located below patches/
|
||||
|
||||
$ quilt add %{QUILT_PC}/baz
|
||||
> File %{QUILT_PC}/baz is located below %{QUILT_PC}/
|
|
@ -0,0 +1,55 @@
|
|||
# Check that manual changes to the series file are detected
|
||||
|
||||
$ mkdir patches
|
||||
$ cat > patches/series
|
||||
< 01.patch
|
||||
< 02.patch
|
||||
< 03.patch
|
||||
|
||||
$ quilt push -q 2
|
||||
> Applying patch %{P}01.patch
|
||||
> Patch %{P}01.patch does not exist; applied empty patch
|
||||
> Applying patch %{P}02.patch
|
||||
> Patch %{P}02.patch does not exist; applied empty patch
|
||||
> Now at patch %{P}02.patch
|
||||
|
||||
$ quilt series -v
|
||||
> + %{P}01.patch
|
||||
> = %{P}02.patch
|
||||
> %{P}03.patch
|
||||
|
||||
# Touch the series file but preserve the order -> OK
|
||||
$ touch patches/series
|
||||
|
||||
$ quilt series -v
|
||||
> + %{P}01.patch
|
||||
> = %{P}02.patch
|
||||
> %{P}03.patch
|
||||
|
||||
# Change the order of the patch series -> complain
|
||||
$ cat > patches/series
|
||||
< 03.patch
|
||||
< 01.patch
|
||||
< 02.patch
|
||||
|
||||
$ quilt series -v
|
||||
> The series file no longer matches the applied patches. Please run 'quilt pop -a'.
|
||||
|
||||
$ quilt pop
|
||||
> Patch %{P}02.patch appears to be empty, removing
|
||||
>
|
||||
> Now at patch %{P}01.patch
|
||||
|
||||
# That wasn't enough, keep complaining
|
||||
$ quilt series -v
|
||||
> The series file no longer matches the applied patches. Please run 'quilt pop -a'.
|
||||
|
||||
$ quilt pop -a
|
||||
> Patch %{P}01.patch appears to be empty, removing
|
||||
>
|
||||
> No patches applied
|
||||
|
||||
$ quilt series -v
|
||||
> %{P}03.patch
|
||||
> %{P}01.patch
|
||||
> %{P}02.patch
|
|
@ -0,0 +1,114 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ cat > foo
|
||||
< foo
|
||||
< bar
|
||||
< baz
|
||||
|
||||
$ quilt new patch
|
||||
> Patch %{P}patch is now on top
|
||||
|
||||
$ quilt add foo
|
||||
> File foo added to patch %{P}patch
|
||||
|
||||
$ sed -e 's:b:B:' foo > foo.new
|
||||
$ mv foo.new foo
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patch
|
||||
|
||||
$ quilt annotate foo
|
||||
> foo
|
||||
> 1 Bar
|
||||
> 1 Baz
|
||||
>
|
||||
> 1 %{P}patch
|
||||
|
||||
$ quilt new patch2
|
||||
> Patch %{P}patch2 is now on top
|
||||
|
||||
$ quilt add foo
|
||||
> File foo added to patch %{P}patch2
|
||||
|
||||
$ sed -e 's:Baz:baz:' foo > foo.new
|
||||
$ mv foo.new foo
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patch2
|
||||
|
||||
$ quilt annotate foo
|
||||
> foo
|
||||
> 1 Bar
|
||||
> 2 baz
|
||||
>
|
||||
> 1 %{P}patch
|
||||
> 2 %{P}patch2
|
||||
|
||||
$ quilt new patch3
|
||||
> Patch %{P}patch3 is now on top
|
||||
|
||||
$ quilt add foo
|
||||
> File foo added to patch %{P}patch3
|
||||
|
||||
$ sed -e '/Bar/d' foo > foo.new
|
||||
$ mv foo.new foo
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patch3
|
||||
|
||||
$ quilt annotate foo
|
||||
> foo
|
||||
> 2 baz
|
||||
>
|
||||
> 1 %{P}patch
|
||||
> 2 %{P}patch2
|
||||
> 3 %{P}patch3
|
||||
|
||||
$ quilt annotate -P patch3 foo
|
||||
> foo
|
||||
> 2 baz
|
||||
>
|
||||
> 1 %{P}patch
|
||||
> 2 %{P}patch2
|
||||
> 3 %{P}patch3
|
||||
|
||||
$ quilt annotate -P patch2 foo
|
||||
> foo
|
||||
> 1 Bar
|
||||
> 2 baz
|
||||
>
|
||||
> 1 %{P}patch
|
||||
> 2 %{P}patch2
|
||||
|
||||
$ quilt annotate -P patch foo
|
||||
> foo
|
||||
> 1 Bar
|
||||
> 1 Baz
|
||||
>
|
||||
> 1 %{P}patch
|
||||
|
||||
$ quilt new patch4
|
||||
> Patch %{P}patch4 is now on top
|
||||
|
||||
$ cat > jkl
|
||||
< abc
|
||||
< def
|
||||
|
||||
$ quilt add jkl wrz
|
||||
> File jkl added to patch %{P}patch4
|
||||
> File wrz added to patch %{P}patch4
|
||||
|
||||
$ rm -f jkl
|
||||
$ cat > wrz
|
||||
< one
|
||||
< two
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patch4
|
||||
|
||||
$ quilt annotate jkl
|
||||
>
|
||||
> 1 %{P}patch4
|
||||
|
||||
$ quilt annotate wrz
|
||||
> 1 one
|
||||
> 1 two
|
||||
>
|
||||
> 1 %{P}patch4
|
|
@ -0,0 +1,35 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ echo a > a
|
||||
$ echo b > b
|
||||
$ diff -u a b > patches/patch
|
||||
$ echo patch -p0 > patches/series
|
||||
$ rm -f b
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}patch
|
||||
> Now at patch %{P}patch
|
||||
|
||||
$ quilt pop -q
|
||||
> Removing patch %{P}patch
|
||||
> No patches applied
|
||||
|
||||
$ patch -s -p0 < patches/patch
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}patch
|
||||
> 1 out of 1 hunk FAILED
|
||||
> Patch %{P}patch can be reverse-applied
|
||||
|
||||
$ echo patch -p0 -R > patches/series
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}patch
|
||||
> Now at patch %{P}patch
|
||||
|
||||
$ quilt pop -q
|
||||
> Removing patch %{P}patch
|
||||
> No patches applied
|
||||
|
||||
$ patch -s -p0 -R < patches/patch
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}patch
|
||||
> 1 out of 1 hunk FAILED
|
||||
> Patch %{P}patch can be reverse-applied
|
|
@ -0,0 +1,55 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ echo a > a
|
||||
$ echo b > b
|
||||
|
||||
$ quilt new a.patch
|
||||
> Patch %{P}a.patch is now on top
|
||||
$ quilt add a
|
||||
> File a added to patch %{P}a.patch
|
||||
$ echo A > a
|
||||
|
||||
$ quilt new b.patch
|
||||
> Patch %{P}b.patch is now on top
|
||||
$ quilt add b
|
||||
> File b added to patch %{P}b.patch
|
||||
$ echo B > b
|
||||
|
||||
$ quilt pop -fa --refresh
|
||||
> Options -f and --refresh are mutually exclusive
|
||||
|
||||
$ quilt pop -a --refresh
|
||||
> Refreshed patch %{P}b.patch
|
||||
> Removing patch %{P}b.patch
|
||||
> Restoring b
|
||||
>
|
||||
> Refreshed patch %{P}a.patch
|
||||
> Removing patch %{P}a.patch
|
||||
> Restoring a
|
||||
>
|
||||
> No patches applied
|
||||
|
||||
$ quilt push -a --refresh
|
||||
> Applying patch %{P}a.patch
|
||||
> patching file a
|
||||
> Patch %{P}a.patch is unchanged
|
||||
>
|
||||
> Applying patch %{P}b.patch
|
||||
> patching file b
|
||||
> Patch %{P}b.patch is unchanged
|
||||
>
|
||||
> Now at patch %{P}b.patch
|
||||
|
||||
$ quilt push -fa --refresh
|
||||
> Options -f and --refresh are mutually exclusive
|
||||
|
||||
$ quilt pop -a --refresh
|
||||
> Patch %{P}b.patch is unchanged
|
||||
> Removing patch %{P}b.patch
|
||||
> Restoring b
|
||||
>
|
||||
> Patch %{P}a.patch is unchanged
|
||||
> Removing patch %{P}a.patch
|
||||
> Restoring a
|
||||
>
|
||||
> No patches applied
|
|
@ -0,0 +1,231 @@
|
|||
Unit test of the backup-files script.
|
||||
|
||||
# Test backup without options; it should link, not copy
|
||||
$ echo foo > foo
|
||||
$ echo bar > "space bar"
|
||||
$ sleep 1
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -b foo
|
||||
> Copying foo
|
||||
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 2
|
||||
$ ls -l backup/foo | awk '{ print $2 }'
|
||||
> 2
|
||||
$ [ backup/foo -nt foo ] && echo "mtimes differ"
|
||||
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -r foo
|
||||
> Restoring foo
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 1
|
||||
|
||||
# Test silent backup with -L; it should copy, not link
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -b -s -L foo
|
||||
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l backup/foo | awk '{ print $2 }'
|
||||
> 1
|
||||
$ [ backup/foo -nt foo ] && echo "mtimes differ"
|
||||
|
||||
# Test restore without options
|
||||
$ echo modified > foo
|
||||
$ sleep 1
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -r foo
|
||||
> Restoring foo
|
||||
|
||||
$ cat foo
|
||||
> foo
|
||||
$ [ -e backup/foo ] && echo "backup/foo not deleted"
|
||||
$ [ -e backup ] && echo "backup directory not deleted"
|
||||
|
||||
# Test backup files with hard links
|
||||
$ ln foo foo2
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -b -s -L foo
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l backup/foo | awk '{ print $2 }'
|
||||
> 2
|
||||
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -b -s -L foo2
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l foo2 | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l backup/foo | awk '{ print $2 }'
|
||||
> 2
|
||||
$ ls -l backup/foo2 | awk '{ print $2 }'
|
||||
> 2
|
||||
|
||||
# Test restore of files with hard links
|
||||
$ rm -f foo foo2
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -r -s foo
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 2
|
||||
$ ls -l backup/foo2 | awk '{ print $2 }'
|
||||
> 2
|
||||
$ [ -e backup/foo ] && echo "backup/foo not deleted"
|
||||
$ [ ! -e foo2 ] || echo "file foo2 shouldn't exist"
|
||||
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -r -s foo2
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 2
|
||||
$ ls -l foo2 | awk '{ print $2 }'
|
||||
> 2
|
||||
$ [ -e backup/foo2 ] && echo "backup/foo2 not deleted"
|
||||
$ [ -e backup ] && echo "backup directory not deleted"
|
||||
|
||||
# Test restore with -t
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -b -s foo
|
||||
$ touch -r foo foo.timeref
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -r -s -t foo
|
||||
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 2
|
||||
$ [ foo -nt foo.timeref ] || echo "touch failed"
|
||||
|
||||
# Test restore with -k
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -b -s -L foo "space bar"
|
||||
$ touch -r "space bar" bar.timeref
|
||||
$ ls -l backup/foo | awk '{ print $2 }'
|
||||
> 2
|
||||
$ ls -l "backup/space bar" | awk '{ print $2 }'
|
||||
> 1
|
||||
$ mkdir tmp
|
||||
$ cd tmp
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B ../backup/ -r -s -k foo "space bar"
|
||||
$ cd ..
|
||||
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l "space bar" | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l backup/foo | awk '{ print $2 }'
|
||||
> 3
|
||||
$ ls -l "backup/space bar" | awk '{ print $2 }'
|
||||
> 2
|
||||
$ ls -l tmp/foo | awk '{ print $2 }'
|
||||
> 3
|
||||
$ ls -l "tmp/space bar" | awk '{ print $2 }'
|
||||
> 2
|
||||
$ rm -rf tmp
|
||||
|
||||
# Test restore all (-)
|
||||
$ rm -f foo "space bar"
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -r -s -t -
|
||||
$ cat foo
|
||||
> foo
|
||||
$ cat "space bar"
|
||||
> bar
|
||||
$ [ "space bar" -nt bar.timeref ] || echo "touch failed"
|
||||
|
||||
# Backup and restore a non-existing files
|
||||
$ mkdir "dir with spaces"
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -b -s -L new "dir with spaces/space file"
|
||||
$ echo data > new
|
||||
$ echo data2 > "dir with spaces/space file"
|
||||
$ ls -l backup/new | awk '{ print $5 }'
|
||||
> 0
|
||||
$ ls -l "backup/dir with spaces/space file" | awk '{ print $5 }'
|
||||
> 0
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -r -s -
|
||||
$ [ ! -e backup/new ] || echo "file backup/new shouldn't exist"
|
||||
$ [ ! -e new ] || echo "file new shouldn't exist"
|
||||
$ [ ! -e "backup/dir with spaces/space file" ] || echo "file backup/dir with spaces/space file shouldn't exist"
|
||||
$ [ ! -e "dir with spaces/space file" ] || echo "file dir with spaces/space file shouldn't exist"
|
||||
|
||||
# Test restore involving a dir name with spaces
|
||||
$ echo data > "dir with spaces/space file"
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -b -L "dir with spaces/space file"
|
||||
> Copying dir with spaces/space file
|
||||
$ rm -rf "dir with spaces"
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -r -
|
||||
> Restoring dir with spaces/space file
|
||||
$ cat "dir with spaces/space file"
|
||||
> data
|
||||
$ [ -e backup ] && echo "backup directory not deleted"
|
||||
|
||||
# Test backup reading file list from a file
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -b -s -L -f -
|
||||
< foo
|
||||
< new
|
||||
< space bar
|
||||
$ echo data > new
|
||||
$ echo modified > foo
|
||||
$ rm -f "space bar"
|
||||
$ [ -e backup/new -a ! -s backup/new ] || echo "file backup/new isn't empty"
|
||||
$ ls -l backup/new | awk '{ print $5 }'
|
||||
> 0
|
||||
$ cat backup/foo
|
||||
> foo
|
||||
$ cat "backup/space bar"
|
||||
> bar
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -r -s -f -
|
||||
< foo
|
||||
< new
|
||||
< space bar
|
||||
$ [ ! -e backup/new ] || echo "file backup/new shouldn't exist"
|
||||
$ [ ! -e new ] || echo "file new shouldn't exist"
|
||||
$ cat foo
|
||||
> foo
|
||||
$ cat "space bar"
|
||||
> bar
|
||||
|
||||
# Test the special -L alone case
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -b -L -f -
|
||||
< new
|
||||
< foo
|
||||
< space bar
|
||||
> New file new
|
||||
> Copying foo
|
||||
> Copying space bar
|
||||
$ ln "space bar" "linked space"
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l "space bar" | awk '{ print $2 }'
|
||||
> 2
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -L -
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l "space bar" | awk '{ print $2 }'
|
||||
> 1
|
||||
$ [ ! -e new ] || echo "file new shouldn't exist"
|
||||
# Second call should be idempotent
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -L -
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l "space bar" | awk '{ print $2 }'
|
||||
> 1
|
||||
$ [ ! -e new ] || echo "file new shouldn't exist"
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B backup/ -r - | sort
|
||||
> Removing new
|
||||
> Restoring foo
|
||||
> Restoring space bar
|
||||
$ rm "linked space"
|
||||
|
||||
# Test copy (as used by quilt snapshot)
|
||||
$ %{QUILT_DIR}/scripts/backup-files -B snapshot/ -c -f -
|
||||
< new
|
||||
< foo
|
||||
< space bar
|
||||
< dir with spaces/space file
|
||||
> New file new
|
||||
> Copying foo
|
||||
> Copying space bar
|
||||
> Copying dir with spaces/space file
|
||||
$ ls -l foo | awk '{ print $2 }'
|
||||
> 2
|
||||
$ ls -l "space bar" | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l "dir with spaces/space file" | awk '{ print $2 }'
|
||||
> 1
|
||||
$ [ ! -e new ] || echo "file new shouldn't exist"
|
||||
$ ls -l snapshot/new | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l snapshot/foo | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l snapshot/"space bar" | awk '{ print $2 }'
|
||||
> 1
|
||||
$ ls -l snapshot/"dir with spaces/space file" | awk '{ print $2 }'
|
||||
> 1
|
||||
$ [ ! -s new ] || echo "file snapshot/new should be empty"
|
||||
$ rm -rf snapshot
|
|
@ -0,0 +1,83 @@
|
|||
# Test that patch names including special characters such as a colons,
|
||||
# brackets or parentheses are properly handled by all quilt commands
|
||||
|
||||
$ mkdir patches
|
||||
|
||||
$ quilt new "patch_with:strange[name]"
|
||||
> Patch %{P}patch_with:strange[name] is now on top
|
||||
|
||||
$ echo foo > foo
|
||||
$ quilt add foo
|
||||
> File foo added to patch %{P}patch_with:strange[name]
|
||||
|
||||
$ quilt files
|
||||
> foo
|
||||
|
||||
$ echo bar > foo
|
||||
$ quilt diff -p ab -P "patch_with:strange[name]"
|
||||
> Index: b/foo
|
||||
> ===================================================================
|
||||
> --- a/foo
|
||||
> +++ b/foo
|
||||
> @@ -1 +1 @@
|
||||
> -foo
|
||||
> +bar
|
||||
|
||||
$ quilt refresh -p ab
|
||||
> Refreshed patch %{P}patch_with:strange[name]
|
||||
|
||||
$ quilt applied
|
||||
> %{P}patch_with:strange[name]
|
||||
|
||||
$ quilt pop -q
|
||||
> Removing patch %{P}patch_with:strange[name]
|
||||
> No patches applied
|
||||
|
||||
$ quilt next
|
||||
> %{P}patch_with:strange[name]
|
||||
|
||||
$ quilt push -q "patch_with:strange[name]"
|
||||
> Applying patch %{P}patch_with:strange[name]
|
||||
> Now at patch %{P}patch_with:strange[name]
|
||||
|
||||
$ quilt top
|
||||
> %{P}patch_with:strange[name]
|
||||
|
||||
$ quilt rename "another:strange(name)"
|
||||
> Patch %{P}patch_with:strange[name] renamed to %{P}another:strange(name)
|
||||
|
||||
$ quilt new "{%'}.patch"
|
||||
> Patch %{P}{%'}.patch is now on top
|
||||
|
||||
$ quilt add foo
|
||||
> File foo added to patch %{P}{%'}.patch
|
||||
|
||||
$ echo baz > foo
|
||||
"
|
||||
$ quilt previous
|
||||
> %{P}another:strange(name)
|
||||
|
||||
$ quilt series
|
||||
> %{P}another:strange(name)
|
||||
> %{P}{%'}.patch
|
||||
|
||||
$ quilt refresh -p0 "{%'}.patch"
|
||||
> Refreshed patch %{P}{%'}.patch
|
||||
|
||||
$ cat "patches/{%'}.patch"
|
||||
> Index: foo
|
||||
> ===================================================================
|
||||
> --- foo.orig
|
||||
> +++ foo
|
||||
> @@ -1 +1 @@
|
||||
> -bar
|
||||
> +baz
|
||||
|
||||
$ quilt pop "another:strange(name)"
|
||||
> Removing patch %{P}{%'}.patch
|
||||
> Restoring foo
|
||||
>
|
||||
> Now at patch %{P}another:strange(name)
|
||||
|
||||
$ quilt remove foo
|
||||
> File foo removed from patch %{P}another:strange(name)
|
|
@ -0,0 +1,76 @@
|
|||
Regresion test case: Empty lines in patch descriptions were
|
||||
accidentally removed.
|
||||
|
||||
$ mkdir patches
|
||||
|
||||
$ echo one > f
|
||||
$ cat > patches/test.diff
|
||||
< C1
|
||||
<
|
||||
< C3
|
||||
<
|
||||
< Index: f
|
||||
< ===================================================================
|
||||
< --- f.orig foo
|
||||
< +++ f bar
|
||||
< @@ -1 +1 @@
|
||||
< -one
|
||||
< +two
|
||||
|
||||
$ cat > patches/series
|
||||
< test.diff -p0 # What a wonderful patch
|
||||
|
||||
$ quilt push
|
||||
> Applying patch %{P}test.diff
|
||||
>~ patching file `?f'?
|
||||
>
|
||||
> Now at patch %{P}test.diff
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}test.diff
|
||||
$ cat patches/test.diff
|
||||
> C1
|
||||
>
|
||||
> C3
|
||||
>
|
||||
> Index: f
|
||||
> ===================================================================
|
||||
> --- f.orig
|
||||
> +++ f
|
||||
> @@ -1 +1 @@
|
||||
> -one
|
||||
> +two
|
||||
|
||||
$ quilt refresh -c
|
||||
> Refreshed patch %{P}test.diff
|
||||
|
||||
$ cat patches/test.diff
|
||||
> C1
|
||||
>
|
||||
> C3
|
||||
>
|
||||
> Index: f
|
||||
> ===================================================================
|
||||
> *** f.orig
|
||||
> --- f
|
||||
> ***************
|
||||
> *** 1 ****
|
||||
> ! one
|
||||
> --- 1 ----
|
||||
> ! two
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}test.diff
|
||||
|
||||
$ cat patches/test.diff
|
||||
> C1
|
||||
>
|
||||
> C3
|
||||
>
|
||||
> Index: f
|
||||
> ===================================================================
|
||||
> --- f.orig
|
||||
> +++ f
|
||||
> @@ -1 +1 @@
|
||||
> -one
|
||||
> +two
|
|
@ -0,0 +1,163 @@
|
|||
This test case creates a patch and then applies that patch to a modified
|
||||
source file. The source file is modified until the patch doesn't apply
|
||||
anymore, then the patch is fixed.
|
||||
|
||||
$ mkdir patches
|
||||
|
||||
$ cat > one.txt
|
||||
< 1
|
||||
< 2
|
||||
< 3
|
||||
< 4
|
||||
< 5
|
||||
< 6
|
||||
< 7
|
||||
< --
|
||||
< a
|
||||
< b
|
||||
< c
|
||||
< d
|
||||
< e
|
||||
< f
|
||||
< g
|
||||
|
||||
$ quilt new a.diff
|
||||
> Patch %{P}a.diff is now on top
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ quilt add one.txt
|
||||
> File one.txt added to patch %{P}a.diff
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ mv one.txt one.orig
|
||||
$ sed -e "s/4/4+/" -e 's/d/d+/' one.orig > one.txt
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}a.diff
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ quilt pop -q
|
||||
> Removing patch %{P}a.diff
|
||||
> No patches applied
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
|
||||
$ sed -e "s/^\\([17]\\)\$/\\1-/" one.orig > one.txt
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}a.diff
|
||||
> Now at patch %{P}a.diff
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ quilt pop -q
|
||||
> Removing patch %{P}a.diff
|
||||
> No patches applied
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ sed -e "s/^\\([1267]\\)\$/\\1-/" one.orig > one.txt
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}a.diff
|
||||
> Now at patch %{P}a.diff
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ quilt pop -q
|
||||
> Removing patch %{P}a.diff
|
||||
> No patches applied
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
|
||||
$ sed -e "s/^\\([123567]\\)\$/\\1-/" one.orig > one.txt
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}a.diff
|
||||
> 1 out of 2 hunks FAILED
|
||||
> Patch %{P}a.diff does not apply (enforce with -f)
|
||||
$ echo %{?}
|
||||
> 1
|
||||
|
||||
$ quilt push -qf
|
||||
> Applying patch %{P}a.diff
|
||||
>~ 1 out of 2 hunks FAILED -- saving rejects to (file )?`?one.txt.rej'?
|
||||
> Applied patch %{P}a.diff (forced; needs refresh)
|
||||
$ echo %{?}
|
||||
> 1
|
||||
|
||||
$ mv one.txt one.x
|
||||
$ sed -e "s/4/4+/" one.x > one.txt
|
||||
$ rm -f one.x
|
||||
$ quilt diff -z | grep -v "^\\(---\\|+++\\)"
|
||||
>~ Index: [^/]+/one\.txt
|
||||
> ===================================================================
|
||||
> @@ -1,7 +1,7 @@
|
||||
> 1-
|
||||
> 2-
|
||||
> 3-
|
||||
> -4
|
||||
> +4+
|
||||
> 5-
|
||||
> 6-
|
||||
> 7-
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ quilt diff | grep -v "^\\(---\\|+++\\)"
|
||||
>~ Index: [^/]+/one\.txt
|
||||
> ===================================================================
|
||||
> @@ -1,7 +1,7 @@
|
||||
> 1-
|
||||
> 2-
|
||||
> 3-
|
||||
> -4
|
||||
> +4+
|
||||
> 5-
|
||||
> 6-
|
||||
> 7-
|
||||
> @@ -9,7 +9,7 @@
|
||||
> a
|
||||
> b
|
||||
> c
|
||||
> -d
|
||||
> +d+
|
||||
> e
|
||||
> f
|
||||
> g
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}a.diff
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ cat patches/a.diff | grep -v "^\\(---\\|+++\\)"
|
||||
>~ Index: [^/]+/one\.txt
|
||||
> ===================================================================
|
||||
> @@ -1,7 +1,7 @@
|
||||
> 1-
|
||||
> 2-
|
||||
> 3-
|
||||
> -4
|
||||
> +4+
|
||||
> 5-
|
||||
> 6-
|
||||
> 7-
|
||||
> @@ -9,7 +9,7 @@
|
||||
> a
|
||||
> b
|
||||
> c
|
||||
> -d
|
||||
> +d+
|
||||
> e
|
||||
> f
|
||||
> g
|
||||
|
||||
$ quilt pop -q
|
||||
> Removing patch %{P}a.diff
|
||||
> No patches applied
|
||||
$ echo %{?}
|
||||
> 0
|
|
@ -0,0 +1,58 @@
|
|||
Check whether quilt generates patches properly so that GNU patch recognizes
|
||||
file creates and deletions.
|
||||
|
||||
$ mkdir patches
|
||||
|
||||
$ echo delete > delete
|
||||
$ quilt new test.diff
|
||||
> Patch %{P}test.diff is now on top
|
||||
|
||||
$ quilt add create
|
||||
> File create added to patch %{P}test.diff
|
||||
|
||||
$ echo create > create
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}test.diff
|
||||
|
||||
$ quilt add delete
|
||||
> File delete added to patch %{P}test.diff
|
||||
|
||||
$ rm -f delete
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}test.diff
|
||||
$ quilt header -r
|
||||
< ---
|
||||
< create | 1 +
|
||||
< delete | 1 -
|
||||
< 2 files changed, 1 insertion(+), 1 deletion(-)
|
||||
<
|
||||
> Replaced header of patch %{P}test.diff
|
||||
|
||||
$ quilt patches -v create
|
||||
> = %{P}test.diff
|
||||
$ quilt patches delete
|
||||
> %{P}test.diff
|
||||
|
||||
$ quilt pop -q
|
||||
> Removing patch %{P}test.diff
|
||||
> No patches applied
|
||||
|
||||
$ quilt patches create
|
||||
> %{P}test.diff
|
||||
$ quilt patches -v delete
|
||||
> %{P}test.diff
|
||||
$ quilt patches -- /dev/null dev/null null ---
|
||||
|
||||
$ echo create > create
|
||||
$ rm -f delete
|
||||
$ patch -p1 --dry-run < patches/test.diff
|
||||
>~ The next patch would create the file `?create'?,
|
||||
> which already exists! Assume -R? [n]
|
||||
> Apply anyway? [n]
|
||||
> Skipping patch.
|
||||
>~ 1 out of 1 hunk ignored( -- saving rejects to( file)? create.rej)?
|
||||
>~ The next patch would delete the file `?delete'?,
|
||||
> which does not exist! Assume -R? [n]
|
||||
> Apply anyway? [n]
|
||||
> Skipping patch.
|
||||
> 1 out of 1 hunk ignored
|
|
@ -0,0 +1,101 @@
|
|||
Test the delete command.
|
||||
|
||||
$ mkdir patches
|
||||
|
||||
$ quilt delete
|
||||
> No series file found
|
||||
|
||||
$ cat > test.txt
|
||||
< Calling pci_match_id() would be more feasible.
|
||||
|
||||
$ quilt new test1
|
||||
> Patch %{P}test1 is now on top
|
||||
|
||||
$ quilt add test.txt
|
||||
> File test.txt added to patch %{P}test1
|
||||
|
||||
$ cat > test.txt
|
||||
< Try the following patch instead.
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}test1
|
||||
|
||||
$ quilt new test2
|
||||
> Patch %{P}test2 is now on top
|
||||
|
||||
$ quilt add test.txt
|
||||
> File test.txt added to patch %{P}test2
|
||||
|
||||
$ cat > test.txt
|
||||
< Ok, that's fine with me if you want to do that instead.
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}test2
|
||||
|
||||
$ quilt delete test1
|
||||
> Patch %{P}test1 is currently applied
|
||||
|
||||
$ quilt pop
|
||||
> Removing patch %{P}test2
|
||||
> Restoring test.txt
|
||||
>
|
||||
> Now at patch %{P}test1
|
||||
|
||||
$ quilt series
|
||||
> %{P}test1
|
||||
> %{P}test2
|
||||
|
||||
$ quilt delete -n
|
||||
> Removed patch %{P}test2
|
||||
|
||||
$ quilt series
|
||||
> %{P}test1
|
||||
|
||||
$ quilt pop
|
||||
> Removing patch %{P}test1
|
||||
> Restoring test.txt
|
||||
>
|
||||
> No patches applied
|
||||
|
||||
$ quilt delete test1
|
||||
> Removed patch %{P}test1
|
||||
|
||||
$ quilt series
|
||||
|
||||
$ echo "test1" > patches/series
|
||||
$ quilt delete -n
|
||||
> Removed patch %{P}test1
|
||||
|
||||
$ quilt series
|
||||
|
||||
# Force the pop operaton to fail
|
||||
$ echo "test3" > patches/series
|
||||
$ echo "test3" > %{QUILT_PC}/applied-patches
|
||||
$ mkdir -p %{QUILT_PC}/test3/dir
|
||||
$ touch %{QUILT_PC}/test3/dir/file
|
||||
$ chmod a-rx %{QUILT_PC}/test3/dir
|
||||
|
||||
# Note that this will succeed (instead of the expected failure) if
|
||||
# running as root, but you shouldn't do that anyway.
|
||||
$ quilt delete "test3"
|
||||
> Removing patch %{P}test3
|
||||
>~ .*find: [`']?\./dir'?: Permission denied
|
||||
|
||||
$ chmod a+rx %{QUILT_PC}/test3/dir
|
||||
|
||||
$ find %{QUILT_PC}/test3
|
||||
> %{QUILT_PC}/test3
|
||||
> %{QUILT_PC}/test3/dir
|
||||
> %{QUILT_PC}/test3/dir/file
|
||||
|
||||
$ quilt applied
|
||||
> No patches applied
|
||||
|
||||
$ quilt series
|
||||
> %{P}test3
|
||||
|
||||
$ quilt delete
|
||||
> No patches applied
|
||||
|
||||
$ quilt delete test3
|
||||
> Removed patch %{P}test3
|
|
@ -0,0 +1,63 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ echo a > test.txt
|
||||
$ echo d > test3.txt
|
||||
|
||||
$ cat > patches/ab.diff
|
||||
< --- a/test.txt
|
||||
< +++ b/test.txt
|
||||
< @@ -1 +1 @@
|
||||
< -a
|
||||
< +b
|
||||
< --- /dev/null
|
||||
< +++ b/test2.txt
|
||||
< @@ -0,0 +1 @@
|
||||
< +c
|
||||
< --- a/test3.txt
|
||||
< +++ /dev/null
|
||||
< @@ -1 +0,0 @@
|
||||
< -d
|
||||
|
||||
$ echo "ab.diff" > patches/series
|
||||
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}ab.diff
|
||||
> Now at patch %{P}ab.diff
|
||||
|
||||
$ quilt diff -p ab --no-index
|
||||
> --- a/test.txt
|
||||
> +++ b/test.txt
|
||||
> @@ -1 +1 @@
|
||||
> -a
|
||||
> +b
|
||||
> --- /dev/null
|
||||
> +++ b/test2.txt
|
||||
> @@ -0,0 +1 @@
|
||||
> +c
|
||||
> --- a/test3.txt
|
||||
> +++ /dev/null
|
||||
> @@ -1 +0,0 @@
|
||||
> -d
|
||||
|
||||
$ rm -f patches/ab.diff
|
||||
$ quilt refresh -p ab --no-index
|
||||
> Refreshed patch %{P}ab.diff
|
||||
|
||||
$ cat patches/ab.diff
|
||||
> --- a/test.txt
|
||||
> +++ b/test.txt
|
||||
> @@ -1 +1 @@
|
||||
> -a
|
||||
> +b
|
||||
> --- /dev/null
|
||||
> +++ b/test2.txt
|
||||
> @@ -0,0 +1 @@
|
||||
> +c
|
||||
> --- a/test3.txt
|
||||
> +++ /dev/null
|
||||
> @@ -1 +0,0 @@
|
||||
> -d
|
||||
|
||||
$ quilt pop -qR
|
||||
> Removing patch %{P}ab.diff
|
||||
> No patches applied
|
|
@ -0,0 +1,19 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ quilt new dotglob.diff
|
||||
> Patch %{P}dotglob.diff is now on top
|
||||
|
||||
$ quilt add .foo
|
||||
> File .foo added to patch %{P}dotglob.diff
|
||||
|
||||
$ echo dot-foo > .foo
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}dotglob.diff
|
||||
|
||||
$ quilt pop -q
|
||||
> Removing patch %{P}dotglob.diff
|
||||
> No patches applied
|
||||
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}dotglob.diff
|
||||
> Now at patch %{P}dotglob.diff
|
|
@ -0,0 +1,37 @@
|
|||
# Check that duplicate patches in generated series files won't cause havoc
|
||||
# See bug #20628 at https://savannah.nongnu.org/bugs/?20628
|
||||
|
||||
$ mkdir patches
|
||||
$ echo "old line" > file.txt
|
||||
|
||||
$ cat > patches/first.patch
|
||||
< --- file.txt
|
||||
< +++ file.txt
|
||||
< @@ -1 +1 @@
|
||||
< -old line
|
||||
< +new line
|
||||
|
||||
$ cat > patches/series
|
||||
< first.patch -p0
|
||||
< first.patch -p0
|
||||
|
||||
$ quilt push
|
||||
> Applying patch %{P}first.patch
|
||||
> patching file file.txt
|
||||
>
|
||||
> Now at patch %{P}first.patch
|
||||
|
||||
$ quilt push
|
||||
> Patch %{P}first.patch is already applied; check your series file
|
||||
|
||||
$ quilt pop
|
||||
> Removing patch %{P}first.patch
|
||||
> Restoring file.txt
|
||||
>
|
||||
> No patches applied
|
||||
|
||||
$ quilt push -qa
|
||||
> Patch %{P}first.patch is already applied; check your series file
|
||||
|
||||
$ quilt pop -q
|
||||
> No patch removed
|
|
@ -0,0 +1,97 @@
|
|||
$ mkdir patches subdir
|
||||
|
||||
# Test the behavior if the editor modifies existing files
|
||||
$ cat > editor
|
||||
< #! /bin/sh
|
||||
< echo Editing $1
|
||||
< sed -e 's:foo:bar:' $1 > $1.new
|
||||
< mv $1.new $1
|
||||
$ chmod +x editor
|
||||
$ export EDITOR=%{PWD}/editor
|
||||
|
||||
$ quilt new patch
|
||||
> Patch %{P}patch is now on top
|
||||
|
||||
$ echo foobar > foobar
|
||||
$ quilt edit foobar
|
||||
> File foobar added to patch %{P}patch
|
||||
> Editing foobar
|
||||
|
||||
$ cat foobar
|
||||
> barbar
|
||||
|
||||
$ cd subdir
|
||||
$ echo foo > foo
|
||||
$ quilt edit foo
|
||||
> File subdir/foo added to patch %{_P}patch
|
||||
> Editing subdir/foo
|
||||
$ cd ..
|
||||
|
||||
$ cat subdir/foo
|
||||
> bar
|
||||
|
||||
$ quilt files
|
||||
> foobar
|
||||
> subdir/foo
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patch
|
||||
|
||||
# Test the behavior if the editor deletes a file completely
|
||||
$ echo foobaz > foobaz
|
||||
$ cat > editor
|
||||
< #! /bin/sh
|
||||
< echo Deleting $1
|
||||
< rm -f $1
|
||||
|
||||
$ quilt edit foobaz
|
||||
> File foobaz added to patch %{P}patch
|
||||
> Deleting foobaz
|
||||
|
||||
$ [ ! -e foobaz ] || echo "File foobaz shouldn't exist"
|
||||
|
||||
# Test the behavior if the editor is called on a new file but
|
||||
# does not actually create it
|
||||
$ cat > editor
|
||||
< #! /bin/sh
|
||||
< echo Doing nothing to $1
|
||||
|
||||
$ quilt edit nofoo
|
||||
> File nofoo added to patch %{P}patch
|
||||
> Doing nothing to nofoo
|
||||
> File nofoo removed from patch %{P}patch
|
||||
|
||||
# Test the behavior if the patch is deleting a file and the
|
||||
# user calls "quilt edit" on that file but makes no change to it
|
||||
$ rm -f foobar
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patch
|
||||
$ quilt diff -p ab --no-index foobar
|
||||
> --- a/foobar
|
||||
> +++ /dev/null
|
||||
> @@ -1 +0,0 @@
|
||||
> -foobar
|
||||
|
||||
$ quilt edit foobar
|
||||
> File foobar is already in patch %{P}patch
|
||||
> Doing nothing to foobar
|
||||
|
||||
$ [ ! -e foobar ] || echo "File foobar shouldn't exist"
|
||||
|
||||
# Test the behavior if the editor creates a brand new file
|
||||
$ cat > editor
|
||||
< #! /bin/sh
|
||||
< echo Creating $1
|
||||
< echo "new line" > $1
|
||||
|
||||
$ quilt edit foo2
|
||||
> File foo2 added to patch %{P}patch
|
||||
> Creating foo2
|
||||
$ cat foo2
|
||||
> new line
|
||||
|
||||
$ quilt files -v
|
||||
> + foo2
|
||||
> - foobar
|
||||
> - foobaz
|
||||
> subdir/foo
|
|
@ -0,0 +1,131 @@
|
|||
# Check that quilt properly deals with patches which delete vs. empty files
|
||||
|
||||
# Prepare the working tree
|
||||
$ mkdir patches
|
||||
$ echo "will be deleted" > deleted1
|
||||
$ echo "will be emptied" > emptied1
|
||||
$ echo "will be deleted" > deleted2
|
||||
$ echo "will be emptied" > emptied2
|
||||
|
||||
# Prepate the patches and series
|
||||
$ cat > patches/series
|
||||
< using-filenames.patch
|
||||
< using-timestamps.patch
|
||||
|
||||
$ cat > patches/using-filenames.patch
|
||||
< diff -ruN a/deleted1 b/deleted1
|
||||
< --- a/deleted1
|
||||
< +++ /dev/null
|
||||
< @@ -1 +0,0 @@
|
||||
< -will be deleted
|
||||
< diff -ruN a/emptied1 b/emptied1
|
||||
< --- a/emptied1
|
||||
< +++ b/emptied1
|
||||
< @@ -1 +0,0 @@
|
||||
< -will be emptied
|
||||
|
||||
$ cat > patches/using-timestamps.patch
|
||||
< diff -ruN a/deleted2 b/deleted2
|
||||
< --- a/deleted2 2014-01-15 11:19:43.000000000 +0100
|
||||
< +++ b/deleted2 1970-01-01 01:00:00.000000000 +0100
|
||||
< @@ -1 +0,0 @@
|
||||
< -will be deleted
|
||||
< diff -ruN a/emptied2 b/emptied2
|
||||
< --- a/emptied2 2014-01-15 11:19:59.000000000 +0100
|
||||
< +++ b/emptied2 2014-01-15 11:20:11.000000000 +0100
|
||||
< @@ -1 +0,0 @@
|
||||
< -will be emptied
|
||||
|
||||
# Test quilt push
|
||||
$ quilt push
|
||||
> Applying patch %{P}using-filenames.patch
|
||||
> patching file deleted1
|
||||
> patching file emptied1
|
||||
>
|
||||
> Now at patch %{P}using-filenames.patch
|
||||
$ [ ! -e deleted1 ] && echo "File deleted1 does not exist"
|
||||
> File deleted1 does not exist
|
||||
$ [ -e deleted1 -a ! -s deleted1 ] && echo "File deleted1 is empty"
|
||||
$ [ ! -e emptied1 ] && echo "File emptied1 does not exist"
|
||||
$ [ -e emptied1 -a ! -s emptied1 ] && echo "File emptied1 is empty"
|
||||
> File emptied1 is empty
|
||||
|
||||
$ quilt push
|
||||
> Applying patch %{P}using-timestamps.patch
|
||||
> patching file deleted2
|
||||
> patching file emptied2
|
||||
>
|
||||
> Now at patch %{P}using-timestamps.patch
|
||||
$ [ ! -e deleted2 ] && echo "File deleted2 does not exist"
|
||||
> File deleted2 does not exist
|
||||
$ [ -e deleted2 -a ! -s deleted2 ] && echo "File deleted2 is empty"
|
||||
$ [ ! -e emptied2 ] && echo "File emptied2 does not exist"
|
||||
$ [ -e emptied2 -a ! -s emptied2 ] && echo "File emptied2 is empty"
|
||||
> File emptied2 is empty
|
||||
|
||||
# Test quilt fold
|
||||
$ quilt pop -aq
|
||||
> Removing patch %{P}using-timestamps.patch
|
||||
> Removing patch %{P}using-filenames.patch
|
||||
> No patches applied
|
||||
|
||||
$ quilt new fold.patch
|
||||
> Patch %{P}fold.patch is now on top
|
||||
|
||||
$ quilt fold < patches/using-filenames.patch
|
||||
> patching file deleted1
|
||||
> patching file emptied1
|
||||
$ [ ! -e deleted1 ] && echo "File deleted1 does not exist"
|
||||
> File deleted1 does not exist
|
||||
$ [ -e deleted1 -a ! -s deleted1 ] && echo "File deleted1 is empty"
|
||||
$ [ ! -e emptied1 ] && echo "File emptied1 does not exist"
|
||||
$ [ -e emptied1 -a ! -s emptied1 ] && echo "File emptied1 is empty"
|
||||
> File emptied1 is empty
|
||||
|
||||
$ quilt fold < patches/using-timestamps.patch
|
||||
> patching file deleted2
|
||||
> patching file emptied2
|
||||
$ [ ! -e deleted2 ] && echo "File deleted2 does not exist"
|
||||
> File deleted2 does not exist
|
||||
$ [ -e deleted2 -a ! -s deleted2 ] && echo "File deleted2 is empty"
|
||||
$ [ ! -e emptied2 ] && echo "File emptied2 does not exist"
|
||||
$ [ -e emptied2 -a ! -s emptied2 ] && echo "File emptied2 is empty"
|
||||
> File emptied2 is empty
|
||||
|
||||
# Test quilt refresh
|
||||
$ quilt delete
|
||||
> Removing patch %{P}fold.patch
|
||||
> No patches applied
|
||||
> Removed patch %{P}fold.patch
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}using-filenames.patch
|
||||
> Now at patch %{P}using-filenames.patch
|
||||
|
||||
$ quilt refresh -pab --sort --no-index
|
||||
> Refreshed patch %{P}using-filenames.patch
|
||||
$ quilt pop -q
|
||||
> Removing patch %{P}using-filenames.patch
|
||||
> No patches applied
|
||||
|
||||
$ quilt push
|
||||
> Applying patch %{P}using-filenames.patch
|
||||
> patching file deleted1
|
||||
> patching file emptied1
|
||||
>
|
||||
> Now at patch %{P}using-filenames.patch
|
||||
$ [ ! -e deleted1 ] && echo "File deleted1 does not exist"
|
||||
> File deleted1 does not exist
|
||||
$ [ -e deleted1 -a ! -s deleted1 ] && echo "File deleted1 is empty"
|
||||
$ [ ! -e emptied1 ] && echo "File emptied1 does not exist"
|
||||
$ [ -e emptied1 -a ! -s emptied1 ] && echo "File emptied1 is empty"
|
||||
> File emptied1 is empty
|
||||
|
||||
$ cat patches/using-filenames.patch
|
||||
> --- a/deleted1
|
||||
> +++ /dev/null
|
||||
> @@ -1 +0,0 @@
|
||||
> -will be deleted
|
||||
> --- a/emptied1
|
||||
> +++ b/emptied1
|
||||
> @@ -1 +0,0 @@
|
||||
> -will be emptied
|
|
@ -0,0 +1,34 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ cat > patches/series
|
||||
< empty1.diff
|
||||
< empty2.diff
|
||||
$ touch patches/empty1.diff patches/empty2.diff
|
||||
|
||||
$ quilt push -qa
|
||||
> Applying patch %{P}empty1.diff
|
||||
> Patch %{P}empty1.diff appears to be empty; applied
|
||||
> Applying patch %{P}empty2.diff
|
||||
> Patch %{P}empty2.diff appears to be empty; applied
|
||||
> Now at patch %{P}empty2.diff
|
||||
|
||||
$ quilt rename empty3.diff
|
||||
> Patch %{P}empty2.diff renamed to %{P}empty3.diff
|
||||
|
||||
$ quilt pop -qa
|
||||
> Patch %{P}empty3.diff appears to be empty, removing
|
||||
> Patch %{P}empty1.diff appears to be empty, removing
|
||||
> No patches applied
|
||||
|
||||
$ quilt new empty_new.diff
|
||||
> Patch %{P}empty_new.diff is now on top
|
||||
|
||||
$ quilt pop -q
|
||||
> Patch %{P}empty_new.diff appears to be empty, removing
|
||||
> No patches applied
|
||||
|
||||
$ quilt delete empty_new.diff
|
||||
> Removed patch %{P}empty_new.diff
|
||||
|
||||
$ quilt rename -P empty3.diff empty_new.diff
|
||||
> Patch %{P}empty3.diff renamed to %{P}empty_new.diff
|
|
@ -0,0 +1,146 @@
|
|||
The text used here was taken from:
|
||||
http://the-tech.mit.edu/Shakespeare/midsummer/full.html
|
||||
|
||||
$ mkdir patches
|
||||
|
||||
$ cat > Oberon.txt
|
||||
< Yet mark'd I where the bolt of Cupid fell:
|
||||
< It fell upon a little western flower,
|
||||
< Before milk-white, now purple with love's wound,
|
||||
< And girls call it love-in-idleness.
|
||||
|
||||
$ quilt new flower.diff
|
||||
> Patch %{P}flower.diff is now on top
|
||||
|
||||
$ quilt files
|
||||
$ quilt add Oberon.txt
|
||||
> File Oberon.txt added to patch %{P}flower.diff
|
||||
|
||||
$ cat >> Oberon.txt
|
||||
< The juice of it on sleeping eye-lids laid
|
||||
< Will make a man or woman madly dote
|
||||
< Upon the next live creature that it sees.
|
||||
|
||||
Or ``quilt edit Oberon.txt''
|
||||
|
||||
$ quilt refresh -p ab
|
||||
> Refreshed patch %{P}flower.diff
|
||||
|
||||
$ cat patches/flower.diff
|
||||
> Index: b/Oberon.txt
|
||||
> ===================================================================
|
||||
> --- a/Oberon.txt
|
||||
> +++ b/Oberon.txt
|
||||
> @@ -2,3 +2,6 @@
|
||||
> It fell upon a little western flower,
|
||||
> Before milk-white, now purple with love's wound,
|
||||
> And girls call it love-in-idleness.
|
||||
> +The juice of it on sleeping eye-lids laid
|
||||
> +Will make a man or woman madly dote
|
||||
> +Upon the next live creature that it sees.
|
||||
|
||||
$ sed -ne '1,4p' Oberon.txt > Oberon.new
|
||||
$ echo "Fetch me that flower; the herb I shew'd thee once:" >> Oberon.new
|
||||
$ sed -e '1,4d' Oberon.txt >> Oberon.new
|
||||
$ mv Oberon.new Oberon.txt
|
||||
$ quilt diff -z -p ab
|
||||
> Index: b/Oberon.txt
|
||||
> ===================================================================
|
||||
> --- a/Oberon.txt
|
||||
> +++ b/Oberon.txt
|
||||
> @@ -2,6 +2,7 @@
|
||||
> It fell upon a little western flower,
|
||||
> Before milk-white, now purple with love's wound,
|
||||
> And girls call it love-in-idleness.
|
||||
> +Fetch me that flower; the herb I shew'd thee once:
|
||||
> The juice of it on sleeping eye-lids laid
|
||||
> Will make a man or woman madly dote
|
||||
> Upon the next live creature that it sees.
|
||||
|
||||
$ quilt diff -p ab
|
||||
> Index: b/Oberon.txt
|
||||
> ===================================================================
|
||||
> --- a/Oberon.txt
|
||||
> +++ b/Oberon.txt
|
||||
> @@ -2,3 +2,7 @@
|
||||
> It fell upon a little western flower,
|
||||
> Before milk-white, now purple with love's wound,
|
||||
> And girls call it love-in-idleness.
|
||||
> +Fetch me that flower; the herb I shew'd thee once:
|
||||
> +The juice of it on sleeping eye-lids laid
|
||||
> +Will make a man or woman madly dote
|
||||
> +Upon the next live creature that it sees.
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}flower.diff
|
||||
|
||||
$ quilt top
|
||||
> %{P}flower.diff
|
||||
|
||||
$ quilt files
|
||||
> Oberon.txt
|
||||
|
||||
$ quilt patches Oberon.txt
|
||||
> %{P}flower.diff
|
||||
$ quilt pop -f
|
||||
> Removing patch %{P}flower.diff
|
||||
> Restoring Oberon.txt
|
||||
>
|
||||
> No patches applied
|
||||
|
||||
$ quilt files patches/flower.diff
|
||||
> Oberon.txt
|
||||
|
||||
$ sed -e "s/girls/maidens/" Oberon.txt > Oberon.new
|
||||
$ mv Oberon.new Oberon.txt
|
||||
$ quilt push
|
||||
> Applying patch %{P}flower.diff
|
||||
>~ patching file `?Oberon.txt'?
|
||||
> Hunk #1 FAILED at 2.
|
||||
>~ 1 out of 1 hunk FAILED -- rejects in file `?Oberon.txt'?
|
||||
> Patch %{P}flower.diff does not apply (enforce with -f)
|
||||
|
||||
$ quilt push -f
|
||||
> Applying patch %{P}flower.diff
|
||||
>~ patching file `?Oberon.txt'?
|
||||
> Hunk #1 FAILED at 2.
|
||||
>~ 1 out of 1 hunk FAILED -- saving rejects to (file )?`?Oberon.txt.rej'?
|
||||
> Applied patch %{P}flower.diff (forced; needs refresh)
|
||||
|
||||
$ cat >> Oberon.txt
|
||||
< Fetch me that flower; the herb I shew'd thee once:
|
||||
< The juice of it on sleeping eye-lids laid
|
||||
< Will make a man or woman madly dote
|
||||
< Upon the next live creature that it sees.
|
||||
|
||||
$ quilt refresh -p ab
|
||||
> Refreshed patch %{P}flower.diff
|
||||
$ rm -f Oberon.txt.rej
|
||||
|
||||
$ cat Oberon.txt
|
||||
> Yet mark'd I where the bolt of Cupid fell:
|
||||
> It fell upon a little western flower,
|
||||
> Before milk-white, now purple with love's wound,
|
||||
> And maidens call it love-in-idleness.
|
||||
> Fetch me that flower; the herb I shew'd thee once:
|
||||
> The juice of it on sleeping eye-lids laid
|
||||
> Will make a man or woman madly dote
|
||||
> Upon the next live creature that it sees.
|
||||
|
||||
$ cat patches/flower.diff
|
||||
> Index: b/Oberon.txt
|
||||
> ===================================================================
|
||||
> --- a/Oberon.txt
|
||||
> +++ b/Oberon.txt
|
||||
> @@ -2,3 +2,7 @@
|
||||
> It fell upon a little western flower,
|
||||
> Before milk-white, now purple with love's wound,
|
||||
> And maidens call it love-in-idleness.
|
||||
> +Fetch me that flower; the herb I shew'd thee once:
|
||||
> +The juice of it on sleeping eye-lids laid
|
||||
> +Will make a man or woman madly dote
|
||||
> +Upon the next live creature that it sees.
|
||||
|
||||
$ quilt grep love
|
||||
> Oberon.txt:Before milk-white, now purple with love's wound,
|
||||
> Oberon.txt:And maidens call it love-in-idleness.
|
|
@ -0,0 +1,23 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ quilt new test.diff
|
||||
> Patch %{P}test.diff is now on top
|
||||
|
||||
$ quilt add test.txt
|
||||
> File test.txt added to patch %{P}test.diff
|
||||
$ cat > test.txt
|
||||
< This is test.txt.
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}test.diff
|
||||
|
||||
What happens when refresh fails because of a permission error?
|
||||
|
||||
$ chmod -w patches
|
||||
$ cat > test.txt
|
||||
< This is updated test.txt.
|
||||
$ quilt refresh --backup
|
||||
>~ mv: cannot move [`']?patches/test.diff'? to [`']?patches/test.diff~'?: Permission denied
|
||||
$ echo %{?}
|
||||
> 1
|
||||
|
||||
$ chmod +w patches
|
|
@ -0,0 +1,39 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ quilt new test.diff
|
||||
> Patch %{P}test.diff is now on top
|
||||
|
||||
$ cat > test.txt
|
||||
< This is test.txt.
|
||||
$ quilt add test.txt
|
||||
> File test.txt added to patch %{P}test.diff
|
||||
|
||||
What happens when diff fails because of a permission error?
|
||||
|
||||
$ chmod -r test.txt
|
||||
|
||||
$ quilt refresh
|
||||
>~ .*diff: test\.txt: Permission denied
|
||||
> Diff failed on file 'test.txt', aborting
|
||||
$ echo %{?}
|
||||
> 1
|
||||
|
||||
$ chmod +r test.txt
|
||||
|
||||
What happens on binary files?
|
||||
|
||||
$ printf "\\002\\000\\001" > test.bin
|
||||
$ quilt add test.bin
|
||||
> File test.bin added to patch %{P}test.diff
|
||||
|
||||
$ printf "\\003\\000\\001" > test.bin
|
||||
$ quilt diff -pab --no-index
|
||||
>~ (Files|Binary files) a/test\.bin and b/test\.bin differ
|
||||
> Diff failed on file 'test.bin', aborting
|
||||
$ echo %{?}
|
||||
> 1
|
||||
|
||||
$ quilt refresh
|
||||
> Diff failed on file 'test.bin', aborting
|
||||
$ echo %{?}
|
||||
> 1
|
|
@ -0,0 +1,29 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ cat > test.txt
|
||||
< This is test.txt.
|
||||
|
||||
$ quilt new test.diff
|
||||
> Patch %{P}test.diff is now on top
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ quilt add test.txt
|
||||
> File test.txt added to patch %{P}test.diff
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ cat >> test.txt
|
||||
< Line two.
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}test.diff
|
||||
$ echo %{?}
|
||||
> 0
|
||||
|
||||
$ sed -e "s/ /_/g" patches/test.diff > patches/test.new
|
||||
$ mv patches/test.new patches/test.diff
|
||||
$ quilt pop
|
||||
> Patch %{P}test.diff does not remove cleanly (refresh it or enforce with -f)
|
||||
$ echo %{?}
|
||||
> 1
|
|
@ -0,0 +1,69 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ cat > patches/series
|
||||
< patch1.diff
|
||||
|
||||
$ cat > patches/patch1.diff
|
||||
< --- q.orig/file1.txt
|
||||
< +++ q/file1.txt
|
||||
< @@ -0,0 +1 @@
|
||||
< +This is file1.txt.
|
||||
< --- q.orig/file2.txt
|
||||
< +++ q/file2.txt
|
||||
< @@ -0,0 +1 @@
|
||||
< +This is file2.txt.
|
||||
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}patch1.diff
|
||||
> Now at patch %{P}patch1.diff
|
||||
|
||||
$ quilt files
|
||||
> file1.txt
|
||||
> file2.txt
|
||||
|
||||
$ quilt fold -q
|
||||
< --- q.orig/file2.txt
|
||||
< +++ q/file2.txt
|
||||
< @@ -1 +0,0 @@
|
||||
< -This is file2.txt.
|
||||
< --- q.orig/dir/file3.txt
|
||||
< +++ q/dir/file3.txt
|
||||
< @@ -0,0 +1 @@
|
||||
< +This is file3.txt.
|
||||
|
||||
$ quilt diff -p ab
|
||||
> Index: b/file1.txt
|
||||
> ===================================================================
|
||||
> --- /dev/null
|
||||
> +++ b/file1.txt
|
||||
> @@ -0,0 +1 @@
|
||||
> +This is file1.txt.
|
||||
> Index: b/dir/file3.txt
|
||||
> ===================================================================
|
||||
> --- /dev/null
|
||||
> +++ b/dir/file3.txt
|
||||
> @@ -0,0 +1 @@
|
||||
> +This is file3.txt.
|
||||
|
||||
$ cd dir
|
||||
$ quilt fold -q
|
||||
< --- dir.orig/file3.txt
|
||||
< +++ dir/file3.txt
|
||||
< @@ -1 +1 @@
|
||||
< -This is file3.txt.
|
||||
< +This is file3.txt, now modified.
|
||||
|
||||
$ cd ..
|
||||
$ quilt diff -p ab
|
||||
> Index: b/file1.txt
|
||||
> ===================================================================
|
||||
> --- /dev/null
|
||||
> +++ b/file1.txt
|
||||
> @@ -0,0 +1 @@
|
||||
> +This is file1.txt.
|
||||
> Index: b/dir/file3.txt
|
||||
> ===================================================================
|
||||
> --- /dev/null
|
||||
> +++ b/dir/file3.txt
|
||||
> @@ -0,0 +1 @@
|
||||
> +This is file3.txt, now modified.
|
|
@ -0,0 +1,120 @@
|
|||
# We create our own working directory to be able to verify
|
||||
# all patch formats, including the ones which mention the
|
||||
# base directory.
|
||||
$ mkdir -p d/patches
|
||||
$ cd d
|
||||
|
||||
$ cat > test.txt
|
||||
< 1
|
||||
< 2
|
||||
< old
|
||||
< 4
|
||||
< 5
|
||||
|
||||
$ quilt new test
|
||||
> Patch %{P}test is now on top
|
||||
|
||||
$ quilt add test.txt
|
||||
> File test.txt added to patch %{P}test
|
||||
|
||||
$ cat > test.txt
|
||||
< 1
|
||||
< 2
|
||||
< new
|
||||
< 4
|
||||
< 5
|
||||
|
||||
$ quilt diff
|
||||
> Index: d/test.txt
|
||||
> ===================================================================
|
||||
> --- d.orig/test.txt
|
||||
> +++ d/test.txt
|
||||
> @@ -1,5 +1,5 @@
|
||||
> 1
|
||||
> 2
|
||||
> -old
|
||||
> +new
|
||||
> 4
|
||||
> 5
|
||||
|
||||
$ quilt diff --no-index
|
||||
> --- d.orig/test.txt
|
||||
> +++ d/test.txt
|
||||
> @@ -1,5 +1,5 @@
|
||||
> 1
|
||||
> 2
|
||||
> -old
|
||||
> +new
|
||||
> 4
|
||||
> 5
|
||||
|
||||
$ quilt diff -R
|
||||
> Index: d/test.txt
|
||||
> ===================================================================
|
||||
> --- d.orig/test.txt
|
||||
> +++ d/test.txt
|
||||
> @@ -1,5 +1,5 @@
|
||||
> 1
|
||||
> 2
|
||||
> -new
|
||||
> +old
|
||||
> 4
|
||||
> 5
|
||||
|
||||
$ quilt diff -U1
|
||||
> Index: d/test.txt
|
||||
> ===================================================================
|
||||
> --- d.orig/test.txt
|
||||
> +++ d/test.txt
|
||||
> @@ -2,3 +2,3 @@
|
||||
> 2
|
||||
> -old
|
||||
> +new
|
||||
> 4
|
||||
|
||||
$ quilt diff -c
|
||||
> Index: d/test.txt
|
||||
> ===================================================================
|
||||
> *** d.orig/test.txt
|
||||
> --- d/test.txt
|
||||
> ***************
|
||||
> *** 1,5 ****
|
||||
> 1
|
||||
> 2
|
||||
> ! old
|
||||
> 4
|
||||
> 5
|
||||
> --- 1,5 ----
|
||||
> 1
|
||||
> 2
|
||||
> ! new
|
||||
> 4
|
||||
> 5
|
||||
|
||||
$ quilt diff -C1
|
||||
> Index: d/test.txt
|
||||
> ===================================================================
|
||||
> *** d.orig/test.txt
|
||||
> --- d/test.txt
|
||||
> ***************
|
||||
> *** 2,4 ****
|
||||
> 2
|
||||
> ! old
|
||||
> 4
|
||||
> --- 2,4 ----
|
||||
> 2
|
||||
> ! new
|
||||
> 4
|
||||
|
||||
$ quilt diff -p ab
|
||||
> Index: b/test.txt
|
||||
> ===================================================================
|
||||
> --- a/test.txt
|
||||
> +++ b/test.txt
|
||||
> @@ -1,5 +1,5 @@
|
||||
> 1
|
||||
> 2
|
||||
> -old
|
||||
> +new
|
||||
> 4
|
||||
> 5
|
|
@ -0,0 +1,48 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ echo foo > foo.orig
|
||||
$ echo foo2 > foo
|
||||
$ echo bar > bar.orig
|
||||
$ echo bar2 > bar
|
||||
$ diff -u foo.orig foo >> patches/foorab.diff
|
||||
$ diff -u bar bar.orig >> patches/foorab.diff
|
||||
$ mv foo.orig foo
|
||||
$ mv bar.orig bar
|
||||
$ echo foorab.diff -p0 > patches/series
|
||||
$ quilt push
|
||||
> Applying patch %{P}foorab.diff
|
||||
>~ patching file `?foo'?
|
||||
>~ patching file `?bar'?
|
||||
> Hunk #1 FAILED at 1.
|
||||
>~ 1 out of 1 hunk FAILED -- rejects in file `?bar'?
|
||||
> Patch %{P}foorab.diff does not apply (enforce with -f)
|
||||
$ echo %{?}
|
||||
> 1
|
||||
|
||||
$ quilt push
|
||||
> Applying patch %{P}foorab.diff
|
||||
>~ patching file `?foo'?
|
||||
>~ patching file `?bar'?
|
||||
> Hunk #1 FAILED at 1.
|
||||
>~ 1 out of 1 hunk FAILED -- rejects in file `?bar'?
|
||||
> Patch %{P}foorab.diff does not apply (enforce with -f)
|
||||
$ echo %{?}
|
||||
> 1
|
||||
|
||||
$ quilt push -qf
|
||||
> Applying patch %{P}foorab.diff
|
||||
>~ 1 out of 1 hunk FAILED( -- saving rejects to( file)? bar.rej)?
|
||||
> Applied patch %{P}foorab.diff (forced; needs refresh)
|
||||
$ echo %{?}
|
||||
> 1
|
||||
|
||||
$ quilt diff
|
||||
> Index: foo
|
||||
> ===================================================================
|
||||
> --- foo.orig
|
||||
> +++ foo
|
||||
> @@ -1 +1 @@
|
||||
> -foo
|
||||
> +foo2
|
||||
$ echo %{?}
|
||||
> 0
|
|
@ -0,0 +1,60 @@
|
|||
If a patch file has hard links, refreshing it should break the links
|
||||
so that the other copies are left unmodified.
|
||||
|
||||
$ mkdir patches
|
||||
|
||||
$ cat > patches/patch
|
||||
< --- file.orig
|
||||
< +++ file
|
||||
< @@ -1 +1 @@
|
||||
< -a
|
||||
< +b
|
||||
$ echo patch -p0 > patches/series
|
||||
$ ln patches/patch hardlink
|
||||
|
||||
$ echo a > file
|
||||
$ quilt push -q
|
||||
> Applying patch %{P}patch
|
||||
> Now at patch %{P}patch
|
||||
|
||||
$ echo c > file
|
||||
$ quilt refresh --no-index
|
||||
> Refreshed patch %{P}patch
|
||||
|
||||
$ cat patches/patch
|
||||
> --- file.orig
|
||||
> +++ file
|
||||
> @@ -1 +1 @@
|
||||
> -a
|
||||
> +c
|
||||
|
||||
$ cat hardlink
|
||||
> --- file.orig
|
||||
> +++ file
|
||||
> @@ -1 +1 @@
|
||||
> -a
|
||||
> +b
|
||||
|
||||
Same goes for a patch header update.
|
||||
|
||||
$ rm -f hardlink
|
||||
$ ln patches/patch hardlink
|
||||
|
||||
$ quilt header -r
|
||||
< c is so much better than a
|
||||
> Replaced header of patch %{P}patch
|
||||
|
||||
$ cat patches/patch
|
||||
> c is so much better than a
|
||||
> --- file.orig
|
||||
> +++ file
|
||||
> @@ -1 +1 @@
|
||||
> -a
|
||||
> +c
|
||||
|
||||
$ cat hardlink
|
||||
> --- file.orig
|
||||
> +++ file
|
||||
> @@ -1 +1 @@
|
||||
> -a
|
||||
> +c
|
|
@ -0,0 +1,57 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ echo foo > foo
|
||||
$ quilt new patch
|
||||
> Patch %{P}patch is now on top
|
||||
|
||||
$ quilt add foo
|
||||
> File foo added to patch %{P}patch
|
||||
|
||||
$ echo bar > foo
|
||||
$ quilt refresh -p ab
|
||||
> Refreshed patch %{P}patch
|
||||
|
||||
$ mv patches/patch patches/patch~
|
||||
$ echo Header > patches/patch
|
||||
$ cat patches/patch~ >> patches/patch
|
||||
$ quilt header
|
||||
> Header
|
||||
|
||||
$ quilt header -r
|
||||
< Header2
|
||||
> Replaced header of patch %{P}patch
|
||||
|
||||
$ quilt header
|
||||
> Header2
|
||||
|
||||
$ quilt header -a
|
||||
< Appended
|
||||
> Appended text to header of patch %{P}patch
|
||||
|
||||
$ quilt header
|
||||
> Header2
|
||||
> Appended
|
||||
|
||||
$ cat patches/patch
|
||||
> Header2
|
||||
> Appended
|
||||
> Index: b/foo
|
||||
> ===================================================================
|
||||
> --- a/foo
|
||||
> +++ b/foo
|
||||
> @@ -1 +1 @@
|
||||
> -foo
|
||||
> +bar
|
||||
|
||||
$ echo -n "No trailing newline" | quilt header -r
|
||||
> Replaced header of patch patches/patch
|
||||
|
||||
$ cat patches/patch
|
||||
> No trailing newline
|
||||
> Index: b/foo
|
||||
> ===================================================================
|
||||
> --- a/foo
|
||||
> +++ b/foo
|
||||
> @@ -1 +1 @@
|
||||
> -foo
|
||||
> +bar
|
|
@ -0,0 +1,257 @@
|
|||
$ mkdir patches
|
||||
|
||||
$ quilt new patch1.diff
|
||||
> Patch %{P}patch1.diff is now on top
|
||||
|
||||
$ quilt add f
|
||||
> File f added to patch %{P}patch1.diff
|
||||
|
||||
$ echo f > f
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patch1.diff
|
||||
|
||||
$ quilt new patchR.diff
|
||||
> Patch %{P}patchR.diff is now on top
|
||||
|
||||
$ quilt add f
|
||||
> File f added to patch %{P}patchR.diff
|
||||
|
||||
$ rm -f f
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patchR.diff
|
||||
|
||||
$ quilt fork patchRp0.diff
|
||||
> Fork of patch %{P}patchR.diff created as %{P}patchRp0.diff
|
||||
|
||||
$ quilt refresh -p0
|
||||
> Refreshed patch %{P}patchRp0.diff
|
||||
|
||||
$ quilt pop -a
|
||||
> Removing patch %{P}patchRp0.diff
|
||||
> Restoring f
|
||||
>
|
||||
> Removing patch %{P}patch1.diff
|
||||
> Removing f
|
||||
>
|
||||
> No patches applied
|
||||
|
||||
$ mkdir t
|
||||
$ mv patches/patch1.diff t/patch1.diff
|
||||
$ mv patches/patchR.diff t/patchR.diff
|
||||
$ mv patches/patchRp0.diff t/patchRp0.diff
|
||||
|
||||
# test importing into an empty series
|
||||
$ rm -rf patches/ %{QUILT_PC}/
|
||||
$ mkdir patches
|
||||
$ quilt import t/patch1.diff
|
||||
> Importing patch t/patch1.diff (stored as %{P}patch1.diff)
|
||||
|
||||
$ quilt push
|
||||
> Applying patch %{P}patch1.diff
|
||||
>~ patching file `?f'?
|
||||
>
|
||||
> Now at patch %{P}patch1.diff
|
||||
|
||||
$ quilt new patch2.diff
|
||||
> Patch %{P}patch2.diff is now on top
|
||||
|
||||
$ quilt add g
|
||||
> File g added to patch %{P}patch2.diff
|
||||
|
||||
$ echo g > g
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patch2.diff
|
||||
|
||||
$ quilt pop
|
||||
> Removing patch %{P}patch2.diff
|
||||
> Removing g
|
||||
>
|
||||
> Now at patch %{P}patch1.diff
|
||||
|
||||
$ quilt header -a
|
||||
< original description
|
||||
> Appended text to header of patch %{P}patch1.diff
|
||||
|
||||
$ quilt pop
|
||||
> Removing patch %{P}patch1.diff
|
||||
> Removing f
|
||||
>
|
||||
> No patches applied
|
||||
|
||||
$ quilt delete patch1
|
||||
> Removed patch %{P}patch1.diff
|
||||
|
||||
$ cat patches/series
|
||||
> patch2.diff
|
||||
|
||||
# test a few error cases
|
||||
|
||||
$ quilt import missing.diff
|
||||
> Patch missing.diff does not exist
|
||||
|
||||
$ quilt import patches/patch1.diff
|
||||
> Importing patch %{P}patch1.diff
|
||||
|
||||
$ quilt import patches/patch2.diff
|
||||
> Patch %{P}patch2.diff already exists in series.
|
||||
|
||||
# a simple use of import
|
||||
|
||||
$ quilt import t/patch1.diff
|
||||
> Patch %{P}patch1.diff exists. Replace with -f.
|
||||
|
||||
$ quilt import -f t/patch1.diff
|
||||
> Replacing patch %{P}patch1.diff with new version
|
||||
|
||||
# an import requiring a description merge
|
||||
$ sed -e 's/original/new/' patches/patch1.diff > t/patch1.diff
|
||||
$ quilt import t/patch1.diff
|
||||
> Patch %{P}patch1.diff exists. Replace with -f.
|
||||
|
||||
$ quilt import -f t/patch1.diff
|
||||
> Patch headers differ:
|
||||
> @@ -1 +1 @@
|
||||
> -original description
|
||||
> +new description
|
||||
> Please use -d {o|a|n} to specify which patch header(s) to keep.
|
||||
|
||||
$ quilt import -d a -f t/patch1.diff
|
||||
> Replacing patch %{P}patch1.diff with new version
|
||||
|
||||
# quilt header does not work in this case because it stops at '---'
|
||||
$ head -n 3 patches/patch1.diff
|
||||
> original description
|
||||
> ---
|
||||
> new description
|
||||
|
||||
$ quilt import -d n -f t/patch1.diff
|
||||
> Replacing patch %{P}patch1.diff with new version
|
||||
|
||||
$ quilt header patch1
|
||||
> new description
|
||||
|
||||
$ quilt delete patch1
|
||||
> Removed patch %{P}patch1.diff
|
||||
|
||||
# make sure it accepts non-conflicting names
|
||||
# a small presentation problem here
|
||||
|
||||
$ cp patches/patch1.diff t/patch1.patch
|
||||
$ quilt import t/patch1.patch
|
||||
> Importing patch t/patch1.patch (stored as %{P}patch1.patch)
|
||||
|
||||
$ ls patches/
|
||||
> patch1.diff
|
||||
> patch1.patch
|
||||
> patch2.diff
|
||||
> series
|
||||
|
||||
$ cat patches/series
|
||||
> patch1.patch
|
||||
> patch2.diff
|
||||
|
||||
$ quilt delete patch1.diff
|
||||
> Patch patch1.diff is not in series
|
||||
|
||||
# test importing a reverse patch
|
||||
$ rm -rf patches/ %{QUILT_PC}/
|
||||
$ mkdir patches
|
||||
$ quilt import -R t/patchR.diff
|
||||
> Importing patch t/patchR.diff (stored as %{P}patchR.diff)
|
||||
|
||||
$ quilt push
|
||||
> Applying patch %{P}patchR.diff
|
||||
>~ patching file `?f'?
|
||||
>
|
||||
> Now at patch %{P}patchR.diff
|
||||
|
||||
$ cat f
|
||||
> f
|
||||
|
||||
$ cat patches/series
|
||||
> patchR.diff -R
|
||||
|
||||
# test that comments are preserved
|
||||
$ echo "# Test of -R import" > patches/series
|
||||
$ echo "patchR.diff -R # This patch was originally -R -p1" >> patches/series
|
||||
|
||||
# refreshing a reverse patch un-reverses it
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patchR.diff
|
||||
|
||||
$ cat patches/series
|
||||
> # Test of -R import
|
||||
> patchR.diff # This patch was originally -R -p1
|
||||
|
||||
$ touch f
|
||||
$ quilt pop
|
||||
> Removing patch %{P}patchR.diff
|
||||
> Removing f
|
||||
>
|
||||
> No patches applied
|
||||
|
||||
# test importing a reverse patch with strip level
|
||||
$ rm -rf patches/ %{QUILT_PC}/
|
||||
$ mkdir patches
|
||||
$ quilt import -R -p0 t/patchRp0.diff
|
||||
> Importing patch t/patchRp0.diff (stored as %{P}patchRp0.diff)
|
||||
|
||||
$ quilt push
|
||||
> Applying patch %{P}patchRp0.diff
|
||||
>~ patching file `?f'?
|
||||
>
|
||||
> Now at patch %{P}patchRp0.diff
|
||||
|
||||
$ cat f
|
||||
> f
|
||||
|
||||
$ cat patches/series
|
||||
> patchRp0.diff -p0 -R
|
||||
|
||||
# refreshing a reverse patch un-reverses it
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patchRp0.diff
|
||||
|
||||
$ cat patches/series
|
||||
> patchRp0.diff -p0
|
||||
|
||||
$ touch f
|
||||
$ quilt pop
|
||||
> Removing patch %{P}patchRp0.diff
|
||||
> Removing f
|
||||
>
|
||||
> No patches applied
|
||||
|
||||
# Test importing multiple patches at once
|
||||
$ rm -rf patches/ %{QUILT_PC}/
|
||||
$ mkdir patches
|
||||
$ quilt import t/patch1.diff t/patchR.diff
|
||||
> Importing patch t/patch1.diff (stored as %{P}patch1.diff)
|
||||
> Importing patch t/patchR.diff (stored as %{P}patchR.diff)
|
||||
|
||||
$ cat patches/series
|
||||
> patch1.diff
|
||||
> patchR.diff
|
||||
|
||||
$ rm -rf patches/ %{QUILT_PC}/
|
||||
$ mkdir patches
|
||||
$ quilt import t/patchR.diff
|
||||
> Importing patch t/patchR.diff (stored as %{P}patchR.diff)
|
||||
$ quilt import t/patch1.diff
|
||||
> Importing patch t/patch1.diff (stored as %{P}patch1.diff)
|
||||
|
||||
$ cat patches/series
|
||||
> patch1.diff
|
||||
> patchR.diff
|
||||
|
||||
# Also test importing when in a subdirectory
|
||||
$ touch empty.patch
|
||||
$ cd t
|
||||
$ touch empty2.patch
|
||||
$ quilt import ../empty.patch
|
||||
> Importing patch ../empty.patch (stored as %{_P}empty.patch)
|
||||
$ quilt import %{PWD}/empty2.patch
|
||||
> Importing patch %{PWD}/empty2.patch (stored as %{_P}empty2.patch)
|
|
@ -0,0 +1,138 @@
|
|||
# same as import.test, but with compressed patches
|
||||
|
||||
$ mkdir patches
|
||||
|
||||
$ quilt new patch1.diff
|
||||
> Patch %{P}patch1.diff is now on top
|
||||
|
||||
$ quilt add f
|
||||
> File f added to patch %{P}patch1.diff
|
||||
|
||||
$ echo f > f
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patch1.diff
|
||||
|
||||
$ quilt pop
|
||||
> Removing patch %{P}patch1.diff
|
||||
> Removing f
|
||||
>
|
||||
> No patches applied
|
||||
|
||||
$ mkdir t
|
||||
$ gzip < patches/patch1.diff > t/patch1.diff.gz
|
||||
$ rm -f patches/patch1.diff
|
||||
|
||||
# test importing into an empty series
|
||||
$ rm -rf patches/ %{QUILT_PC}/
|
||||
$ mkdir patches
|
||||
$ quilt import t/patch1.diff.gz
|
||||
> Importing patch t/patch1.diff.gz (stored as %{P}patch1.diff.gz)
|
||||
|
||||
$ quilt push
|
||||
> Applying patch %{P}patch1.diff.gz
|
||||
>~ patching file `?f'?
|
||||
>
|
||||
> Now at patch %{P}patch1.diff.gz
|
||||
|
||||
$ quilt new patch2.diff.gz
|
||||
> Patch %{P}patch2.diff.gz is now on top
|
||||
|
||||
$ quilt add g
|
||||
> File g added to patch %{P}patch2.diff.gz
|
||||
|
||||
$ echo g > g
|
||||
|
||||
$ quilt refresh
|
||||
> Refreshed patch %{P}patch2.diff.gz
|
||||
|
||||
$ quilt pop
|
||||
> Removing patch %{P}patch2.diff.gz
|
||||
> Removing g
|
||||
>
|
||||
> Now at patch %{P}patch1.diff.gz
|
||||
|
||||
$ quilt header -a
|
||||
< original description
|
||||
> Appended text to header of patch %{P}patch1.diff.gz
|
||||
|
||||
$ quilt pop
|
||||
> Removing patch %{P}patch1.diff.gz
|
||||
> Removing f
|
||||
>
|
||||
> No patches applied
|
||||
|
||||
$ quilt delete patch1
|
||||
> Removed patch %{P}patch1.diff.gz
|
||||
|
||||
$ cat patches/series
|
||||
> patch2.diff.gz
|
||||
|
||||
# test a few error cases
|
||||
|
||||
$ quilt import missing.diff.gz
|
||||
> Patch missing.diff.gz does not exist
|
||||
|
||||
$ quilt import patches/patch1.diff.gz
|
||||
> Importing patch %{P}patch1.diff.gz
|
||||
|
||||
$ quilt import patches/patch2.diff.gz
|
||||
> Patch %{P}patch2.diff.gz already exists in series.
|
||||
|
||||
# a simple use of import
|
||||
|
||||
$ quilt import t/patch1.diff.gz
|
||||
> Patch %{P}patch1.diff.gz exists. Replace with -f.
|
||||
|
||||
$ quilt import -f t/patch1.diff.gz
|
||||
> Replacing patch %{P}patch1.diff.gz with new version
|
||||
|
||||
# an import requiring a description merge
|
||||
$ zcat patches/patch1.diff.gz | sed -e 's/original/new/' | gzip > t/patch1.diff.gz
|
||||
$ quilt import t/patch1.diff.gz
|
||||
> Patch %{P}patch1.diff.gz exists. Replace with -f.
|
||||
|
||||
$ quilt import -f t/patch1.diff.gz
|
||||
> Patch headers differ:
|
||||
> @@ -1 +1 @@
|
||||
> -original description
|
||||
> +new description
|
||||
> Please use -d {o|a|n} to specify which patch header(s) to keep.
|
||||
|
||||
$ quilt import -d a -f t/patch1.diff.gz
|
||||
> Replacing patch %{P}patch1.diff.gz with new version
|
||||
|
||||
# quilt header does not work in this case because it stops at '---'
|
||||
$ zcat patches/patch1.diff.gz | head -n 3
|
||||
> original description
|
||||
> ---
|
||||
> new description
|
||||
|
||||
$ quilt import -d n -f t/patch1.diff.gz
|
||||
> Replacing patch %{P}patch1.diff.gz with new version
|
||||
|
||||
$ quilt header patch1
|
||||
> new description
|
||||
|
||||
$ quilt delete patch1
|
||||
> Removed patch %{P}patch1.diff.gz
|
||||
|
||||
# make sure it accepts non-conflicting names
|
||||
# a small presentation problem here
|
||||
|
||||
$ cp patches/patch1.diff.gz t/patch1.patch.gz
|
||||
$ quilt import t/patch1.patch.gz
|
||||
> Importing patch t/patch1.patch.gz (stored as %{P}patch1.patch.gz)
|
||||
|
||||
$ ls patches/
|
||||
> patch1.diff.gz
|
||||
> patch1.patch.gz
|
||||
> patch2.diff.gz
|
||||
> series
|
||||
|
||||
$ cat patches/series
|
||||
> patch1.patch.gz
|
||||
> patch2.diff.gz
|
||||
|
||||
$ quilt delete patch1.diff.gz
|
||||
> Patch patch1.diff.gz is not in series
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue