summaryrefslogtreecommitdiffstats
path: root/emacs.d/lisp/magit
diff options
context:
space:
mode:
Diffstat (limited to 'emacs.d/lisp/magit')
-rw-r--r--emacs.d/lisp/magit/.gitignore37
-rw-r--r--emacs.d/lisp/magit/50magit.el3
-rw-r--r--emacs.d/lisp/magit/AUTHORS6
-rw-r--r--emacs.d/lisp/magit/COPYING676
-rw-r--r--emacs.d/lisp/magit/ChangeLog1
-rw-r--r--emacs.d/lisp/magit/Makefile.am24
-rw-r--r--emacs.d/lisp/magit/NEWS93
-rw-r--r--emacs.d/lisp/magit/README44
-rwxr-xr-xemacs.d/lisp/magit/autogen.sh2
-rw-r--r--emacs.d/lisp/magit/configure.ac8
-rw-r--r--emacs.d/lisp/magit/fdl.texi451
-rw-r--r--emacs.d/lisp/magit/magit-pkg.el.in1
-rw-r--r--emacs.d/lisp/magit/magit.el3244
-rw-r--r--emacs.d/lisp/magit/magit.texi639
-rw-r--r--emacs.d/lisp/magit/test/BAR.21
-rw-r--r--emacs.d/lisp/magit/test/FOO.21
16 files changed, 5231 insertions, 0 deletions
diff --git a/emacs.d/lisp/magit/.gitignore b/emacs.d/lisp/magit/.gitignore
new file mode 100644
index 0000000..aee86f2
--- /dev/null
+++ b/emacs.d/lisp/magit/.gitignore
@@ -0,0 +1,37 @@
+/INSTALL
+/Makefile
+/Makefile.in
+/aclocal.m4
+/build-stamp
+/config.log
+/config.status
+/configure
+/debian/debhelper.log
+/debian/files
+/debian/magit.debhelper.log
+/debian/magit.postinst.debhelper
+/debian/magit.prerm.debhelper
+/install-sh
+/install-stamp
+/magit-0.5.tar.gz
+/magit.info
+/missing
+/texinfo.tex
+/debian/magit/
+/autom4te.cache/
+/magit-0.6.tar.gz
+*.elc
+*~
+/magit.aux
+/magit.cp
+/magit.dvi
+/magit.fn
+/magit.ky
+/magit.log
+/magit.pg
+/magit.toc
+/magit.tp
+/magit.vr
+/magit.pdf
+/magit.ps
+/magit-pkg.el
diff --git a/emacs.d/lisp/magit/50magit.el b/emacs.d/lisp/magit/50magit.el
new file mode 100644
index 0000000..b04034d
--- /dev/null
+++ b/emacs.d/lisp/magit/50magit.el
@@ -0,0 +1,3 @@
+;;; Autoloads for magit
+
+(autoload 'magit-status "magit" nil t)
diff --git a/emacs.d/lisp/magit/AUTHORS b/emacs.d/lisp/magit/AUTHORS
new file mode 100644
index 0000000..af133ff
--- /dev/null
+++ b/emacs.d/lisp/magit/AUTHORS
@@ -0,0 +1,6 @@
+Marius Vollmer <marius.vollmer@uni-dortmund.de>
+Linh Dang <dang.linh@gmail.com>
+Alex Ott <ott@flash.lan>
+Marcin Bachry <hegel666@gmail.com>
+Alexey Voinov <alexey.v.voinov@gmail.com
+John Wiegley <johnw@newartisans.com>
diff --git a/emacs.d/lisp/magit/COPYING b/emacs.d/lisp/magit/COPYING
new file mode 100644
index 0000000..4432540
--- /dev/null
+++ b/emacs.d/lisp/magit/COPYING
@@ -0,0 +1,676 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state 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 3 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU 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 Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
diff --git a/emacs.d/lisp/magit/ChangeLog b/emacs.d/lisp/magit/ChangeLog
new file mode 100644
index 0000000..d65ee7e
--- /dev/null
+++ b/emacs.d/lisp/magit/ChangeLog
@@ -0,0 +1 @@
+There is no ChangeLog.
diff --git a/emacs.d/lisp/magit/Makefile.am b/emacs.d/lisp/magit/Makefile.am
new file mode 100644
index 0000000..8ae4192
--- /dev/null
+++ b/emacs.d/lisp/magit/Makefile.am
@@ -0,0 +1,24 @@
+lispdir = $(datadir)/emacs/site-lisp
+sitestartdir = $(sysconfdir)/emacs/site-start.d
+
+lisp_DATA = magit.el magit.elc
+sitestart_DATA = 50magit.el
+
+info_TEXINFOS = magit.texi
+
+CLEANFILES = magit.elc
+EXTRA_DIST = magit.el 50magit.el
+
+%.elc: %.el
+ @if [ $(builddir) != $(srcdir) ]; then ln $(srcdir)/$*.el .; fi
+ emacs --batch --eval '(byte-compile-file "$*.el")'
+ @if [ $(builddir) != $(srcdir) ]; then rm -f $*.el; fi
+
+
+elpa: magit-pkg.el info
+ -@rm -rf magit-$(VERSION)
+ mkdir magit-$(VERSION)
+ cp magit.el magit-pkg.el magit.info magit-$(VERSION)
+ (cd magit-$(VERSION); ginstall-info --dir-file=dir magit.info)
+ tar cf magit-$(VERSION).tar magit-$(VERSION)
+ @rm -rf magit-$(VERSION)
diff --git a/emacs.d/lisp/magit/NEWS b/emacs.d/lisp/magit/NEWS
new file mode 100644
index 0000000..9906dac
--- /dev/null
+++ b/emacs.d/lisp/magit/NEWS
@@ -0,0 +1,93 @@
+Changes in magit 0.8:
+
+* By setting magit-repo-dirs, you can get better repo completion.
+ Magit will offer all subdirectories (upto magit-repo-dirs level
+ deep) of the listed directories when magit-status asks for a
+ directory to work on.
+
+ You can get the old behavior with a double prefix to magit-status.
+
+* Hitting 'c' or 'C' while resolving a conflict in the middle of a
+ rebase will offer to continue the rebase instead of trying to commit
+ your changes.
+
+* Pulling will ask which branch to pull from when you don't have a
+ default branch configured.
+
+* Switching to a remote branch will offer to create a local tracking
+ branch for it.
+
+* Hitting C-c C-s while editing a commit message will toggle the
+ "--signoff" option.
+
+* Hitting 's' on the "Untracked files" section title will stage all
+ untracked files.
+
+* Hitting 'C-u S' will stage all untracked and tracked files.
+
+* Performance improvements in the status buffer.
+
+* Bug fixes to make Magit work better with newer Gits.
+
+Changes in magit 0.7:
+
+* Tagging, on 't' and 'T'.
+
+* Stashing, on 'z' and 'Z'.
+
+* Wazzup, on 'w'. Wazzup gives you an overview over how other
+ branches relate to the current one.
+
+* There is more control over pushing. 'P' now takes a prefix argument
+ and pushing a branch without a default remote will ask for one.
+
+* Logs have changed a bit: 'l' shows the traditional brief log, and
+ 'L' shows a more verbose log. Use the prefix arg to specify the
+ range of the log.
+
+* M-x magit-status doesn't prompt anymore for a directory when invoked
+ from within a Git repository. Use C-u to force a prompt.
+
+* When you have nothing staged, 'c' will now explicitly ask whether to
+ commit everything instead of just going ahead and do it. This can
+ be customized.
+
+* The digit keys '1', '2', '3', and '4' now show sections on the
+ respective level and hide everything below. With Meta, they work on
+ all sections; without, they work only on sections that are a parent
+ or child of the current section.
+
+* Typing '+' and '-' will change the size of hunks, via the "-U"
+ option to git diff. '0' resets hunks to their default size.
+
+* Typing 'k' on the "Untracked files" section title will offer to
+ delete all untracked files.
+
+* Magit understands a bit of git-svn: the status buffer shows unpushed
+ and unpulled commits, 'N r' runs git svn rebase, and 'N c' runs git
+ svn dcommit.
+
+* Magit now also works when the direcory is accessed via tramp.
+
+* M-x magit-status can also create new repositories when given a
+ directory that is not a Git repository.
+
+* Magit works better with oldish Gits that don't understand "--graph",
+ for example.
+
+* The name of the Git program and common options for it can be
+ customized.
+
+Changes in magit 0.6:
+
+Almost everything has changed. Please read the manual again. Some
+highlights:
+
+* Magit now works with Git 1.6.0. (John Wiegley)
+
+* Support for interactive rewriting.
+
+* Sections can be shown and hidden.
+
+* Staging, unstaging, applying, reverting and discarding changes can
+ now be done line-by-line, not only hunk-by-hunk.
diff --git a/emacs.d/lisp/magit/README b/emacs.d/lisp/magit/README
new file mode 100644
index 0000000..b3e41d3
--- /dev/null
+++ b/emacs.d/lisp/magit/README
@@ -0,0 +1,44 @@
+It's Magit! A Emacs mode for Git.
+
+I started to write Magit to learn about Git and to figure out how I
+would be using Git in a 'natural' way. Magit will grow and hopefully
+become more coherent as I learn more about Git and good ways to use
+it. Feedback is welcome!
+
+* Installing
+
+Magit can be installed with the popular recipe of
+
+ $ ./autogen.sh # If you got the sources directly from Git
+ $ ./configure
+ $ make install
+
+This will put magit.el into /usr/local/share/emacs/site-lisp, where
+Emacs should be able to find it. Then add
+
+ (require 'magit)
+
+to your .emacs file.
+
+* Getting started
+
+To get started with Magit, open any file in a Git repository in Emacs
+and run 'M-x magit-status'. Read the online help of magit-mode ('C-h
+m' in the Magit buffer), make some changes to your files, and try to
+commit them.
+
+* Learning more
+
+The Magit User Manual describes things with more words than the online
+help. You can read it in Emacs with 'C-u C-h i magit.info' for
+example, or on the web at
+
+ http://zagadka.vm.bytemark.co.uk/magit/magit.html
+
+If you have questions, please use the mailing list at
+
+ http://groups.google.com/group/magit/
+
+Magit's web home is currently at
+
+ http://zagadka.vm.bytemark.co.uk/magit/
diff --git a/emacs.d/lisp/magit/autogen.sh b/emacs.d/lisp/magit/autogen.sh
new file mode 100755
index 0000000..f586638
--- /dev/null
+++ b/emacs.d/lisp/magit/autogen.sh
@@ -0,0 +1,2 @@
+#! /bin/sh
+autoreconf --install
diff --git a/emacs.d/lisp/magit/configure.ac b/emacs.d/lisp/magit/configure.ac
new file mode 100644
index 0000000..da592b9
--- /dev/null
+++ b/emacs.d/lisp/magit/configure.ac
@@ -0,0 +1,8 @@
+AC_INIT(magit, 0.8)
+AC_CONFIG_SRCDIR([magit.el])
+AM_INIT_AUTOMAKE
+
+AC_CONFIG_FILES([Makefile
+ magit-pkg.el])
+
+AC_OUTPUT
diff --git a/emacs.d/lisp/magit/fdl.texi b/emacs.d/lisp/magit/fdl.texi
new file mode 100644
index 0000000..96ce74e
--- /dev/null
+++ b/emacs.d/lisp/magit/fdl.texi
@@ -0,0 +1,451 @@
+@c The GNU Free Documentation License.
+@center Version 1.2, November 2002
+
+@c This file is intended to be included within another document,
+@c hence no sectioning command or @node.
+
+@display
+Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@enumerate 0
+@item
+PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+functional and useful document @dfn{free} in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
+
+This License is a kind of ``copyleft'', which means that derivative
+works of the document must themselves be free in the same sense. It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does. But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book. We recommend this License
+principally for works whose purpose is instruction or reference.
+
+@item
+APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License. Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein. The ``Document'', below,
+refers to any such manual or work. Any member of the public is a
+licensee, and is addressed as ``you''. You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
+
+A ``Modified Version'' of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A ``Secondary Section'' is a named appendix or a front-matter section
+of the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall
+subject (or to related matters) and contains nothing that could fall
+directly within that overall subject. (Thus, if the Document is in
+part a textbook of mathematics, a Secondary Section may not explain
+any mathematics.) The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The ``Invariant Sections'' are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License. If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant. The Document may contain zero
+Invariant Sections. If the Document does not identify any Invariant
+Sections then there are none.
+
+The ``Cover Texts'' are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License. A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
+
+A ``Transparent'' copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, that is suitable for revising the document
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters. A copy made in an otherwise Transparent file
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text. A copy that is not ``Transparent'' is called ``Opaque''.
+
+Examples of suitable formats for Transparent copies include plain
+@sc{ascii} without markup, Texinfo input format, La@TeX{} input
+format, @acronym{SGML} or @acronym{XML} using a publicly available
+@acronym{DTD}, and standard-conforming simple @acronym{HTML},
+PostScript or @acronym{PDF} designed for human modification. Examples
+of transparent image formats include @acronym{PNG}, @acronym{XCF} and
+@acronym{JPG}. Opaque formats include proprietary formats that can be
+read and edited only by proprietary word processors, @acronym{SGML} or
+@acronym{XML} for which the @acronym{DTD} and/or processing tools are
+not generally available, and the machine-generated @acronym{HTML},
+PostScript or @acronym{PDF} produced by some word processors for
+output purposes only.
+
+The ``Title Page'' means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page. For works in
+formats which do not have any title page as such, ``Title Page'' means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+A section ``Entitled XYZ'' means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language. (Here XYZ stands for a
+specific section name mentioned below, such as ``Acknowledgements'',
+``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title''
+of such a section when you modify the Document means that it remains a
+section ``Entitled XYZ'' according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document. These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
+@item
+VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License. You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute. However, you may accept
+compensation in exchange for copies. If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+@item
+COPYING IN QUANTITY
+
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover. Both covers must also clearly and legibly identify
+you as the publisher of these copies. The front cover must present
+the full title with all words of the title equally prominent and
+visible. You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to give
+them a chance to provide you with an updated version of the Document.
+
+@item
+MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it. In addition, you must do these things in the Modified Version:
+
+@enumerate A
+@item
+Use in the Title Page (and on the covers, if any) a title distinct
+from that of the Document, and from those of previous versions
+(which should, if there were any, be listed in the History section
+of the Document). You may use the same title as a previous version
+if the original publisher of that version gives permission.
+
+@item
+List on the Title Page, as authors, one or more persons or entities
+responsible for authorship of the modifications in the Modified
+Version, together with at least five of the principal authors of the
+Document (all of its principal authors, if it has fewer than five),
+unless they release you from this requirement.
+
+@item
+State on the Title page the name of the publisher of the
+Modified Version, as the publisher.
+
+@item
+Preserve all the copyright notices of the Document.
+
+@item
+Add an appropriate copyright notice for your modifications
+adjacent to the other copyright notices.
+
+@item
+Include, immediately after the copyright notices, a license notice
+giving the public permission to use the Modified Version under the
+terms of this License, in the form shown in the Addendum below.
+
+@item
+Preserve in that license notice the full lists of Invariant Sections
+and required Cover Texts given in the Document's license notice.
+
+@item
+Include an unaltered copy of this License.
+
+@item
+Preserve the section Entitled ``History'', Preserve its Title, and add
+to it an item stating at least the title, year, new authors, and
+publisher of the Modified Version as given on the Title Page. If
+there is no section Entitled ``History'' in the Document, create one
+stating the title, year, authors, and publisher of the Document as
+given on its Title Page, then add an item describing the Modified
+Version as stated in the previous sentence.
+
+@item
+Preserve the network location, if any, given in the Document for
+public access to a Transparent copy of the Document, and likewise
+the network locations given in the Document for previous versions
+it was based on. These may be placed in the ``History'' section.
+You may omit a network location for a work that was published at
+least four years before the Document itself, or if the original
+publisher of the version it refers to gives permission.
+
+@item
+For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
+the Title of the section, and preserve in the section all the
+substance and tone of each of the contributor acknowledgements and/or
+dedications given therein.
+
+@item
+Preserve all the Invariant Sections of the Document,
+unaltered in their text and in their titles. Section numbers
+or the equivalent are not considered part of the section titles.
+
+@item
+Delete any section Entitled ``Endorsements''. Such a section
+may not be included in the Modified Version.
+
+@item
+Do not retitle any existing section to be Entitled ``Endorsements'' or
+to conflict in title with any Invariant Section.
+
+@item
+Preserve any Warranty Disclaimers.
+@end enumerate
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant. To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section Entitled ``Endorsements'', provided it contains
+nothing but endorsements of your Modified Version by various
+parties---for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version. Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity. If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+@item
+COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice, and that you preserve all their Warranty Disclaimers.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy. If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections Entitled ``History''
+in the various original documents, forming one section Entitled
+``History''; likewise combine any sections Entitled ``Acknowledgements'',
+and any sections Entitled ``Dedications''. You must delete all
+sections Entitled ``Endorsements.''
+
+@item
+COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other documents
+released under this License, and replace the individual copies of this
+License in the various documents with a single copy that is included in
+the collection, provided that you follow the rules of this License for
+verbatim copying of each of the documents in all other respects.
+
+You may extract a single document from such a collection, and distribute
+it individually under this License, provided you insert a copy of this
+License into the extracted document, and follow this License in all
+other respects regarding verbatim copying of that document.
+
+@item
+AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, is called an ``aggregate'' if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included in an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
+
+@item
+TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections. You may include a
+translation of this License, and all the license notices in the
+Document, and any Warranty Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers. In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled ``Acknowledgements'',
+``Dedications'', or ``History'', the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
+
+@item
+TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document except
+as expressly provided for under this License. Any other attempt to
+copy, modify, sublicense or distribute the Document 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.
+
+@item
+FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions
+of the GNU Free Documentation 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. See
+@uref{http://www.gnu.org/copyleft/}.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License ``or any later version'' applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation. If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.
+@end enumerate
+
+@page
+@heading ADDENDUM: How to use this License for your documents
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+@smallexample
+@group
+ Copyright (C) @var{year} @var{your name}.
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.2
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ Texts. A copy of the license is included in the section entitled ``GNU
+ Free Documentation License''.
+@end group
+@end smallexample
+
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the ``with@dots{}Texts.'' line with this:
+
+@smallexample
+@group
+ with the Invariant Sections being @var{list their titles}, with
+ the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
+ being @var{list}.
+@end group
+@end smallexample
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
+
+@c Local Variables:
+@c ispell-local-pdict: "ispell-dict"
+@c End:
+
diff --git a/emacs.d/lisp/magit/magit-pkg.el.in b/emacs.d/lisp/magit/magit-pkg.el.in
new file mode 100644
index 0000000..59335e5
--- /dev/null
+++ b/emacs.d/lisp/magit/magit-pkg.el.in
@@ -0,0 +1 @@
+(define-package "magit" "@VERSION@" "Control Git from Emacs.")
diff --git a/emacs.d/lisp/magit/magit.el b/emacs.d/lisp/magit/magit.el
new file mode 100644
index 0000000..bfbfe9b
--- /dev/null
+++ b/emacs.d/lisp/magit/magit.el
@@ -0,0 +1,3244 @@
+;;; Magit -- control Git from Emacs.
+
+;; Copyright (C) 2008, 2009 Marius Vollmer
+;; Copyright (C) 2008 Linh Dang
+;; Copyright (C) 2008 Alex Ott
+;; Copyright (C) 2008 Marcin Bachry
+;; Copyright (C) 2009 Alexey Voinov
+;; Copyright (C) 2009 John Wiegley
+;;
+;; Magit 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 3, or (at your option)
+;; any later version.
+;;
+;; Magit 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 Magit. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary
+
+;; Invoking the magit-status function will show a buffer with the
+;; status of the current git repository and its working tree. That
+;; buffer offers key bindings for manipulating the status in simple
+;; ways.
+;;
+;; The status buffer mainly shows the difference between the working
+;; tree and the index, and the difference between the index and the
+;; current HEAD. You can add individual hunks from the working tree
+;; to the index, and you can commit the index.
+;;
+;; See the Magit User Manual for more information.
+
+;;; TODO
+
+;; For 0.8:
+;;
+;; - Fix display of unmerged files.
+;; - Fix performance problems with large status buffers.
+;; - Handle the case where remote and local branches have different names.
+;;
+;; Later:
+;;
+;; - Queuing of asynchronous commands.
+;; - Good email integration.
+;; - Showing tags.
+;; - Visiting from staged hunks doesn't always work since the line
+;; numbers don't refer to the working tree. Fix that somehow.
+;; - Figure out how to discard staged changes for files that also have
+;; unstaged changes.
+;; - Get current defun from removed lines in a diff
+;; - Amending commits other than HEAD.
+;; - 'Subsetting', only looking at a subset of all files.
+
+(require 'cl)
+(require 'parse-time)
+(require 'log-edit)
+(require 'easymenu)
+(require 'diff-mode)
+
+(defgroup magit nil
+ "Controlling Git from Emacs."
+ :prefix "magit-"
+ :group 'tools)
+
+(defcustom magit-git-executable "git"
+ "The name of the Git executable."
+ :group 'magit
+ :type 'string)
+
+(defcustom magit-git-standard-options '("--no-pager")
+ "Standard options when running Git."
+ :group 'magit
+ :type '(repeat string))
+
+(defcustom magit-repo-dirs nil
+ "Directories containing Git repositories.
+Magit will look into these directories for Git repositories and offers them as choices for magit-status."
+ :group 'magit
+ :type '(repeat string))
+
+(defcustom magit-repo-dirs-depth 3
+ "When looking for Git repositors below the directories in magit-repo-dirs, Magit will only descend this many levels deep."
+ :group 'magit
+ :type 'integer)
+
+(defcustom magit-save-some-buffers t
+ "Non-nil means that \\[magit-status] will save modified buffers before running.
+Setting this to t will ask which buffers to save, setting it to 'dontask will
+save all modified buffers without asking."
+ :group 'magit
+ :type '(choice (const :tag "Never" nil)
+ (const :tag "Ask" t)
+ (const :tag "Save without asking" dontask)))
+
+(defcustom magit-commit-all-when-nothing-staged 'ask
+ "Determines what \\[magit-log-edit] does when nothing is staged.
+Setting this to nil will make it do nothing, setting it to t will arrange things so that the actual commit command will use the \"--all\" option, setting it to 'ask will first ask for confirmation whether to do this, and setting it to 'ask-stage will cause all changes to be staged, after a confirmation."
+ :group 'magit
+ :type '(choice (const :tag "No" nil)
+ (const :tag "Always" t)
+ (const :tag "Ask" ask)
+ (const :tag "Ask to stage everything" ask-stage)))
+
+(defcustom magit-commit-signoff nil
+ "When performing git commit adds --signoff"
+ :group 'magit
+ :type 'boolean)
+
+(defcustom magit-log-cutoff-length 100
+ "The maximum number of commits to show in the log and whazzup buffers"
+ :group 'magit
+ :type 'integer)
+
+(defcustom magit-process-popup-time -1
+ "Popup the process buffer if a command takes longer than this many seconds."
+ :group 'magit
+ :type '(choice (const :tag "Never" -1)
+ (const :tag "Immediately" 0)
+ (integer :tag "After this many seconds")))
+
+(defcustom magit-log-edit-confirm-cancellation nil
+ "Require acknowledgement before cancelling the log edit buffer."
+ :group 'magit
+ :type 'boolean)
+
+(defface magit-header
+ '((t))
+ "Face for generic header lines.
+
+Many Magit faces inherit from this one by default."
+ :group 'magit)
+
+(defface magit-section-title
+ '((t :weight bold :inherit magit-header))
+ "Face for section titles."
+ :group 'magit)
+
+(defface magit-branch
+ '((t :weight bold :inherit magit-header))
+ "Face for the current branch."
+ :group 'magit)
+
+(defface magit-diff-file-header
+ '((t :inherit magit-header))
+ "Face for diff file header lines."
+ :group 'magit)
+
+(defface magit-diff-hunk-header
+ '((t :slant italic :inherit magit-header))
+ "Face for diff hunk header lines."
+ :group 'magit)
+
+(defface magit-diff-add
+ '((((class color) (background light))
+ :foreground "blue1")
+ (((class color) (background dark))
+ :foreground "white"))
+ "Face for lines in a diff that have been added."
+ :group 'magit)
+
+(defface magit-diff-none
+ '((t))
+ "Face for lines in a diff that are unchanged."
+ :group 'magit)
+
+(defface magit-diff-del
+ '((((class color) (background light))
+ :foreground "red")
+ (((class color) (background dark))
+ :foreground "OrangeRed"))
+ "Face for lines in a diff that have been deleted."
+ :group 'magit)
+
+(defface magit-item-highlight
+ '((((class color) (background light))
+ :background "gray95")
+ (((class color) (background dark))
+ :background "dim gray"))
+ "Face for highlighting the current item."
+ :group 'magit)
+
+(defface magit-item-mark
+ '((((class color) (background light))
+ :foreground "red")
+ (((class color) (background dark))
+ :foreground "orange"))
+ "Face for highlighting marked item."
+ :group 'magit)
+
+(defface magit-log-tag-label
+ '((((class color) (background light))
+ :background "LightGoldenRod")
+ (((class color) (background dark))
+ :background "DarkGoldenRod"))
+ "Face for git tag labels shown in log buffer."
+ :group 'magit)
+
+(defface magit-log-head-label
+ '((((class color) (background light))
+ :background "spring green")
+ (((class color) (background dark))
+ :background "DarkGreen"))
+ "Face for branch head labels shown in log buffer."
+ :group 'magit)
+
+;;; Macros
+
+(defmacro magit-with-refresh (&rest body)
+ (declare (indent 0))
+ `(magit-refresh-wrapper (lambda () ,@body)))
+
+;;; Utilities
+
+(defun magit-use-region-p ()
+ (if (fboundp 'use-region-p)
+ (use-region-p)
+ (and transient-mark-mode mark-active)))
+
+(defun magit-goto-line (line)
+ ;; Like goto-line but doesn't set the mark.
+ (save-restriction
+ (widen)
+ (goto-char 1)
+ (forward-line (1- line))))
+
+(defun magit-trim-line (str)
+ (if (string= str "")
+ nil
+ (if (equal (elt str (- (length str) 1)) ?\n)
+ (substring str 0 (- (length str) 1))
+ str)))
+
+(defun magit-split-lines (str)
+ (if (string= str "")
+ nil
+ (let ((lines (nreverse (split-string str "\n"))))
+ (if (string= (car lines) "")
+ (setq lines (cdr lines)))
+ (nreverse lines))))
+
+(defun magit-git-insert (args)
+ (apply #'process-file
+ magit-git-executable
+ nil (list t nil) nil
+ (append magit-git-standard-options args)))
+
+(defun magit-git-output (args)
+ (with-output-to-string
+ (with-current-buffer
+ standard-output
+ (magit-git-insert args))))
+
+(defun magit-git-string (&rest args)
+ (magit-trim-line (magit-git-output args)))
+
+(defun magit-git-lines (&rest args)
+ (magit-split-lines (magit-git-output args)))
+
+(defun magit-git-exit-code (&rest args)
+ (apply #'process-file magit-git-executable nil nil nil
+ (append magit-git-standard-options args)))
+
+(defun magit-file-lines (file)
+ (when (file-exists-p file)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (let ((rev (nreverse (split-string (buffer-string) "\n"))))
+ (nreverse (if (equal (car rev) "")
+ (cdr rev)
+ rev))))))
+
+(defun magit-write-file-lines (file lines)
+ (with-temp-buffer
+ (dolist (l lines)
+ (insert l "\n"))
+ (write-file file)))
+
+(defun magit-concat-with-delim (delim seqs)
+ (cond ((null seqs)
+ nil)
+ ((null (cdr seqs))
+ (car seqs))
+ (t
+ (concat (car seqs) delim (magit-concat-with-delim delim (cdr seqs))))))
+
+(defun magit-get (&rest keys)
+ (magit-git-string "config" (magit-concat-with-delim "." keys)))
+
+(defun magit-set (val &rest keys)
+ (if val
+ (magit-git-string "config" (magit-concat-with-delim "." keys) val)
+ (magit-git-string "config" "--unset" (magit-concat-with-delim "." keys))))
+
+(defun magit-remove-conflicts (alist)
+ (let ((dict (make-hash-table :test 'equal))
+ (result nil))
+ (dolist (a alist)
+ (puthash (car a) (cons (cdr a) (gethash (car a) dict))
+ dict))
+ (maphash (lambda (key value)
+ (if (= (length value) 1)
+ (push (cons key (car value)) result)
+ (let ((sub (magit-remove-conflicts
+ (mapcar (lambda (entry)
+ (let ((dir (directory-file-name
+ (subseq entry 0 (- (length key))))))
+ (cons (concat (file-name-nondirectory dir) "/" key)
+ entry)))
+ value))))
+ (setq result (append result sub)))))
+ dict)
+ result))
+
+(defun magit-git-repo-p (dir)
+ (file-exists-p (expand-file-name ".git" dir)))
+
+(defun magit-list-repos* (dir level)
+ (if (magit-git-repo-p dir)
+ (list dir)
+ (apply #'append
+ (mapcar (lambda (entry)
+ (unless (or (string= (substring entry -3) "/..")
+ (string= (substring entry -2) "/."))
+ (magit-list-repos* entry (+ level 1))))
+ (and (file-directory-p dir)
+ (< level magit-repo-dirs-depth)
+ (directory-files dir t nil t))))))
+
+(defun magit-list-repos (dirs)
+ (magit-remove-conflicts
+ (apply #'append
+ (mapcar (lambda (dir)
+ (mapcar #'(lambda (repo)
+ (cons (file-name-nondirectory repo)
+ repo))
+ (magit-list-repos* dir 0)))
+ dirs))))
+
+(defun magit-get-top-dir (cwd)
+ (let ((cwd (expand-file-name cwd)))
+ (and (file-directory-p cwd)
+ (let* ((default-directory cwd)
+ (magit-dir
+ (magit-git-string "rev-parse" "--git-dir")))
+ (and magit-dir
+ (file-name-as-directory
+ (or (file-name-directory magit-dir) cwd)))))))
+
+(defun magit-get-ref (ref)
+ (magit-git-string "symbolic-ref" "-q" ref))
+
+(defun magit-get-current-branch ()
+ (let* ((head (magit-get-ref "HEAD"))
+ (pos (and head (string-match "^refs/heads/" head))))
+ (if pos
+ (substring head 11)
+ nil)))
+
+(defun magit-ref-exists-p (ref)
+ (= (magit-git-exit-code "show-ref" "--verify" ref) 0))
+
+(defun magit-read-top-dir (rawp)
+ (if (and (not rawp) magit-repo-dirs)
+ (let* ((repos (magit-list-repos magit-repo-dirs))
+ (reply (completing-read "Git repository: "
+ (magit-list-repos magit-repo-dirs))))
+ (file-name-as-directory
+ (cdr (assoc reply repos))))
+ (file-name-as-directory
+ (read-directory-name "Git repository: "
+ (or (magit-get-top-dir default-directory)
+ default-directory)))))
+
+(defun magit-name-rev (rev)
+ (and rev
+ (let ((name (magit-git-string "name-rev" "--name-only" rev)))
+ (if (or (not name) (string= name "undefined"))
+ rev
+ name))))
+
+(defun magit-put-line-property (prop val)
+ (put-text-property (line-beginning-position) (line-beginning-position 2)
+ prop val))
+
+(defun magit-format-commit (commit format)
+ (magit-git-string "log" "--max-count=1"
+ (concat "--pretty=format:" format)
+ commit))
+
+(defun magit-current-line ()
+ (buffer-substring-no-properties (line-beginning-position)
+ (line-end-position)))
+
+(defun magit-insert-region (beg end buf)
+ (let ((text (buffer-substring-no-properties beg end)))
+ (with-current-buffer buf
+ (insert text))))
+
+(defun magit-insert-current-line (buf)
+ (let ((text (buffer-substring-no-properties
+ (line-beginning-position) (line-beginning-position 2))))
+ (with-current-buffer buf
+ (insert text))))
+
+(defun magit-file-uptodate-p (file)
+ (eq (magit-git-exit-code "diff" "--quiet" "--" file) 0))
+
+(defun magit-anything-staged-p ()
+ (not (eq (magit-git-exit-code "diff" "--quiet" "--cached") 0)))
+
+(defun magit-everything-clean-p ()
+ (and (not (magit-anything-staged-p))
+ (eq (magit-git-exit-code "diff" "--quiet") 0)))
+
+(defun magit-commit-parents (commit)
+ (cdr (split-string (magit-git-string "rev-list" "-1" "--parents" commit))))
+
+;; XXX - let the user choose the parent
+
+(defun magit-choose-parent-id (commit op)
+ (let* ((parents (magit-commit-parents commit)))
+ (if (> (length parents) 1)
+ (error "Can't %s merge commits." op)
+ nil)))
+
+;;; Revisions and ranges
+
+(defun magit-list-interesting-refs ()
+ (let ((refs ()))
+ (dolist (line (magit-git-lines "show-ref"))
+ (if (string-match "[^ ]+ +\\(.*\\)" line)
+ (let ((ref (match-string 1 line)))
+ (cond ((string-match "refs/heads/\\(.*\\)" ref)
+ (let ((branch (match-string 1 ref)))
+ (push (cons branch branch) refs)))
+ ((string-match "refs/tags/\\(.*\\)" ref)
+ (push (cons (format "%s (tag)" (match-string 1 ref)) ref)
+ refs))
+ ((string-match "refs/remotes/\\([^/]+\\)/\\(.+\\)" ref)
+ (push (cons (format "%s (%s)"
+ (match-string 2 ref)
+ (match-string 1 ref))
+ ref)
+ refs))))))
+ refs))
+
+(defun magit-read-rev (prompt &optional def)
+ (let* ((prompt (if def
+ (format "%s (default %s): " prompt def)
+ (format "%s: " prompt)))
+ (interesting-refs (magit-list-interesting-refs))
+ (reply (completing-read prompt interesting-refs
+ nil nil nil nil def))
+ (rev (or (cdr (assoc reply interesting-refs)) reply)))
+ (if (string= rev "")
+ nil
+ rev)))
+
+(defun magit-read-rev-range (op &optional def-beg def-end)
+ (let ((beg (magit-read-rev (format "%s start" op)
+ def-beg)))
+ (if (not beg)
+ nil
+ (let ((end (magit-read-rev (format "%s end" op) def-end)))
+ (cons beg end)))))
+
+(defun magit-rev-to-git (rev)
+ (or rev
+ (error "No revision specified"))
+ (if (string= rev ".")
+ (magit-marked-commit)
+ rev))
+
+(defun magit-rev-range-to-git (range)
+ (or range
+ (error "No revision range specified"))
+ (if (stringp range)
+ range
+ (if (cdr range)
+ (format "%s..%s"
+ (magit-rev-to-git (car range))
+ (magit-rev-to-git (cdr range)))
+ (format "%s" (magit-rev-to-git (car range))))))
+
+(defun magit-rev-describe (rev)
+ (or rev
+ (error "No revision specified"))
+ (if (string= rev ".")
+ "mark"
+ (magit-name-rev rev)))
+
+(defun magit-rev-range-describe (range things)
+ (or range
+ (error "No revision range specified"))
+ (if (stringp range)
+ (format "%s in %s" things range)
+ (if (cdr range)
+ (format "%s from %s to %s" things
+ (magit-rev-describe (car range))
+ (magit-rev-describe (cdr range)))
+ (format "%s at %s" things (magit-rev-describe (car range))))))
+
+(defun magit-default-rev ()
+ (magit-name-rev (magit-commit-at-point t)))
+
+;;; Sections
+
+;; A buffer in magit-mode is organized into hierarchical sections.
+;; These sections are used for navigation and for hiding parts of the
+;; buffer.
+;;
+;; Most sections also represent the objects that Magit works with,
+;; such as files, diffs, hunks, commits, etc. The 'type' of a section
+;; identifies what kind of object it represents (if any), and the
+;; parent and grand-parent, etc provide the context.
+
+(defstruct magit-section
+ parent title beginning end children hidden type info
+ needs-refresh-on-show)
+
+(defvar magit-top-section nil)
+(make-variable-buffer-local 'magit-top-section)
+(put 'magit-top-section 'permanent-local t)
+
+(defvar magit-old-top-section nil)
+
+(defvar magit-section-hidden-default nil)
+
+(defun magit-new-section (title type)
+ (let* ((s (make-magit-section :parent magit-top-section
+ :title title
+ :type type
+ :hidden magit-section-hidden-default))
+ (old (and magit-old-top-section
+ (magit-find-section (magit-section-path s)
+ magit-old-top-section))))
+ (if magit-top-section
+ (setf (magit-section-children magit-top-section)
+ (cons s (magit-section-children magit-top-section)))
+ (setq magit-top-section s))
+ (if old
+ (setf (magit-section-hidden s) (magit-section-hidden old)))
+ s))
+
+(defun magit-cancel-section (section)
+ (delete-region (magit-section-beginning section)
+ (magit-section-end section))
+ (let ((parent (magit-section-parent section)))
+ (if parent
+ (setf (magit-section-children parent)
+ (delq section (magit-section-children parent)))
+ (setq magit-top-section nil))))
+
+(defmacro magit-with-section (title type &rest body)
+ (declare (indent 2))
+ (let ((s (gensym)))
+ `(let* ((,s (magit-new-section ,title ,type))
+ (magit-top-section ,s))
+ (setf (magit-section-beginning ,s) (point))
+ ,@body
+ (setf (magit-section-end ,s) (point))
+ (setf (magit-section-children ,s)
+ (nreverse (magit-section-children ,s)))
+ ,s)))
+
+(defun magit-set-section-info (info &optional section)
+ (setf (magit-section-info (or section magit-top-section)) info))
+
+(defun magit-set-section-needs-refresh-on-show (flag &optional section)
+ (setf (magit-section-needs-refresh-on-show
+ (or section magit-top-section))
+ flag))
+
+(defmacro magit-create-buffer-sections (&rest body)
+ (declare (indent 0))
+ `(let ((inhibit-read-only t))
+ (erase-buffer)
+ (let ((magit-old-top-section magit-top-section))
+ (setq magit-top-section nil)
+ ,@body
+ (when (null magit-top-section)
+ (magit-with-section 'top nil
+ (insert "(empty)\n")))
+ (magit-propertize-section magit-top-section)
+ (magit-section-set-hidden magit-top-section
+ (magit-section-hidden magit-top-section)))))
+
+(defun magit-propertize-section (section)
+ (put-text-property (magit-section-beginning section)
+ (magit-section-end section)
+ 'magit-section section)
+ (dolist (s (magit-section-children section))
+ (magit-propertize-section s)))
+
+(defun magit-find-section (path top)
+ (if (null path)
+ top
+ (let ((sec (find-if (lambda (s) (equal (car path)
+ (magit-section-title s)))
+ (magit-section-children top))))
+ (if sec
+ (magit-find-section (cdr path) sec)
+ nil))))
+
+(defun magit-section-path (section)
+ (if (not (magit-section-parent section))
+ '()
+ (append (magit-section-path (magit-section-parent section))
+ (list (magit-section-title section)))))
+
+(defun magit-find-section-at (pos secs)
+ (while (and secs
+ (not (and (<= (magit-section-beginning (car secs)) pos)
+ (< pos (magit-section-end (car secs))))))
+ (setq secs (cdr secs)))
+ (if secs
+ (or (magit-find-section-at pos (magit-section-children (car secs)))
+ (car secs))
+ nil))
+
+(defun magit-find-section-after (pos secs)
+ (while (and secs
+ (not (> (magit-section-beginning (car secs)) pos)))
+ (setq secs (cdr secs)))
+ (car secs))
+
+(defun magit-find-section-before (pos secs)
+ (let ((prev nil))
+ (while (and secs
+ (not (> (magit-section-beginning (car secs)) pos)))
+ (setq prev (car secs))
+ (setq secs (cdr secs)))
+ prev))
+
+(defun magit-current-section ()
+ (or (get-text-property (point) 'magit-section)
+ magit-top-section))
+
+(defun magit-insert-section (section-title-and-type
+ buffer-title washer cmd &rest args)
+ (let* ((body-beg nil)
+ (section-title (if (consp section-title-and-type)
+ (car section-title-and-type)
+ section-title-and-type))
+ (section-type (if (consp section-title-and-type)
+ (cdr section-title-and-type)
+ nil))
+ (section
+ (magit-with-section section-title section-type
+ (if buffer-title
+ (insert (propertize buffer-title 'face 'magit-section-title)
+ "\n"))
+ (setq body-beg (point))
+ (apply 'process-file cmd nil t nil (append magit-git-standard-options args))
+ (if (not (eq (char-before) ?\n))
+ (insert "\n"))
+ (if washer
+ (save-restriction
+ (narrow-to-region body-beg (point))
+ (goto-char (point-min))
+ (funcall washer)
+ (goto-char (point-max)))))))
+ (if (= body-beg (point))
+ (magit-cancel-section section)
+ (insert "\n"))
+ section))
+
+(defun magit-git-section (section-title-and-type
+ buffer-title washer &rest args)
+ (apply #'magit-insert-section
+ section-title-and-type
+ buffer-title
+ washer
+ magit-git-executable
+ (append magit-git-standard-options args)))
+
+(defun magit-next-section (section)
+ (let ((parent (magit-section-parent section)))
+ (if parent
+ (let ((next (cadr (memq section
+ (magit-section-children parent)))))
+ (or next
+ (magit-next-section parent))))))
+
+(defun magit-goto-next-section ()
+ (interactive)
+ (let* ((section (magit-current-section))
+ (next (or (and (not (magit-section-hidden section))
+ (magit-section-children section)
+ (magit-find-section-after (point)
+ (magit-section-children
+ section)))
+ (magit-next-section section))))
+
+ (if next
+ (progn
+ (goto-char (magit-section-beginning next))
+ (if (memq magit-submode '(log reflog))
+ (magit-show-commit next))
+ (if (not (magit-section-hidden next))
+ (let ((offset (- (line-number-at-pos
+ (magit-section-beginning next))
+ (line-number-at-pos
+ (magit-section-end next)))))
+ (if (< offset (window-height))
+ (recenter offset)))))
+ (message "No next section"))))
+
+(defun magit-prev-section (section)
+ (let ((parent (magit-section-parent section)))
+ (if parent
+ (let ((prev (cadr (memq section
+ (reverse (magit-section-children parent))))))
+ (cond (prev
+ (while (and (not (magit-section-hidden prev))
+ (magit-section-children prev))
+ (setq prev (car (reverse (magit-section-children prev)))))
+ prev)
+ (t
+ parent))))))
+
+(defun magit-goto-previous-section ()
+ (interactive)
+ (let ((section (magit-current-section)))
+ (cond ((= (point) (magit-section-beginning section))
+ (let ((prev (magit-prev-section (magit-current-section))))
+ (if prev
+ (progn
+ (if (memq magit-submode '(log reflog))
+ (magit-show-commit (or prev section)))
+ (goto-char (magit-section-beginning prev)))
+ (message "No previous section"))))
+ (t
+ (let ((prev (magit-find-section-before (point)
+ (magit-section-children
+ section))))
+ (if (memq magit-submode '(log reflog))
+ (magit-show-commit (or prev section)))
+ (goto-char (magit-section-beginning (or prev section))))))))
+
+(defun magit-goto-section (path)
+ (let ((sec (magit-find-section path magit-top-section)))
+ (if sec
+ (goto-char (magit-section-beginning sec))
+ (message "No such section"))))
+
+(defun magit-for-all-sections (func &optional top)
+ (let ((section (or top magit-top-section)))
+ (when section
+ (funcall func section)
+ (dolist (c (magit-section-children section))
+ (magit-for-all-sections func c)))))
+
+(defun magit-section-set-hidden (section hidden)
+ (setf (magit-section-hidden section) hidden)
+ (if (and (not hidden)
+ (magit-section-needs-refresh-on-show section))
+ (magit-refresh)
+ (let ((inhibit-read-only t)
+ (beg (save-excursion
+ (goto-char (magit-section-beginning section))
+ (forward-line)
+ (point)))
+ (end (magit-section-end section)))
+ (put-text-property beg end 'invisible hidden))
+ (if (not hidden)
+ (dolist (c (magit-section-children section))
+ (magit-section-set-hidden c (magit-section-hidden c))))))
+
+(defun magit-section-any-hidden (section)
+ (or (magit-section-hidden section)
+ (some #'magit-section-any-hidden (magit-section-children section))))
+
+(defun magit-section-collapse (section)
+ (dolist (c (magit-section-children section))
+ (setf (magit-section-hidden c) t))
+ (magit-section-set-hidden section nil))
+
+(defun magit-section-expand (section)
+ (dolist (c (magit-section-children section))
+ (setf (magit-section-hidden c) nil))
+ (magit-section-set-hidden section nil))
+
+(defun magit-section-expand-all-aux (section)
+ (dolist (c (magit-section-children section))
+ (setf (magit-section-hidden c) nil)
+ (magit-section-expand-all-aux c)))
+
+(defun magit-section-expand-all (section)
+ (magit-section-expand-all-aux section)
+ (magit-section-set-hidden section nil))
+
+(defun magit-section-hideshow (flag-or-func)
+ (let ((section (magit-current-section)))
+ (cond ((magit-section-parent section)
+ (goto-char (magit-section-beginning section))
+ (if (functionp flag-or-func)
+ (funcall flag-or-func section)
+ (magit-section-set-hidden section flag-or-func))))))
+
+(defun magit-show-section ()
+ (interactive)
+ (magit-section-hideshow nil))
+
+(defun magit-hide-section ()
+ (interactive)
+ (magit-section-hideshow t))
+
+(defun magit-collapse-section ()
+ (interactive)
+ (magit-section-hideshow #'magit-section-collapse))
+
+(defun magit-expand-section ()
+ (interactive)
+ (magit-section-hideshow #'magit-section-expand))
+
+(defun magit-toggle-section ()
+ (interactive)
+ (magit-section-hideshow
+ (lambda (s)
+ (magit-section-set-hidden s (not (magit-section-hidden s))))))
+
+(defun magit-expand-collapse-section ()
+ (interactive)
+ (magit-section-hideshow
+ (lambda (s)
+ (cond ((magit-section-any-hidden s)
+ (magit-section-expand-all s))
+ (t
+ (magit-section-collapse s))))))
+
+(defun magit-cycle-section ()
+ (interactive)
+ (magit-section-hideshow
+ (lambda (s)
+ (cond ((magit-section-hidden s)
+ (magit-section-collapse s))
+ ((notany #'magit-section-hidden (magit-section-children s))
+ (magit-section-set-hidden s t))
+ (t
+ (magit-section-expand s))))))
+
+(defun magit-section-lineage (s)
+ (and s (cons s (magit-section-lineage (magit-section-parent s)))))
+
+(defun magit-section-show-level (section level threshold path)
+ (magit-section-set-hidden section (>= level threshold))
+ (when (< level threshold)
+ (if path
+ (magit-section-show-level (car path) (1+ level) threshold (cdr path))
+ (dolist (c (magit-section-children section))
+ (magit-section-show-level c (1+ level) threshold nil)))))
+
+(defun magit-show-level (level all)
+ (magit-with-refresh
+ (if all
+ (magit-section-show-level magit-top-section 0 level nil)
+ (let ((path (reverse (magit-section-lineage (magit-current-section)))))
+ (magit-section-show-level (car path) 0 level (cdr path))))))
+
+(defun magit-show-only-files ()
+ (interactive)
+ (if (eq magit-submode 'status)
+ (call-interactively 'magit-show-level-2)
+ (call-interactively 'magit-show-level-1)))
+
+(defun magit-show-only-files-all ()
+ (interactive)
+ (if (eq magit-submode 'status)
+ (call-interactively 'magit-show-level-2-all)
+ (call-interactively 'magit-show-level-1-all)))
+
+(defmacro magit-define-level-shower-1 (level all)
+ (let ((fun (intern (format "magit-show-level-%s%s"
+ level (if all "-all" ""))))
+ (doc (format "Show sections on level %s." level)))
+ `(defun ,fun ()
+ ,doc
+ (interactive)
+ (magit-show-level ,level ,all))))
+
+(defmacro magit-define-level-shower (level)
+ `(progn
+ (magit-define-level-shower-1 ,level nil)
+ (magit-define-level-shower-1 ,level t)))
+
+(defmacro magit-define-section-jumper (sym title)
+ (let ((fun (intern (format "magit-jump-to-%s" sym)))
+ (doc (format "Jump to section `%s'." title)))
+ `(defun ,fun ()
+ ,doc
+ (interactive)
+ (magit-goto-section '(,sym)))))
+
+(defvar magit-highlight-overlay nil)
+
+(defvar magit-highlighted-section nil)
+
+(defun magit-highlight-section ()
+ (let ((section (magit-current-section)))
+ (when (not (eq section magit-highlighted-section))
+ (setq magit-highlighted-section section)
+ (if (not magit-highlight-overlay)
+ (let ((ov (make-overlay 1 1)))
+ (overlay-put ov 'face 'magit-item-highlight)
+ (setq magit-highlight-overlay ov)))
+ (if (and section (magit-section-type section))
+ (move-overlay magit-highlight-overlay
+ (magit-section-beginning section)
+ (magit-section-end section)
+ (current-buffer))
+ (delete-overlay magit-highlight-overlay)))))
+
+(defun magit-section-context-type (section)
+ (if (null section)
+ '()
+ (let ((c (or (magit-section-type section)
+ (if (symbolp (magit-section-title section))
+ (magit-section-title section)))))
+ (if c
+ (cons c (magit-section-context-type
+ (magit-section-parent section)))
+ '()))))
+
+(defun magit-prefix-p (prefix list)
+ ;;; Very schemish...
+ (or (null prefix)
+ (if (eq (car prefix) '*)
+ (or (magit-prefix-p (cdr prefix) list)
+ (and (not (null list))
+ (magit-prefix-p prefix (cdr list))))
+ (and (not (null list))
+ (equal (car prefix) (car list))
+ (magit-prefix-p (cdr prefix) (cdr list))))))
+
+(defmacro magit-section-case (head &rest clauses)
+ (declare (indent 1))
+ (let ((section (car head))
+ (info (cadr head))
+ (type (gensym))
+ (context (gensym))
+ (opname (caddr head)))
+ `(let* ((,section (magit-current-section))
+ (,info (magit-section-info ,section))
+ (,type (magit-section-type ,section))
+ (,context (magit-section-context-type ,section)))
+ (cond ,@(mapcar (lambda (clause)
+ (if (eq (car clause) t)
+ clause
+ (let ((prefix (reverse (car clause)))
+ (body (cdr clause)))
+ `((magit-prefix-p ',prefix ,context)
+ ,@body))))
+ clauses)
+ ,@(if opname
+ `(((not ,type)
+ (error "Nothing to %s here." ,opname))
+ (t
+ (error "Can't %s a %s."
+ ,opname
+ (or (get ,type 'magit-description)
+ ,type)))))))))
+
+(defmacro magit-section-action (head &rest clauses)
+ (declare (indent 1))
+ `(magit-with-refresh
+ (magit-section-case ,head ,@clauses)))
+
+(defun magit-wash-sequence (func)
+ (while (and (not (eobp))
+ (funcall func))))
+
+;;; Running commands
+
+(defun magit-set-mode-line-process (str)
+ (let ((pr (if str (concat " " str) "")))
+ (save-excursion
+ (magit-for-all-buffers (lambda ()
+ (setq mode-line-process pr))))))
+
+(defun magit-process-indicator-from-command (comps)
+ (if (magit-prefix-p (cons magit-git-executable magit-git-standard-options)
+ comps)
+ (setq comps (nthcdr (+ (length magit-git-standard-options) 1) comps)))
+ (cond ((or (null (cdr comps))
+ (not (member (car comps) '("remote"))))
+ (car comps))
+ (t
+ (concat (car comps) " " (cadr comps)))))
+
+(defvar magit-process nil)
+(defvar magit-process-client-buffer nil)
+
+(defun magit-run* (cmd-and-args
+ &optional logline noerase noerror nowait input)
+ (if (and magit-process
+ (get-buffer "*magit-process*"))
+ (error "Git is already running."))
+ (let ((cmd (car cmd-and-args))
+ (args (cdr cmd-and-args))
+ (dir default-directory)
+ (buf (get-buffer-create "*magit-process*"))
+ (successp nil))
+ (magit-set-mode-line-process
+ (magit-process-indicator-from-command cmd-and-args))
+ (setq magit-process-client-buffer (current-buffer))
+ (save-excursion
+ (set-buffer buf)
+ (setq buffer-read-only t)
+ (let ((inhibit-read-only t))
+ (setq default-directory dir)
+ (if noerase
+ (goto-char (point-max))
+ (erase-buffer))
+ (insert "$ " (or logline
+ (magit-concat-with-delim " " cmd-and-args))
+ "\n")
+ (cond (nowait
+ (setq magit-process
+ (apply 'start-file-process cmd buf cmd args))
+ (set-process-sentinel magit-process 'magit-process-sentinel)
+ (set-process-filter magit-process 'magit-process-filter)
+ (when input
+ (with-current-buffer input
+ (process-send-region magit-process
+ (point-min) (point-max)))
+ (process-send-eof magit-process)
+ (sit-for 0.1 t))
+ (cond ((= magit-process-popup-time 0)
+ (pop-to-buffer (process-buffer magit-process)))
+ ((> magit-process-popup-time 0)
+ (run-with-timer
+ magit-process-popup-time nil
+ (function
+ (lambda (buf)
+ (with-current-buffer buf
+ (when magit-process
+ (display-buffer (process-buffer magit-process))
+ (goto-char (point-max))))))
+ (current-buffer))))
+ (setq successp t))
+ (input
+ (with-current-buffer input
+ (setq default-directory dir)
+ (setq successp
+ (equal (apply 'call-process-region
+ (point-min) (point-max)
+ cmd nil buf nil args) 0)))
+ (magit-set-mode-line-process nil)
+ (magit-need-refresh magit-process-client-buffer))
+ (t
+ (setq successp
+ (equal (apply 'process-file cmd nil buf nil args) 0))
+ (magit-set-mode-line-process nil)
+ (magit-need-refresh magit-process-client-buffer))))
+ (or successp
+ noerror
+ (error "Git failed."))
+ successp)))
+
+(defun magit-process-sentinel (process event)
+ (let ((msg (format "Git %s." (substring event 0 -1)))
+ (successp (string-match "^finished" event)))
+ (with-current-buffer (process-buffer process)
+ (let ((inhibit-read-only t))
+ (goto-char (point-max))
+ (insert msg "\n")
+ (message msg)))
+ (setq magit-process nil)
+ (magit-set-mode-line-process nil)
+ (magit-refresh-buffer magit-process-client-buffer)))
+
+(defun magit-process-filter (proc string)
+ (save-current-buffer
+ (set-buffer (process-buffer proc))
+ (let ((inhibit-read-only t))
+ (goto-char (process-mark proc))
+ ;; Find last ^M in string. If one was found, ignore everything
+ ;; before it and delete the current line.
+ (let ((ret-pos (position ?\r string :from-end t)))
+ (cond (ret-pos
+ (goto-char (line-beginning-position))
+ (delete-region (point) (line-end-position))
+ (insert (substring string (+ ret-pos 1))))
+ (t
+ (insert string))))
+ (set-marker (process-mark proc) (point)))))
+
+(defun magit-run (cmd &rest args)
+ (magit-with-refresh
+ (magit-run* (cons cmd args))))
+
+(defun magit-run-git (&rest args)
+ (magit-with-refresh
+ (magit-run* (append (cons magit-git-executable
+ magit-git-standard-options)
+ args))))
+
+(defun magit-run-with-input (input cmd &rest args)
+ (magit-with-refresh
+ (magit-run* (cons cmd args) nil nil nil nil input)))
+
+(defun magit-run-git-with-input (input &rest args)
+ (magit-with-refresh
+ (magit-run* (append (cons magit-git-executable
+ magit-git-standard-options)
+ args)
+ nil nil nil nil input)))
+
+(defun magit-run-git-async (&rest args)
+ (magit-run* (append (cons magit-git-executable
+ magit-git-standard-options)
+ args)
+ nil nil nil t))
+
+(defun magit-run-async-with-input (input cmd &rest args)
+ (magit-run* (cons cmd args) nil nil nil t input))
+
+(defun magit-display-process ()
+ (interactive)
+ (display-buffer "*magit-process*"))
+
+;;; Mode
+
+;; We define individual functions (instead of using lambda etc) so
+;; that the online help can show something meaningful.
+
+(magit-define-section-jumper untracked "Untracked files")
+(magit-define-section-jumper unstaged "Unstaged changes")
+(magit-define-section-jumper staged "Staged changes")
+(magit-define-section-jumper unpushed "Unpushed commits")
+(magit-define-section-jumper svn-unpushed "Unpushed commits (SVN)")
+
+(magit-define-level-shower 1)
+(magit-define-level-shower 2)
+(magit-define-level-shower 3)
+(magit-define-level-shower 4)
+
+(defvar magit-mode-map
+ (let ((map (make-keymap)))
+ (suppress-keymap map t)
+ (define-key map (kbd "n") 'magit-goto-next-section)
+ (define-key map (kbd "p") 'magit-goto-previous-section)
+ (define-key map (kbd "TAB") 'magit-toggle-section)
+ (define-key map (kbd "<backtab>") 'magit-expand-collapse-section)
+ (define-key map (kbd "1") 'magit-show-level-1)
+ (define-key map (kbd "2") 'magit-show-level-2)
+ (define-key map (kbd "3") 'magit-show-level-3)
+ (define-key map (kbd "4") 'magit-show-level-4)
+ (define-key map (kbd "M-1") 'magit-show-level-1-all)
+ (define-key map (kbd "M-2") 'magit-show-level-2-all)
+ (define-key map (kbd "M-3") 'magit-show-level-3-all)
+ (define-key map (kbd "M-4") 'magit-show-level-4-all)
+ (define-key map (kbd "M-h") 'magit-show-only-files)
+ (define-key map (kbd "M-H") 'magit-show-only-files-all)
+ (define-key map (kbd "M-s") 'magit-show-level-4)
+ (define-key map (kbd "M-S") 'magit-show-level-4-all)
+ (define-key map (kbd "g") 'magit-refresh)
+ (define-key map (kbd "G") 'magit-refresh-all)
+ (define-key map (kbd "s") 'magit-stage-item)
+ (define-key map (kbd "S") 'magit-stage-all)
+ (define-key map (kbd "u") 'magit-unstage-item)
+ (define-key map (kbd "U") 'magit-unstage-all)
+ (define-key map (kbd "i") 'magit-ignore-item)
+ (define-key map (kbd "I") 'magit-ignore-item-locally)
+ (define-key map (kbd "?") 'magit-describe-item)
+ (define-key map (kbd ".") 'magit-mark-item)
+ (define-key map (kbd "=") 'magit-diff-with-mark)
+ (define-key map (kbd "-") 'magit-diff-smaller-hunks)
+ (define-key map (kbd "+") 'magit-diff-larger-hunks)
+ (define-key map (kbd "0") 'magit-diff-default-hunks)
+ (define-key map (kbd "l") 'magit-log)
+ (define-key map (kbd "L") 'magit-log-long)
+ (define-key map (kbd "h") 'magit-reflog-head)
+ (define-key map (kbd "H") 'magit-reflog)
+ (define-key map (kbd "d") 'magit-diff-working-tree)
+ (define-key map (kbd "D") 'magit-diff)
+ (define-key map (kbd "a") 'magit-apply-item)
+ (define-key map (kbd "A") 'magit-cherry-pick-item)
+ (define-key map (kbd "v") 'magit-revert-item)
+ (define-key map (kbd "x") 'magit-reset-head)
+ (define-key map (kbd "X") 'magit-reset-working-tree)
+ (define-key map (kbd "k") 'magit-discard-item)
+ (define-key map (kbd "!") 'magit-shell-command)
+ (define-key map (kbd "RET") 'magit-visit-item)
+ (define-key map (kbd "SPC") 'magit-show-item-or-scroll-up)
+ (define-key map (kbd "DEL") 'magit-show-item-or-scroll-down)
+ (define-key map (kbd "C-w") 'magit-copy-item-as-kill)
+ (define-key map (kbd "b") 'magit-checkout)
+ (define-key map (kbd "B") 'magit-create-branch)
+ (define-key map (kbd "m") 'magit-manual-merge)
+ (define-key map (kbd "M") 'magit-automatic-merge)
+ (define-key map (kbd "e") 'magit-interactive-resolve-item)
+ (define-key map (kbd "N r") 'magit-svn-rebase)
+ (define-key map (kbd "N c") 'magit-svn-dcommit)
+ (define-key map (kbd "R") 'magit-rebase-step)
+ (define-key map (kbd "r s") 'magit-rewrite-start)
+ (define-key map (kbd "r t") 'magit-rewrite-stop)
+ (define-key map (kbd "r a") 'magit-rewrite-abort)
+ (define-key map (kbd "r f") 'magit-rewrite-finish)
+ (define-key map (kbd "r *") 'magit-rewrite-set-unused)
+ (define-key map (kbd "r .") 'magit-rewrite-set-used)
+ (define-key map (kbd "P") 'magit-push)
+ (define-key map (kbd "f") 'magit-remote-update)
+ (define-key map (kbd "F") 'magit-pull)
+ (define-key map (kbd "c") 'magit-log-edit)
+ (define-key map (kbd "C") 'magit-add-log)
+ (define-key map (kbd "t") 'magit-tag)
+ (define-key map (kbd "T") 'magit-annotated-tag)
+ (define-key map (kbd "z") 'magit-stash)
+ (define-key map (kbd "Z") 'magit-stash-snapshot)
+ (define-key map (kbd "w") 'magit-wazzup)
+ (define-key map (kbd "$") 'magit-display-process)
+ (define-key map (kbd "E") 'magit-interactive-rebase)
+ (define-key map (kbd "V") 'magit-show-branches)
+ (define-key map (kbd "q") 'quit-window)
+ map))
+
+(easy-menu-define magit-mode-menu magit-mode-map
+ "Magit menu"
+ '("Magit"
+ ["Refresh" magit-refresh t]
+ ["Refresh all" magit-refresh-all t]
+ "---"
+ ["Stage" magit-stage-item t]
+ ["Stage all" magit-stage-all t]
+ ["Unstage" magit-unstage-item t]
+ ["Unstage all" magit-unstage-all t]
+ ["Commit" magit-log-edit t]
+ ["Add log entry" magit-add-log t]
+ ["Tag" magit-tag t]
+ ["Annotated tag" magit-annotated-tag t]
+ "---"
+ ["Diff working tree" magit-diff-working-tree t]
+ ["Diff" magit-diff t]
+ ["Log" magit-log t]
+ ["Long Log" magit-log-long t]
+ ["Reflog head" magit-reflog-head t]
+ ["Reflog" magit-reflog t]
+ "---"
+ ["Cherry pick" magit-cherry-pick-item t]
+ ["Apply" magit-apply-item t]
+ ["Revert" magit-revert-item t]
+ "---"
+ ["Ignore" magit-ignore-item t]
+ ["Ignore locally" magit-ignore-item-locally t]
+ ["Discard" magit-discard-item t]
+ ["Reset head" magit-reset-head t]
+ ["Reset working tree" magit-reset-working-tree t]
+ ["Stash" magit-stash t]
+ ["Snapshot" magit-stash-snapshot t]
+ "---"
+ ["Switch branch" magit-checkout t]
+ ["Create branch" magit-create-branch t]
+ ["Merge" magit-automatic-merge t]
+ ["Merge (no commit)" magit-manual-merge t]
+ ["Interactive resolve" magit-interactive-resolve-item t]
+ ["Rebase" magit-rebase-step t]
+ ("Git SVN"
+ ["Rebase" magit-svn-rebase (magit-svn-enabled)]
+ ["Commit" magit-svn-dcommit (magit-svn-enabled)]
+ )
+ ("Rewrite"
+ ["Start" magit-rewrite-start t]
+ ["Stop" magit-rewrite-stop t]
+ ["Finish" magit-rewrite-finish t]
+ ["Abort" magit-rewrite-abort t]
+ ["Set used" magit-rewrite-set-used t]
+ ["Set unused" magit-rewrite-set-unused t])
+ "---"
+ ["Push" magit-push t]
+ ["Pull" magit-pull t]
+ ["Remote update" magit-remote-update t]
+ "---"
+ ["Display Git output" magit-display-process t]
+ ["Quit Magit" quit-window t]))
+
+(defvar magit-mode-hook nil)
+
+(put 'magit-mode 'mode-class 'special)
+
+(defvar magit-submode nil)
+(make-variable-buffer-local 'magit-submode)
+(put 'magit-submode 'permanent-local t)
+
+(defvar magit-refresh-function nil)
+(make-variable-buffer-local 'magit-refresh-function)
+(put 'magit-refresh-function 'permanent-local t)
+
+(defvar magit-refresh-args nil)
+(make-variable-buffer-local 'magit-refresh-args)
+(put 'magit-refresh-args 'permanent-local t)
+
+(defvar last-point)
+
+(defun magit-remember-point ()
+ (setq last-point (point)))
+
+(defun magit-invisible-region-end (pos)
+ (while (and (not (= pos (point-max))) (invisible-p pos))
+ (setq pos (next-char-property-change pos)))
+ pos)
+
+(defun magit-invisible-region-start (pos)
+ (while (and (not (= pos (point-min))) (invisible-p pos))
+ (setq pos (1- (previous-char-property-change pos))))
+ pos)
+
+(defun magit-correct-point-after-command ()
+ ;; Emacs often leaves point in invisible regions, it seems. To fix
+ ;; this, we move point ourselves and never let Emacs do its own
+ ;; adjustements.
+ ;;
+ ;; When point has to be moved out of an invisible region, it can be
+ ;; moved to its end or its beginning. We usually move it to its
+ ;; end, except when that would move point back to where it was
+ ;; before the last command.
+ ;;
+ (if (invisible-p (point))
+ (let ((end (magit-invisible-region-end (point))))
+ (goto-char (if (= end last-point)
+ (magit-invisible-region-start (point))
+ end))))
+ (setq disable-point-adjustment t))
+
+(defun magit-post-command-hook ()
+ (magit-correct-point-after-command)
+ (magit-highlight-section))
+
+(defun magit-mode ()
+ "Review the status of a git repository and act on it.
+
+Please see the manual for a complete description of Magit.
+
+\\{magit-mode-map}"
+ (kill-all-local-variables)
+ (buffer-disable-undo)
+ (setq buffer-read-only t)
+ (make-local-variable 'line-move-visual)
+ (setq major-mode 'magit-mode
+ mode-name "Magit"
+ mode-line-process ""
+ truncate-lines t
+ line-move-visual nil)
+ (add-hook 'pre-command-hook #'magit-remember-point nil t)
+ (add-hook 'post-command-hook #'magit-post-command-hook t t)
+ (use-local-map magit-mode-map)
+ (run-mode-hooks 'magit-mode-hook))
+
+(defun magit-mode-init (dir submode refresh-func &rest refresh-args)
+ (setq default-directory dir
+ magit-submode submode
+ magit-refresh-function refresh-func
+ magit-refresh-args refresh-args)
+ (magit-mode)
+ (magit-refresh-buffer))
+
+(defun magit-find-buffer (submode &optional dir)
+ (let ((topdir (magit-get-top-dir (or dir default-directory))))
+ (dolist (buf (buffer-list))
+ (if (save-excursion
+ (set-buffer buf)
+ (and default-directory
+ (equal (expand-file-name default-directory) topdir)
+ (eq major-mode 'magit-mode)
+ (eq magit-submode submode)))
+ (return buf)))))
+
+(defun magit-find-status-buffer (&optional dir)
+ (magit-find-buffer 'status dir))
+
+(defun magit-for-all-buffers (func &optional dir)
+ (dolist (buf (buffer-list))
+ (save-excursion
+ (set-buffer buf)
+ (if (and (eq major-mode 'magit-mode)
+ (or (null dir)
+ (equal default-directory dir)))
+ (funcall func)))))
+
+(defun magit-refresh-buffer (&optional buffer)
+ (with-current-buffer (or buffer (current-buffer))
+ (let* ((old-line (line-number-at-pos))
+ (old-section (magit-current-section))
+ (old-path (and old-section
+ (magit-section-path (magit-current-section))))
+ (section-line (and old-section
+ (count-lines
+ (magit-section-beginning old-section)
+ (point)))))
+ (if magit-refresh-function
+ (apply magit-refresh-function
+ magit-refresh-args))
+ (magit-refresh-marked-commits-in-buffer)
+ (let ((s (and old-path (magit-find-section old-path magit-top-section))))
+ (cond (s
+ (goto-char (magit-section-beginning s))
+ (forward-line section-line))
+ (t
+ (magit-goto-line old-line)))
+ (dolist (w (get-buffer-window-list (current-buffer)))
+ (set-window-point w (point)))
+ (magit-highlight-section)))))
+
+(defun magit-string-has-prefix-p (string prefix)
+ (eq (compare-strings string nil (length prefix) prefix nil nil) t))
+
+(defun magit-revert-buffers (dir)
+ (dolist (buffer (buffer-list))
+ (when (and buffer
+ (buffer-file-name buffer)
+ (magit-string-has-prefix-p (buffer-file-name buffer) dir)
+ (not (verify-visited-file-modtime buffer))
+ (not (buffer-modified-p buffer)))
+ (with-current-buffer buffer
+ (ignore-errors
+ (revert-buffer t t nil))))))
+
+(defvar magit-refresh-needing-buffers nil)
+(defvar magit-refresh-pending nil)
+
+(defun magit-refresh-wrapper (func)
+ (if magit-refresh-pending
+ (funcall func)
+ (let* ((dir default-directory)
+ (status-buffer (magit-find-buffer 'status dir))
+ (magit-refresh-needing-buffers nil)
+ (magit-refresh-pending t))
+ (unwind-protect
+ (funcall func)
+ (when magit-refresh-needing-buffers
+ (magit-revert-buffers dir)
+ (dolist (b (adjoin status-buffer
+ magit-refresh-needing-buffers))
+ (magit-refresh-buffer b)))))))
+
+(defun magit-need-refresh (&optional buffer)
+ (let ((buffer (or buffer (current-buffer))))
+ (when (not (memq buffer magit-refresh-needing-buffers))
+ (setq magit-refresh-needing-buffers
+ (cons buffer magit-refresh-needing-buffers)))))
+
+(defun magit-refresh ()
+ (interactive)
+ (magit-with-refresh
+ (magit-need-refresh)))
+
+(defun magit-refresh-all ()
+ (interactive)
+ (magit-for-all-buffers #'magit-refresh-buffer default-directory))
+
+;;; Untracked files
+
+(defun magit-wash-untracked-file ()
+ (if (looking-at "^? \\(.*\\)$")
+ (let ((file (match-string-no-properties 1)))
+ (delete-region (point) (+ (line-end-position) 1))
+ (magit-with-section file 'file
+ (magit-set-section-info file)
+ (insert "\t" file "\n"))
+ t)
+ nil))
+
+(defun magit-wash-untracked-files ()
+ ;; Setting magit-old-top-section to nil speeds up washing: no time
+ ;; is wasted looking up the old visibility, which doesn't matter for
+ ;; untracked files.
+ ;;
+ ;; XXX - speed this up in a more general way.
+ ;;
+ (let ((magit-old-top-section nil))
+ (magit-wash-sequence #'magit-wash-untracked-file)))
+
+(defun magit-insert-untracked-files ()
+ (magit-git-section 'untracked "Untracked files:"
+ 'magit-wash-untracked-files
+ "ls-files" "-t" "--others" "--exclude-standard"))
+
+;;; Diffs and Hunks
+
+(defvar magit-diff-context-lines 3)
+
+(defun magit-diff-U-arg ()
+ (format "-U%d" magit-diff-context-lines))
+
+(defun magit-diff-smaller-hunks (&optional count)
+ (interactive "p")
+ (setq magit-diff-context-lines (max 0 (- magit-diff-context-lines count)))
+ (magit-refresh))
+
+(defun magit-diff-larger-hunks (&optional count)
+ (interactive "p")
+ (setq magit-diff-context-lines (+ magit-diff-context-lines count))
+ (magit-refresh))
+
+(defun magit-diff-default-hunks ()
+ (interactive "")
+ (setq magit-diff-context-lines 3)
+ (magit-refresh))
+
+(defun magit-diff-line-file ()
+ (cond ((looking-at "^diff --git ./\\(.*\\) ./\\(.*\\)$")
+ (match-string-no-properties 2))
+ ((looking-at "^diff --cc +\\(.*\\)$")
+ (match-string-no-properties 1))
+ (t
+ nil)))
+
+(defun magit-wash-diffs ()
+ (magit-wash-sequence #'magit-wash-diff-or-other-file))
+
+(defun magit-wash-diff-or-other-file ()
+ (or (magit-wash-diff)
+ (magit-wash-other-file)))
+
+(defun magit-wash-other-file ()
+ (if (looking-at "^? \\(.*\\)$")
+ (let ((file (match-string-no-properties 1)))
+ (delete-region (point) (+ (line-end-position) 1))
+ (magit-with-section file 'file
+ (magit-set-section-info file)
+ (insert "\tNew " file "\n"))
+ t)
+ nil))
+
+(defvar magit-hide-diffs nil)
+
+(defun magit-insert-diff-title (status file file2)
+ (let ((status-text (case status
+ ((unmerged)
+ (format "Unmerged %s" file))
+ ((new)
+ (format "New %s" file))
+ ((deleted)
+ (format "Deleted %s" file))
+ ((renamed)
+ (format "Renamed %s (from %s)"
+ file file2))
+ ((modified)
+ (format "Modified %s" file))
+ (t
+ (format "? %s" file)))))
+ (insert "\t" status-text "\n")))
+
+(defun magit-wash-diff-section ()
+ (cond ((looking-at "^\\* Unmerged path \\(.*\\)")
+ (let ((file (match-string-no-properties 1)))
+ (delete-region (point) (line-end-position))
+ (insert "\tUnmerged " file "\n")
+ (magit-set-section-info (list 'unmerged file nil))
+ t))
+ ((looking-at "^diff")
+ (let ((file (magit-diff-line-file))
+ (end (save-excursion
+ (forward-line) ;; skip over "diff" line
+ (if (search-forward-regexp "^diff\\|^@@" nil t)
+ (goto-char (match-beginning 0))
+ (goto-char (point-max)))
+ (point-marker))))
+ (let* ((status (cond
+ ((looking-at "^diff --cc")
+ 'unmerged)
+ ((save-excursion
+ (search-forward-regexp "^new file" end t))
+ 'new)
+ ((save-excursion
+ (search-forward-regexp "^deleted" end t))
+ 'deleted)
+ ((save-excursion
+ (search-forward-regexp "^rename" end t))
+ 'renamed)
+ (t
+ 'modified)))
+ (file2 (cond
+ ((save-excursion
+ (search-forward-regexp "^rename from \\(.*\\)"
+ end t))
+ (match-string-no-properties 1)))))
+ (magit-set-section-info (list status file file2))
+ (magit-insert-diff-title status file file2)
+ (goto-char end)
+ (let ((magit-section-hidden-default nil))
+ (magit-wash-sequence #'magit-wash-hunk))))
+ t)
+ (t
+ nil)))
+
+(defun magit-wash-diff ()
+ (let ((magit-section-hidden-default magit-hide-diffs))
+ (magit-with-section (magit-current-line) 'diff
+ (magit-wash-diff-section))))
+
+(defun magit-diff-item-kind (diff)
+ (car (magit-section-info diff)))
+
+(defun magit-diff-item-file (diff)
+ (cadr (magit-section-info diff)))
+
+(defun magit-diff-item-file2 (diff)
+ (caddr (magit-section-info diff)))
+
+(defun magit-wash-hunk ()
+ (cond ((looking-at "\\(^@+\\)[^@]*@+")
+ (let ((n-columns (1- (length (match-string 1))))
+ (head (match-string 0)))
+ (magit-with-section head 'hunk
+ (magit-put-line-property 'face 'magit-diff-hunk-header)
+ (forward-line)
+ (while (not (or (eobp)
+ (looking-at "^diff\\|^@@")))
+ (let ((prefix (buffer-substring-no-properties
+ (point) (min (+ (point) n-columns) (point-max)))))
+ (cond ((string-match "\\+" prefix)
+ (magit-put-line-property 'face 'magit-diff-add))
+ ((string-match "-" prefix)
+ (magit-put-line-property 'face 'magit-diff-del))
+ (t
+ (magit-put-line-property 'face 'magit-diff-none))))
+ (forward-line))))
+ t)
+ (t
+ nil)))
+
+(defvar magit-diff-options nil)
+
+(defun magit-insert-diff (file)
+ (let ((cmd magit-git-executable)
+ (args (append (list "diff")
+ (list (magit-diff-U-arg))
+ magit-diff-options
+ (list "--" file))))
+ (let ((p (point)))
+ (magit-git-insert args)
+ (if (not (eq (char-before) ?\n))
+ (insert "\n"))
+ (save-restriction
+ (narrow-to-region p (point))
+ (goto-char p)
+ (magit-wash-diff-section)
+ (goto-char (point-max))))))
+
+(defvar magit-last-raw-diff nil)
+(defvar magit-ignore-unmerged-raw-diffs nil)
+
+(defun magit-wash-raw-diffs ()
+ (let ((magit-last-raw-diff nil))
+ (magit-wash-sequence #'magit-wash-raw-diff)))
+
+(defun magit-wash-raw-diff ()
+ (if (looking-at
+ ":\\([0-7]+\\) \\([0-7]+\\) [0-9a-f]+ [0-9a-f]+ \\(.\\)[0-9]*\t\\([^\t\n]+\\)$")
+ (let ((old-perm (match-string-no-properties 1))
+ (new-perm (match-string-no-properties 2))
+ (status (case (string-to-char (match-string-no-properties 3))
+ (?A 'new)
+ (?D 'deleted)
+ (?M 'modified)
+ (?U 'unmerged)
+ (?T 'new-type)
+ (t nil)))
+ (file (match-string-no-properties 4)))
+ ;; If this is for the same file as the last diff, ignore it.
+ ;; Unmerged files seem to get two entries.
+ ;; We also ignore unmerged files when told so.
+ (if (or (equal file magit-last-raw-diff)
+ (and magit-ignore-unmerged-raw-diffs (eq status 'unmerged)))
+ (delete-region (point) (+ (line-end-position) 1))
+ (setq magit-last-raw-diff file)
+ ;; The 'diff' section that is created here will not work with
+ ;; magit-insert-diff-item-patch etc when we leave it empty.
+ ;; Luckily, raw diffs are only produced for staged and
+ ;; unstaged changes, and we never call
+ ;; magit-insert-diff-item-patch on them. This is a bit
+ ;; brittle, of course.
+ (let ((magit-section-hidden-default magit-hide-diffs))
+ (magit-with-section file 'diff
+ (delete-region (point) (+ (line-end-position) 1))
+ (if (not (magit-section-hidden magit-top-section))
+ (magit-insert-diff file)
+ (magit-set-section-info (list status file nil))
+ (magit-set-section-needs-refresh-on-show t)
+ (magit-insert-diff-title status file nil)))))
+ t)
+ nil))
+
+(defun magit-hunk-item-diff (hunk)
+ (let ((diff (magit-section-parent hunk)))
+ (or (eq (magit-section-type diff) 'diff)
+ (error "Huh? Parent of hunk not a diff."))
+ diff))
+
+(defun magit-diff-item-insert-header (diff buf)
+ (let ((beg (save-excursion
+ (goto-char (magit-section-beginning diff))
+ (forward-line)
+ (point)))
+ (end (if (magit-section-children diff)
+ (magit-section-beginning (car (magit-section-children diff)))
+ (magit-section-end diff))))
+ (magit-insert-region beg end buf)))
+
+(defun magit-insert-diff-item-patch (diff buf)
+ (let ((beg (save-excursion
+ (goto-char (magit-section-beginning diff))
+ (forward-line)
+ (point)))
+ (end (magit-section-end diff)))
+ (magit-insert-region beg end buf)))
+
+(defun magit-insert-hunk-item-patch (hunk buf)
+ (magit-diff-item-insert-header (magit-hunk-item-diff hunk) buf)
+ (magit-insert-region (magit-section-beginning hunk) (magit-section-end hunk)
+ buf))
+
+(defun magit-insert-hunk-item-region-patch (hunk reverse beg end buf)
+ (magit-diff-item-insert-header (magit-hunk-item-diff hunk) buf)
+ (save-excursion
+ (goto-char (magit-section-beginning hunk))
+ (magit-insert-current-line buf)
+ (forward-line)
+ (let ((copy-op (if reverse "+" "-")))
+ (while (< (point) (magit-section-end hunk))
+ (if (and (<= beg (point)) (< (point) end))
+ (magit-insert-current-line buf)
+ (cond ((looking-at " ")
+ (magit-insert-current-line buf))
+ ((looking-at copy-op)
+ (let ((text (buffer-substring-no-properties
+ (+ (point) 1) (line-beginning-position 2))))
+ (with-current-buffer buf
+ (insert " " text))))))
+ (forward-line))))
+ (with-current-buffer buf
+ (diff-fixup-modifs (point-min) (point-max))))
+
+(defun magit-hunk-item-is-conflict-p (hunk)
+ ;;; XXX - Using the title is a bit too clever...
+ (string-match "^diff --cc"
+ (magit-section-title (magit-hunk-item-diff hunk))))
+
+(defun magit-hunk-item-target-line (hunk)
+ (save-excursion
+ (beginning-of-line)
+ (let ((line (line-number-at-pos)))
+ (if (looking-at "-")
+ (error "Can't visit removed lines."))
+ (goto-char (magit-section-beginning hunk))
+ (if (not (looking-at "@@+ .* \\+\\([0-9]+\\),[0-9]+ @@+"))
+ (error "Hunk header not found."))
+ (let ((target (parse-integer (match-string 1))))
+ (forward-line)
+ (while (< (line-number-at-pos) line)
+ ;; XXX - deal with combined diffs
+ (if (not (looking-at "-"))
+ (setq target (+ target 1)))
+ (forward-line))
+ target))))
+
+(defun magit-apply-diff-item (diff &rest args)
+ (when (zerop magit-diff-context-lines)
+ (setq args (cons "--unidiff-zero" args)))
+ (let ((tmp (get-buffer-create "*magit-tmp*")))
+ (with-current-buffer tmp
+ (erase-buffer))
+ (magit-insert-diff-item-patch diff "*magit-tmp*")
+ (apply #'magit-run-git-with-input tmp
+ "apply" (append args (list "-")))))
+
+(defun magit-apply-hunk-item* (hunk reverse &rest args)
+ (when (zerop magit-diff-context-lines)
+ (setq args (cons "--unidiff-zero" args)))
+ (let ((tmp (get-buffer-create "*magit-tmp*")))
+ (with-current-buffer tmp
+ (erase-buffer))
+ (if (magit-use-region-p)
+ (magit-insert-hunk-item-region-patch
+ hunk reverse (region-beginning) (region-end) tmp)
+ (magit-insert-hunk-item-patch hunk tmp))
+ (apply #'magit-run-git-with-input tmp
+ "apply" (append args (list "-")))))
+
+(defun magit-apply-hunk-item (hunk &rest args)
+ (apply #'magit-apply-hunk-item* hunk nil args))
+
+(defun magit-apply-hunk-item-reverse (hunk &rest args)
+ (apply #'magit-apply-hunk-item* hunk t (cons "--reverse" args)))
+
+(defun magit-insert-unstaged-changes (title)
+ (let ((magit-hide-diffs t))
+ (let ((magit-diff-options '()))
+ (magit-git-section 'unstaged title 'magit-wash-raw-diffs
+ "diff-files"))))
+
+(defun magit-insert-staged-changes (no-commit)
+ (let ((magit-hide-diffs t)
+ (base (if no-commit
+ (magit-git-string "mktree")
+ "HEAD")))
+ (let ((magit-diff-options '("--cached"))
+ (magit-ignore-unmerged-raw-diffs t))
+ (magit-git-section 'staged "Staged changes:" 'magit-wash-raw-diffs
+ "diff-index" "--cached"
+ base))))
+
+;;; Logs and Commits
+
+(defun magit-parse-log-ref (refname)
+ "Return shortened and propertized version of full REFNAME, like
+\"refs/remotes/origin/master\"."
+ (let ((face 'magit-log-head-label))
+ (cond ((string-match "^\\(tag: +\\)?refs/tags/\\(.+\\)" refname)
+ (setq refname (match-string 2 refname)
+ face 'magit-log-tag-label))
+ ((string-match "^refs/remotes/\\(.+\\)" refname)
+ (setq refname (match-string 1 refname)))
+ ((string-match "[^/]+$" refname)
+ (setq refname (match-string 0 refname))))
+ (propertize refname 'face face)))
+
+(defun magit-parse-log-refs (refstring)
+ "Parse REFSTRING annotation from `git log --decorate'
+output (for example: \"refs/remotes/origin/master,
+refs/heads/master\") and return prettified string for displaying
+in log buffer."
+ (mapconcat 'identity
+ (mapcar 'magit-parse-log-ref
+ (remove-if (lambda (refname)
+ (string-match "/HEAD$" refname))
+ (reverse (split-string refstring ", *" t))))
+ " - "))
+
+(defun magit-wash-log-line ()
+ (if (and (search-forward-regexp "[0-9a-fA-F]\\{40\\}" (line-end-position) t)
+ (goto-char (match-beginning 0))
+ (not (looking-back "commit ")))
+ (let ((commit (match-string-no-properties 0)))
+ (delete-region (match-beginning 0) (match-end 0))
+ (fixup-whitespace)
+ (goto-char (line-beginning-position))
+ (when (search-forward-regexp "^[|*\\/ ]+\\((\\(tag:.+?\\|refs/.+?\\))\\)"
+ (line-end-position) t)
+ (let ((refstring (match-string-no-properties 2)))
+ (delete-region (match-beginning 1) (match-end 1))
+ (insert (magit-parse-log-refs refstring)))
+ (goto-char (line-beginning-position)))
+ (magit-with-section commit 'commit
+ (magit-set-section-info commit)
+ (forward-line)))
+ (forward-line))
+ t)
+
+(defun magit-wash-log ()
+ (let ((magit-old-top-section nil))
+ (magit-wash-sequence #'magit-wash-log-line)))
+
+(defvar magit-currently-shown-commit nil)
+
+(defun magit-wash-commit ()
+ (cond ((search-forward-regexp "^diff" nil t)
+ (goto-char (match-beginning 0))
+ (magit-wash-diffs))))
+
+(defun magit-refresh-commit-buffer (commit)
+ (magit-create-buffer-sections
+ (magit-git-section nil nil
+ 'magit-wash-commit
+ "log" "--max-count=1"
+ "--pretty=medium"
+ "--cc" "-p" commit)))
+
+(defun magit-show-commit (commit &optional scroll)
+ (when (magit-section-p commit)
+ (setq commit (magit-section-info commit)))
+ (let ((dir default-directory)
+ (buf (get-buffer-create "*magit-commit*")))
+ (cond ((equal magit-currently-shown-commit commit)
+ (let ((win (get-buffer-window buf)))
+ (cond ((not win)
+ (display-buffer buf))
+ (scroll
+ (with-selected-window win
+ (funcall scroll))))))
+ (t
+ (setq magit-currently-shown-commit commit)
+ (display-buffer buf)
+ (with-current-buffer buf
+ (set-buffer buf)
+ (goto-char (point-min))
+ (magit-mode-init dir 'commit
+ #'magit-refresh-commit-buffer commit))))))
+
+(defvar magit-marked-commit nil)
+
+(defvar magit-mark-overlay nil)
+(make-variable-buffer-local 'magit-mark-overlay)
+(put 'magit-mark-overlay 'permanent-local t)
+
+(defun magit-refresh-marked-commits ()
+ (magit-for-all-buffers #'magit-refresh-marked-commits-in-buffer))
+
+(defun magit-refresh-marked-commits-in-buffer ()
+ (if (not magit-mark-overlay)
+ (let ((ov (make-overlay 1 1)))
+ (overlay-put ov 'face 'magit-item-mark)
+ (setq magit-mark-overlay ov)))
+ (delete-overlay magit-mark-overlay)
+ (magit-for-all-sections
+ (lambda (section)
+ (when (and (eq (magit-section-type section) 'commit)
+ (equal (magit-section-info section)
+ magit-marked-commit))
+ (move-overlay magit-mark-overlay
+ (magit-section-beginning section)
+ (magit-section-end section)
+ (current-buffer))))))
+
+(defun magit-set-marked-commit (commit)
+ (setq magit-marked-commit commit)
+ (magit-refresh-marked-commits))
+
+(defun magit-marked-commit ()
+ (or magit-marked-commit
+ (error "No commit marked")))
+
+(defun magit-insert-unpulled-commits (remote branch)
+ (magit-git-section 'unpulled
+ "Unpulled commits:" 'magit-wash-log
+ "log" "--pretty=format:* %H %s"
+ (format "HEAD..%s/%s" remote branch)))
+
+(defun magit-insert-unpushed-commits (remote branch)
+ (magit-git-section 'unpushed
+ "Unpushed commits:" 'magit-wash-log
+ "log" "--pretty=format:* %H %s"
+ (format "%s/%s..HEAD" remote branch)))
+
+(defun magit-insert-unpulled-svn-commits ()
+ (magit-git-section 'svn-unpulled
+ "Unpulled commits (SVN):" 'magit-wash-log
+ "log" "--pretty=format:* %H %s"
+ (format "HEAD..%s" (magit-get-svn-ref))))
+
+(defun magit-insert-unpushed-svn-commits ()
+ (magit-git-section 'svn-unpushed
+ "Unpushed commits (SVN):" 'magit-wash-log
+ "log" "--pretty=format:* %H %s"
+ (format "%s..HEAD" (magit-get-svn-ref))))
+
+;;; Status
+
+(defun magit-refresh-status ()
+ (magit-create-buffer-sections
+ (magit-with-section 'status nil
+ (let* ((branch (magit-get-current-branch))
+ (remote (and branch (magit-get "branch" branch "remote")))
+ (svn-enabled (magit-svn-enabled))
+ (head (magit-git-string
+ "log" "--max-count=1" "--abbrev-commit" "--pretty=oneline"))
+ (no-commit (not head)))
+ (if remote
+ (insert (format "Remote: %s %s\n"
+ remote (magit-get "remote" remote "url"))))
+ (insert (format "Local: %s %s\n"
+ (propertize (or branch "(detached)")
+ 'face 'magit-branch)
+ (abbreviate-file-name default-directory)))
+ (insert (format "Head: %s\n"
+ (if no-commit "nothing commited (yet)" head)))
+ (let ((merge-heads (magit-file-lines ".git/MERGE_HEAD")))
+ (if merge-heads
+ (insert (format "Merging: %s\n"
+ (magit-concat-with-delim
+ ", "
+ (mapcar 'magit-name-rev merge-heads))))))
+ (let ((rebase (magit-rebase-info)))
+ (if rebase
+ (insert (apply 'format "Rebasing: %s (%s of %s)\n" rebase))))
+ (insert "\n")
+ (magit-git-exit-code "update-index" "--refresh")
+ (magit-insert-untracked-files)
+ (magit-insert-stashes)
+ (magit-insert-topics)
+ (magit-insert-pending-changes)
+ (magit-insert-pending-commits)
+ (when remote
+ (magit-insert-unpulled-commits remote branch))
+ (when svn-enabled
+ (magit-insert-unpulled-svn-commits))
+ (let ((staged (or no-commit (magit-anything-staged-p))))
+ (magit-insert-unstaged-changes
+ (if staged "Unstaged changes:" "Changes:"))
+ (if staged
+ (magit-insert-staged-changes no-commit)))
+ (when remote
+ (magit-insert-unpushed-commits remote branch))
+ (when svn-enabled
+ (magit-insert-unpushed-svn-commits))))))
+
+(defun magit-init (dir)
+ "Initialize git repository in specified directory"
+ (interactive (list (read-directory-name "Directory for Git repository: ")))
+ (let ((topdir (magit-get-top-dir dir)))
+ (when (or (not topdir)
+ (yes-or-no-p
+ (format
+ (if (string-equal topdir (expand-file-name dir))
+ "There is already a Git repository in %s. Reinitialize? "
+ "There is a Git repository in %s. Create another in %s? ")
+ topdir dir)))
+ (unless (file-directory-p dir)
+ (and (y-or-n-p (format "Directory %s does not exists. Create it? " dir))
+ (make-directory dir)))
+ (let ((default-directory dir))
+ (magit-run* (list "git" "init"))))))
+
+;;;###autoload
+(defun magit-status (dir)
+ (interactive (list (or (and (not current-prefix-arg)
+ (magit-get-top-dir default-directory))
+ (magit-read-top-dir (and (consp current-prefix-arg)
+ (> (car current-prefix-arg) 4))))))
+ (if magit-save-some-buffers
+ (save-some-buffers (eq magit-save-some-buffers 'dontask)))
+ (let ((topdir (magit-get-top-dir dir)))
+ (unless topdir
+ (when (y-or-n-p (format "There is no Git repository in %S. Create one? "
+ dir))
+ (magit-init dir)
+ (setq topdir (magit-get-top-dir dir))))
+ (when topdir
+ (let ((buf (or (magit-find-buffer 'status topdir)
+ (switch-to-buffer
+ (get-buffer-create
+ (concat "*magit: "
+ (file-name-nondirectory
+ (directory-file-name topdir)) "*"))))))
+ (switch-to-buffer buf)
+ (magit-mode-init topdir 'status #'magit-refresh-status)))))
+
+;;; Staging and Unstaging
+
+(defun magit-stage-item ()
+ "Add the item at point to the staging area."
+ (interactive)
+ (magit-section-action (item info "stage")
+ ((untracked file)
+ (magit-run-git "add" info))
+ ((untracked)
+ (apply #'magit-run-git "add" "--"
+ (magit-git-lines "ls-files" "--other" "--exclude-standard")))
+ ((unstaged diff hunk)
+ (if (magit-hunk-item-is-conflict-p item)
+ (error (concat "Can't stage individual resolution hunks. "
+ "Please stage the whole file.")))
+ (magit-apply-hunk-item item "--cached"))
+ ((unstaged diff)
+ (magit-run-git "add" "-u" (magit-diff-item-file item)))
+ ((staged *)
+ (error "Already staged"))
+ ((hunk)
+ (error "Can't stage this hunk"))
+ ((diff)
+ (error "Can't stage this diff"))))
+
+(defun magit-unstage-item ()
+ "Remove the item at point from the staging area."
+ (interactive)
+ (magit-section-action (item info "unstage")
+ ((staged diff hunk)
+ (magit-apply-hunk-item-reverse item "--cached"))
+ ((staged diff)
+ (if (eq (car info) 'unmerged)
+ (error "Can't unstage a unmerged file. Resolve it first."))
+ (magit-run-git "reset" "-q" "HEAD" "--" (magit-diff-item-file item)))
+ ((unstaged *)
+ (error "Already unstaged"))
+ ((hunk)
+ (error "Can't unstage this hunk"))
+ ((diff)
+ (error "Can't unstage this diff"))))
+
+(defun magit-stage-all (&optional also-untracked-p)
+ (interactive "P")
+ (if also-untracked-p
+ (magit-run-git "add" ".")
+ (magit-run-git "add" "-u" ".")))
+
+(defun magit-unstage-all ()
+ (interactive)
+ (magit-run-git "reset" "HEAD"))
+
+;;; Branches
+
+(defun magit-maybe-create-local-tracking-branch (rev)
+ (if (string-match "^refs/remotes/\\([^/]+\\)/\\(.+\\)" rev)
+ (let ((remote (match-string 1 rev))
+ (branch (match-string 2 rev)))
+ (when (and (not (magit-ref-exists-p (concat "refs/heads/" branch)))
+ (yes-or-no-p
+ (format "Create local tracking branch for %s? " branch)))
+ (magit-run-git "checkout" "-b" branch rev)
+ t))
+ nil))
+
+(defun magit-checkout (rev)
+ (interactive (list (magit-read-rev "Switch to" (magit-default-rev))))
+ (if rev
+ (if (not (magit-maybe-create-local-tracking-branch rev))
+ (magit-run-git "checkout" (magit-rev-to-git rev)))))
+
+(defun magit-read-create-branch-args ()
+ (let* ((cur-branch (magit-get-current-branch))
+ (branch (read-string "Create branch: "))
+ (parent (magit-read-rev "Parent" cur-branch)))
+ (list branch parent)))
+
+(defun magit-create-branch (branch parent)
+ (interactive (magit-read-create-branch-args))
+ (if (and branch (not (string= branch ""))
+ parent)
+ (magit-run-git "checkout" "-b"
+ branch
+ (magit-rev-to-git parent))))
+
+;;; Merging
+
+(defun magit-guess-branch ()
+ (let ((sec (magit-current-section)))
+ (if (and sec (eq (magit-section-type sec) 'wazzup))
+ (magit-section-info sec))))
+
+(defun magit-manual-merge (rev)
+ (interactive (list (magit-read-rev "Manually merge" (magit-guess-branch))))
+ (if rev
+ (magit-run-git "merge" "--no-ff" "--no-commit"
+ (magit-rev-to-git rev))))
+
+(defun magit-automatic-merge (rev)
+ (interactive (list (magit-read-rev "Merge" (magit-guess-branch))))
+ (if rev
+ (magit-run-git "merge" (magit-rev-to-git rev))))
+
+;;; Rebasing
+
+(defun magit-rebase-info ()
+ (cond ((file-exists-p ".git/rebase-apply")
+ (list (magit-name-rev
+ (car (magit-file-lines ".git/rebase-apply/onto")))
+ (car (magit-file-lines ".git/rebase-apply/next"))
+ (car (magit-file-lines ".git/rebase-apply/last"))))
+ ((file-exists-p ".dotest")
+ (list (magit-name-rev (car (magit-file-lines ".dotest/onto")))
+ (car (magit-file-lines ".dotest/next"))
+ (car (magit-file-lines ".dotest/last"))))
+ ((file-exists-p ".git/.dotest-merge")
+ (list (car (magit-file-lines ".git/.dotest-merge/onto_name"))
+ (car (magit-file-lines ".git/.dotest-merge/msgnum"))
+ (car (magit-file-lines ".git/.dotest-merge/end"))))
+ (t
+ nil)))
+
+(defun magit-rebase-step ()
+ (interactive)
+ (let ((info (magit-rebase-info)))
+ (if (not info)
+ (let ((rev (magit-read-rev "Rebase to")))
+ (if rev
+ (magit-run-git "rebase" (magit-rev-to-git rev))))
+ (let ((cursor-in-echo-area t)
+ (message-log-max nil))
+ (message "Rebase in progress. Abort, Skip, or Continue? ")
+ (let ((reply (read-event)))
+ (case reply
+ ((?A ?a)
+ (magit-run-git "rebase" "--abort"))
+ ((?S ?s)
+ (magit-run-git "rebase" "--skip"))
+ ((?C ?c)
+ (magit-run-git "rebase" "--continue"))))))))
+
+;; git svn commands
+
+(defun magit-svn-rebase ()
+ (interactive)
+ (magit-run-git-async "svn" "rebase"))
+
+(defun magit-svn-dcommit ()
+ (interactive)
+ (magit-run-git-async "svn" "dcommit"))
+
+(defun magit-svn-enabled ()
+ (not (null (magit-get-svn-ref))))
+
+(defun magit-get-svn-ref ()
+ (cond ((magit-ref-exists-p "refs/remotes/git-svn")
+ "refs/remotes/git-svn")
+ ((magit-ref-exists-p "refs/remotes/trunk")
+ "refs/remotes/trunk")
+ (t
+ nil)))
+
+;;; Resetting
+
+(defun magit-reset-head (rev &optional hard)
+ (interactive (list (magit-read-rev (format "%s head to"
+ (if current-prefix-arg
+ "Hard reset"
+ "Reset"))
+ (or (magit-default-rev)
+ "HEAD^"))
+ current-prefix-arg))
+ (if rev
+ (magit-run-git "reset" (if hard "--hard" "--soft")
+ (magit-rev-to-git rev))))
+
+(defun magit-reset-working-tree ()
+ (interactive)
+ (if (yes-or-no-p "Discard all uncommitted changes? ")
+ (magit-run-git "reset" "--hard")))
+
+;;; Rewriting
+
+(defun magit-read-rewrite-info ()
+ (when (file-exists-p ".git/magit-rewrite-info")
+ (with-temp-buffer
+ (insert-file-contents ".git/magit-rewrite-info")
+ (goto-char (point-min))
+ (read (current-buffer)))))
+
+(defun magit-write-rewrite-info (info)
+ (with-temp-file ".git/magit-rewrite-info"
+ (prin1 info (current-buffer))
+ (princ "\n" (current-buffer))))
+
+(defun magit-insert-pending-commits ()
+ (let* ((info (magit-read-rewrite-info))
+ (pending (cdr (assq 'pending info))))
+ (when pending
+ (magit-with-section 'pending nil
+ (insert (propertize "Pending commits:\n"
+ 'face 'magit-section-title))
+ (dolist (p pending)
+ (let* ((commit (car p))
+ (properties (cdr p))
+ (used (plist-get properties 'used)))
+ (magit-with-section commit 'commit
+ (magit-set-section-info commit)
+ (insert (magit-git-string
+ "log" "--max-count=1"
+ (if used
+ "--pretty=format:. %s"
+ "--pretty=format:* %s")
+ commit "--")
+ "\n")))))
+ (insert "\n"))))
+
+(defun magit-rewrite-set-commit-property (commit prop value)
+ (let* ((info (magit-read-rewrite-info))
+ (pending (cdr (assq 'pending info)))
+ (p (assoc commit pending)))
+ (when p
+ (setf (cdr p) (plist-put (cdr p) prop value))
+ (magit-write-rewrite-info info)
+ (magit-need-refresh))))
+
+(defun magit-rewrite-set-used ()
+ (interactive)
+ (magit-section-action (item info)
+ ((pending commit)
+ (magit-rewrite-set-commit-property info 'used t))))
+
+(defun magit-rewrite-set-unused ()
+ (interactive)
+ (magit-section-action (item info)
+ ((pending commit)
+ (magit-rewrite-set-commit-property info 'used nil))))
+
+(defun magit-insert-pending-changes ()
+ (let* ((info (magit-read-rewrite-info))
+ (orig (cadr (assq 'orig info))))
+ (when orig
+ (let ((magit-hide-diffs t))
+ (magit-git-section 'pending-changes
+ "Pending changes"
+ 'magit-wash-diffs
+ "diff" (magit-diff-U-arg) "-R" orig)))))
+
+(defun magit-rewrite-start (from &optional onto)
+ (interactive (list (magit-read-rev "Rewrite from" (magit-default-rev))))
+ (or (magit-everything-clean-p)
+ (error "You have uncommitted changes."))
+ (or (not (magit-read-rewrite-info))
+ (error "Rewrite in progress."))
+ (let* ((orig (magit-git-string "rev-parse" "HEAD"))
+ (base (or (car (magit-commit-parents from))
+ (error "Can't rewrite a commit without a parent, sorry.")))
+ (pending (magit-git-lines "rev-list" (concat base ".."))))
+ (magit-write-rewrite-info `((orig ,orig)
+ (pending ,@(mapcar #'list pending))))
+ (magit-run-git "reset" "--hard" base)))
+
+(defun magit-rewrite-stop (&optional noconfirm)
+ (interactive)
+ (let* ((info (magit-read-rewrite-info)))
+ (or info
+ (error "No rewrite in progress."))
+ (when (or noconfirm
+ (yes-or-no-p "Stop rewrite? "))
+ (magit-write-rewrite-info nil)
+ (magit-need-refresh))))
+
+(defun magit-rewrite-abort ()
+ (interactive)
+ (let* ((info (magit-read-rewrite-info))
+ (orig (cadr (assq 'orig info))))
+ (or info
+ (error "No rewrite in progress."))
+ (or (magit-everything-clean-p)
+ (error "You have uncommitted changes."))
+ (when (yes-or-no-p "Abort rewrite? ")
+ (magit-write-rewrite-info nil)
+ (magit-run-git "reset" "--hard" orig))))
+
+(defun magit-rewrite-finish ()
+ (interactive)
+ (magit-with-refresh
+ (magit-rewrite-finish-step t)))
+
+(defun magit-rewrite-finish-step (first-p)
+ (let ((info (magit-read-rewrite-info)))
+ (or info
+ (error "No rewrite in progress."))
+ (let* ((pending (cdr (assq 'pending info)))
+ (first-unused (find-if (lambda (p)
+ (not (plist-get (cdr p) 'used)))
+ pending
+ :from-end t))
+ (commit (car first-unused)))
+ (cond ((not first-unused)
+ (magit-rewrite-stop t))
+ ((magit-apply-commit commit t (not first-p))
+ (magit-rewrite-set-commit-property commit 'used t)
+ (magit-rewrite-finish-step nil))))))
+
+;;; Updating, pull, and push
+
+(defun magit-remote-update ()
+ (interactive)
+ (if (magit-svn-enabled)
+ (magit-run-git-async "svn" "fetch")
+ (magit-run-git-async "remote" "update")))
+
+(defun magit-pull ()
+ (interactive)
+ (let* ((branch (magit-get-current-branch))
+ (config-branch (and branch (magit-get "branch" branch "merge")))
+ (merge-branch (or config-branch
+ (magit-read-rev (format "Pull from")))))
+ (if (and branch (not config-branch))
+ (magit-set merge-branch "branch" branch "merge"))
+ (magit-run-git-async "pull" "-v")))
+
+(defun magit-shell-command (command)
+ (interactive "sCommand: ")
+ (require 'pcomplete)
+ (let ((args (car (with-temp-buffer
+ (insert command)
+ (pcomplete-parse-buffer-arguments))))
+ (magit-process-popup-time 0))
+ (magit-run* args nil nil nil t)))
+
+(defun magit-read-remote (prompt def)
+ (completing-read (if def
+ (format "%s (default %s): " prompt def)
+ (format "%s: " prompt))
+ (magit-git-lines "remote")
+ nil nil nil nil def))
+
+(defun magit-push ()
+ (interactive)
+ (let* ((branch (or (magit-get-current-branch)
+ (error "Don't push a detached head. That's gross.")))
+ (branch-remote (magit-get "branch" branch "remote"))
+ (push-remote (if (or current-prefix-arg
+ (not branch-remote))
+ (magit-read-remote (format "Push %s to" branch)
+ branch-remote)
+ branch-remote)))
+ (if (and (not branch-remote)
+ (not current-prefix-arg))
+ (magit-set push-remote "branch" branch "remote"))
+ (magit-run-git-async "push" "-v" push-remote branch)))
+
+;;; Log edit mode
+
+(defvar magit-log-edit-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "C-c C-c") 'magit-log-edit-commit)
+ (define-key map (kbd "C-c C-a") 'magit-log-edit-toggle-amending)
+ (define-key map (kbd "C-c C-s") 'magit-log-edit-toggle-signoff)
+ (define-key map (kbd "M-p") 'log-edit-previous-comment)
+ (define-key map (kbd "M-n") 'log-edit-next-comment)
+ (define-key map (kbd "C-c C-k") 'magit-log-edit-cancel-log-message)
+ map))
+
+(defvar magit-pre-log-edit-window-configuration nil)
+
+(defun magit-log-fill-paragraph (&optional justify)
+ "Fill the paragraph, but preserve open parentheses at beginning of lines.
+Prefix arg means justify as well."
+ (interactive "P")
+ ;; Add lines starting with a left paren or an asterisk.
+ (let ((paragraph-start (concat paragraph-start "\\|*\\|(")))
+ (let ((end (progn (forward-paragraph) (point)))
+ (beg (progn (backward-paragraph) (point)))
+ (adaptive-fill-mode nil))
+ (fill-region beg end justify)
+ t)))
+
+(define-derived-mode magit-log-edit-mode text-mode "Magit Log Edit"
+ (set (make-local-variable 'fill-paragraph-function)
+ 'magit-log-fill-paragraph)
+ (use-local-map magit-log-edit-map))
+
+(defun magit-log-edit-cleanup ()
+ (save-excursion
+ (goto-char (point-min))
+ (flush-lines "^#")
+ (goto-char (point-min))
+ (if (re-search-forward "[ \t\n]*\\'" nil t)
+ (replace-match "\n" nil nil))))
+
+(defun magit-log-edit-append (str)
+ (save-excursion
+ (set-buffer (get-buffer-create "*magit-log-edit*"))
+ (goto-char (point-max))
+ (insert str "\n")))
+
+(defconst magit-log-header-end "-- End of Magit header --\n")
+
+(defun magit-log-edit-get-fields ()
+ (let ((buf (get-buffer "*magit-log-edit*"))
+ (result nil))
+ (if buf
+ (save-excursion
+ (set-buffer buf)
+ (goto-char (point-min))
+ (while (looking-at "^\\([A-Za-z0-9-_]+\\): *\\(.*\\)$")
+ (setq result (acons (intern (downcase (match-string 1)))
+ (match-string 2)
+ result))
+ (forward-line))
+ (if (not (looking-at (regexp-quote magit-log-header-end)))
+ (setq result nil))))
+ (nreverse result)))
+
+(defun magit-log-edit-set-fields (fields)
+ (let ((buf (get-buffer-create "*magit-log-edit*")))
+ (save-excursion
+ (set-buffer buf)
+ (goto-char (point-min))
+ (if (search-forward-regexp (format "^\\([A-Za-z0-9-_]+:.*\n\\)+%s"
+ (regexp-quote magit-log-header-end))
+ nil t)
+ (delete-region (match-beginning 0) (match-end 0)))
+ (goto-char (point-min))
+ (when fields
+ (while fields
+ (insert (capitalize (symbol-name (caar fields))) ": "
+ (cdar fields) "\n")
+ (setq fields (cdr fields)))
+ (insert magit-log-header-end)))))
+
+(defun magit-log-edit-set-field (name value)
+ (let* ((fields (magit-log-edit-get-fields))
+ (cell (assq name fields)))
+ (cond (cell
+ (if value
+ (rplacd cell value)
+ (setq fields (delq cell fields))))
+ (t
+ (if value
+ (setq fields (append fields (list (cons name value)))))))
+ (magit-log-edit-set-fields fields)))
+
+(defun magit-log-edit-get-field (name)
+ (cdr (assq name (magit-log-edit-get-fields))))
+
+(defun magit-log-edit-setup-author-env (author)
+ (cond (author
+ ;; XXX - this is a bit strict, probably.
+ (or (string-match "\\(.*\\) <\\(.*\\)>, \\(.*\\)" author)
+ (error "Can't parse author string."))
+ ;; Shucks, setenv destroys the match data.
+ (let ((name (match-string 1 author))
+ (email (match-string 2 author))
+ (date (match-string 3 author)))
+ (setenv "GIT_AUTHOR_NAME" name)
+ (setenv "GIT_AUTHOR_EMAIL" email)
+ (setenv "GIT_AUTHOR_DATE" date)))
+ (t
+ (setenv "GIT_AUTHOR_NAME")
+ (setenv "GIT_AUTHOR_EMAIL")
+ (setenv "GIT_AUTHOR_DATE"))))
+
+(defun magit-log-edit-push-to-comment-ring (comment)
+ (when (or (ring-empty-p log-edit-comment-ring)
+ (not (equal comment (ring-ref log-edit-comment-ring 0))))
+ (ring-insert log-edit-comment-ring comment)))
+
+(defun magit-log-edit-commit ()
+ (interactive)
+ (let* ((fields (magit-log-edit-get-fields))
+ (amend (equal (cdr (assq 'amend fields)) "yes"))
+ (commit-all (equal (cdr (assq 'commit-all fields)) "yes"))
+ (sign-off-field (assq 'sign-off fields))
+ (sign-off (if sign-off-field
+ (equal (cdr sign-off-field) "yes")
+ magit-commit-signoff))
+ (tag (cdr (assq 'tag fields)))
+ (author (cdr (assq 'author fields))))
+ (magit-log-edit-push-to-comment-ring (buffer-string))
+ (magit-log-edit-setup-author-env author)
+ (magit-log-edit-set-fields nil)
+ (magit-log-edit-cleanup)
+ (if (= (buffer-size) 0)
+ (insert "(Empty description)\n"))
+ (let ((commit-buf (current-buffer)))
+ (with-current-buffer (magit-find-buffer 'status default-directory)
+ (cond (tag
+ (magit-run-git-with-input commit-buf "tag" tag "-a" "-F" "-"))
+ (t
+ (apply #'magit-run-async-with-input commit-buf
+ magit-git-executable
+ (append magit-git-standard-options
+ (list "commit" "-F" "-")
+ (if commit-all '("--all") '())
+ (if amend '("--amend") '())
+ (if sign-off '("--signoff") '())))))))
+ (erase-buffer)
+ (bury-buffer)
+ (when (file-exists-p ".git/MERGE_MSG")
+ (delete-file ".git/MERGE_MSG"))
+ (when magit-pre-log-edit-window-configuration
+ (set-window-configuration magit-pre-log-edit-window-configuration)
+ (setq magit-pre-log-edit-window-configuration nil))))
+
+(defun magit-log-edit-cancel-log-message ()
+ (interactive)
+ (when (or (not magit-log-edit-confirm-cancellation)
+ (yes-or-no-p
+ "Really cancel editing the log (any changes will be lost)?"))
+ (erase-buffer)
+ (bury-buffer)
+ (when magit-pre-log-edit-window-configuration
+ (set-window-configuration magit-pre-log-edit-window-configuration)
+ (setq magit-pre-log-edit-window-configuration nil))))
+
+(defun magit-log-edit-toggle-amending ()
+ (interactive)
+ (let* ((fields (magit-log-edit-get-fields))
+ (cell (assq 'amend fields)))
+ (if cell
+ (rplacd cell (if (equal (cdr cell) "yes") "no" "yes"))
+ (setq fields (acons 'amend "yes" fields))
+ (magit-log-edit-append
+ (magit-format-commit "HEAD" "%s%n%n%b")))
+ (magit-log-edit-set-fields fields)))
+
+(defun magit-log-edit-toggle-signoff ()
+ (interactive)
+ (let* ((fields (magit-log-edit-get-fields))
+ (cell (assq 'sign-off fields)))
+ (if cell
+ (rplacd cell (if (equal (cdr cell) "yes") "no" "yes"))
+ (setq fields (acons 'sign-off (if magit-commit-signoff "no" "yes")
+ fields)))
+ (magit-log-edit-set-fields fields)))
+
+(defun magit-pop-to-log-edit (operation)
+ (let ((dir default-directory)
+ (buf (get-buffer-create "*magit-log-edit*")))
+ (setq magit-pre-log-edit-window-configuration
+ (current-window-configuration))
+ (pop-to-buffer buf)
+ (when (file-exists-p ".git/MERGE_MSG")
+ (insert-file-contents ".git/MERGE_MSG"))
+ (setq default-directory dir)
+ (magit-log-edit-mode)
+ (message "Type C-c C-c to %s (C-c C-k to cancel)." operation)))
+
+(defun magit-log-edit ()
+ (interactive)
+ (cond ((magit-rebase-info)
+ (if (y-or-n-p "Rebase in progress. Continue it? ")
+ (magit-run-git "rebase" "--continue")))
+ (t
+ (magit-log-edit-set-field 'tag nil)
+ (when (and magit-commit-all-when-nothing-staged
+ (not (magit-anything-staged-p)))
+ (cond ((eq magit-commit-all-when-nothing-staged 'ask-stage)
+ (if (and (not (magit-everything-clean-p))
+ (y-or-n-p "Nothing staged. Stage everything now? "))
+ (magit-stage-all)))
+ ((not (magit-log-edit-get-field 'commit-all))
+ (magit-log-edit-set-field
+ 'commit-all
+ (if (or (eq magit-commit-all-when-nothing-staged t)
+ (y-or-n-p
+ "Nothing staged. Commit all unstaged changes? "))
+ "yes" "no")))))
+ (magit-pop-to-log-edit "commit"))))
+
+(defun magit-add-log ()
+ (interactive)
+ (cond ((magit-rebase-info)
+ (if (y-or-n-p "Rebase in progress. Continue it? ")
+ (magit-run-git "rebase" "--continue")))
+ (t
+ (let ((section (magit-current-section)))
+ (let ((fun (if (eq (magit-section-type section) 'hunk)
+ (save-window-excursion
+ (save-excursion
+ (magit-visit-item)
+ (add-log-current-defun)))
+ nil))
+ (file (magit-diff-item-file
+ (cond ((eq (magit-section-type section) 'hunk)
+ (magit-hunk-item-diff section))
+ ((eq (magit-section-type section) 'diff)
+ section)
+ (t
+ (error "No change at point"))))))
+ (magit-log-edit)
+ (goto-char (point-min))
+ (cond ((not (search-forward-regexp
+ (format "^\\* %s" (regexp-quote file)) nil t))
+ ;; No entry for file, create it.
+ (goto-char (point-max))
+ (insert (format "\n* %s" file))
+ (if fun
+ (insert (format " (%s)" fun)))
+ (insert ": "))
+ (fun
+ ;; found entry for file, look for fun
+ (let ((limit (or (save-excursion
+ (and (search-forward-regexp "^\\* "
+ nil t)
+ (match-beginning 0)))
+ (point-max))))
+ (cond ((search-forward-regexp (format "(.*\\<%s\\>.*):"
+ (regexp-quote fun))
+ limit t)
+ ;; found it, goto end of current entry
+ (if (search-forward-regexp "^(" limit t)
+ (backward-char 2)
+ (goto-char limit)))
+ (t
+ ;; not found, insert new entry
+ (goto-char limit)
+ (if (bolp)
+ (open-line 1)
+ (newline))
+ (insert (format "(%s): " fun))))))))))))
+
+;;; Tags
+
+(defun magit-tag (name)
+ (interactive "sNew tag name: ")
+ (magit-run-git "tag" name))
+
+(defun magit-annotated-tag (name)
+ (interactive "sNew tag name: ")
+ (magit-log-edit-set-field 'tag name)
+ (magit-pop-to-log-edit "tag"))
+
+;;; Stashing
+
+(defun magit-wash-stash ()
+ (if (search-forward-regexp "stash@{\\(.*\\)}" (line-end-position) t)
+ (let ((stash (match-string-no-properties 0))
+ (name (match-string-no-properties 1)))
+ (delete-region (match-beginning 0) (match-end 0))
+ (goto-char (match-beginning 0))
+ (fixup-whitespace)
+ (goto-char (line-beginning-position))
+ (insert name)
+ (goto-char (line-beginning-position))
+ (magit-with-section stash 'stash
+ (magit-set-section-info stash)
+ (forward-line)))
+ (forward-line))
+ t)
+
+(defun magit-wash-stashes ()
+ (let ((magit-old-top-section nil))
+ (magit-wash-sequence #'magit-wash-stash)))
+
+(defun magit-insert-stashes ()
+ (magit-git-section 'stashes
+ "Stashes:" 'magit-wash-stashes
+ "stash" "list"))
+
+(defun magit-stash (description)
+ (interactive "sStash description: ")
+ (magit-run-git "stash" "save" description))
+
+(defun magit-stash-snapshot ()
+ (interactive)
+ (magit-with-refresh
+ (magit-run-git "stash" "save"
+ (format-time-string "Snapshot taken at %Y-%m-%d %H:%M:%S"
+ (current-time)))
+ (magit-run-git "stash" "apply" "stash@{0}")))
+
+(defvar magit-currently-shown-stash nil)
+
+(defun magit-show-stash (stash &optional scroll)
+ (when (magit-section-p stash)
+ (setq stash (magit-section-info stash)))
+ (let ((dir default-directory)
+ (buf (get-buffer-create "*magit-stash*")))
+ (cond ((equal magit-currently-shown-stash stash)
+ (let ((win (get-buffer-window buf)))
+ (cond ((not win)
+ (display-buffer buf))
+ (scroll
+ (with-selected-window win
+ (funcall scroll))))))
+ (t
+ (setq magit-currently-shown-stash stash)
+ (display-buffer buf)
+ (with-current-buffer buf
+ (set-buffer buf)
+ (goto-char (point-min))
+ (let* ((range (cons (concat stash "^2^") stash))
+ (args (magit-rev-range-to-git range)))
+ (magit-mode-init dir 'diff #'magit-refresh-diff-buffer
+ range args)))))))
+
+;;; Topic branches (using topgit)
+
+(defun magit-wash-topic ()
+ (if (search-forward-regexp "^..\\(t/\\S-+\\)\\s-+\\(\\S-+\\)\\s-+\\(\\S-+\\)"
+ (line-end-position) t)
+ (let ((topic (match-string 1)))
+ (delete-region (match-beginning 2) (match-end 2))
+ (goto-char (line-beginning-position))
+ (delete-char 4)
+ (insert "\t")
+ (goto-char (line-beginning-position))
+ (magit-with-section topic 'topic
+ (magit-set-section-info topic)
+ (forward-line)))
+ (delete-region (line-beginning-position) (1+ (line-end-position))))
+ t)
+
+(defun magit-wash-topics ()
+ (let ((magit-old-top-section nil))
+ (magit-wash-sequence #'magit-wash-topic)))
+
+(defun magit-insert-topics ()
+ (magit-git-section 'topics
+ "Topics:" 'magit-wash-topics
+ "branch" "-v"))
+
+;;; Commits
+
+(defun magit-commit-at-point (&optional nil-ok-p)
+ (let* ((section (magit-current-section))
+ (commit (and (eq (magit-section-type section) 'commit)
+ (magit-section-info section))))
+ (if nil-ok-p
+ commit
+ (or commit
+ (error "No commit at point.")))))
+
+(defun magit-apply-commit (commit &optional docommit noerase revert)
+ (let* ((parent-id (magit-choose-parent-id commit "cherry-pick"))
+ (success (magit-run* `(,magit-git-executable
+ ,@magit-git-standard-options
+ ,(if revert "revert" "cherry-pick")
+ ,@(if parent-id
+ (list "-m" (number-to-string parent-id)))
+ ,@(if (not docommit) (list "--no-commit"))
+ ,commit)
+ nil noerase)))
+ (when (or (not docommit) success)
+ (cond (revert
+ (magit-log-edit-append
+ (magit-format-commit commit "Reverting \"%s\"")))
+ (t
+ (magit-log-edit-append
+ (magit-format-commit commit "%s%n%n%b"))
+ (magit-log-edit-set-field
+ 'author
+ (magit-format-commit commit "%an <%ae>, %ai")))))
+ success))
+
+(defun magit-apply-item ()
+ (interactive)
+ (magit-section-action (item info "apply")
+ ((pending commit)
+ (magit-apply-commit info)
+ (magit-rewrite-set-commit-property info 'used t))
+ ((commit)
+ (magit-apply-commit info))
+ ((unstaged *)
+ (error "Change is already in your working tree"))
+ ((staged *)
+ (error "Change is already in your working tree"))
+ ((hunk)
+ (magit-apply-hunk-item item))
+ ((diff)
+ (magit-apply-diff-item item))
+ ((stash)
+ (magit-run-git "stash" "apply" info))))
+
+(defun magit-cherry-pick-item ()
+ (interactive)
+ (magit-section-action (item info "cherry-pick")
+ ((pending commit)
+ (magit-apply-commit info t)
+ (magit-rewrite-set-commit-property info 'used t))
+ ((commit)
+ (magit-apply-commit info t))
+ ((stash)
+ (magit-run-git "stash" "pop" info))))
+
+(defun magit-revert-item ()
+ (interactive)
+ (magit-section-action (item info "revert")
+ ((pending commit)
+ (magit-apply-commit info nil nil t)
+ (magit-rewrite-set-commit-property info 'used nil))
+ ((commit)
+ (magit-apply-commit info nil nil t))
+ ((hunk)
+ (magit-apply-hunk-item-reverse item))
+ ((diff)
+ (magit-apply-diff-item item "--reverse"))))
+
+(defvar magit-have-graph 'unset)
+(defvar magit-have-decorate 'unset)
+(make-variable-buffer-local 'magit-have-graph)
+(put 'magit-have-graph 'permanent-local t)
+(make-variable-buffer-local 'magit-have-decorate)
+(put 'magit-have-decorate 'permanent-local t)
+
+(defun magit-configure-have-graph ()
+ (if (eq magit-have-graph 'unset)
+ (let ((res (magit-git-exit-code "log" "--graph" "--max-count=0")))
+ (setq magit-have-graph (eq res 0)))))
+
+(defun magit-configure-have-decorate ()
+ (if (eq magit-have-decorate 'unset)
+ (let ((res (magit-git-exit-code "log" "--decorate=full" "--max-count=0")))
+ (setq magit-have-decorate (eq res 0)))))
+
+(defun magit-refresh-log-buffer (range style args)
+ (magit-configure-have-graph)
+ (magit-configure-have-decorate)
+ (magit-create-buffer-sections
+ (apply #'magit-git-section nil
+ (magit-rev-range-describe range "Commits")
+ 'magit-wash-log
+ `("log"
+ ,(format "--max-count=%s" magit-log-cutoff-length)
+ ,style
+ ,@(if magit-have-decorate (list "--decorate=full"))
+ ,@(if magit-have-graph (list "--graph"))
+ ,args "--"))))
+
+(defun magit-log (&optional arg)
+ (interactive "P")
+ (let* ((range (if arg
+ (magit-read-rev-range "Log" "HEAD")
+ "HEAD"))
+ (topdir (magit-get-top-dir default-directory))
+ (args (magit-rev-range-to-git range)))
+ (switch-to-buffer "*magit-log*")
+ (magit-mode-init topdir 'log #'magit-refresh-log-buffer range
+ "--pretty=oneline" args)))
+
+(defun magit-log-long (&optional arg)
+ (interactive "P")
+ (let* ((range (if arg
+ (magit-read-rev-range "Long log" "HEAD")
+ "HEAD"))
+ (topdir (magit-get-top-dir default-directory))
+ (args (magit-rev-range-to-git range)))
+ (switch-to-buffer "*magit-log*")
+ (magit-mode-init topdir 'log #'magit-refresh-log-buffer range
+ "--stat" args)))
+
+;;; Reflog
+
+(defun magit-refresh-reflog-buffer (head args)
+ (magit-create-buffer-sections
+ (magit-git-section 'reflog
+ (format "Local history of head %s" head)
+ 'magit-wash-log
+ "log" "--walk-reflogs"
+ (format "--max-count=%s" magit-log-cutoff-length)
+ "--pretty=oneline"
+ args)))
+
+(defun magit-reflog (head)
+ (interactive (list (magit-read-rev "Reflog of" "HEAD")))
+ (if head
+ (let* ((topdir (magit-get-top-dir default-directory))
+ (args (magit-rev-to-git head)))
+ (switch-to-buffer "*magit-reflog*")
+ (magit-mode-init topdir 'reflog
+ #'magit-refresh-reflog-buffer head args))))
+
+(defun magit-reflog-head ()
+ (interactive)
+ (magit-reflog "HEAD"))
+
+;;; Diffing
+
+(defun magit-refresh-diff-buffer (range args)
+ (magit-create-buffer-sections
+ (magit-git-section 'diffbuf
+ (magit-rev-range-describe range "Changes")
+ 'magit-wash-diffs
+ "diff" (magit-diff-U-arg) args)))
+
+(defun magit-diff (range)
+ (interactive (list (magit-read-rev-range "Diff")))
+ (if range
+ (let* ((dir default-directory)
+ (args (magit-rev-range-to-git range))
+ (buf (get-buffer-create "*magit-diff*")))
+ (display-buffer buf)
+ (save-excursion
+ (set-buffer buf)
+ (magit-mode-init dir 'diff #'magit-refresh-diff-buffer range args)))))
+
+(defun magit-diff-working-tree (rev)
+ (interactive (list (magit-read-rev "Diff with (default HEAD)")))
+ (magit-diff (or rev "HEAD")))
+
+(defun magit-diff-with-mark ()
+ (interactive)
+ (magit-diff (cons (magit-marked-commit)
+ (magit-commit-at-point))))
+
+;;; Wazzup
+
+(defun magit-wazzup-toggle-ignore (branch edit)
+ (let ((ignore-file ".git/info/wazzup-exclude"))
+ (if edit
+ (setq branch (read-string "Branch to ignore for wazzup: " branch)))
+ (let ((ignored (magit-file-lines ignore-file)))
+ (cond ((member branch ignored)
+ (when (or (not edit)
+ (y-or-n-p "Branch %s is already ignored. Unignore?"))
+ (setq ignored (delete branch ignored))))
+ (t
+ (setq ignored (append ignored (list branch)))))
+ (magit-write-file-lines ignore-file ignored)
+ (magit-need-refresh))))
+
+(defun magit-refresh-wazzup-buffer (head all)
+ (magit-create-buffer-sections
+ (magit-with-section 'wazzupbuf nil
+ (insert (format "Wazzup, %s\n\n" head))
+ (let* ((excluded (magit-file-lines ".git/info/wazzup-exclude"))
+ (all-branches (magit-list-interesting-refs))
+ (branches (if all all-branches
+ (remove-if (lambda (b) (member (cdr b) excluded))
+ all-branches)))
+ (reported (make-hash-table :test #'equal)))
+ (dolist (branch branches)
+ (let* ((name (car branch))
+ (ref (cdr branch))
+ (hash (magit-git-string "rev-parse" ref))
+ (reported-branch (gethash hash reported)))
+ (unless (or (and reported-branch
+ (string= (file-name-nondirectory ref)
+ reported-branch))
+ (not (magit-git-string "merge-base" head ref)))
+ (puthash hash (file-name-nondirectory ref) reported)
+ (let* ((n (length (magit-git-lines "log" "--pretty=oneline"
+ (concat head ".." ref))))
+ (section
+ (let ((magit-section-hidden-default t))
+ (magit-git-section
+ (cons ref 'wazzup)
+ (format "%s unmerged commits in %s%s"
+ n name
+ (if (member ref excluded)
+ " (normally ignored)"
+ ""))
+ 'magit-wash-log
+ "log"
+ (format "--max-count=%s" magit-log-cutoff-length)
+ "--pretty=oneline"
+ (format "%s..%s" head ref)
+ "--"))))
+ (magit-set-section-info ref section)))))))))
+
+(defun magit-wazzup (&optional all)
+ (interactive "P")
+ (let* ((topdir (magit-get-top-dir default-directory)))
+ (switch-to-buffer "*magit-wazzup*")
+ (magit-mode-init topdir 'wazzup
+ #'magit-refresh-wazzup-buffer
+ (magit-get-current-branch) all)))
+
+;;; Miscellaneous
+
+(defun magit-ignore-file (file edit local)
+ (let ((ignore-file (if local ".git/info/exclude" ".gitignore")))
+ (if edit
+ (setq file (read-string "File to ignore: " file)))
+ (append-to-file (concat "/" file "\n") nil ignore-file)
+ (magit-need-refresh)))
+
+(defun magit-ignore-item ()
+ (interactive)
+ (magit-section-action (item info "ignore")
+ ((untracked file)
+ (magit-ignore-file info current-prefix-arg nil))
+ ((wazzup)
+ (magit-wazzup-toggle-ignore info current-prefix-arg))))
+
+(defun magit-ignore-item-locally ()
+ (interactive)
+ (magit-section-action (item info "ignore")
+ ((untracked file)
+ (magit-ignore-file info current-prefix-arg t))))
+
+(defun magit-discard-diff (diff stagedp)
+ (let ((kind (magit-diff-item-kind diff))
+ (file (magit-diff-item-file diff)))
+ (cond ((eq kind 'deleted)
+ (when (yes-or-no-p (format "Resurrect %s? " file))
+ (magit-run-git "reset" "-q" "--" file)
+ (magit-run-git "checkout" "--" file)))
+ ((eq kind 'new)
+ (if (yes-or-no-p (format "Delete %s? " file))
+ (magit-run-git "rm" "-f" "--" file)))
+ (t
+ (if (yes-or-no-p (format "Discard changes to %s? " file))
+ (if stagedp
+ (magit-run-git "checkout" "HEAD" "--" file)
+ (magit-run-git "checkout" "--" file)))))))
+
+(defun magit-discard-item ()
+ (interactive)
+ (magit-section-action (item info "discard")
+ ((untracked file)
+ (if (yes-or-no-p (format "Delete %s? " info))
+ (magit-run "rm" info)))
+ ((untracked)
+ (if (yes-or-no-p "Delete all untracked files and directories? ")
+ (magit-run "git" "clean" "-df")))
+ ((unstaged diff hunk)
+ (when (yes-or-no-p (if (magit-use-region-p)
+ "Discard changes in region? "
+ "Discard hunk? "))
+ (magit-apply-hunk-item-reverse item)))
+ ((staged diff hunk)
+ (if (magit-file-uptodate-p (magit-diff-item-file
+ (magit-hunk-item-diff item)))
+ (when (yes-or-no-p (if (magit-use-region-p)
+ "Discard changes in region? "
+ "Discard hunk? "))
+ (magit-apply-hunk-item-reverse item "--index"))
+ (error "Can't discard this hunk. Please unstage it first.")))
+ ((unstaged diff)
+ (magit-discard-diff item nil))
+ ((staged diff)
+ (if (magit-file-uptodate-p (magit-diff-item-file item))
+ (magit-discard-diff item t)
+ (error "Can't discard staged changes to this file. Please unstage it first.")))
+ ((hunk)
+ (error "Can't discard this hunk"))
+ ((diff)
+ (error "Can't discard this diff"))
+ ((stash)
+ (when (yes-or-no-p "Discard stash? ")
+ (magit-run-git "stash" "drop" info)))))
+
+(defun magit-visit-item ()
+ (interactive)
+ (magit-section-action (item info "visit")
+ ((untracked file)
+ (find-file info))
+ ((diff)
+ (find-file (magit-diff-item-file item)))
+ ((hunk)
+ (let ((file (magit-diff-item-file (magit-hunk-item-diff item)))
+ (line (magit-hunk-item-target-line item)))
+ (find-file file)
+ (goto-line line)))
+ ((commit)
+ (magit-show-commit info)
+ (pop-to-buffer "*magit-commit*"))
+ ((stash)
+ (magit-show-stash info)
+ (pop-to-buffer "*magit-diff*"))
+ ((topic)
+ (magit-checkout info))))
+
+(defun magit-show-item-or-scroll-up ()
+ (interactive)
+ (magit-section-action (item info)
+ ((commit)
+ (magit-show-commit info #'scroll-up))
+ ((stash)
+ (magit-show-stash info #'scroll-up))
+ (t
+ (scroll-up))))
+
+(defun magit-show-item-or-scroll-down ()
+ (interactive)
+ (magit-section-action (item info)
+ ((commit)
+ (magit-show-commit info #'scroll-down))
+ ((stash)
+ (magit-show-stash info #'scroll-down))
+ (t
+ (scroll-down))))
+
+(defun magit-mark-item (&optional unmark)
+ (interactive "P")
+ (if unmark
+ (magit-set-marked-commit nil)
+ (magit-section-action (item info "mark")
+ ((commit)
+ (magit-set-marked-commit (if (eq magit-marked-commit info)
+ nil
+ info))))))
+
+(defun magit-describe-item ()
+ (interactive)
+ (let ((section (magit-current-section)))
+ (message "Section: %s %s-%s %S %S %S"
+ (magit-section-type section)
+ (magit-section-beginning section)
+ (magit-section-end section)
+ (magit-section-title section)
+ (magit-section-info section)
+ (magit-section-context-type section))))
+
+(defun magit-copy-item-as-kill ()
+ "Copy sha1 of commit at point into kill ring."
+ (interactive)
+ (magit-section-action (item info "copy")
+ ((commit)
+ (kill-new info)
+ (message "%s" info))))
+
+(defun magit-interactive-rebase ()
+ "Start a git rebase -i session, old school-style."
+ (interactive)
+ (server-start)
+ (let* ((section (get-text-property (point) 'magit-section))
+ (commit (and (member 'commit (magit-section-context-type section))
+ (magit-section-info section)))
+ (old-editor (getenv "GIT_EDITOR")))
+ (setenv "GIT_EDITOR" (expand-file-name "emacsclient" exec-directory))
+ (unwind-protect
+ (magit-run-git-async "rebase" "-i"
+ (or (and commit (concat commit "^"))
+ (read-string "Interactively rebase to: ")))
+ (if old-editor
+ (setenv "GIT_EDITOR" old-editor)))))
+
+(defun magit-show-branches ()
+ "Show all of the current branches in other-window."
+ (interactive)
+ (save-selected-window
+ (switch-to-buffer-other-window "*magit-branches*")
+ (erase-buffer)
+ (insert (magit-git-string "branch" "-va"))
+ (insert "\n")))
+
+(defvar magit-ediff-file)
+(defvar magit-ediff-windows)
+
+(defun magit-interactive-resolve (file)
+ (let ((merge-status (magit-git-string "ls-files" "-u" "--" file))
+ (base-buffer (generate-new-buffer (concat file ".base")))
+ (our-buffer (generate-new-buffer (concat file ".current")))
+ (their-buffer (generate-new-buffer (concat file ".merged")))
+ (windows (current-window-configuration)))
+ (if (null merge-status)
+ (error "Cannot resolve %s" file))
+ (with-current-buffer base-buffer
+ (if (string-match "^[0-9]+ [0-9a-f]+ 1" merge-status)
+ (insert (magit-git-string "cat-file" "blob"
+ (concat ":1:" file)))))
+ (with-current-buffer our-buffer
+ (if (string-match "^[0-9]+ [0-9a-f]+ 2" merge-status)
+ (insert (magit-git-string "cat-file" "blob"
+ (concat ":2:" file)))))
+ (with-current-buffer their-buffer
+ (if (string-match "^[0-9]+ [0-9a-f]+ 3" merge-status)
+ (insert (magit-git-string "cat-file" "blob"
+ (concat ":3:" file)))))
+ ;; We have now created the 3 buffer with ours, theirs and the ancestor files
+ (with-current-buffer (ediff-merge-buffers-with-ancestor our-buffer their-buffer base-buffer)
+ (make-local-variable 'magit-ediff-file)
+ (setq magit-ediff-file file)
+ (make-local-variable 'magit-ediff-windows)
+ (setq magit-ediff-windows windows)
+ (make-local-variable 'ediff-quit-hook)
+ (add-hook 'ediff-quit-hook
+ (lambda ()
+ (let ((buffer-A ediff-buffer-A)
+ (buffer-B ediff-buffer-B)
+ (buffer-C ediff-buffer-C)
+ (buffer-Ancestor ediff-ancestor-buffer)
+ (file magit-ediff-file)
+ (windows magit-ediff-windows))
+ (ediff-cleanup-mess)
+ (find-file file)
+ (erase-buffer)
+ (insert-buffer-substring buffer-C)
+ (kill-buffer buffer-A)
+ (kill-buffer buffer-B)
+ (kill-buffer buffer-C)
+ (when (bufferp buffer-Ancestor) (kill-buffer buffer-Ancestor))
+ (set-window-configuration windows)
+ (message "Conflict resolution finished; you may save the buffer")))))))
+
+
+(defun magit-interactive-resolve-item ()
+ (interactive)
+ (magit-section-action (item info "resolv")
+ ((diff)
+ (magit-interactive-resolve (cadr info)))))
+
+
+(provide 'magit)
diff --git a/emacs.d/lisp/magit/magit.texi b/emacs.d/lisp/magit/magit.texi
new file mode 100644
index 0000000..4930d92
--- /dev/null
+++ b/emacs.d/lisp/magit/magit.texi
@@ -0,0 +1,639 @@
+\input texinfo.tex @c -*-texinfo-*-
+@c %**start of header
+@setfilename magit.info
+@settitle Magit User Manual
+@c %**end of header
+
+@dircategory Emacs
+@direntry
+* Magit: (magit). Using Git from Emacs with Magit.
+@end direntry
+
+@copying
+Copyright @copyright{} 2008, 2009 Marius Vollmer
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.2 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
+Texts.
+@end quotation
+@end copying
+
+@node Top
+@top Magit User Manual
+
+Magit is an interface to the version control system Git, implemented
+as an extension to Emacs.
+
+@menu
+* Introduction::
+* Acknowledgments::
+* Sections::
+* Status::
+* Untracked files::
+* Staging and Committing::
+* History::
+* Reflogs::
+* Diffing::
+* Tagging::
+* Resetting::
+* Stashing::
+* Branching::
+* Wazzup::
+* Merging::
+* Rebasing::
+* Rewriting::
+* Pushing and Pulling::
+* Interfacing with Subversion::
+@end menu
+
+@node Introduction
+@chapter Introduction
+
+With Magit, you can inspect and modify your Git repositories with
+Emacs. You can review and commit the changes you have made to the
+tracked files, for example, and you can browse the history of past
+changes. There is support for cherry picking, reverting, merging,
+rebasing, and other common Git operations.
+
+Magit is not a complete interface to Git; it just aims to make the
+most common Git operations convenient. Thus, Magit will likely not
+save you from learning Git itself.
+
+This manual provides a tour of all Magit features. It does not give a
+introduction to version control in general, or to Git in particular.
+
+The main entry point to Magit is @kbd{M-x magit-status}, which will
+put you in Magit's status buffer. You will be using it frequently, so
+it is probably a good idea to bind @code{magit-status} to a key of
+your choice.
+
+In addition to the status buffer, Magit will also create buffers that
+show lists of commits, buffers with diffs, and other kinds of buffers.
+All these buffers are in @code{magit-mode} and have the same key
+bindings. Not all commands make sense in all contexts, but a given
+key will always do the same thing in all Magit buffers.
+
+Naturally, Magit runs the @code{git} command to do most of the work.
+The @code{*magit-process*} buffer contains the transcript of the most
+recent command. You can switch to it with @kbd{$}.
+
+@node Acknowledgments
+@chapter Acknowledgments
+
+From day one of the first Magit announcement, John Wiegley has
+contributed numerous fixes, UI improvements, and new features.
+Thanks!
+
+Linh Dang and Christian Neukirchen also contributed from day one.
+Thanks!
+
+Phil Hagelberg joined a few days later. Thanks!
+
+Alex Ott contributed support for git svn. Thanks!
+
+Marcin Bachry contributed bug fixes and support for decorated logs.
+Thanks!
+
+Alexey Voinov fixed bugs. Thanks!
+
+RĂ©mi Vanicat helped with Tramp support. Thanks!
+
+@node Sections
+@chapter Sections
+
+All Magit buffers are structured into nested 'sections'. These
+sections can be hidden and shown individually. When a section is
+hidden, only its first line is shown and all its children are
+completely invisible.
+
+The most fine-grained way to control the visibility of sections is the
+@kbd{TAB} key. It will to toggle the current section (the section
+that contains point) between being hidden and being shown.
+
+Typing @kbd{S-TAB} toggles the visibility of the children of the
+current section. When all of them are shown, they will all be hidden.
+Otherwise, when some or all are hidden, they will all be shown.
+
+The digit keys @kbd{1}, @kbd{2}, @kbd{3}, and @kbd{4} control the
+visibility of sections based on levels. Hitting @kbd{2}, for example,
+will show sections on levels one and two, and will hide sections on
+level 3. However, only sections that are a parent or child of the
+current section are affected.
+
+For example, when the current section is on level 3 and you hit
+@kbd{1}, the grand-parent of the current section (which is on level
+one) will be shown, and the parent of the current section (level 2)
+will be hidden. The visibility of no other section will be changed.
+
+This sounds a bit complicated, but you'll figure it out.
+
+Using @kbd{M-1}, @kbd{M-2}, @kbd{M-3}, and @kbd{M-4} is similar to the
+unmodified digits, but now all sections on the respective level are
+affected, regardless of whether or not they are related to the current
+section.
+
+For example, @kbd{M-1} will only show the first lines of the top-level
+sections and will hide everything else. Typing @kbd{M-4} on the other
+hand will show everything.
+
+Because of the way the status buffer is set up, some changes to
+section visibility are more common than others. Files are on level 2
+and diff hunks are on level 4. Thus, you can type @kbd{2} to collapse
+the diff of the current file, and @kbd{M-2} to collapse all files.
+This returns the status buffer to its default setup and is a quick way
+to unclutter it after drilling down into the modified files.
+
+Because @kbd{2} and @kbd{M-2} are so common in the status buffer, they
+are bound to additional, more mnemonic keys: @kbd{M-h} (hide) and
+@kbd{M-H} (hide all). Likewise @kbd{4} and @kbd{M-4} are also
+available as @kbd{M-s} (show) and @kbd{M-S} (show all).
+
+In other buffers than the status buffer, @kbd{M-h}, @kbd{M-H},
+@kbd{M-s}, and @kbd{M-S} might work on different levels than on 2 and
+4, but they keep their general meaning: @kbd{M-H} hides all detail,
+and @kbd{M-S} shows everything.
+
+@node Status
+@chapter Status
+
+Running @kbd{M-x magit-status} displays the main interface of Magit,
+the status buffer. You can have multiple status buffers active at the
+same time, each associated with its own Git repository.
+
+When invoking @kbd{M-x magit-status} from within a Git repository, it
+will switch to the status buffer of that repository. Otherwise, it
+will prompt for a directory. With a prefix argument, it will always
+prompt.
+
+You can set @code{magit-repo-dirs} to customize how
+@code{magit-status} asks for the repository to work on. When
+@code{magit-repo-dirs} is nil, @code{magit-status} will simply ask for
+a directory.
+
+If you specify a directory that is not a Git repository, @kbd{M-x
+magit-status} will offer to initialize it as one.
+
+When @code{magit-repo-dirs} is not nil, it is treated as a list of
+directory names, and @code{magit-status} will find all Git
+repositories in those directories and offer them for completion.
+(Magit will only look @code{magit-repo-dirs-depth} levels deep,
+however.)
+
+With two prefix arguments, @code{magit-status} will always prompt for
+a raw directory.
+
+Thus, you would normally set @code{magit-repo-dirs} to the places
+where you keep most of your Git repositories and switch between them
+with @kbd{C-u M-x magit-status}. If you want to go to a repository
+outside of your normal working areas, or if you want to create a new
+repository, you would use @kbd{C-u C-u M-x magit-status}.
+
+You need to explicitly refresh the status buffer when you have made
+changes to the repository from outside of Emacs. You can type @kbd{g}
+in the status buffer itself, or just use @kbd{M-x magit-status}
+instead of @kbd{C-x b} when switching to it. You also need to refresh
+the status buffer in this way after saving a file in Emacs.
+
+The header at the top of the status buffer shows a short summary of
+the repository state: where it is located, which branch is checked
+out, etc. Below the header are a number of sections that show details
+about the working tree and the staging area. You can hide and show
+them as described in the previous section.
+
+The first section shows @emph{Untracked files}, if there are any. See
+@ref{Untracked files} for more details.
+
+Two section show your local changes. They are explained fully in the
+next chapter, @ref{Staging and Committing}.
+
+If the current branch is associated with a remote tracking branch, the
+status buffer shows the differences between the current branch and the
+tracking branch. See @ref{Pushing and Pulling} for more information.
+
+During a history rewriting session, the status buffer shows the
+@emph{Pending changes} and @emph{Pending commits} sections. See
+@ref{Rewriting} for more details.
+
+@node Untracked files
+@chapter Untracked files
+
+Untracked files are shown in the @emph{Untracked files} section.
+
+You can add a untracked file to the staging area with @kbd{s}. If
+point is on the @emph{Untracked files} section title when you it
+@kbd{s}, all untracked files are staged.
+
+Typing @kbd{C-u S} anywhere will also stage all untracked files,
+together with all changes to the tracked files.
+
+You can instruct Git to ignore them by typing @kbd{i}. This will add
+the filename to the @code{.gitignore} file. Typing @kbd{C-u i} will
+ask you for the name of the file to ignore. This is useful to ignore
+whole directories, for example. The @kbd{I} command is similar to
+@kbd{i} but will add the file to @code{.git/info/exclude} instead.
+
+To delete a untracked file forever, use @kbd{k}. If point is on the
+@emph{Untracked files} section title when you it @kbd{k}, all
+untracked files are deleted.
+
+@node Staging and Committing
+@chapter Staging and Committing
+
+Comitting with Git is a two step process: first you add the changes
+you want to commit to a 'staging area', and then you commit them to
+the repository. This allows you to only commit a subset of your local
+changes.
+
+Magit allows you to ignore the staging area if you wish. As long as
+your staging area is unused, Magit will show your uncomitted changes
+in a section named @emph{Changes}.
+
+When the staging area is in use, Magit uses two sections:
+@emph{Unstaged changes} and @emph{Staged changes}. The @emph{Staged
+changes} section shows the changes that will be included in the next
+commit, while the @emph{Unstaged changes} section shows the changes
+that will be left out.
+
+To move a unstaged hunk into the staging area, move point into the
+hunk and type @kbd{s}. Likewise, to unstage a hunk, move point into
+it and type @kbd{u}. If point is in a diff header when you type
+@kbd{s} or @kbd{u}, all hunks belonging to that diff are moved at the
+same time.
+
+If the region is active when you type @kbd{s} or @kbd{u}, only the
+changes in the region are staged or unstaged. (This works line by
+line: if the beginning of a line is in the region it is included in
+the changes, otherwise it is not.)
+
+To move all hunks of all diffs into the staging area in one go, type
+@kbd{S}. To unstage everything, type @kbd{U}.
+
+Typing @kbd{C-u S} will stage all untracked files in addition to the
+changes to tracked files.
+
+You can discard uncommitted changes by moving point into a hunk and
+typing @kbd{k}. The changes to discard are selected as with @kbd{s}
+and @kbd{u}.
+
+Before committing, you should write a short description of the
+changes.
+
+Type @kbd{c} to pop up a buffer where you can write your change
+description. Once you are happy with the description, type @kbd{C-c
+C-c} in that buffer to perform the commit.
+
+Typing @kbd{c} when the staging area is unused is a special situation.
+Normally, the next commit would be empty, but you can configure Magit
+to do something more useful by customizing the
+@code{magit-commit-all-when-nothing-staged} variable. One choice is
+to instruct the subsequent @kbd{C-c C-c} to commit all changes.
+Another choice is stage everything at the time of hitting @kbd{c}.
+
+You can type @kbd{C-c C-a} in the buffer with the change description
+to toggle a flag that determines whether the next commit will
+@emph{amend} the current commit in HEAD.
+
+Typing @kbd{C-c C-s} will toggle the @code{--signoff} option. The
+default is determined by the @code{magit-commit-signoff} customization
+variable.
+
+If you change your mind and don't want to go ahead with your commit
+while you are in the @code{*magit-log-edit*} buffer, you can just
+switch to another buffer, continue editing there, staging and
+unstaging things until you are happy, and then return to the
+@code{*magit-log-edit*} buffer, maybe via @kbd{C-x b}, or by hitting
+@kbd{c} again in a Magit buffer.
+
+If you want to erase the @code{*magit-log-edit*} buffer and bury it,
+you can hit @kbd{C-c C-k} in it.
+
+Typing @kbd{C} will also pop up the change description buffer, but in
+addition, it will try to insert a ChangeLog-style entry for the change
+that point is in.
+
+@node History
+@chapter History
+
+To show the repository history of your current head, type @kbd{l}. A
+new buffer will be shown that displays the history in a terse form.
+The first paragraph of each commit message is displayed, next to a
+representation of the relationships between commits.
+
+Giving a prefix argument to @kbd{l} will ask for the starting and end
+point of the history. This can be used to show the commits that are
+in one branch, but not in another, for example.
+
+Typing @kbd{L} (or @kbd{C-u L}) will show the log in a more verbose
+form.
+
+You can move point to a commit and then cause various things to happen
+with it. (The following commands work in any list of commit, such as
+the one shown in the @emph{Unpushed commits} section.)
+
+Typing @kbd{RET} will pop up more information about the current commit
+and move point into the new buffer. Typing @kbd{SPC} and @kbd{DEL}
+will also show the information, but will scroll the new buffer up or
+down (respectively) when typed again.
+
+Typing @kbd{a} will apply the current commit to your current branch.
+This is useful when you are browsing the history of some other branch
+and you want to `cherry-pick' some changes from it. A typical
+situation is applying selected bug fixes from the development version
+of a program to a release branch. The cherry-picked changes will not
+be committed automatically; you need to do that explicitly.
+
+Typing @kbd{A} will cherry-pick the current commit and will also
+commit the changes automatically when there have not been any
+conflicts.
+
+Typing @kbd{v} will revert the current commit. Thus, it will apply
+the changes made by that commit in reverse. This is obviously useful
+to cleanly undo changes that turned out to be wrong. As with @kbd{a},
+you need to commit the changes explicitly.
+
+Typing @kbd{C-w} will copy the sha1 of the current commit into the
+kill ring.
+
+Typing @kbd{=} will show the differences from the current commit to
+the @dfn{marked} commit.
+
+You can mark the current commit by typing @kbd{.}. When the current
+commit is already marked, typing @kbd{.} will unmark it. To unmark
+the marked commit no matter where point is, use @kbd{C-u .}.
+
+Some commands, such as @kbd{=}, will use the current commit and the
+marked commit as implicit arguments. Other commands will offer the
+marked commit as a default when prompting for their arguments.
+
+@node Reflogs
+@chapter Reflogs
+
+You can use @kbd{h} and @kbd{H} to browse your @emph{reflog}, the
+local history of changes made to your repository heads. Typing
+@kbd{H} will ask for a head, while @kbd{h} will show the reflog of
+@code{HEAD}.
+
+The resulting buffer is just like the buffer produced by @kbd{l} and
+@kbd{L} that shows the commit history.
+
+@node Diffing
+@chapter Diffing
+
+To show the changes from you working tree to another revision, type
+@kbd{d}. To show the changes between two arbitrary revisions, type
+@kbd{D}.
+
+You can use @kbd{a} within the diff output to apply the changes to
+your working tree. As usual when point is in a diff header for a
+file, all changes for that file are applied, and when it is in a hunk,
+only that hunk is. When the region is active, the applied changes are
+restricted to that region.
+
+Typing @kbd{v} will apply the selected changes in reverse.
+
+@node Tagging
+@chapter Tagging
+
+Typing @kbd{t} will make a lighweight tag. Typing @kbd{T} will make a
+annotated tag. It will put you in the normal @code{*magit-log-edit}
+buffer for writing commit messages, but typing @kbd{C-c C-c} in it
+will make the tag instead. This is controlled by the @code{Tag} field
+that will be added to the @code{*magit-log-edit*} buffer. You can
+edit it, if you like.
+
+@node Resetting
+@chapter Resetting
+
+Once you have added a commit to your local repository, you can not
+change that commit anymore in any way. But you can reset your current
+head to an earlier commit and start over.
+
+If you have published your history already, rewriting it in this way
+can be confusing and should be avoided. However, rewriting your local
+history is fine and it is often cleaner to fix mistakes this way than
+by reverting commits (with @kbd{v}, for example).
+
+Typing @kbd{x} will ask for a revision and reset your current head to
+it. No changes will be made to your working tree and staging area.
+Thus, the @emph{Staged changes} section in the status buffer will show
+the changes that you have removed from your commit history. You can
+commit the changes again as if you had just made them, thus rewriting
+history.
+
+Typing @kbd{x} while point is in a line that describes a commit will
+offer this commit as the default revision to reset to. Thus, you can
+move point to one of the commits in the @emph{Unpushed commits}
+section and hit @kbd{x RET} to reset your current head to it.
+
+Type @kbd{X} to reset your working tree and staging area to the most
+recently committed state. This will discard your local modifications,
+so be careful.
+
+You can give a prefix to @kbd{x} if you want to reset both the current
+head and your working tree to a given commit. This is the same as
+first using an unprefixed @kbd{x} to reset only the head, and then
+using @kbd{X}.
+
+@node Stashing
+@chapter Stashing
+
+You can create a new stash with @kbd{z}. Your stashes will be listed
+in the status buffer, and you can apply them with @kbd{a} and pop them
+with @kbd{A}. To drop a stash, use @kbd{k}.
+
+Typing @kbd{Z} will create a stash just like @kbd{z}, but will leave
+the changes in your working tree and index.
+
+You can visit and show stashes in the usual way: Typing @kbd{SPC} and
+@kbd{DEL} will pop up a buffer with the description of the stash and
+scroll it, typing @kbd{RET} will move point into that buffer.
+
+@node Branching
+@chapter Branching
+
+The current branch is indicated in the header of the status buffer.
+You can switch to a different branch by typing @kbd{b}. This will
+immediately checkout the branch into your working copy, so you
+shouldn't have any local modifications when switching branches.
+
+If you try to switch to a remote branch, Magit will offer to create a
+local tracking branch for it instead. This way, you can easily start
+working on new branches that have appeared in a remote repository.
+
+Similar to @kbd{x}, typing @kbd{b} while point is at a commit
+description will offer that commit as the default to switch to.
+This will result in a detached head.
+
+To create a new branch and switch to it immediately, type @kbd{B}.
+
+@node Wazzup
+@chapter Wazzup
+
+Typing @kbd{w} will show a summary of how your other branches relate
+to the current branch.
+
+For each branch, you will get a section that lists the commits in that
+branch that are not in the current branch. The sections are initially
+collapsed; you need to explicitly open them with @kbd{TAB} (or
+similar) to show the lists of commits.
+
+When point is on a @emph{N unmerged commits in ...} title, the
+corresponding branch will be offered as the default for a merge.
+
+Hitting @kbd{i} on a branch title will ignore this branch in the
+wazzup view. You can use @kbd{C-u w} to show all branches, including
+the ignored ones. Hitting @kbd{i} on an already ignored branch in
+that view will unignore it.
+
+@node Merging
+@chapter Merging
+
+Magit offers two ways to merge branches: manually and automatic. A
+manual merge will apply all changes to your working tree and staging
+area, but will not commit them, while a automatic merge will go ahead
+and commit them immediately.
+
+Type @kbd{m} to initiate a manual merge, and type @kbd{M} for a
+automatic merge.
+
+A manual merge is useful when carefully merging a new feature that you
+want to review and test before even committing it. A automatic merge
+is appropriate when you are on a feature branch and want to catch up
+with the master, say.
+
+After initiating a manual merge, the header of the status buffer will
+remind you that the next commit will be a merge commit (with more than
+one parent). If you want to abort a manual merge, just do a hard
+reset to HEAD with @kbd{X}.
+
+Merges can fail if the two branches you merge want to introduce
+conflicting changes. In that case, the automatic merge stops before the
+commit, essentially falling back to a manual merge. You need to resolve
+the conflicts for example with @kbd{e} and stage the resolved files, for
+example with @kbd{S}.
+
+You can not stage individual hunks one by one as you resolve them, you
+can only stage whole files once all conflicts in them have been
+resolved.
+
+@node Rebasing
+@chapter Rebasing
+
+Typing @kbd{R} in the status buffer will initiate a rebase or, if one
+is already in progress, ask you how to continue.
+
+When a rebase is stopped in the middle because of a conflict, the
+header of the status buffer will indicate how far along you are in the
+series of commits that are being replayed. When that happens, you
+should resolve the conflicts and stage everything and hit @kbd{R c} to
+continue the rebase. Alternatively, hitting @kbd{c} or @kbd{C} while
+in the middle of a rebase will also ask you whether to continue the
+rebase.
+
+Of course, you can initiate a rebase in any number of ways, by
+configuring @code{git pull} to rebase instead of merge, for example.
+Such a rebase can be finished with @kbd{R} as well.
+
+@node Rewriting
+@chapter Rewriting
+
+As hinted at earlier, you can rewrite your commit history. For
+example, you can reset he current head to an earlier commit with
+@kbd{x}. This leaves the working tree unchanged, and the status
+buffer will show all the changes that have been made since that new
+value of the current head. You can commit these changes again,
+possibly splitting them into multiple commits as you go along.
+
+Amending your last commit is a common special case of rewriting
+history like this.
+
+Another common way to rewrite history is to reset the head to an
+earlier commit, and then to cherry pick the previous commits in a
+different order. You could pick them from the reflog, for example.
+
+Magit has several commands that can simplify the book keeping
+associated with rewriting. These commands all start with the @kbd{r}
+prefix key.
+
+Typing @kbd{r s} will start a rewrite operation. You will be prompted
+for a @emph{base} commit, and all commits between the current head and
+this commit are put in a list of @emph{Pending commits} (including the
+base commit). The current head will then be reset to the parent of
+the base commit.
+
+You would then typically use @kbd{a} and @kbd{A} to cherry pick
+commits from the list of pending commits in the desired order, until
+all have been applied. Magit shows which commits have been applied by
+changing their marker from @code{*} to @code{.}.
+
+Using @kbd{A} will immediately commit the commit (as usual). If you
+want to combine multiple previous commits into a single new one, use
+@kbd{a} to apply them all to your working tree, and then commit them
+together.
+
+Magit has no explicit support for rewriting merge commits. It will
+happily include merge commits in the list of pending commits, but
+there is no way of replaying them automatically. You have to redo the
+merge explicitly.
+
+You can also use @kbd{v} to revert a commit when you have changed your
+mind. This will change the @code{.} mark back to @code{*}.
+
+Once you are done with the rewrite, type @kbd{r t} to remove the book
+keeping information from the status buffer.
+
+If you rather wish to start over, type @kbd{r a}. This will abort the
+rewriting, resetting the current head back to the value it had before
+the rewrite was started with @kbd{r s}.
+
+Typing @kbd{r f} will @emph{finish} the rewrite: it will apply all
+unused commits one after the other, as if you would us @kbd{A} with
+all of them.
+
+You can change the @kbd{*} and @kbd{.} marks of a pending commit
+explicitly with @kbd{r *} and @kbd{r .}.
+
+In addition to a list of pending commits, the status buffer will show
+the @emph{Pending changes}. This section shows the diff between the
+original head and the current head. You can use it to review the
+changes that you still need to rewrite, and you can apply hunks from
+it, like from any other diff.
+
+@node Pushing and Pulling
+@chapter Pushing and Pulling
+
+Magit will run @code{git push} when you type @kbd{P}. If you give a
+prefix argument to @kbd{P}, you will be prompted for the repository to
+push to. When no default remote repositor has been configured yet for
+the current branch, you will be prompted as well. Typing @kbd{P} will
+only push the current branch to the remote. In other words, it will
+run @code{git push <remote> <branch>}.
+
+Typing @kbd{f} will run @code{git remote update} and @kbd{F} will run
+@code{git pull}. When you don't have a default branch configured to
+be pulled into the current one, you will be asked for it.
+
+If there is a default remote repository for the current branch, Magit
+will show that repository in the status buffer header.
+
+In this case, the status buffer will also have a @emph{Unpushed
+commits} section that shows the commits on your current head that are
+not in the branch named @code{<remote>/<branch>}. This section works
+just like the history buffer: you can see details about a commit with
+@kbd{RET}, compare two of them with @kbd{.} and @kbd{=}, and you can
+reset your current head to one of them with @kbd{x}, for example.
+
+When the remote branch has changes that are not in the current branch,
+Magit shows them in a section called @emph{Unpulled changes}. Typing
+@kbd{F} will merge them into the current branch.
+
+@node Interfacing with Subversion
+@chapter Interfacing with Subversion
+
+Typing @kbd{N r} runs @code{git svn rebase} and typing @kbd{N c} runs
+@code{git svn dcommit}.
+
+@bye
diff --git a/emacs.d/lisp/magit/test/BAR.2 b/emacs.d/lisp/magit/test/BAR.2
new file mode 100644
index 0000000..2614c5e
--- /dev/null
+++ b/emacs.d/lisp/magit/test/BAR.2
@@ -0,0 +1 @@
+Hi Ho.
diff --git a/emacs.d/lisp/magit/test/FOO.2 b/emacs.d/lisp/magit/test/FOO.2
new file mode 100644
index 0000000..10ddd6d
--- /dev/null
+++ b/emacs.d/lisp/magit/test/FOO.2
@@ -0,0 +1 @@
+Hello!