From: Andreas Gerler Date: Thu, 24 Dec 2015 16:31:46 +0000 (+0100) Subject: updating magit. X-Git-Url: http://git.bundesbrandschatzamt.de/?a=commitdiff_plain;h=769059819d9f11add499cbbeac376a30e5b18e56;p=emacsconfig.git updating magit. --- diff --git a/elpa/magit-20151119.202/AUTHORS.md b/elpa/magit-20151119.202/AUTHORS.md deleted file mode 100644 index 4e547a58..00000000 --- a/elpa/magit-20151119.202/AUTHORS.md +++ /dev/null @@ -1,235 +0,0 @@ -Authors -======= - -The following people have contributed to Magit, including the -libraries `git-commit.el`, `magit-popup.el`, and `with-editor.el` -which are distributed as separate Elpa packages. - -For statistics see http://magit.vc/stats/authors.html. - -Names below are sorted alphabetically. - -Author ------- - -- Marius Vollmer - -Maintainer ----------- - -- Jonas Bernoulli - -Developers ----------- - -- Kyle Meyer -- Noam Postavsky - -Retired Maintainers and Developers ----------------------------------- - -- Nicolas Dudebout -- Peter J. Weisberg -- Pieter Praet -- Phil Jackson -- Rémi Vanicat -- Yann Hodique - -Contributors ------------- - -- Aaron Culich -- Abdo Roig-Maranges -- acple -- Adam Spiers -- Adeodato Simó -- Ævar Arnfjörð Bjarmason -- Alan Falloon -- Alex Dunn -- Alexey Voinov -- Alex Kost -- Alex Ott -- Andreas Fuchs -- Andreas Liljeqvist -- Andreas Rottmann -- Andrei Chițu -- Andrew Kirkpatrick -- Andrew Schwartzmeyer -- Andrey Smirnov -- Andriy Kmit' -- Andy Sawyer -- Barak A. Pearlmutter -- Bastian Beischer -- Ben Walton -- Bradley Wright -- Brandon W Maister -- Brian Warner -- Bryan Shell -- Chris Bernard -- Chris Done -- Chris Moore -- Chris Ring -- Christian Dietrich -- Christian Kluge -- Christopher Monsanto -- Cornelius Mika -- Craig Andera -- Dale Hagglund -- Damien Cassou -- Daniel Brockman -- Daniel Farina -- Daniel Hackney -- Dan LaManna -- David Abrahams -- David Hull -- David Wallin -- Dennis Paskorz -- Divye Kapoor -- Dominique Quatravaux -- Eli Barzilay -- Eric Davis -- Eric Schulte -- Evgkeni Sampelnikof -- Felix Geller -- Feng Li -- Florian Ragwitz -- Geoff Shannon -- George Kadianakis -- Graham Clark -- Greg A. Woods -- Greg Lucas -- Greg Sexton -- Guillaume Martres -- Hannu Koivisto -- Hans-Peter Deifel -- Ian Eure -- Ingo Lohmar -- Jan Tatarik -- Jasper St. Pierre -- Jeff Bellegarde -- Jeff Dairiki -- Jesse Alama -- Johann Klähn -- John Mastro -- John Wiegley -- Jonas Bernoulli -- Jonathan Roes -- Jordan Greenberg -- Josiah Schwab -- Julien Danjou -- Justin Caratzas -- Kan-Ru Chen -- Kan-Ru Chen -- Kimberly Wolk -- Kyle Meyer -- Laurent Laffont -- Leandro Facchinetti -- Lele Gaifax -- Leo Liu -- Leonardo Etcheverry -- Lingchao Xin -- Lluís Vilanova -- Loic Dachary -- Luís Borges de Oliveira -- Luke Amdor -- Manuel Vázquez Acosta -- Marcel Wolf -- Marc Herbert -- Marcin Bachry -- Marco Craveiro -- Marian Schubert -- Marius Vollmer -- Mark Hepburn -- Mark Karpov -- Mark Oteiza -- Matus Goljer -- Michael Fogleman -- Michael Griffiths -- Michal Sojka -- Miles Bader -- Mitchel Humpherys -- Moritz Bunkus -- Natalie Weizenbaum -- Nguyễn Tuấn Anh -- Nic Ferier -- Nick Alcock -- Nick Alexander -- Nick Dimiduk -- Nicklas Lindgren -- Nicolas Dudebout -- Nicolas Petton -- Nicolas Richard -- Nikolay Martynov -- Noam Postavsky -- Ole Arndt -- Oleh Krehel -- Óscar Fuentes -- Paul Stadig -- Pavel Holejsovsky -- Pekka Pessi -- Peter Eisentraut -- Peter Jaros -- Peter J. Weisberg -- Peter Vasil -- Philippe Vaucher -- Philipp Haselwarter -- Philip Weaver -- Phil Jackson -- Phil Sainty -- Pieter Praet -- Prathamesh Sonpatki -- rabio -- Rafael Laboissiere -- Raimon Grau -- Ramkumar Ramachandra -- Remco van 't Veer -- Rémi Vanicat -- René Stadler -- Richard Kim -- Robert Boone -- Robin Green -- Roger Crew -- Romain Francoise -- Ron Parker -- Roy Crihfield -- Rüdiger Sonderfeld -- Ryan C. Thompson -- Samuel Bronson -- Sanjoy Das -- Sean Bryant -- Sebastian Wiesner -- Sébastien Gross -- Seong-Kook Shin -- Sergey Pashinin -- Sergey Vinokurov -- Servilio Afre Puentes -- Štěpán Němec -- Steven Chow -- Steven E. Harris -- Steven Thomas -- Steven Vancoillie -- Steve Purcell -- Suhail Shergill -- Syohei Yoshida -- Takafumi Arakaki -- Teemu Likonen -- Teruki Shigitani -- Thierry Volpiatto -- Thomas A Caswell -- Thomas Frössman -- Thomas Jost -- Thomas Riccardi -- Tibor Simko -- Timo Juhani Lindfors -- Tim Perkins -- Tim Wraight -- Ting-Yu Lin -- Tom Feist -- Vineet Naik -- Wei Huang -- Wilfred Hughes -- Win Treese -- Xavier Noria -- Yann Hodique -- York Zhao -- Yuichi Higashi diff --git a/elpa/magit-20151119.202/COPYING b/elpa/magit-20151119.202/COPYING deleted file mode 100644 index 44325404..00000000 --- a/elpa/magit-20151119.202/COPYING +++ /dev/null @@ -1,676 +0,0 @@ - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - 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. - - - Copyright (C) - - 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 . - -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: - - Copyright (C) - 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 -. - - 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 -. - diff --git a/elpa/magit-20151119.202/dir b/elpa/magit-20151119.202/dir deleted file mode 100644 index 5fec5439..00000000 --- a/elpa/magit-20151119.202/dir +++ /dev/null @@ -1,18 +0,0 @@ -This is the file .../info/dir, which contains the -topmost node of the Info hierarchy, called (dir)Top. -The first time you invoke Info you start off looking at this node. - -File: dir, Node: Top This is the top of the INFO tree - - This (the Directory node) gives a menu of major topics. - Typing "q" exits, "?" lists all Info commands, "d" returns here, - "h" gives a primer for first-timers, - "mEmacs" visits the Emacs manual, etc. - - In Emacs, you can click mouse button 2 on a menu item or cross reference - to select it. - -* Menu: - -Emacs -* Magit: (magit). Using Git from Emacs with Magit. diff --git a/elpa/magit-20151119.202/git-rebase.el b/elpa/magit-20151119.202/git-rebase.el deleted file mode 100644 index 8ae5f10c..00000000 --- a/elpa/magit-20151119.202/git-rebase.el +++ /dev/null @@ -1,406 +0,0 @@ -;;; git-rebase.el --- Edit Git rebase files - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Phil Jackson -;; Maintainer: Jonas Bernoulli - -;; This file is not part of GNU Emacs. - -;; This file 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. - -;; This file 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 file. If not, see . - -;;; Commentary: - -;; This package assists the user in editing the list of commits to be -;; rewritten during an interactive rebase. - -;; When the user initiates an interactive rebase, e.g. using "r e" in -;; a Magit buffer or on the command line using "git rebase -i REV", -;; Git invokes the `$GIT_SEQUENCE_EDITOR' (or if that is undefined -;; `$GIT_EDITOR' or even `$EDITOR') letting the user rearrange, drop, -;; reword, edit, and squash commits. - -;; This package provides the major-mode `git-rebase-mode' which makes -;; doing so much more fun, by making the buffer more colorful and -;; providing the following commands: -;; -;; C-c C-c Tell Git to make it happen. -;; C-c C-k Tell Git that you changed your mind, i.e. abort. -;; -;; p Move point to previous line. -;; n Move point to next line. -;; -;; M-p Move the commit at point up. -;; M-n Move the commit at point down. -;; -;; k Drop the commit at point. -;; c Don't drop the commit at point. -;; r Change the message of the commit at point. -;; e Edit the commit at point. -;; s Squash the commit at point, into the one above. -;; f Like "s" but don't also edit the commit message. -;; x Add a script to be run with the commit at point -;; being checked out. -;; -;; RET Show the commit at point in another buffer. -;; C-/ Undo last change. - -;; You should probably also read the `git-rebase' manpage. - -;;; Code: - -(require 'dash) -(require 'easymenu) -(require 'server) -(require 'with-editor) -(require 'magit) - -(eval-when-compile (require 'recentf)) - -;;; Options -;;;; Variables - -(defgroup git-rebase nil - "Edit Git rebase sequences." - :group 'tools) - -(defcustom git-rebase-auto-advance t - "Whether to move to next line after changing a line." - :group 'git-rebase - :type 'boolean) - -(defcustom git-rebase-show-instructions t - "Whether to show usage instructions inside the rebase buffer." - :group 'git-rebase - :type 'boolean) - -(defcustom git-rebase-confirm-cancel t - "Whether confirmation is required to cancel." - :group 'git-rebase - :type 'boolean) - -;;;; Faces - -(defgroup git-rebase-faces nil - "Faces used by Git-Rebase mode." - :group 'faces - :group 'git-rebase) - -(defface git-rebase-hash - '((((class color) (background light)) :foreground "grey60") - (((class color) (background dark)) :foreground "grey40")) - "Face for commit hashes." - :group 'git-rebase-faces) - -(defface git-rebase-description nil - "Face for commit descriptions." - :group 'git-rebase-faces) - -(defface git-rebase-killed-action - '((t (:inherit font-lock-comment-face :strike-through t))) - "Face for commented action and exec lines." - :group 'git-rebase-faces) - -;;; Keymaps - -(defvar git-rebase-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map special-mode-map) - (define-key map (kbd "q") 'undefined) - (define-key map [remap undo] 'git-rebase-undo) - (define-key map (kbd "RET") 'git-rebase-show-commit) - (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up) - (define-key map (kbd "x") 'git-rebase-exec) - (define-key map (kbd "c") 'git-rebase-pick) - (define-key map (kbd "r") 'git-rebase-reword) - (define-key map (kbd "w") 'git-rebase-reword) - (define-key map (kbd "e") 'git-rebase-edit) - (define-key map (kbd "s") 'git-rebase-squash) - (define-key map (kbd "f") 'git-rebase-fixup) - (define-key map (kbd "y") 'git-rebase-insert) - (define-key map (kbd "k") 'git-rebase-kill-line) - (define-key map (kbd "C-k") 'git-rebase-kill-line) - (define-key map (kbd "p") 'git-rebase-backward-line) - (define-key map (kbd "n") 'forward-line) - (define-key map (kbd "M-p") 'git-rebase-move-line-up) - (define-key map (kbd "M-n") 'git-rebase-move-line-down) - (define-key map (kbd "M-") 'git-rebase-move-line-up) - (define-key map (kbd "M-") 'git-rebase-move-line-down) - (define-key map (kbd "C-x C-t") 'git-rebase-move-line-up) - map) - "Keymap for Git-Rebase mode.") - -(put 'git-rebase-reword :advertised-binding "r") - -(easy-menu-define git-rebase-mode-menu git-rebase-mode-map - "Git-Rebase mode menu" - '("Rebase" - ["Pick" git-rebase-pick t] - ["Reword" git-rebase-reword t] - ["Edit" git-rebase-edit t] - ["Squash" git-rebase-squash t] - ["Fixup" git-rebase-fixup t] - ["Kill" git-rebase-kill-line t] - ["Execute" git-rebase-exec t] - ["Move Down" git-rebase-move-line-down t] - ["Move Up" git-rebase-move-line-up t] - "---" - ["Cancel" with-editor-cancel t] - ["Finish" with-editor-finish t])) - -(defvar git-rebase-command-descriptions - '((with-editor-finish . "tell Git to make it happen") - (with-editor-cancel . "tell Git that you changed your mind, i.e. abort") - (previous-line . "move point to previous line") - (next-line . "move point to next line") - (git-rebase-move-line-up . "move the commit at point up") - (git-rebase-move-line-down . "move the commit at point down") - (git-rebase-show-commit . "show the commit at point in another buffer") - (undo . "undo last change") - (git-rebase-kill-line . "drop the commit at point"))) - -;;; Commands - -(defun git-rebase-pick () - "Use commit on current line." - (interactive) - (git-rebase-set-action "pick")) - -(defun git-rebase-reword () - "Edit message of commit on current line." - (interactive) - (git-rebase-set-action "reword")) - -(defun git-rebase-edit () - "Stop at the commit on the current line." - (interactive) - (git-rebase-set-action "edit")) - -(defun git-rebase-squash () - "Meld commit on current line into previous commit, edit message." - (interactive) - (git-rebase-set-action "squash")) - -(defun git-rebase-fixup () - "Meld commit on current line into previous commit, discard its message." - (interactive) - (git-rebase-set-action "fixup")) - -(defconst git-rebase-line - "^\\(#?\\(?:[fprse]\\|pick\\|reword\\|edit\\|squash\\|fixup\\|exec\\)\\) \ -\\(?:\\([^ \n]+\\) \\(.*\\)\\)?") - -(defun git-rebase-set-action (action) - (goto-char (line-beginning-position)) - (if (and (looking-at git-rebase-line) - (not (string-match-p "\\(e\\|exec\\)$" (match-string 1)))) - (let ((inhibit-read-only t)) - (replace-match action t t nil 1) - (when git-rebase-auto-advance - (forward-line))) - (ding))) - -(defun git-rebase-move-line-up () - "Move the current commit (or command) up." - (interactive) - (goto-char (line-beginning-position)) - (if (bobp) - (ding) - (when (looking-at git-rebase-line) - (let ((inhibit-read-only t)) - (transpose-lines 1)) - (forward-line -2)))) - -(defun git-rebase-move-line-down () - "Move the current commit (or command) down." - (interactive) - (goto-char (line-beginning-position)) - (when (and (looking-at git-rebase-line) - (save-excursion - (forward-line) - (looking-at git-rebase-line))) - (forward-line) - (let ((inhibit-read-only t)) - (transpose-lines 1)) - (forward-line -1))) - -(defun git-rebase-kill-line () - "Kill the current action line." - (interactive) - (goto-char (line-beginning-position)) - (when (and (looking-at git-rebase-line) - (not (eq (char-after) ?#))) - (let ((inhibit-read-only t)) - (insert ?#)) - (when git-rebase-auto-advance - (forward-line)))) - -(defun git-rebase-insert (rev) - "Read an arbitrary commit and insert it below current line." - (interactive (list (magit-read-branch-or-commit "Insert revision"))) - (forward-line) - (--if-let (magit-rev-format "%h %s" rev) - (let ((inhibit-read-only t)) - (insert "pick " it ?\n)) - (user-error "Unknown revision"))) - -(defun git-rebase-exec (arg) - "Insert a shell command to be run after the proceeding commit. - -If there already is such a command on the current line, then edit -that instead. With a prefix argument insert a new command even -when there already is one on the current line. With empty input -remove the command on the current line, if any." - (interactive "P") - (let ((inhibit-read-only t) initial command) - (unless arg - (goto-char (line-beginning-position)) - (when (looking-at "^#?\\(e\\|exec\\) \\(.*\\)") - (setq initial (match-string-no-properties 2)))) - (setq command (read-shell-command "Execute: " initial)) - (pcase (list command initial) - (`("" nil) (ding)) - (`("" ,_) - (delete-region (match-beginning 0) (1+ (match-end 0)))) - (`(,_ nil) - (forward-line) - (insert (concat "exec " command "\n")) - (unless git-rebase-auto-advance - (forward-line -1))) - (_ - (replace-match (concat "exec " command) t t) - (if git-rebase-auto-advance - (forward-line) - (goto-char (line-beginning-position))))))) - -(defun git-rebase-undo (&optional arg) - "Undo some previous changes. -Like `undo' but works in read-only buffers." - (interactive "P") - (let ((inhibit-read-only t)) - (undo arg))) - -(defun git-rebase-show-commit () - "Show the commit on the current line if any." - (interactive) - (save-excursion - (goto-char (line-beginning-position)) - (--if-let (and (looking-at git-rebase-line) - (match-string 2)) - (apply #'magit-show-commit it (magit-diff-arguments)) - (ding)))) - -(defun git-rebase-backward-line (&optional n) - "Move N lines backward (forward if N is negative). -Like `forward-line' but go into the opposite direction." - (interactive "p") - (forward-line (- n))) - -;;; Mode - -;;;###autoload -(define-derived-mode git-rebase-mode special-mode "Git Rebase" - "Major mode for editing of a Git rebase file. - -Rebase files are generated when you run 'git rebase -i' or run -`magit-interactive-rebase'. They describe how Git should perform -the rebase. See the documentation for git-rebase (e.g., by -running 'man git-rebase' at the command line) for details." - :group 'git-rebase - (setq font-lock-defaults '(git-rebase-mode-font-lock-keywords t t)) - (unless git-rebase-show-instructions - (let ((inhibit-read-only t)) - (flush-lines "^\\($\\|#\\)"))) - (with-editor-mode 1) - (when git-rebase-confirm-cancel - (add-hook 'with-editor-cancel-query-functions - 'git-rebase-cancel-confirm nil t)) - (add-hook 'with-editor-pre-cancel-hook 'git-rebase-autostash-save nil t) - (add-hook 'with-editor-post-cancel-hook 'git-rebase-autostash-apply nil t)) - -(defun git-rebase-cancel-confirm (force) - (or (not (buffer-modified-p)) force (y-or-n-p "Abort this rebase? "))) - -(defun git-rebase-autostash-save () - (--when-let (magit-file-line (magit-git-dir "rebase-merge/autostash")) - (push (cons 'stash it) with-editor-cancel-alist))) - -(defun git-rebase-autostash-apply () - (--when-let (cdr (assq 'stash with-editor-cancel-alist)) - (magit-stash-apply it))) - -(defconst git-rebase-mode-font-lock-keywords - `(("^\\([efprs]\\|pick\\|reword\\|edit\\|squash\\|fixup\\) \\([^ \n]+\\) \\(.*\\)" - (1 'font-lock-keyword-face) - (2 'git-rebase-hash) - (3 'git-rebase-description)) - ("^\\(exec\\) \\(.*\\)" - (1 'font-lock-keyword-face) - (2 'git-rebase-description)) - ("^#.*" 0 'font-lock-comment-face) - ("^#[^ \n].*" 0 'git-rebase-killed-action t)) - "Font lock keywords for Git-Rebase mode.") - -(defun git-rebase-mode-show-keybindings () - "Modify the \"Commands:\" section of the comment Git generates -at the bottom of the file so that in place of the one-letter -abbreviation for the command, it shows the command's keybinding. -By default, this is the same except for the \"pick\" command." - (let ((inhibit-read-only t)) - (save-excursion - (goto-char (point-min)) - (when (and git-rebase-show-instructions - (re-search-forward "^# Commands:\n" nil t)) - (--each git-rebase-command-descriptions - (insert (format "# %-8s %s\n" - (substitute-command-keys (format "\\[%s]" (car it))) - (cdr it)))) - (while (re-search-forward "^#\\( ?\\)\\([^,],\\) \\([^ ]+\\) = " nil t) - (replace-match " " t t nil 1) - (let ((cmd (intern (concat "git-rebase-" (match-string 3))))) - (replace-match - (format "%-8s" - (mapconcat #'key-description - (--filter (not (eq (elt it 0) 'menu-bar)) - (reverse (where-is-internal cmd))) - ", ")) - t t nil 2))))))) - -(add-hook 'git-rebase-mode-hook 'git-rebase-mode-show-keybindings t) - -(defun git-rebase-mode-disable-before-save-hook () - (set (make-local-variable 'before-save-hook) nil)) - -(add-hook 'git-rebase-mode-hook 'git-rebase-mode-disable-before-save-hook) - -;;;###autoload -(defconst git-rebase-filename-regexp "/git-rebase-todo\\'") -;;;###autoload -(add-to-list 'auto-mode-alist - (cons git-rebase-filename-regexp 'git-rebase-mode)) - -(add-to-list 'with-editor-server-window-alist - (cons git-rebase-filename-regexp 'switch-to-buffer)) - -(eval-after-load 'recentf - '(add-to-list 'recentf-exclude git-rebase-filename-regexp)) - -(provide 'git-rebase) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; git-rebase.el ends here diff --git a/elpa/magit-20151119.202/magit-apply.el b/elpa/magit-20151119.202/magit-apply.el deleted file mode 100644 index 2c2c5a48..00000000 --- a/elpa/magit-20151119.202/magit-apply.el +++ /dev/null @@ -1,519 +0,0 @@ -;;; magit-apply.el --- apply Git diffs - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library implements commands for applying Git diffs or parts -;; of such a diff. The supported "apply variants" are apply, stage, -;; unstage, discard, and reverse - more than Git itself knows about, -;; at least at the porcelain level. - -;;; Code: - -(require 'magit-core) -(require 'magit-diff) -(require 'magit-wip) - -;; For `magit-apply' -(declare-function magit-am-popup 'magit-sequence) -;; For `magit-discard-files' -(declare-function magit-checkout-stage 'magit) -(declare-function magit-checkout-read-stage 'magit) - -(require 'dired) - -;;; Options - -(defcustom magit-delete-by-moving-to-trash t - "Whether Magit uses the system's trash can." - :package-version '(magit . "2.1.0") - :group 'magit - :type 'boolean) - -;;; Commands -;;;; Apply - -(defun magit-apply (&rest args) - "Apply the change at point. -With a prefix argument and if necessary, attempt a 3-way merge." - (interactive (and current-prefix-arg (list "--3way"))) - (--when-let (magit-apply--get-selection) - (pcase (list (magit-diff-type) (magit-diff-scope)) - (`(,(or `unstaged `staged) ,_) - (user-error "Change is already in the working tree")) - (`(untracked ,(or `file `files)) - (magit-am-popup)) - (`(,_ region) (magit-apply-region it args)) - (`(,_ hunk) (magit-apply-hunk it args)) - (`(,_ hunks) (magit-apply-hunks it args)) - (`(,_ file) (magit-apply-diff it args)) - (`(,_ files) (magit-apply-diffs it args))))) - -(defun magit-apply-diffs (sections &rest args) - (setq sections (magit-apply--get-diffs sections)) - (magit-apply-patch sections args - (mapconcat - (lambda (s) - (concat (magit-diff-file-header s) - (buffer-substring (magit-section-content s) - (magit-section-end s)))) - sections ""))) - -(defun magit-apply-diff (section &rest args) - (setq section (car (magit-apply--get-diffs (list section)))) - (magit-apply-patch section args - (concat (magit-diff-file-header section) - (buffer-substring (magit-section-content section) - (magit-section-end section))))) - -(defun magit-apply-hunks (sections &rest args) - (let ((section (magit-section-parent (car sections)))) - (when (string-match "^diff --cc" (magit-section-value section)) - (user-error "Cannot un-/stage resolution hunks. Stage the whole file")) - (magit-apply-patch section args - (concat (magit-section-diff-header section) - (mapconcat - (lambda (s) - (buffer-substring (magit-section-start s) - (magit-section-end s))) - sections ""))))) - -(defun magit-apply-hunk (section &rest args) - (when (string-match "^diff --cc" (magit-section-parent-value section)) - (user-error "Cannot un-/stage resolution hunks. Stage the whole file")) - (magit-apply-patch (magit-section-parent section) args - (concat (magit-diff-file-header section) - (buffer-substring (magit-section-start section) - (magit-section-end section))))) - -(defun magit-apply-region (section &rest args) - (unless (magit-diff-context-p) - (user-error "Not enough context to apply region. Increase the context")) - (when (string-match "^diff --cc" (magit-section-parent-value section)) - (user-error "Cannot un-/stage resolution hunks. Stage the whole file")) - (magit-apply-patch (magit-section-parent section) args - (concat (magit-diff-file-header section) - (magit-diff-hunk-region-patch section args)))) - -(defun magit-apply-patch (section:s args patch) - (let* ((files (if (atom section:s) - (list (magit-section-value section:s)) - (mapcar 'magit-section-value section:s))) - (command (symbol-name this-command)) - (command (if (and command (string-match "^magit-\\([^-]+\\)" command)) - (match-string 1 command) - "apply"))) - (when (and magit-wip-before-change-mode (not inhibit-magit-refresh)) - (magit-wip-commit-before-change files (concat " before " command))) - (with-temp-buffer - (insert patch) - (magit-run-git-with-input nil - "apply" args "-p0" - (unless (magit-diff-context-p) "--unidiff-zero") - "--ignore-space-change" "-")) - (unless inhibit-magit-refresh - (when magit-wip-after-apply-mode - (magit-wip-commit-after-apply files (concat " after " command))) - (magit-refresh)))) - -(defun magit-apply--get-selection () - (or (magit-region-sections 'hunk 'file) - (let ((section (magit-current-section))) - (pcase (magit-section-type section) - ((or `hunk `file) section) - ((or `staged `unstaged `untracked - `stashed-index `stashed-worktree `stashed-untracked) - (magit-section-children section)) - (_ (user-error "Cannot apply this, it's not a change")))))) - -(defun magit-apply--get-diffs (sections) - (magit-section-case - ([file diffstat] - (--map (or (magit-get-section - (append `((file . ,(magit-section-value it))) - (magit-section-ident magit-root-section))) - (error "Cannot get required diff headers")) - sections)) - (t sections))) - -;;;; Stage - -(defun magit-stage () - "Add the change at point to the staging area." - (interactive) - (--when-let (magit-apply--get-selection) - (let ((inhibit-magit-revert t)) - (pcase (list (magit-diff-type) (magit-diff-scope)) - (`(untracked ,_) (magit-stage-untracked)) - (`(unstaged region) (magit-apply-region it "--cached")) - (`(unstaged hunk) (magit-apply-hunk it "--cached")) - (`(unstaged hunks) (magit-apply-hunks it "--cached")) - (`(unstaged file) (magit-stage-1 "-u" (list (magit-section-value it)))) - (`(unstaged files) (magit-stage-1 "-u" (magit-region-values))) - (`(unstaged list) (magit-stage-1 "-u")) - (`(staged ,_) (user-error "Already staged")) - (`(committed ,_) (user-error "Cannot stage committed changes")) - (`(undefined ,_) (user-error "Cannot stage this change")))))) - -;;;###autoload -(defun magit-stage-file (file) - "Stage all changes to FILE. -With a prefix argument or when there is no file at point ask for -the file to be staged. Otherwise stage the file at point without -requiring confirmation." - (interactive - (let* ((atpoint (magit-section-when (file))) - (current (magit-file-relative-name)) - (choices (nconc (magit-modified-files) - (magit-untracked-files))) - (default (car (member (or atpoint current) choices)))) - (list (if (or current-prefix-arg (not default)) - (magit-completing-read "Stage file" choices - nil t nil nil default) - default)))) - (magit-with-toplevel - (magit-stage-1 nil (list file)))) - -;;;###autoload -(defun magit-stage-modified (&optional all) - "Stage all changes to files modified in the worktree. -Stage all new content of tracked files and remove tracked files -that no longer exist in the working tree from the index also. -With a prefix argument also stage previously untracked (but not -ignored) files. -\('git add --update|--all .')." - (interactive (progn (unless (or (not (magit-anything-staged-p)) - (magit-confirm 'stage-all-changes)) - (user-error "Abort")) - (list current-prefix-arg))) - (magit-with-toplevel - (magit-stage-1 (if all "--all" "-u")))) - -(defun magit-stage-1 (arg &optional files) - (magit-wip-commit-before-change files " before stage") - (magit-run-git-no-revert "add" arg (if files (cons "--" files) ".")) - (magit-wip-commit-after-apply files " after stage")) - -(defun magit-stage-untracked () - (let* ((section (magit-current-section)) - (files (pcase (magit-diff-scope) - (`file (list (magit-section-value section))) - (`files (magit-region-values)) - (`list (magit-untracked-files)))) - plain repos) - (dolist (file files) - (if (magit-git-repo-p file t) - (push file repos) - (push file plain))) - (magit-wip-commit-before-change files " before stage") - (when plain - (magit-run-git-no-revert "add" "--" plain)) - (dolist (repo repos) - (let ((inhibit-magit-revert t)) - (save-excursion - (goto-char (magit-section-start - (magit-get-section - `((file . ,repo) (untracked) (status))))) - (call-interactively 'magit-submodule-add)))) - (magit-wip-commit-after-apply files " after stage"))) - -;;;; Unstage - -(defun magit-unstage () - "Remove the change at point from the staging area." - (interactive) - (--when-let (magit-apply--get-selection) - (let ((inhibit-magit-revert t)) - (pcase (list (magit-diff-type) (magit-diff-scope)) - (`(untracked ,_) (user-error "Cannot unstage untracked changes")) - (`(unstaged ,_) (user-error "Already unstaged")) - (`(staged region) (magit-apply-region it "--reverse" "--cached")) - (`(staged hunk) (magit-apply-hunk it "--reverse" "--cached")) - (`(staged hunks) (magit-apply-hunks it "--reverse" "--cached")) - (`(staged file) (magit-unstage-1 (list (magit-section-value it)))) - (`(staged files) (magit-unstage-1 (magit-region-values))) - (`(staged list) (magit-unstage-all)) - (`(committed ,_) (user-error "Cannot unstage committed changes")) - (`(undefined ,_) (user-error "Cannot unstage this change")))))) - -;;;###autoload -(defun magit-unstage-file (file) - "Unstage all changes to FILE. -With a prefix argument or when there is no file at point ask for -the file to be unstaged. Otherwise unstage the file at point -without requiring confirmation." - (interactive - (let* ((atpoint (magit-section-when (file))) - (current (magit-file-relative-name)) - (choices (magit-staged-files)) - (default (car (member (or atpoint current) choices)))) - (list (if (or current-prefix-arg (not default)) - (magit-completing-read "Unstage file" choices - nil t nil nil default) - default)))) - (magit-with-toplevel - (magit-unstage-1 (list file)))) - -(defun magit-unstage-1 (files) - (magit-wip-commit-before-change files " before unstage") - (if (magit-no-commit-p) - (magit-run-git "rm" "--cached" "--" files) - (magit-run-git "reset" "HEAD" "--" files)) - (magit-wip-commit-after-apply files " after unstage")) - -;;;###autoload -(defun magit-unstage-all () - "Remove all changes from the staging area." - (interactive) - (when (or (and (not (magit-anything-unstaged-p)) - (not (magit-untracked-files))) - (magit-confirm 'unstage-all-changes)) - (magit-wip-commit-before-change nil " before unstage") - (magit-run-git "reset" "HEAD" "--") - (magit-wip-commit-after-apply nil " after unstage"))) - -;;;; Discard - -(defun magit-discard () - "Remove the change at point." - (interactive) - (--when-let (magit-apply--get-selection) - (pcase (list (magit-diff-type) (magit-diff-scope)) - (`(committed ,_) (user-error "Cannot discard committed changes")) - (`(undefined ,_) (user-error "Cannot discard this change")) - (`(,_ region) (magit-discard-region it)) - (`(,_ hunk) (magit-discard-hunk it)) - (`(,_ hunks) (magit-discard-hunks it)) - (`(,_ file) (magit-discard-file it)) - (`(,_ files) (magit-discard-files it)) - (`(,_ list) (magit-discard-files it))))) - -(defun magit-discard-region (section) - (when (magit-confirm 'discard "Discard region") - (magit-discard-apply section 'magit-apply-region))) - -(defun magit-discard-hunk (section) - (when (magit-confirm 'discard "Discard hunk") - (magit-discard-apply section 'magit-apply-hunk))) - -(defun magit-discard-apply (section apply) - (if (eq (magit-diff-type section) 'unstaged) - (funcall apply section "--reverse") - (if (magit-anything-unstaged-p - nil (if (eq (magit-section-type section) 'file) - (magit-section-value section) - (magit-section-parent-value section))) - (progn (let ((inhibit-magit-refresh t)) - (funcall apply section "--reverse" "--cached") - (funcall apply section "--reverse")) - (magit-refresh)) - (funcall apply section "--reverse" "--index")))) - -(defun magit-discard-hunks (sections) - (when (magit-confirm 'discard - (format "Discard %s hunks from %s" - (length sections) - (magit-section-parent-value (car sections)))) - (magit-discard-apply-n sections 'magit-apply-hunks))) - -(defun magit-discard-apply-n (sections apply) - (let ((section (car sections))) - (if (eq (magit-diff-type section) 'unstaged) - (funcall apply sections "--reverse") - (if (magit-anything-unstaged-p - nil (if (eq (magit-section-type section) 'file) - (magit-section-value section) - (magit-section-parent-value section))) - (progn (let ((inhibit-magit-refresh t)) - (funcall apply sections "--reverse" "--cached") - (funcall apply sections "--reverse")) - (magit-refresh)) - (funcall apply sections "--reverse" "--index"))))) - -(defun magit-discard-file (section) - (magit-discard-files (list section))) - -(defun magit-discard-files (sections) - (let ((auto-revert-verbose nil) - (type (magit-diff-type (car sections))) - (status (magit-file-status)) - files delete resurrect rename discard discard-new resolve) - (dolist (section sections) - (let ((file (magit-section-value section))) - (push file files) - (pcase (cons (pcase type - (`staged ?X) - (`unstaged ?Y) - (`untracked ?Z)) - (cddr (assoc file status))) - (`(?Z) (--each (magit-untracked-files nil file) - (push it delete))) - ((or `(?Z ?? ??) `(?Z ?! ?!)) (push file delete)) - ((or `(?Z ?D ? ) `(,_ ?D ?D)) (push file delete)) - ((or `(,_ ?U ,_) `(,_ ,_ ?U)) (push file resolve)) - (`(,_ ?A ?A) (push file resolve)) - (`(?X ?M ,(or ? ?M ?D)) (push section discard)) - (`(?Y ,_ ?M ) (push section discard)) - (`(?X ?A ?M ) (push file discard-new)) - (`(?X ?C ?M ) (push file discard-new)) - (`(?X ?A ,(or ? ?D)) (push file delete)) - (`(?X ?C ,(or ? ?D)) (push file delete)) - (`(?X ?D ,(or ? ?M )) (push file resurrect)) - (`(?Y ,_ ?D ) (push file resurrect)) - (`(?X ?R ,(or ? ?M ?D)) (push file rename))))) - (unwind-protect - (let ((inhibit-magit-refresh t)) - (magit-wip-commit-before-change files " before discard") - (when resolve - (dolist (file (nreverse resolve)) - (magit-checkout-stage file (magit-checkout-read-stage file)))) - (magit-discard-files--resurrect (nreverse resurrect)) - (magit-discard-files--delete (nreverse delete) status) - (magit-discard-files--rename (nreverse rename) status) - (magit-discard-files--discard (nreverse discard) - (nreverse discard-new)) - (magit-wip-commit-after-apply files " after discard")) - (magit-refresh)))) - -(defun magit-discard-files--resurrect (files) - (when (magit-confirm-files 'resurrect files) - (if (eq (magit-diff-type) 'staged) - (magit-call-git "reset" "--" files) - (magit-call-git "checkout" "--" files)))) - -(defun magit-discard-files--delete (files status) - (when (if magit-delete-by-moving-to-trash - (magit-confirm-files 'trash files) - (magit-confirm-files 'delete files)) - (let ((delete-by-moving-to-trash magit-delete-by-moving-to-trash)) - (dolist (file files) - (if (memq (magit-diff-type) '(unstaged untracked)) - (dired-delete-file file dired-recursive-deletes - magit-delete-by-moving-to-trash) - (pcase (nth 3 (assoc file status)) - (? (delete-file file t) - (magit-call-git "rm" "--cached" "--" file)) - (?M (let ((temp (magit-git-string "checkout-index" "--temp" file))) - (string-match - (format "\\(.+?\\)\t%s" (regexp-quote file)) temp) - (rename-file (match-string 1 temp) - (setq temp (concat file ".~{index}~"))) - (delete-file temp t)) - (magit-call-git "rm" "--cached" "--force" "--" file)) - (?D (magit-call-git "checkout" "--" file) - (delete-file file t) - (magit-call-git "rm" "--cached" "--force" "--" file)))))))) - -(defun magit-discard-files--rename (files status) - (when (magit-confirm 'rename "Undo rename %s" "Undo %i renames" - (mapcar (lambda (file) - (setq file (assoc file status)) - (format "%s -> %s" (cadr file) (car file))) - files)) - (dolist (file files) - (let ((orig (cadr (assoc file status)))) - (if (file-exists-p file) - (magit-call-git "mv" file orig) - (magit-call-git "rm" "--cached" "--" file) - (magit-call-git "reset" "--" orig)))))) - -(defun magit-discard-files--discard (sections new-files) - (let ((files (mapcar #'magit-section-value sections))) - (when (magit-confirm-files - 'discard (append files new-files) - (format "Discard %s changes in" (magit-diff-type))) - (if (eq (magit-diff-type (car sections)) 'unstaged) - (magit-call-git "checkout" "--" files) - (when new-files - (magit-call-git "add" "--" new-files) - (magit-call-git "reset" "--" new-files)) - (let ((binaries (magit-staged-binary-files))) - (when binaries - (setq sections - (--filter (not (member (magit-section-value it) binaries)) - sections))) - (if (= (length sections) 1) - (magit-discard-apply (car sections) 'magit-apply-diff) - (magit-discard-apply-n sections 'magit-apply-diffs)) - (when binaries - (let ((modified (magit-modified-files t))) - (setq binaries (--separate (member it modified) binaries))) - (when (cadr binaries) - (magit-call-git "reset" "--" (cadr binaries))) - (when (car binaries) - (user-error - (concat - "Cannot discard staged changes to binary files, " - "which also have unstaged changes. Unstage instead."))))))))) - -;;;; Reverse - -(defun magit-reverse (&rest args) - "Reverse the change at point in the working tree." - (interactive (and current-prefix-arg (list "--3way"))) - (--when-let (magit-apply--get-selection) - (pcase (list (magit-diff-type) (magit-diff-scope)) - (`(untracked ,_) (user-error "Cannot reverse untracked changes")) - (`(unstaged ,_) (user-error "Cannot reverse unstaged changes")) - (`(,_ region) (magit-reverse-region it args)) - (`(,_ hunk) (magit-reverse-hunk it args)) - (`(,_ hunks) (magit-reverse-hunks it args)) - (`(,_ file) (magit-reverse-file it args)) - (`(,_ files) (magit-reverse-files it args)) - (`(,_ list) (magit-reverse-files it args))))) - -(defun magit-reverse-region (section args) - (when (magit-confirm 'reverse "Reverse region") - (apply 'magit-apply-region section "--reverse" args))) - -(defun magit-reverse-hunk (section args) - (when (magit-confirm 'reverse "Reverse hunk") - (apply 'magit-apply-hunk section "--reverse" args))) - -(defun magit-reverse-hunks (sections args) - (when (magit-confirm 'reverse - (format "Reverse %s hunks from %s" - (length sections) - (magit-section-parent-value (car sections)))) - (magit-apply-hunks sections "--reverse" args))) - -(defun magit-reverse-file (section args) - (magit-reverse-files (list section) args)) - -(defun magit-reverse-files (sections args) - (-let [(binaries sections) - (let ((bs (magit-staged-binary-files))) - (--separate (member (magit-section-value it) bs) sections))] - (when (magit-confirm-files 'reverse (mapcar #'magit-section-value sections)) - (if (= (length sections) 1) - (magit-apply-diff (car sections) "--reverse" args) - (magit-apply-diffs sections "--reverse" args))) - (when binaries - (user-error "Cannot reverse binary files")))) - -;;; magit-apply.el ends soon -(provide 'magit-apply) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-apply.el ends here diff --git a/elpa/magit-20151119.202/magit-autoloads.el b/elpa/magit-20151119.202/magit-autoloads.el deleted file mode 100644 index 144338ab..00000000 --- a/elpa/magit-20151119.202/magit-autoloads.el +++ /dev/null @@ -1,1336 +0,0 @@ -;;; magit-autoloads.el --- automatically extracted autoloads -;; -;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) - -;;;### (autoloads nil "git-rebase" "git-rebase.el" (22093 56217 0 -;;;;;; 0)) -;;; Generated autoloads from git-rebase.el - -(autoload 'git-rebase-mode "git-rebase" "\ -Major mode for editing of a Git rebase file. - -Rebase files are generated when you run 'git rebase -i' or run -`magit-interactive-rebase'. They describe how Git should perform -the rebase. See the documentation for git-rebase (e.g., by -running 'man git-rebase' at the command line) for details. - -\(fn)" t nil) - -(defconst git-rebase-filename-regexp "/git-rebase-todo\\'") - -(add-to-list 'auto-mode-alist (cons git-rebase-filename-regexp 'git-rebase-mode)) - -;;;*** - -;;;### (autoloads nil "magit" "magit.el" (22093 56217 0 0)) -;;; Generated autoloads from magit.el - -(autoload 'magit-status "magit" "\ -Show the status of the current Git repository in a buffer. -With a prefix argument prompt for a repository to be shown. -With two prefix arguments prompt for an arbitrary directory. -If that directory isn't the root of an existing repository -then offer to initialize it as a new repository. - -\(fn &optional DIRECTORY)" t nil) - -(autoload 'magit-status-internal "magit" "\ - - -\(fn DIRECTORY)" nil nil) - (autoload 'magit-show-refs-popup "magit" nil t) - -(autoload 'magit-show-refs-head "magit" "\ -List and compare references in a dedicated buffer. -Refs are compared with `HEAD'. - -\(fn &optional ARGS)" t nil) - -(autoload 'magit-show-refs-current "magit" "\ -List and compare references in a dedicated buffer. -Refs are compared with the current branch or `HEAD' if -it is detached. - -\(fn &optional ARGS)" t nil) - -(autoload 'magit-show-refs "magit" "\ -List and compare references in a dedicated buffer. -Refs are compared with a branch read form the user. - -\(fn &optional REF ARGS)" t nil) - -(autoload 'magit-find-file "magit" "\ -View FILE from REV. -Switch to a buffer visiting blob REV:FILE, -creating one if none already exists. - -\(fn REV FILE)" t nil) - -(autoload 'magit-find-file-other-window "magit" "\ -View FILE from REV, in another window. -Like `magit-find-file', but create a new window or reuse an -existing one. - -\(fn REV FILE)" t nil) - -(autoload 'magit-dired-jump "magit" "\ -Visit file at point using Dired. -With a prefix argument, visit in other window. If there -is no file at point then instead visit `default-directory'. - -\(fn &optional OTHER-WINDOW)" t nil) - -(autoload 'magit-checkout-file "magit" "\ -Checkout FILE from REV. - -\(fn REV FILE)" t nil) - -(autoload 'magit-init "magit" "\ -Initialize a Git repository, then show its status. - -If the directory is below an existing repository, then the user -has to confirm that a new one should be created inside. If the -directory is the root of the existing repository, then the user -has to confirm that it should be reinitialized. - -Non-interactively DIRECTORY is (re-)initialized unconditionally. - -\(fn DIRECTORY)" t nil) - (autoload 'magit-branch-popup "magit" nil t) - -(autoload 'magit-checkout "magit" "\ -Checkout REVISION, updating the index and the working tree. -If REVISION is a local branch then that becomes the current -branch. If it is something else then `HEAD' becomes detached. -Checkout fails if the working tree or the staging area contain -changes. - -\(git checkout REVISION). - -\(fn REVISION)" t nil) - -(autoload 'magit-branch "magit" "\ -Create BRANCH at branch or revision START-POINT. - -\(git branch [ARGS] BRANCH START-POINT). - -\(fn BRANCH START-POINT &optional ARGS)" t nil) - -(autoload 'magit-branch-and-checkout "magit" "\ -Create and checkout BRANCH at branch or revision START-POINT. - -\(git checkout [ARGS] -b BRANCH START-POINT). - -\(fn BRANCH START-POINT &optional ARGS)" t nil) - -(autoload 'magit-branch-spinoff "magit" "\ -Create new branch from the unpushed commits. - -Create and checkout a new branch starting at and tracking the -current branch. That branch in turn is reset to the last commit -it shares with its upstream. If the current branch has no -upstream or no unpushed commits, then the new branch is created -anyway and the previously current branch is not touched. - -This is useful to create a feature branch after work has already -began on the old branch (likely but not necessarily \"master\"). - -\(fn BRANCH &rest ARGS)" t nil) - -(autoload 'magit-branch-reset "magit" "\ -Reset a branch to the tip of another branch or any other commit. - -When resetting to another branch, then also set that branch as -the upstream of the branch being reset. - -When the branch being reset is the current branch, then do a -hard reset. If there are any uncommitted changes, then the user -has to confirming the reset because those changes would be lost. - -This is useful when you have started work on a feature branch but -realize it's all crap and want to start over. - -\(fn BRANCH TO &optional ARGS)" t nil) - -(autoload 'magit-branch-delete "magit" "\ -Delete one or multiple branches. -If the region marks multiple branches, then offer to delete -those, otherwise prompt for a single branch to be deleted, -defaulting to the branch at point. - -\(fn BRANCHES &optional FORCE)" t nil) - -(autoload 'magit-branch-set-upstream "magit" "\ -Change the UPSTREAM branch of BRANCH. - -\(fn BRANCH UPSTREAM)" t nil) - -(autoload 'magit-branch-unset-upstream "magit" "\ -Unset the upstream branch of BRANCH. - -\(fn BRANCH)" t nil) - -(autoload 'magit-branch-rename "magit" "\ -Rename branch OLD to NEW. -With prefix, forces the rename even if NEW already exists. - -\(git branch -m|-M OLD NEW). - -\(fn OLD NEW &optional FORCE)" t nil) - -(autoload 'magit-branch-edit-description "magit" "\ -Edit the description of BRANCH. - -\(fn BRANCH)" t nil) - (autoload 'magit-merge-popup "magit" nil t) - -(autoload 'magit-merge "magit" "\ -Merge commit REV into the current branch; using default message. - -Unless there are conflicts or a prefix argument is used create a -merge commit using a generic commit message and without letting -the user inspect the result. With a prefix argument pretend the -merge failed to give the user the opportunity to inspect the -merge. - -\(git merge --no-edit|--no-commit [ARGS] REV) - -\(fn REV &optional ARGS NOCOMMIT)" t nil) - -(autoload 'magit-merge-editmsg "magit" "\ -Merge commit REV into the current branch; and edit message. -Perform the merge and prepare a commit message but let the user -edit it. - -\(git merge --edit [ARGS] rev) - -\(fn REV &optional ARGS)" t nil) - -(autoload 'magit-merge-nocommit "magit" "\ -Merge commit REV into the current branch; pretending it failed. -Pretend the merge failed to give the user the opportunity to -inspect the merge and change the commit message. - -\(git merge --no-commit [ARGS] rev) - -\(fn REV &optional ARGS)" t nil) - -(autoload 'magit-merge-preview "magit" "\ -Preview result of merging REV into the current branch. - -\(fn REV)" t nil) - -(autoload 'magit-merge-abort "magit" "\ -Abort the current merge operation. - -\(git merge --abort) - -\(fn)" t nil) - -(autoload 'magit-reset-index "magit" "\ -Reset the index to COMMIT. -Keep the head and working tree as-is, so if COMMIT refers to the -head this effectivley unstages all changes. - -\(git reset COMMIT) - -\(fn COMMIT)" t nil) - -(autoload 'magit-reset "magit" "\ -Reset the head and index to COMMIT, but not the working tree. -With a prefix argument also reset the working tree. - -\(git reset --mixed|--hard COMMIT) - -\(fn COMMIT &optional HARD)" t nil) - -(autoload 'magit-reset-head "magit" "\ -Reset the head and index to COMMIT, but not the working tree. - -\(git reset --mixed COMMIT) - -\(fn COMMIT)" t nil) - -(autoload 'magit-reset-soft "magit" "\ -Reset the head to COMMIT, but not the index and working tree. - -\(git reset --soft REVISION) - -\(fn COMMIT)" t nil) - -(autoload 'magit-reset-hard "magit" "\ -Reset the head, index, and working tree to COMMIT. - -\(git reset --hard REVISION) - -\(fn COMMIT)" t nil) - (autoload 'magit-tag-popup "magit" nil t) - -(autoload 'magit-tag "magit" "\ -Create a new tag with the given NAME at REV. -With a prefix argument annotate the tag. - -\(git tag [--annotate] NAME REV) - -\(fn NAME REV &optional ARGS)" t nil) - -(autoload 'magit-tag-delete "magit" "\ -Delete one or more tags. -If the region marks multiple tags (and nothing else), then offer -to delete those, otherwise prompt for a single tag to be deleted, -defaulting to the tag at point. - -\(git tag -d TAGS) - -\(fn TAGS)" t nil) - (autoload 'magit-notes-popup "magit" nil t) - (autoload 'magit-submodule-popup "magit" nil t) - -(autoload 'magit-submodule-add "magit" "\ -Add the repository at URL as a submodule. -Optional PATH is the path to the submodule relative to the root -of the superproject. If it is nil then the path is determined -based on URL. - -\(fn URL &optional PATH)" t nil) - -(autoload 'magit-submodule-setup "magit" "\ -Clone and register missing submodules and checkout appropriate commits. - -\(fn)" t nil) - -(autoload 'magit-submodule-init "magit" "\ -Register submodules listed in \".gitmodules\" into \".git/config\". - -\(fn)" t nil) - -(autoload 'magit-submodule-update "magit" "\ -Clone missing submodules and checkout appropriate commits. -With a prefix argument also register submodules in \".git/config\". - -\(fn &optional INIT)" t nil) - -(autoload 'magit-submodule-sync "magit" "\ -Update each submodule's remote URL according to \".gitmodules\". - -\(fn)" t nil) - -(autoload 'magit-submodule-fetch "magit" "\ -Fetch all submodules. -With a prefix argument fetch all remotes. - -\(fn &optional ALL)" t nil) - -(autoload 'magit-submodule-deinit "magit" "\ -Unregister the submodule at PATH. - -\(fn PATH)" t nil) - -(defvar global-magit-file-mode nil "\ -Non-nil if Global-Magit-File mode is enabled. -See the command `global-magit-file-mode' for a description of this minor mode. -Setting this variable directly does not take effect; -either customize it (see the info node `Easy Customization') -or call the function `global-magit-file-mode'.") - -(custom-autoload 'global-magit-file-mode "magit" nil) - -(autoload 'global-magit-file-mode "magit" "\ -Toggle Magit-File mode in all buffers. -With prefix ARG, enable Global-Magit-File mode if ARG is positive; -otherwise, disable it. If called from Lisp, enable the mode if -ARG is omitted or nil. - -Magit-File mode is enabled in all buffers where -`magit-file-mode-turn-on' would do it. -See `magit-file-mode' for more information on Magit-File mode. - -\(fn &optional ARG)" t nil) - (autoload 'magit-dispatch-popup "magit" nil t) - (autoload 'magit-run-popup "magit" nil t) - -(autoload 'magit-git-command "magit" "\ -Execute a Git subcommand asynchronously, displaying the output. -With a prefix argument run Git in the root of the current -repository, otherwise in `default-directory'. - -\(fn ARGS DIRECTORY)" t nil) - -(autoload 'magit-git-command-topdir "magit" "\ -Execute a Git subcommand asynchronously, displaying the output. -Run Git in the top-level directory of the current repository. - -\(fn)" t nil) - -(autoload 'magit-shell-command "magit" "\ -Execute a shell command asynchronously, displaying the output. -With a prefix argument run the command in the root of the current -repository, otherwise in `default-directory'. - -\(fn ARGS DIRECTORY)" t nil) - -(autoload 'magit-shell-command-topdir "magit" "\ -Execute a shell command asynchronously, displaying the output. -Run the command in the top-level directory of the current repository. - -\(fn)" t nil) - -(autoload 'magit-version "magit" "\ -Return the version of Magit currently in use. -When called interactive also show the used versions of Magit, -Git, and Emacs in the echo area. - -\(fn)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-apply" "magit-apply.el" (22093 56217 -;;;;;; 0 0)) -;;; Generated autoloads from magit-apply.el - -(autoload 'magit-stage-file "magit-apply" "\ -Stage all changes to FILE. -With a prefix argument or when there is no file at point ask for -the file to be staged. Otherwise stage the file at point without -requiring confirmation. - -\(fn FILE)" t nil) - -(autoload 'magit-stage-modified "magit-apply" "\ -Stage all changes to files modified in the worktree. -Stage all new content of tracked files and remove tracked files -that no longer exist in the working tree from the index also. -With a prefix argument also stage previously untracked (but not -ignored) files. -\('git add --update|--all .'). - -\(fn &optional ALL)" t nil) - -(autoload 'magit-unstage-file "magit-apply" "\ -Unstage all changes to FILE. -With a prefix argument or when there is no file at point ask for -the file to be unstaged. Otherwise unstage the file at point -without requiring confirmation. - -\(fn FILE)" t nil) - -(autoload 'magit-unstage-all "magit-apply" "\ -Remove all changes from the staging area. - -\(fn)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-bisect" "magit-bisect.el" (22093 56217 -;;;;;; 0 0)) -;;; Generated autoloads from magit-bisect.el - (autoload 'magit-bisect-popup "magit-bisect" nil t) - -(autoload 'magit-bisect-start "magit-bisect" "\ -Start a bisect session. - -Bisecting a bug means to find the commit that introduced it. -This command starts such a bisect session by asking for a know -good and a bad commit. To move the session forward use the -other actions from the bisect popup (\\\\[magit-bisect-popup]). - -\(fn BAD GOOD)" t nil) - -(autoload 'magit-bisect-reset "magit-bisect" "\ -After bisecting, cleanup bisection state and return to original `HEAD'. - -\(fn)" t nil) - -(autoload 'magit-bisect-good "magit-bisect" "\ -While bisecting, mark the current commit as good. -Use this after you have asserted that the commit does not contain -the bug in question. - -\(fn)" t nil) - -(autoload 'magit-bisect-bad "magit-bisect" "\ -While bisecting, mark the current commit as bad. -Use this after you have asserted that the commit does contain the -bug in question. - -\(fn)" t nil) - -(autoload 'magit-bisect-skip "magit-bisect" "\ -While bisecting, skip the current commit. -Use this if for some reason the current commit is not a good one -to test. This command lets Git choose a different one. - -\(fn)" t nil) - -(autoload 'magit-bisect-run "magit-bisect" "\ -Bisect automatically by running commands after each step. - -Unlike `git bisect run' this can be used before bisecting has -begun. In that case it behaves like `git bisect start; git -bisect run'. - -\(fn CMDLINE &optional BAD GOOD)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-blame" "magit-blame.el" (22093 56217 -;;;;;; 0 0)) -;;; Generated autoloads from magit-blame.el - (autoload 'magit-blame-popup "magit-blame" nil t) - -(autoload 'magit-blame "magit-blame" "\ -Display edit history of FILE up to REVISION. - -Interactively blame the file being visited in the current buffer. -If the buffer visits a revision of that file, then blame up to -that revision, otherwise blame the file's full history, including -uncommitted changes. - -If Magit-Blame mode is already turned on then blame recursively, by -visiting REVISION:FILE (using `magit-find-file'), where revision -is the revision before the revision that added the lines at -point. - -ARGS is a list of additional arguments to pass to `git blame'; -only arguments available from `magit-blame-popup' should be used. - -\(fn REVISION FILE &optional ARGS)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-commit" "magit-commit.el" (22093 56217 -;;;;;; 0 0)) -;;; Generated autoloads from magit-commit.el - -(autoload 'magit-commit "magit-commit" "\ -Create a new commit on HEAD. -With a prefix argument amend to the commit at HEAD instead. - -\(git commit [--amend] ARGS) - -\(fn &optional ARGS)" t nil) - -(autoload 'magit-commit-amend "magit-commit" "\ -Amend the last commit. - -\(git commit --amend ARGS) - -\(fn &optional ARGS)" t nil) - -(autoload 'magit-commit-extend "magit-commit" "\ -Amend the last commit, without editing the message. - -With a prefix argument keep the committer date, otherwise change -it. The option `magit-commit-extend-override-date' can be used -to inverse the meaning of the prefix argument. -\(git commit ---amend --no-edit) - -\(fn &optional ARGS OVERRIDE-DATE)" t nil) - -(autoload 'magit-commit-reword "magit-commit" "\ -Reword the last commit, ignoring staged changes. - -With a prefix argument keep the committer date, otherwise change -it. The option `magit-commit-reword-override-date' can be used -to inverse the meaning of the prefix argument. - -Non-interactively respect the optional OVERRIDE-DATE argument -and ignore the option. - -\(git commit --amend --only) - -\(fn &optional ARGS OVERRIDE-DATE)" t nil) - -(autoload 'magit-commit-fixup "magit-commit" "\ -Create a fixup commit. - -With a prefix argument the target COMMIT has to be confirmed. -Otherwise the commit at point may be used without confirmation -depending on the value of option `magit-commit-squash-confirm'. - -\(fn &optional COMMIT ARGS)" t nil) - -(autoload 'magit-commit-squash "magit-commit" "\ -Create a squash commit, without editing the squash message. - -With a prefix argument the target COMMIT has to be confirmed. -Otherwise the commit at point may be used without confirmation -depending on the value of option `magit-commit-squash-confirm'. - -\(fn &optional COMMIT ARGS)" t nil) - -(autoload 'magit-commit-augment "magit-commit" "\ -Create a squash commit, editing the squash message. - -With a prefix argument the target COMMIT has to be confirmed. -Otherwise the commit at point may be used without confirmation -depending on the value of option `magit-commit-squash-confirm'. - -\(fn &optional COMMIT ARGS)" t nil) - -(autoload 'magit-commit-instant-fixup "magit-commit" "\ -Create a fixup commit targeting COMMIT and instantly rebase. - -\(fn &optional COMMIT ARGS)" t nil) - -(autoload 'magit-commit-instant-squash "magit-commit" "\ -Create a squash commit targeting COMMIT and instantly rebase. - -\(fn &optional COMMIT ARGS)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-diff" "magit-diff.el" (22093 56217 0 -;;;;;; 0)) -;;; Generated autoloads from magit-diff.el - -(autoload 'magit-diff-dwim "magit-diff" "\ -Show changes for the thing at point. - -\(fn &optional ARGS FILES)" t nil) - -(autoload 'magit-diff "magit-diff" "\ -Show differences between two commits. - -REV-OR-RANGE should be a RANGE or a single revision. If it is a -revision, then show changes in the working tree relative to that -revision. If it is a range, but one side is omitted, then show -changes relative to `HEAD'. - -If the region is active, use the revisions on the first and last -line of the region as the two sides of the range. With a prefix -argument, instead of diffing the revisions, choose a revision to -view changes along, starting at the common ancestor of both -revisions (i.e., use a \"...\" range). - -\(fn REV-OR-RANGE &optional ARGS FILES)" t nil) - -(autoload 'magit-diff-working-tree "magit-diff" "\ -Show changes between the current working tree and the `HEAD' commit. -With a prefix argument show changes between the working tree and -a commit read from the minibuffer. - -\(fn &optional REV ARGS FILES)" t nil) - -(autoload 'magit-diff-staged "magit-diff" "\ -Show changes between the index and the `HEAD' commit. -With a prefix argument show changes between the index and -a commit read from the minibuffer. - -\(fn &optional REV ARGS FILES)" t nil) - -(autoload 'magit-diff-unstaged "magit-diff" "\ -Show changes between the working tree and the index. - -\(fn &optional ARGS FILES)" t nil) - -(autoload 'magit-diff-unpushed "magit-diff" "\ -Show unpushed changes. - -\(fn &optional ARGS FILES)" t nil) - -(autoload 'magit-diff-unpulled "magit-diff" "\ -Show unpulled changes. - -\(fn &optional ARGS FILES)" t nil) - -(autoload 'magit-diff-while-committing "magit-diff" "\ -While committing, show the changes that are about to be committed. -While amending, invoking the command again toggles between -showing just the new changes or all the changes that will -be commited. - -\(fn &optional ARGS FILES)" t nil) - -(autoload 'magit-diff-paths "magit-diff" "\ -Show changes between any two files on disk. - -\(fn A B)" t nil) - -(autoload 'magit-show-commit "magit-diff" "\ -Show the revision at point. -If there is no revision at point or with a prefix argument prompt -for a revision. - -\(fn REV &optional ARGS FILES MODULE)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-ediff" "magit-ediff.el" (22093 56217 -;;;;;; 0 0)) -;;; Generated autoloads from magit-ediff.el - (autoload 'magit-ediff-popup "magit-ediff" nil t) - -(autoload 'magit-ediff-resolve "magit-ediff" "\ -Resolve outstanding conflicts in FILE using Ediff. -FILE has to be relative to the top directory of the repository. - -In the rare event that you want to manually resolve all -conflicts, including those already resolved by Git, use -`ediff-merge-revisions-with-ancestor'. - -\(fn FILE)" t nil) - -(autoload 'magit-ediff-stage "magit-ediff" "\ -Stage and unstage changes to FILE using Ediff. -FILE has to be relative to the top directory of the repository. - -\(fn FILE)" t nil) - -(autoload 'magit-ediff-compare "magit-ediff" "\ -Compare REVA:FILEA with REVB:FILEB using Ediff. - -FILEA and FILEB have to be relative to the top directory of the -repository. If REVA or REVB is nil then this stands for the -working tree state. - -If the region is active, use the revisions on the first and last -line of the region. With a prefix argument, instead of diffing -the revisions, choose a revision to view changes along, starting -at the common ancestor of both revisions (i.e., use a \"...\" -range). - -\(fn REVA REVB FILEA FILEB)" t nil) - -(autoload 'magit-ediff-dwim "magit-ediff" "\ -Compare, stage, or resolve using Ediff. -This command tries to guess what file, and what commit or range -the user wants to compare, stage, or resolve using Ediff. It -might only be able to guess either the file, or range or commit, -in which case the user is asked about the other. It might not -always guess right, in which case the appropriate `magit-ediff-*' -command has to be used explicitly. If it cannot read the user's -mind at all, then it asks the user for a command to run. - -\(fn)" t nil) - -(autoload 'magit-ediff-show-staged "magit-ediff" "\ -Show staged changes using Ediff. - -This only allows looking at the changes; to stage, unstage, -and discard changes using Ediff, use `magit-ediff-stage'. - -FILE must be relative to the top directory of the repository. - -\(fn FILE)" t nil) - -(autoload 'magit-ediff-show-unstaged "magit-ediff" "\ -Show unstaged changes using Ediff. - -This only allows looking at the changes; to stage, unstage, -and discard changes using Ediff, use `magit-ediff-stage'. - -FILE must be relative to the top directory of the repository. - -\(fn FILE)" t nil) - -(autoload 'magit-ediff-show-working-tree "magit-ediff" "\ -Show changes between HEAD and working tree using Ediff. -FILE must be relative to the top directory of the repository. - -\(fn FILE)" t nil) - -(autoload 'magit-ediff-show-commit "magit-ediff" "\ -Show changes introduced by COMMIT using Ediff. - -\(fn COMMIT)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-extras" "magit-extras.el" (22093 56217 -;;;;;; 0 0)) -;;; Generated autoloads from magit-extras.el - -(autoload 'magit-run-git-gui "magit-extras" "\ -Run `git gui' for the current git repository. - -\(fn)" t nil) - -(autoload 'magit-run-git-gui-blame "magit-extras" "\ -Run `git gui blame' on the given FILENAME and COMMIT. -Interactively run it for the current file and the HEAD, with a -prefix or when the current file cannot be determined let the user -choose. When the current buffer is visiting FILENAME instruct -blame to center around the line point is on. - -\(fn COMMIT FILENAME &optional LINENUM)" t nil) - -(autoload 'magit-run-gitk "magit-extras" "\ -Run `gitk' in the current repository. - -\(fn)" t nil) - -(autoload 'magit-run-gitk-branches "magit-extras" "\ -Run `gitk --branches' in the current repository. - -\(fn)" t nil) - -(autoload 'magit-run-gitk-all "magit-extras" "\ -Run `gitk --all' in the current repository. - -\(fn)" t nil) - -(autoload 'magit-clean "magit-extras" "\ -Remove untracked files from the working tree. -With a prefix argument also remove ignored files, -with two prefix arguments remove ignored files only. - -\(git clean -f -d [-x|-X]) - -\(fn &optional ARG)" t nil) - -(autoload 'magit-gitignore "magit-extras" "\ -Instruct Git to ignore FILE-OR-PATTERN. -With a prefix argument only ignore locally. - -\(fn FILE-OR-PATTERN &optional LOCAL)" t nil) - -(autoload 'magit-gitignore-locally "magit-extras" "\ -Instruct Git to locally ignore FILE-OR-PATTERN. - -\(fn FILE-OR-PATTERN)" t nil) - -(autoload 'magit-add-change-log-entry "magit-extras" "\ -Find change log file and add date entry and item for current change. -This differs from `add-change-log-entry' (which see) in that -it acts on the current hunk in a Magit buffer instead of on -a position in a file-visiting buffer. - -\(fn &optional WHOAMI FILE-NAME OTHER-WINDOW)" t nil) - -(autoload 'magit-add-change-log-entry-other-window "magit-extras" "\ -Find change log file in other window and add entry and item. -This differs from `add-change-log-entry-other-window' (which see) -in that it acts on the current hunk in a Magit buffer instead of -on a position in a file-visiting buffer. - -\(fn &optional WHOAMI FILE-NAME)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-log" "magit-log.el" (22093 56217 0 0)) -;;; Generated autoloads from magit-log.el - -(autoload 'magit-log-current "magit-log" "\ -Show log for the current branch. -When `HEAD' is detached or with a prefix argument show log for -one or more revs read from the minibuffer. - -\(fn REVS &optional ARGS FILES)" t nil) - -(autoload 'magit-log "magit-log" "\ -Show log for one or more revs read from the minibuffer. -The user can input any revision or revisions separated by a -space, or even ranges, but only branches and tags, and a -representation of the commit at point, are available as -completion candidates. - -\(fn REVS &optional ARGS FILES)" t nil) - -(autoload 'magit-log-head "magit-log" "\ -Show log for `HEAD'. - -\(fn &optional ARGS FILES)" t nil) - -(autoload 'magit-log-branches "magit-log" "\ -Show log for all local branches and `HEAD'. - -\(fn &optional ARGS FILES)" t nil) - -(autoload 'magit-log-all-branches "magit-log" "\ -Show log for all local and remote branches and `HEAD'. - -\(fn &optional ARGS FILES)" t nil) - -(autoload 'magit-log-all "magit-log" "\ -Show log for all references and `HEAD'. - -\(fn &optional ARGS FILES)" t nil) - -(autoload 'magit-log-buffer-file "magit-log" "\ -Show log for the blob or file visited in the current buffer. -With a prefix argument or when `--follow' is part of -`magit-log-arguments', then follow renames. - -\(fn &optional FOLLOW BEG END)" t nil) - -(autoload 'magit-reflog-current "magit-log" "\ -Display the reflog of the current branch. - -\(fn)" t nil) - -(autoload 'magit-reflog "magit-log" "\ -Display the reflog of a branch. - -\(fn REF)" t nil) - -(autoload 'magit-reflog-head "magit-log" "\ -Display the `HEAD' reflog. - -\(fn)" t nil) - -(autoload 'magit-cherry "magit-log" "\ -Show commits in a branch that are not merged in the upstream branch. - -\(fn HEAD UPSTREAM)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-remote" "magit-remote.el" (22093 56217 -;;;;;; 0 0)) -;;; Generated autoloads from magit-remote.el - -(autoload 'magit-clone "magit-remote" "\ -Clone the REPOSITORY to DIRECTORY. -Then show the status buffer for the new repository. - -\(fn REPOSITORY DIRECTORY)" t nil) - (autoload 'magit-remote-popup "magit-remote" nil t) - -(autoload 'magit-remote-add "magit-remote" "\ -Add a remote named REMOTE and fetch it. - -\(fn REMOTE URL)" t nil) - -(autoload 'magit-remote-rename "magit-remote" "\ -Rename the remote named OLD to NEW. - -\(fn OLD NEW)" t nil) - -(autoload 'magit-remote-set-url "magit-remote" "\ -Change the url of the remote named REMOTE to URL. - -\(fn REMOTE URL)" t nil) - -(autoload 'magit-remote-remove "magit-remote" "\ -Delete the remote named REMOTE. - -\(fn REMOTE)" t nil) - (autoload 'magit-fetch-popup "magit-remote" nil t) - -(autoload 'magit-fetch-current "magit-remote" "\ -Fetch from the upstream repository of the current branch. -If `HEAD' is detached or if the upstream is not configured, -then read the remote. - -\(fn REMOTE &optional ARGS)" t nil) - -(autoload 'magit-fetch "magit-remote" "\ -Fetch from another repository. - -\(fn REMOTE &optional ARGS)" t nil) - -(autoload 'magit-fetch-all "magit-remote" "\ -Fetch from all configured remotes. - -\(fn &optional ARGS)" t nil) - (autoload 'magit-pull-popup "magit-remote" nil t) - -(autoload 'magit-pull-current "magit-remote" "\ -Fetch and merge into current branch. - -\(fn REMOTE BRANCH &optional ARGS)" t nil) - -(autoload 'magit-pull "magit-remote" "\ -Fetch from another repository and merge a fetched branch. - -\(fn REMOTE BRANCH &optional ARGS)" t nil) - (autoload 'magit-push-popup "magit-remote" nil t) - -(autoload 'magit-push-current "magit-remote" "\ -Push the current branch to its upstream branch. -If the upstream isn't set, then read the remote branch. - -If `magit-push-always-verify' is not nil, however, always read -the remote branch. - -\(fn BRANCH REMOTE &optional REMOTE-BRANCH ARGS)" t nil) - -(autoload 'magit-push "magit-remote" "\ -Push a branch to its upstream branch. -If the upstream isn't set, then read the remote branch. - -If `magit-push-always-verify' is not nil, however, always read -the remote branch. - -\(fn BRANCH REMOTE &optional REMOTE-BRANCH ARGS)" t nil) - -(autoload 'magit-push-elsewhere "magit-remote" "\ -Push a branch or commit to some remote branch. -Read the local and remote branch. - -\(fn BRANCH REMOTE REMOTE-BRANCH &optional ARGS)" t nil) - -(autoload 'magit-push-quickly "magit-remote" "\ -Push the current branch to some remote. -When the Git variable `magit.pushRemote' is set, then push to -that remote. If that variable is undefined or the remote does -not exist, then push to \"origin\". If that also doesn't exist -then raise an error. The local branch is pushed to the remote -branch with the same name. - -\(fn &optional ARGS)" t nil) - -(autoload 'magit-push-implicitly "magit-remote" "\ -Push without explicitly specifing what to push. -This runs `git push -v'. What is being pushed depends on various -Git variables as described in the `git-push(1)' and `git-config(1)' -manpages. - -\(fn &optional ARGS)" t nil) - -(autoload 'magit-push-matching "magit-remote" "\ -Push all matching branches to another repository. -If multiple remotes exit, then read one from the user. -If just one exists, use that without requiring confirmation. - -\(fn REMOTE &optional ARGS)" t nil) - -(autoload 'magit-push-tag "magit-remote" "\ -Push a tag to another repository. - -\(fn TAG REMOTE &optional ARGS)" t nil) - (autoload 'magit-patch-popup "magit-remote" nil t) - -(autoload 'magit-format-patch "magit-remote" "\ -Create patches for the commits in RANGE. -When a single commit is given for RANGE, create a patch for the -changes introduced by that commit (unlike 'git format-patch' -which creates patches for all commits that are reachable from -HEAD but not from the specified commit). - -\(fn RANGE ARGS)" t nil) - -(autoload 'magit-request-pull "magit-remote" "\ -Request upstream to pull from you public repository. - -URL is the url of your publically accessible repository. -START is a commit that already is in the upstream repository. -END is the last commit, usually a branch name, which upstream -is asked to pull. START has to be reachable from that commit. - -\(fn URL START END)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-sequence" "magit-sequence.el" (22093 -;;;;;; 56217 0 0)) -;;; Generated autoloads from magit-sequence.el - -(autoload 'magit-sequencer-continue "magit-sequence" "\ -Resume the current cherry-pick or revert sequence. - -\(fn)" t nil) - -(autoload 'magit-sequencer-skip "magit-sequence" "\ -Skip the stopped at commit during a cherry-pick or revert sequence. - -\(fn)" t nil) - -(autoload 'magit-sequencer-abort "magit-sequence" "\ -Abort the current cherry-pick or revert sequence. -This discards all changes made since the sequence started. - -\(fn)" t nil) - (autoload 'magit-cherry-pick-popup "magit-sequence" nil t) - -(autoload 'magit-cherry-pick "magit-sequence" "\ -Cherry-pick COMMIT. -Prompt for a commit, defaulting to the commit at point. If -the region selects multiple commits, then pick all of them, -without prompting. - -\(fn COMMIT &optional ARGS)" t nil) - -(autoload 'magit-cherry-apply "magit-sequence" "\ -Apply the changes in COMMIT but do not commit them. -Prompt for a commit, defaulting to the commit at point. If -the region selects multiple commits, then apply all of them, -without prompting. - -\(fn COMMIT &optional ARGS)" t nil) - (autoload 'magit-revert-popup "magit-sequence" nil t) - -(autoload 'magit-revert "magit-sequence" "\ -Revert COMMIT by creating a new commit. -Prompt for a commit, defaulting to the commit at point. If -the region selects multiple commits, then revert all of them, -without prompting. - -\(fn COMMIT &optional ARGS)" t nil) - -(autoload 'magit-revert-no-commit "magit-sequence" "\ -Revert COMMIT by applying it in reverse to the worktree. -Prompt for a commit, defaulting to the commit at point. If -the region selects multiple commits, then revert all of them, -without prompting. - -\(fn COMMIT &optional ARGS)" t nil) - (autoload 'magit-am-popup "magit-sequence" nil t) - -(autoload 'magit-am-apply-patches "magit-sequence" "\ -Apply the patches FILES. - -\(fn &optional FILES ARGS)" t nil) - -(autoload 'magit-am-apply-maildir "magit-sequence" "\ -Apply the patches from MAILDIR. - -\(fn &optional MAILDIR ARGS)" t nil) - -(autoload 'magit-am-continue "magit-sequence" "\ -Resume the current patch applying sequence. - -\(fn)" t nil) - -(autoload 'magit-am-skip "magit-sequence" "\ -Skip the stopped at patch during a patch applying sequence. - -\(fn)" t nil) - -(autoload 'magit-am-abort "magit-sequence" "\ -Abort the current patch applying sequence. -This discards all changes made since the sequence started. - -\(fn)" t nil) - (autoload 'magit-rebase-popup "magit-sequence" nil t) - -(autoload 'magit-rebase "magit-sequence" "\ -Start a non-interactive rebase sequence. -All commits not in UPSTREAM are rebased. - -\(fn UPSTREAM &optional ARGS)" t nil) - -(autoload 'magit-rebase-subset "magit-sequence" "\ -Start a non-interactive rebase sequence. -Rebase commits from START to `HEAD' onto NEWBASE. -START has to be selected from a list of recent commits. - -\(fn NEWBASE START &optional ARGS)" t nil) - -(autoload 'magit-rebase-interactive "magit-sequence" "\ -Start an interactive rebase sequence. - -\(fn COMMIT &optional ARGS)" t nil) - -(autoload 'magit-rebase-unpushed "magit-sequence" "\ -Start an interactive rebase sequence of all unpushed commits. - -\(fn &optional ARGS)" t nil) - -(autoload 'magit-rebase-autosquash "magit-sequence" "\ -Combine squash and fixup commits with their intended targets. - -\(fn &optional ARGS)" t nil) - -(autoload 'magit-rebase-edit-commit "magit-sequence" "\ -Edit a single older commit using rebase. - -\(fn COMMIT &optional ARGS)" t nil) - -(autoload 'magit-rebase-reword-commit "magit-sequence" "\ -Reword a single older commit using rebase. - -\(fn COMMIT &optional ARGS)" t nil) - -(autoload 'magit-rebase-continue "magit-sequence" "\ -Restart the current rebasing operation. - -\(fn)" t nil) - -(autoload 'magit-rebase-skip "magit-sequence" "\ -Skip the current commit and restart the current rebase operation. - -\(fn)" t nil) - -(autoload 'magit-rebase-edit "magit-sequence" "\ -Edit the todo list of the current rebase operation. - -\(fn)" t nil) - -(autoload 'magit-rebase-abort "magit-sequence" "\ -Abort the current rebase operation, restoring the original branch. - -\(fn)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-stash" "magit-stash.el" (22093 56217 -;;;;;; 0 0)) -;;; Generated autoloads from magit-stash.el - (autoload 'magit-stash-popup "magit-stash" nil t) - -(autoload 'magit-stash "magit-stash" "\ -Create a stash of the index and working tree. -Untracked files are included according to popup arguments. -One prefix argument is equivalent to `--include-untracked' -while two prefix arguments are equivalent to `--all'. - -\(fn MESSAGE &optional INCLUDE-UNTRACKED)" t nil) - -(autoload 'magit-stash-index "magit-stash" "\ -Create a stash of the index only. -Unstaged and untracked changes are not stashed. The stashed -changes are applied in reverse to both the index and the -worktree. This command can fail when the worktree is not clean. -Applying the resulting stash has the inverse effect. - -\(fn MESSAGE)" t nil) - -(autoload 'magit-stash-worktree "magit-stash" "\ -Create a stash of the working tree only. -Untracked files are included according to popup arguments. -One prefix argument is equivalent to `--include-untracked' -while two prefix arguments are equivalent to `--all'. - -\(fn MESSAGE &optional INCLUDE-UNTRACKED)" t nil) - -(autoload 'magit-stash-keep-index "magit-stash" "\ -Create a stash of the index and working tree, keeping index intact. -Untracked files are included according to popup arguments. -One prefix argument is equivalent to `--include-untracked' -while two prefix arguments are equivalent to `--all'. - -\(fn MESSAGE &optional INCLUDE-UNTRACKED)" t nil) - -(autoload 'magit-snapshot "magit-stash" "\ -Create a snapshot of the index and working tree. -Untracked files are included according to popup arguments. -One prefix argument is equivalent to `--include-untracked' -while two prefix arguments are equivalent to `--all'. - -\(fn &optional INCLUDE-UNTRACKED)" t nil) - -(autoload 'magit-snapshot-index "magit-stash" "\ -Create a snapshot of the index only. -Unstaged and untracked changes are not stashed. - -\(fn)" t nil) - -(autoload 'magit-snapshot-worktree "magit-stash" "\ -Create a snapshot of the working tree only. -Untracked files are included according to popup arguments. -One prefix argument is equivalent to `--include-untracked' -while two prefix arguments are equivalent to `--all'. - -\(fn &optional INCLUDE-UNTRACKED)" t nil) - -(autoload 'magit-stash-apply "magit-stash" "\ -Apply a stash to the working tree. -Try to preserve the stash index. If that fails because there -are staged changes, apply without preserving the stash index. - -\(fn STASH)" t nil) - -(autoload 'magit-stash-drop "magit-stash" "\ -Remove a stash from the stash list. -When the region is active offer to drop all contained stashes. - -\(fn STASH)" t nil) - -(autoload 'magit-stash-clear "magit-stash" "\ -Remove all stashes saved in REF's reflog by deleting REF. - -\(fn REF)" t nil) - -(autoload 'magit-stash-branch "magit-stash" "\ -Create and checkout a new BRANCH from STASH. - -\(fn STASH BRANCH)" t nil) - -(autoload 'magit-stash-format-patch "magit-stash" "\ -Create a patch from STASH - -\(fn STASH)" t nil) - -(autoload 'magit-stash-list "magit-stash" "\ -List all stashes in a buffer. - -\(fn)" t nil) - -(autoload 'magit-stash-show "magit-stash" "\ -Show all diffs of a stash in a buffer. - -\(fn STASH &optional ARGS FILES)" t nil) - -;;;*** - -;;;### (autoloads nil "magit-wip" "magit-wip.el" (22093 56217 0 0)) -;;; Generated autoloads from magit-wip.el - -(defvar magit-wip-after-save-mode nil "\ -Non-nil if Magit-Wip-After-Save mode is enabled. -See the command `magit-wip-after-save-mode' for a description of this minor mode. -Setting this variable directly does not take effect; -either customize it (see the info node `Easy Customization') -or call the function `magit-wip-after-save-mode'.") - -(custom-autoload 'magit-wip-after-save-mode "magit-wip" nil) - -(autoload 'magit-wip-after-save-mode "magit-wip" "\ -Toggle Magit-Wip-After-Save-Local mode in all buffers. -With prefix ARG, enable Magit-Wip-After-Save mode if ARG is positive; -otherwise, disable it. If called from Lisp, enable the mode if -ARG is omitted or nil. - -Magit-Wip-After-Save-Local mode is enabled in all buffers where -`magit-wip-after-save-local-mode-turn-on' would do it. -See `magit-wip-after-save-local-mode' for more information on Magit-Wip-After-Save-Local mode. - -\(fn &optional ARG)" t nil) - -(defvar magit-wip-after-apply-mode nil "\ -Non-nil if Magit-Wip-After-Apply mode is enabled. -See the command `magit-wip-after-apply-mode' for a description of this minor mode.") - -(custom-autoload 'magit-wip-after-apply-mode "magit-wip" nil) - -(autoload 'magit-wip-after-apply-mode "magit-wip" "\ -Commit to work-in-progress refs. - -After applying a change using any \"apply variant\" -command (apply, stage, unstage, discard, and reverse) commit the -affected files to the current wip refs. For each branch there -may be two wip refs; one contains snapshots of the files as found -in the worktree and the other contains snapshots of the entries -in the index. - -\(fn &optional ARG)" t nil) - -(defvar magit-wip-before-change-mode nil "\ -Non-nil if Magit-Wip-Before-Change mode is enabled. -See the command `magit-wip-before-change-mode' for a description of this minor mode.") - -(custom-autoload 'magit-wip-before-change-mode "magit-wip" nil) - -(autoload 'magit-wip-before-change-mode "magit-wip" "\ -Commit to work-in-progress refs before certain destructive changes. - -Before invoking a revert command or an \"apply variant\" -command (apply, stage, unstage, discard, and reverse) commit the -affected tracked files to the current wip refs. For each branch -there may be two wip refs; one contains snapshots of the files -as found in the worktree and the other contains snapshots of the -entries in the index. - -Only changes to files which could potentially be affected by the -command which is about to be called are committed. - -\(fn &optional ARG)" t nil) - -;;;*** - -;;;### (autoloads nil nil ("magit-core.el" "magit-git.el" "magit-mode.el" -;;;;;; "magit-pkg.el" "magit-process.el" "magit-section.el" "magit-utils.el") -;;;;;; (22093 56217 977843 0)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: -;;; magit-autoloads.el ends here diff --git a/elpa/magit-20151119.202/magit-bisect.el b/elpa/magit-20151119.202/magit-bisect.el deleted file mode 100644 index dfee00a5..00000000 --- a/elpa/magit-20151119.202/magit-bisect.el +++ /dev/null @@ -1,203 +0,0 @@ -;;; magit-bisect.el --- bisect support for Magit - -;; Copyright (C) 2011-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; Use a binary search to find the commit that introduced a bug. - -;;; Code: - -(require 'magit) - -(defface magit-bisect-good - '((t :foreground "DarkOliveGreen")) - "Face for good bisect revisions." - :group 'magit-faces) - -(defface magit-bisect-skip - '((t :foreground "DarkGoldenrod")) - "Face for skipped bisect revisions." - :group 'magit-faces) - -(defface magit-bisect-bad - '((t :foreground "IndianRed4")) - "Face for bad bisect revisions." - :group 'magit-faces) - -;;;###autoload (autoload 'magit-bisect-popup "magit-bisect" nil t) -(magit-define-popup magit-bisect-popup - "Popup console for bisect commands." - 'magit-commands - :man-page "git-bisect" - :actions '((?B "Start" magit-bisect-start) - (?s "Start script" magit-bisect-run)) - :sequence-actions '((?b "Bad" magit-bisect-bad) - (?g "Good" magit-bisect-good) - (?k "Skip" magit-bisect-skip) - (?r "Reset" magit-bisect-reset) - (?s "Run script" magit-bisect-run)) - :sequence-predicate 'magit-bisect-in-progress-p) - -;;;###autoload -(defun magit-bisect-start (bad good) - "Start a bisect session. - -Bisecting a bug means to find the commit that introduced it. -This command starts such a bisect session by asking for a know -good and a bad commit. To move the session forward use the -other actions from the bisect popup (\ -\\\\[magit-bisect-popup])." - (interactive (if (magit-bisect-in-progress-p) - (user-error "Already bisecting") - (magit-bisect-start-read-args))) - (magit-bisect-async "start" (list bad good) t)) - -(defun magit-bisect-start-read-args () - (let ((b (magit-read-branch-or-commit "Start bisect with bad revision"))) - (list b (magit-read-other-branch-or-commit "Good revision" b)))) - -;;;###autoload -(defun magit-bisect-reset () - "After bisecting, cleanup bisection state and return to original `HEAD'." - (interactive) - (when (magit-confirm 'reset-bisect) - (magit-run-git "bisect" "reset") - (ignore-errors (delete-file (magit-git-dir "BISECT_CMD_OUTPUT"))))) - -;;;###autoload -(defun magit-bisect-good () - "While bisecting, mark the current commit as good. -Use this after you have asserted that the commit does not contain -the bug in question." - (interactive) - (magit-bisect-async "good")) - -;;;###autoload -(defun magit-bisect-bad () - "While bisecting, mark the current commit as bad. -Use this after you have asserted that the commit does contain the -bug in question." - (interactive) - (magit-bisect-async "bad")) - -;;;###autoload -(defun magit-bisect-skip () - "While bisecting, skip the current commit. -Use this if for some reason the current commit is not a good one -to test. This command lets Git choose a different one." - (interactive) - (magit-bisect-async "skip")) - -;;;###autoload -(defun magit-bisect-run (cmdline &optional bad good) - "Bisect automatically by running commands after each step. - -Unlike `git bisect run' this can be used before bisecting has -begun. In that case it behaves like `git bisect start; git -bisect run'." - (interactive (let ((args (and (not (magit-bisect-in-progress-p)) - (magit-bisect-start-read-args)))) - (cons (read-shell-command "Bisect shell command: ") args))) - (when (and bad good) - (magit-bisect-start bad good)) - (magit-bisect-async "run" (list cmdline))) - -(defun magit-bisect-async (subcommand &optional args no-assert) - (unless (or no-assert (magit-bisect-in-progress-p)) - (user-error "Not bisecting")) - (magit-with-toplevel - (let ((file (magit-git-dir "BISECT_CMD_OUTPUT"))) - (ignore-errors (delete-file file)) - (magit-run-git-with-logfile file "bisect" subcommand args)) - (magit-process-wait) - (magit-refresh))) - -(defun magit-bisect-in-progress-p () - (file-exists-p (magit-git-dir "BISECT_LOG"))) - -(defun magit-insert-bisect-output () - "While bisecting, insert section with output from `git bisect'." - (when (magit-bisect-in-progress-p) - (let ((lines - (or (magit-file-lines (magit-git-dir "BISECT_CMD_OUTPUT")) - (list "Bisecting: (no saved bisect output)" - "It appears you have invoked `git bisect' from a shell." - "There is nothing wrong with that, we just cannot display" - "anything useful here. Consult the shell output instead."))) - (done-re "^[a-z0-9]\\{40\\} is the first bad commit$")) - (magit-insert-section (bisect-output t) - (magit-insert-heading - (propertize (or (and (string-match done-re (car lines)) (pop lines)) - (--first (string-match done-re it) lines) - (pop lines)) - 'face 'magit-section-heading)) - (dolist (line lines) - (insert line "\n")))) - (insert "\n"))) - -(defun magit-insert-bisect-rest () - "While bisecting, insert section visualizing the bisect state." - (when (magit-bisect-in-progress-p) - (magit-insert-section (bisect-view) - (magit-insert-heading "Bisect Rest:") - (magit-git-wash (apply-partially 'magit-log-wash-log 'bisect-vis) - "bisect" "visualize" "git" "log" - "--format=%h%d %s" "--decorate=full")))) - -(defun magit-insert-bisect-log () - "While bisecting, insert section logging bisect progress." - (when (magit-bisect-in-progress-p) - (magit-insert-section (bisect-log) - (magit-insert-heading "Bisect Log:") - (magit-git-wash #'magit-wash-bisect-log "bisect" "log") - (insert ?\n)))) - -(defun magit-wash-bisect-log (args) - (let (beg) - (while (progn (setq beg (point-marker)) - (re-search-forward "^\\(git bisect [^\n]+\n\\)" nil t)) - (magit-bind-match-strings (heading) nil - (magit-delete-match) - (save-restriction - (narrow-to-region beg (point)) - (goto-char (point-min)) - (magit-insert-section (bisect-log heading t) - (insert (propertize heading 'face 'magit-section-secondary-heading)) - (magit-insert-heading) - (magit-wash-sequence - (apply-partially 'magit-log-wash-rev 'bisect-log - (magit-abbrev-length))) - (insert ?\n))))) - (when (re-search-forward - "# first bad commit: \\[\\([a-z0-9]\\{40\\}\\)\\] [^\n]+\n" nil t) - (magit-bind-match-strings (hash) nil - (magit-delete-match) - (magit-insert-section (bisect-log) - (insert hash " is the first bad commit\n")))))) - -;;; magit-bisect.el ends soon -(provide 'magit-bisect) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-bisect.el ends here diff --git a/elpa/magit-20151119.202/magit-blame.el b/elpa/magit-20151119.202/magit-blame.el deleted file mode 100644 index 23c516fa..00000000 --- a/elpa/magit-20151119.202/magit-blame.el +++ /dev/null @@ -1,517 +0,0 @@ -;;; magit-blame.el --- blame support for Magit - -;; Copyright (C) 2012-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; Annotates each line in file-visiting buffer with information from -;; the revision which last modified the line. - -;;; Code: - -(require 'magit) - -;;; Options - -(defgroup magit-blame nil - "Blame support for Magit." - :group 'magit-extensions) - -(defcustom magit-blame-heading-format "%-20a %C %s" - "Format string used for blame headings. - -The following placeholders are recognized: - - %H hash - %s summary - %a author - %A author time - %c committer - %C committer time - -The author and committer time formats can be specified with -`magit-blame-time-format'." - :group 'magit-blame - :type 'string) - -(defcustom magit-blame-time-format "%F %H:%M" - "Format for time strings in blame headings." - :group 'magit-blame - :type 'string) - -(defcustom magit-blame-show-headings t - "Whether to initially show blame block headings. -The headings can also be toggled locally using command -`magit-blame-toggle-headings'." - :group 'magit-blame - :type 'boolean) - -(defcustom magit-blame-disable-modes '(fci-mode yascroll-bar-mode) - "List of modes not compatible with Magit-Blame mode. -This modes are turned off when Magit-Blame mode is turned on, -and then turned on again when turning off the latter." - :group 'magit-blame - :type '(repeat (symbol :tag "Mode"))) - -(make-variable-buffer-local 'magit-blame-disabled-modes) - -(defcustom magit-blame-mode-lighter " Blame" - "The mode-line lighter of the Magit-Blame mode." - :group 'magit-blame - :type '(choice (const :tag "No lighter" "") string)) - -(unless (find-lisp-object-file-name 'magit-blame-goto-chunk-hook 'defvar) - (add-hook 'magit-blame-goto-chunk-hook 'magit-blame-maybe-update-revision-buffer)) -(defcustom magit-blame-goto-chunk-hook '(magit-blame-maybe-update-revision-buffer) - "Hook run by `magit-blame-next-chunk' and `magit-blame-previous-chunk'." - :package-version '(magit . "2.1.0") - :group 'magit-blame - :type 'hook - :options '(magit-blame-maybe-update-revision-buffer)) - -(defface magit-blame-heading - '((((class color) (background light)) - :background "grey80" - :foreground "black") - (((class color) (background dark)) - :background "grey25" - :foreground "black")) - "Face for blame headings." - :group 'magit-faces) - -(defface magit-blame-summary - '((t :inherit magit-blame-heading)) - "Face used for commit summary in blame headings." - :group 'magit-faces) - -(defface magit-blame-hash - '((t :inherit magit-blame-heading)) - "Face used for commit hash in blame headings." - :group 'magit-faces) - -(defface magit-blame-name - '((t :inherit magit-blame-heading)) - "Face used for author and committer names in blame headings." - :group 'magit-faces) - -(defface magit-blame-date - '((t :inherit magit-blame-heading)) - "Face used for dates in blame headings." - :group 'magit-faces) - -;;; Code - -(defvar magit-blame-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\r" 'magit-show-commit) - (define-key map "\s" 'magit-diff-show-or-scroll-up) - (define-key map "\d" 'magit-diff-show-or-scroll-down) - (define-key map "b" 'magit-blame-popup) - (define-key map "n" 'magit-blame-next-chunk) - (define-key map "N" 'magit-blame-next-chunk-same-commit) - (define-key map "p" 'magit-blame-previous-chunk) - (define-key map "P" 'magit-blame-previous-chunk-same-commit) - (define-key map "q" 'magit-blame-quit) - (define-key map "t" 'magit-blame-toggle-headings) - (define-key map "\M-w" 'magit-blame-copy-hash) - map) - "Keymap for `magit-blame-mode'.") - -(defun magit-blame-put-keymap-before-view-mode () - "Put `magit-blame-mode' ahead of `view-mode' in `minor-mode-map-alist'." - (--when-let (assq 'magit-blame-mode - (cl-member 'view-mode minor-mode-map-alist :key #'car)) - (setq minor-mode-map-alist - (cons it (delq it minor-mode-map-alist)))) - (remove-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode)) - -(add-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode) - -(defvar-local magit-blame-buffer-read-only nil) -(defvar-local magit-blame-cache nil) -(defvar-local magit-blame-process nil) -(defvar-local magit-blame-recursive-p nil) -(defvar-local magit-blame-separator nil) - -(define-minor-mode magit-blame-mode - "Display blame information inline." - :lighter magit-blame-mode-lighter - (cond (magit-blame-mode - (when (called-interactively-p 'any) - (setq magit-blame-mode nil) - (user-error - (concat "Don't call `magit-blame-mode' directly; " - "instead use `magit-blame' or `magit-blame-popup'"))) - (setq magit-blame-buffer-read-only buffer-read-only) - (read-only-mode 1) - (dolist (mode magit-blame-disable-modes) - (when (and (boundp mode) (symbol-value mode)) - (funcall mode -1) - (push mode magit-blame-disabled-modes))) - (setq magit-blame-separator (magit-blame-format-separator))) - (t - (unless magit-blame-buffer-read-only - (read-only-mode -1)) - (dolist (mode magit-blame-disabled-modes) - (funcall mode 1)) - (when (process-live-p magit-blame-process) - (kill-process magit-blame-process)) - (save-excursion - (save-restriction - (widen) - (dolist (ov (overlays-in (point-min) (point-max))) - (when (overlay-get ov 'magit-blame) - (delete-overlay ov)))))))) - -(defadvice auto-revert-handler (around magit-blame activate) - "If Magit-Blame mode is on, then do nothing. -See #1731." - (unless magit-blame-mode - ad-do-it)) - -;;;###autoload (autoload 'magit-blame-popup "magit-blame" nil t) -(magit-define-popup magit-blame-popup - "Popup console for blame commands." - 'magit-commands - :man-page "git-blame" - :switches '((?w "Ignore whitespace" "-w") - (?r "Do not treat root commits as boundaries" "--root")) - :options '((?C "Detect lines moved or copied within a file" "-C" read-string) - (?M "Detect lines moved or copied between files" "-M" read-string)) - :actions '((?b "Blame" magit-blame)) - :default-arguments '("-w") - :default-action 'magit-blame) - -;;;###autoload -(defun magit-blame (revision file &optional args line) - "Display edit history of FILE up to REVISION. - -Interactively blame the file being visited in the current buffer. -If the buffer visits a revision of that file, then blame up to -that revision, otherwise blame the file's full history, including -uncommitted changes. - -If Magit-Blame mode is already turned on then blame recursively, by -visiting REVISION:FILE (using `magit-find-file'), where revision -is the revision before the revision that added the lines at -point. - -ARGS is a list of additional arguments to pass to `git blame'; -only arguments available from `magit-blame-popup' should be used. -\n(fn REVISION FILE &optional ARGS)" ; LINE is for internal use - (interactive - (let ((args (magit-blame-arguments))) - (if magit-blame-mode - (--if-let (magit-blame-chunk-get :previous-hash) - (list it (magit-blame-chunk-get :previous-file) - args (magit-blame-chunk-get :previous-start)) - (user-error "Block has no further history")) - (--if-let (magit-file-relative-name nil 'tracked) - (list (or magit-buffer-refname magit-buffer-revision) it args) - (if buffer-file-name - (user-error "Buffer isn't visiting a tracked file") - (user-error "Buffer isn't visiting a file")))))) - (magit-with-toplevel - (if revision - (magit-find-file revision file) - (let ((default-directory default-directory)) - (--if-let (find-buffer-visiting file) - (progn (switch-to-buffer it) - (save-buffer)) - (find-file file)))) - ;; ^ Make sure this doesn't affect the value used below. b640c6f - (widen) - (when line - (setq magit-blame-recursive-p t) - (goto-char (point-min)) - (forward-line (1- line))) - (unless magit-blame-mode - (setq magit-blame-cache (make-hash-table :test 'equal)) - (let ((show-headings magit-blame-show-headings)) - (magit-blame-mode 1) - (setq-local magit-blame-show-headings show-headings)) - (message "Blaming...") - (let ((magit-process-popup-time -1) - (inhibit-magit-refresh t)) - (magit-run-git-async - "blame" "--incremental" args - "-L" (format "%s,%s" - (line-number-at-pos (window-start)) - (line-number-at-pos (1- (window-end nil t)))) - revision "--" file)) - (setq magit-blame-process magit-this-process) - (set-process-filter magit-this-process 'magit-blame-process-filter) - (set-process-sentinel - magit-this-process - `(lambda (process event) - (when (memq (process-status process) '(exit signal)) - (magit-process-sentinel process event) - (magit-blame-assert-buffer process) - (with-current-buffer (process-get process 'command-buf) - (when magit-blame-mode - (let ((magit-process-popup-time -1) - (inhibit-magit-refresh t) - (default-directory ,default-directory)) - (magit-run-git-async "blame" "--incremental" ,@args - ,revision "--" ,file)) - (setq magit-blame-process magit-this-process) - (set-process-filter - magit-this-process 'magit-blame-process-filter) - (set-process-sentinel - magit-this-process 'magit-blame-process-sentinel))))))))) - -(defun magit-blame-process-sentinel (process event) - (let ((status (process-status process))) - (when (memq status '(exit signal)) - (magit-process-sentinel process event) - (if (eq status 'exit) - (message "Blaming...done") - (magit-blame-assert-buffer process) - (with-current-buffer (process-get process 'command-buf) - (magit-blame-mode -1)) - (message "Blaming...failed"))))) - -(defvar magit-blame-log nil - "Whether to log blame output to the process buffer. -This is intended for debugging purposes.") - -(defun magit-blame-process-filter (process string) - (when magit-blame-log - (magit-process-filter process string)) - (--when-let (process-get process 'partial-line) - (setq string (concat it string)) - (setf (process-get process 'partial-line) nil)) - (magit-blame-assert-buffer process) - (with-current-buffer (process-get process 'command-buf) - (when magit-blame-mode - (let ((chunk (process-get process 'chunk)) - (lines (split-string string "\n" t))) - (unless (string-match-p "\n\\'" string) - (process-put process 'chunk chunk) - (process-put process 'partial-line (car (last lines))) - (setq lines (butlast lines))) - (dolist (line lines) - (cond - ((equal line "")) - ((not chunk) - (string-match - "^\\(.\\{40\\}\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\)" line) - (setq chunk - (list :hash (let ((hash (match-string 1 line))) - (unless (equal hash (make-string 40 ?0)) - hash)) - :previous-start (string-to-number (match-string 2 line)) - :start (string-to-number (match-string 3 line)) - :lines (string-to-number (match-string 4 line))))) - ((string-match "^filename \\(.+\\)" line) - (let* ((hash (plist-get chunk :hash)) - (file (match-string 1 line))) - (--if-let (gethash hash magit-blame-cache) - (setq chunk (nconc chunk it)) - (plist-put chunk :filename file) - (puthash hash chunk magit-blame-cache))) - (magit-blame-make-overlay chunk) - (setq chunk nil)) - ((string-match "^previous \\(.\\{40\\}\\) \\(.+\\)" line) - (plist-put chunk :previous-hash (match-string 1 line)) - (plist-put chunk :previous-file (match-string 2 line))) - ((string-match "^\\([^ ]+?-mail\\) <\\([^>]+\\)>" line) - (plist-put chunk (intern (concat ":" (match-string 1 line))) - (string-to-number (match-string 2 line)))) - ((string-match "^\\([^ ]+?-\\(?:time\\|tz\\)\\) \\(.+\\)" line) - (plist-put chunk (intern (concat ":" (match-string 1 line))) - (string-to-number (match-string 2 line)))) - ((string-match "^\\([^ ]+\\) \\(.+\\)" line) - (plist-put chunk (intern (concat ":" (match-string 1 line))) - (match-string 2 line)))) - (process-put process 'chunk chunk)))))) - -(defun magit-blame-assert-buffer (process) - (unless (buffer-live-p (process-get process 'command-buf)) - (kill-process process) - (user-error "Buffer being blamed has been killed"))) - -(defun magit-blame-make-overlay (chunk) - (let ((ov (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (forward-line (1- (plist-get chunk :start))) - (--when-let (--first (overlay-get it 'magit-blame) - (overlays-at (point))) - (delete-overlay it)) - (make-overlay (point) - (progn (forward-line - (plist-get chunk :lines)) - (point)))))) - (heading (magit-blame-format-heading chunk))) - (overlay-put ov 'magit-blame chunk) - (overlay-put ov 'magit-blame-heading heading) - (overlay-put ov 'before-string - (if magit-blame-show-headings - heading - magit-blame-separator)))) - -(defun magit-blame-format-separator () - (propertize - (concat (propertize " " 'display '(space :height (2))) - (propertize "\n" 'line-height t)) - 'face (list :background (face-attribute 'magit-blame-heading :background)))) - -(defun magit-blame-format-heading (chunk) - (with-temp-buffer - (insert (format-spec - (concat magit-blame-heading-format "\n") - `((?H . ,(propertize (or (plist-get chunk :hash) "") - 'face 'magit-blame-hash)) - (?s . ,(propertize (or (plist-get chunk :summary) "") - 'face 'magit-blame-summary)) - (?a . ,(propertize (or (plist-get chunk :author) "") - 'face 'magit-blame-name)) - (?A . ,(propertize (magit-blame-format-time-string - magit-blame-time-format - (plist-get chunk :author-time) - (plist-get chunk :author-tz)) - 'face 'magit-blame-date)) - (?c . ,(propertize (or (plist-get chunk :committer) "") - 'face 'magit-blame-name)) - (?C . ,(propertize (magit-blame-format-time-string - magit-blame-time-format - (plist-get chunk :committer-time) - (plist-get chunk :committer-tz)) - 'face 'magit-blame-date))))) - (goto-char (point-min)) - (while (not (eobp)) - (let ((face (get-text-property (point) 'face)) - (next (or (next-single-property-change (point) 'face) - (point-max)))) - (unless face - (put-text-property (point) next 'face 'magit-blame-heading)) - (goto-char next))) - (buffer-string))) - -(defun magit-blame-format-time-string (format time tz) - (format-time-string - format (seconds-to-time (+ time (* (/ tz 100) 60 60) (* (% tz 100) 60))))) - -(defun magit-blame-quit () - "Turn off Magit-Blame mode. -If the buffer was created during a recursive blame, -then also kill the buffer." - (interactive) - (if magit-blame-recursive-p - (kill-buffer) - (magit-blame-mode -1))) - -(defun magit-blame-next-chunk () - "Move to the next chunk." - (interactive) - (--if-let (next-single-char-property-change (point) 'magit-blame) - (progn (goto-char it) - (run-hooks 'magit-blame-goto-chunk-hook)) - (user-error "No more chunks"))) - -(defun magit-blame-previous-chunk () - "Move to the previous chunk." - (interactive) - (--if-let (previous-single-char-property-change (point) 'magit-blame) - (progn (goto-char it) - (run-hooks 'magit-blame-goto-chunk-hook)) - (user-error "No more chunks"))) - -(defun magit-blame-next-chunk-same-commit (&optional previous) - "Move to the next chunk from the same commit.\n\n(fn)" - (interactive) - (-if-let (hash (magit-blame-chunk-get :hash)) - (let ((pos (point)) ov) - (save-excursion - (while (and (not ov) - (not (= pos (if previous (point-min) (point-max)))) - (setq pos (funcall - (if previous - 'previous-single-char-property-change - 'next-single-char-property-change) - pos 'magit-blame))) - (--when-let (magit-blame-overlay-at pos) - (when (equal (magit-blame-chunk-get :hash pos) hash) - (setq ov it))))) - (if ov - (goto-char (overlay-start ov)) - (user-error "No more chunks from same commit"))) - (user-error "This chunk hasn't been blamed yet"))) - -(defun magit-blame-previous-chunk-same-commit () - "Move to the previous chunk from the same commit." - (interactive) - (magit-blame-next-chunk-same-commit 'previous-single-char-property-change)) - -(defun magit-blame-toggle-headings () - "Show or hide blame chunk headings." - (interactive) - (setq-local magit-blame-show-headings (not magit-blame-show-headings)) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (while (not (eobp)) - (let ((next (next-single-char-property-change (point) 'magit-blame))) - (--when-let (magit-blame-overlay-at (point)) - (overlay-put it 'before-string - (if magit-blame-show-headings - (overlay-get it 'magit-blame-heading) - magit-blame-separator))) - (goto-char (or next (point-max)))))))) - -(defun magit-blame-copy-hash () - "Save hash of the current chunk's commit to the kill ring." - (interactive) - (kill-new (message "%s" (magit-blame-chunk-get :hash)))) - -(defun magit-blame-chunk-get (key &optional pos) - (--when-let (magit-blame-overlay-at pos) - (plist-get (overlay-get it 'magit-blame) key))) - -(defun magit-blame-overlay-at (&optional pos) - (--first (overlay-get it 'magit-blame) - (overlays-at (or pos (point))))) - -(defun magit-blame-maybe-update-revision-buffer () - (unless magit--update-revision-buffer - (setq magit--update-revision-buffer nil) - (-when-let* ((commit (magit-blame-chunk-get :hash)) - (buffer (magit-mode-get-buffer 'magit-revision-mode nil t))) - (setq magit--update-revision-buffer (list commit buffer)) - (run-with-idle-timer - magit-update-other-window-delay nil - (lambda () - (-let [(rev buf) magit--update-revision-buffer] - (setq magit--update-revision-buffer nil) - (when (buffer-live-p buf) - (let ((magit-display-buffer-noselect t)) - (apply #'magit-show-commit rev (magit-diff-arguments)))))))))) - -;;; magit-blame.el ends soon -(provide 'magit-blame) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-blame.el ends here diff --git a/elpa/magit-20151119.202/magit-commit.el b/elpa/magit-20151119.202/magit-commit.el deleted file mode 100644 index 9d72a2de..00000000 --- a/elpa/magit-20151119.202/magit-commit.el +++ /dev/null @@ -1,396 +0,0 @@ -;;; magit-commit.el --- create Git commits - -;; Copyright (C) 2008-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library implements commands for creating Git commits. These -;; commands just initiate the commit, support for writing the commit -;; messages is implemented in `git-commit.el'. - -;;; Code: - -(require 'magit) -(require 'magit-sequence) - -(eval-when-compile (require 'epa)) ; for `epa-protocol' -(eval-when-compile (require 'epg)) -(declare-function epg-sub-key-id 'epg) -(declare-function epg-key-sub-key-list 'epg) -(declare-function epg-key-user-id-list 'epg) -(declare-function epg-user-id-string 'epg) -(declare-function epg-decode-dn 'epg) -(declare-function epg-list-keys 'epg) - -;;; Options - -(defcustom magit-commit-arguments nil - "The arguments used when committing." - :group 'magit-commands - :type '(repeat (string :tag "Argument"))) - -(defcustom magit-commit-ask-to-stage 'verbose - "Whether to ask to stage everything when committing and nothing is staged." - :package-version '(magit . "2.3.0") - :group 'magit-commands - :type '(choice (const :tag "Ask showing diff" verbose) - (const :tag "Ask" t) - (const :tag "Don't ask" nil))) - -(defcustom magit-commit-show-diff t - "Whether the relevant diff is automatically shown when committing." - :package-version '(magit . "2.3.0") - :group 'magit-commands - :type 'boolean) - -(defcustom magit-commit-extend-override-date t - "Whether using `magit-commit-extend' changes the committer date." - :package-version '(magit . "2.3.0") - :group 'magit-commands - :type 'boolean) - -(defcustom magit-commit-reword-override-date t - "Whether using `magit-commit-reword' changes the committer date." - :package-version '(magit . "2.3.0") - :group 'magit-commands - :type 'boolean) - -(defcustom magit-commit-squash-confirm t - "Whether the commit targeted by squash and fixup has to be confirmed. -When non-nil then the commit at point (if any) is used as default -choice, otherwise it has to be confirmed. This option only -affects `magit-commit-squash' and `magit-commit-fixup'. The -\"instant\" variants always require confirmation because making -an error while using those is harder to recover from." - :package-version '(magit . "2.1.0") - :group 'magit-commands - :type 'boolean) - -;;; Code - -(defun magit-commit-popup (&optional arg) - "Popup console for commit commands." - (interactive "P") - (--if-let (magit-commit-message-buffer) - (switch-to-buffer it) - (magit-invoke-popup 'magit-commit-popup nil arg))) - -(defvar magit-commit-popup - '(:variable magit-commit-arguments - :man-page "git-commit" - :switches ((?a "Stage all modified and deleted files" "--all") - (?e "Allow empty commit" "--allow-empty") - (?v "Show diff of changes to be committed" "--verbose") - (?n "Bypass git hooks" "--no-verify") - (?s "Add Signed-off-by line" "--signoff") - (?R "Claim authorship and reset author date" "--reset-author")) - :options ((?A "Override the author" "--author=" read-from-minibuffer) - (?S "Sign using gpg" "--gpg-sign=" magit-read-gpg-secret-key) - (?C "Reuse commit message" "--reuse-message=" read-from-minibuffer)) - :actions ((?c "Commit" magit-commit) - (?e "Extend" magit-commit-extend) - (?f "Fixup" magit-commit-fixup) - (?F "Instant Fixup" magit-commit-instant-fixup) nil - (?w "Reword" magit-commit-reword) - (?s "Squash" magit-commit-squash) - (?S "Instant Squash" magit-commit-instant-squash) nil - (?a "Amend" magit-commit-amend) - (?A "Augment" magit-commit-augment)) - :max-action-columns 4 - :default-action 'magit-commit)) - -(magit-define-popup-keys-deferred 'magit-commit-popup) - -(defun magit-commit-arguments nil - (if (eq magit-current-popup 'magit-commit-popup) - magit-current-popup-args - magit-commit-arguments)) - -(defun magit-commit-message-buffer () - (let* ((find-file-visit-truename t) ; git uses truename of COMMIT_EDITMSG - (topdir (magit-toplevel))) - (--first (equal topdir (with-current-buffer it - (and git-commit-mode (magit-toplevel)))) - (append (buffer-list (selected-frame)) - (buffer-list))))) - -;;;###autoload -(defun magit-commit (&optional args) - "Create a new commit on HEAD. -With a prefix argument amend to the commit at HEAD instead. -\n(git commit [--amend] ARGS)" - (interactive (if current-prefix-arg - (list (cons "--amend" (magit-commit-arguments))) - (list (magit-commit-arguments)))) - (when (setq args (magit-commit-assert args)) - (magit-run-git-with-editor "commit" args))) - -;;;###autoload -(defun magit-commit-amend (&optional args) - "Amend the last commit. -\n(git commit --amend ARGS)" - (interactive (list (magit-commit-arguments))) - (magit-run-git-with-editor "commit" "--amend" args)) - -;;;###autoload -(defun magit-commit-extend (&optional args override-date) - "Amend the last commit, without editing the message. - -With a prefix argument keep the committer date, otherwise change -it. The option `magit-commit-extend-override-date' can be used -to inverse the meaning of the prefix argument. \n(git commit ---amend --no-edit)" - (interactive (list (magit-commit-arguments) - (if current-prefix-arg - (not magit-commit-extend-override-date) - magit-commit-extend-override-date))) - (when (setq args (magit-commit-assert args (not override-date))) - (let ((process-environment process-environment)) - (unless override-date - (setenv "GIT_COMMITTER_DATE" (magit-rev-format "%cD"))) - (magit-run-git-with-editor "commit" "--amend" "--no-edit" args)))) - -;;;###autoload -(defun magit-commit-reword (&optional args override-date) - "Reword the last commit, ignoring staged changes. - -With a prefix argument keep the committer date, otherwise change -it. The option `magit-commit-reword-override-date' can be used -to inverse the meaning of the prefix argument. - -Non-interactively respect the optional OVERRIDE-DATE argument -and ignore the option. -\n(git commit --amend --only)" - (interactive (list (magit-commit-arguments) - (if current-prefix-arg - (not magit-commit-reword-override-date) - magit-commit-reword-override-date))) - (let ((process-environment process-environment)) - (unless override-date - (setenv "GIT_COMMITTER_DATE" (magit-rev-format "%cD"))) - (magit-run-git-with-editor "commit" "--amend" "--only" args))) - -;;;###autoload -(defun magit-commit-fixup (&optional commit args) - "Create a fixup commit. - -With a prefix argument the target COMMIT has to be confirmed. -Otherwise the commit at point may be used without confirmation -depending on the value of option `magit-commit-squash-confirm'." - (interactive (list (magit-commit-at-point) - (magit-commit-arguments))) - (magit-commit-squash-internal "--fixup" commit args)) - -;;;###autoload -(defun magit-commit-squash (&optional commit args) - "Create a squash commit, without editing the squash message. - -With a prefix argument the target COMMIT has to be confirmed. -Otherwise the commit at point may be used without confirmation -depending on the value of option `magit-commit-squash-confirm'." - (interactive (list (magit-commit-at-point) - (magit-commit-arguments))) - (magit-commit-squash-internal "--squash" commit args)) - -;;;###autoload -(defun magit-commit-augment (&optional commit args) - "Create a squash commit, editing the squash message. - -With a prefix argument the target COMMIT has to be confirmed. -Otherwise the commit at point may be used without confirmation -depending on the value of option `magit-commit-squash-confirm'." - (interactive (list (magit-commit-at-point) - (magit-commit-arguments))) - (magit-commit-squash-internal "--squash" commit args nil t)) - -;;;###autoload -(defun magit-commit-instant-fixup (&optional commit args) - "Create a fixup commit targeting COMMIT and instantly rebase." - (interactive (list (magit-commit-at-point) - (magit-commit-arguments))) - (magit-commit-squash-internal "--fixup" commit args t)) - -;;;###autoload -(defun magit-commit-instant-squash (&optional commit args) - "Create a squash commit targeting COMMIT and instantly rebase." - (interactive (list (magit-commit-at-point) - (magit-commit-arguments))) - (magit-commit-squash-internal "--squash" commit args t)) - -(defun magit-commit-squash-internal - (option commit &optional args rebase edit confirmed) - (-when-let (args (magit-commit-assert args t)) - (if (and commit - (or confirmed - (not (or rebase - current-prefix-arg - magit-commit-squash-confirm)))) - (let ((magit-commit-show-diff nil)) - (magit-run-git-with-editor "commit" - (unless edit "--no-edit") - (concat option "=" commit) - args)) - (magit-log-select - `(lambda (commit) - (magit-commit-squash-internal ,option commit ',args ,rebase ,edit t) - ,@(when rebase - `((magit-rebase-interactive-1 commit - (list "--autosquash" "--autostash") - "" "true")))) - (format "Type %%p on a commit to %s into it," - (substring option 2))) - (when magit-commit-show-diff - (let ((magit-display-buffer-noselect t)) - (magit-diff-staged)))))) - -(defun magit-commit-assert (args &optional strict) - (cond - ((or (magit-anything-staged-p) - (and (magit-anything-unstaged-p) - ;; ^ Everything of nothing is still nothing. - (member "--all" args)) - (and (not strict) - ;; ^ For amend variants that don't make sense otherwise. - (or (member "--amend" args) - (member "--allow-empty" args)))) - (or args (list "--"))) - ((and (magit-rebase-in-progress-p) - (not (magit-anything-unstaged-p)) - (y-or-n-p "Nothing staged. Continue in-progress rebase? ")) - (magit-run-git-sequencer "rebase" "--continue") - nil) - ((and (file-exists-p (magit-git-dir "MERGE_MSG")) - (not (magit-anything-unstaged-p))) - (or args (list "--"))) - ((not (magit-anything-unstaged-p)) - (user-error "Nothing staged (or unstaged)")) - (magit-commit-ask-to-stage - (when (eq magit-commit-ask-to-stage 'verbose) - (magit-diff-unstaged)) - (prog1 (when (y-or-n-p "Nothing staged. Stage and commit everything? ") - (magit-run-git "add" "-u" ".") - (or args (list "--"))) - (when (and (eq magit-commit-ask-to-stage 'verbose) - (derived-mode-p 'magit-diff-mode)) - (magit-mode-bury-buffer)))) - (t - (user-error "Nothing staged")))) - -(defun magit-commit-diff () - (--when-let (and git-commit-mode - magit-commit-show-diff - (pcase last-command - (`magit-commit - (apply-partially 'magit-diff-staged nil)) - (`magit-commit-amend 'magit-diff-while-amending) - (`magit-commit-reword 'magit-diff-while-amending))) - (let ((magit-inhibit-save-previous-winconf 'unset) - (magit-display-buffer-noselect t)) - (funcall it (car (magit-diff-arguments)))))) - -(add-hook 'server-switch-hook 'magit-commit-diff) - -(add-to-list 'with-editor-server-window-alist - (cons git-commit-filename-regexp 'switch-to-buffer)) - -(defvar magit-gpg-secret-key-hist nil) - -(defun magit-read-gpg-secret-key (prompt &optional initial-input) - (require 'epa) - (let ((keys (--map (list (epg-sub-key-id (car (epg-key-sub-key-list it))) - (-when-let (id-obj (car (epg-key-user-id-list it))) - (let ((id-str (epg-user-id-string id-obj))) - (if (stringp id-str) - id-str - (epg-decode-dn id-obj))))) - (epg-list-keys (epg-make-context epa-protocol) nil t)))) - (magit-completing-read prompt keys nil nil nil 'magit-gpg-secret-key-hist - (car (or magit-gpg-secret-key-hist keys))))) - -(defvar magit-commit-add-log-insert-function 'magit-commit-add-log-insert - "Used by `magit-commit-add-log' to insert a single entry.") - -(defun magit-commit-add-log () - "Add a stub for the current change into the commit message buffer. -If no commit is in progress, then initiate it. Use the function -specified by variable `magit-commit-add-log-insert-function' to -actually insert the entry." - (interactive) - (let ((hunk (magit-section-when 'hunk it)) - (log (magit-commit-message-buffer)) buf pos) - (save-window-excursion - (call-interactively #'magit-diff-visit-file) - (setq buf (current-buffer) - pos (point))) - (unless log - (unless (magit-commit-assert nil) - (user-error "Abort")) - (magit-commit) - (while (not (setq log (magit-commit-message-buffer))) - (sit-for 0.01))) - (save-excursion - (with-current-buffer buf - (goto-char pos) - (funcall magit-commit-add-log-insert-function log - (magit-file-relative-name) - (and hunk (add-log-current-defun))))))) - -(defun magit-commit-add-log-insert (buffer file defun) - (with-current-buffer buffer - (undo-boundary) - (goto-char (point-max)) - (while (re-search-backward (concat "^" comment-start) nil t)) - (cond ((re-search-backward (format "* %s\\(?: (\\([^)]+\\))\\)?: " file) - nil t) - (when (equal (match-string 1) defun) - (setq defun nil)) - (re-search-forward ": ")) - (t - (when (re-search-backward "^[\\*(].+\n" nil t) - (goto-char (match-end 0))) - (while (re-search-forward "^[^\\*#\n].*\n" nil t)) - (if defun - (progn (insert (format "* %s (%s): \n" file defun)) - (setq defun nil)) - (insert (format "* %s: \n" file))) - (backward-char) - (unless (looking-at "\n[\n\\']") - (insert ?\n) - (backward-char)))) - (when defun - (forward-line) - (let ((limit (save-excursion - (and (re-search-forward "^\\*" nil t) - (point))))) - (unless (or (looking-back (format "(%s): " defun) - (line-beginning-position)) - (re-search-forward (format "^(%s): " defun) limit t)) - (while (re-search-forward "^[^\\*#\n].*\n" limit t)) - (insert (format "(%s): \n" defun)) - (backward-char)))))) - -;;; magit-commit.el ends soon -(provide 'magit-commit) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-commit.el ends here diff --git a/elpa/magit-20151119.202/magit-core.el b/elpa/magit-20151119.202/magit-core.el deleted file mode 100644 index 844671b5..00000000 --- a/elpa/magit-20151119.202/magit-core.el +++ /dev/null @@ -1,76 +0,0 @@ -;;; magit-core.el --- core functionality - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library requires several other libraries, so that yet other -;; libraries can just require this one, instead of having to require -;; all the other ones. In other words this separates the low-level -;; stuff from the rest. It also defines some Custom groups. - -;;; Code: - -(require 'magit-utils) -(require 'magit-section) -(require 'magit-git) -(require 'magit-mode) -(require 'magit-popup) -(require 'magit-process) - -(defgroup magit nil - "Controlling Git from Emacs." - :group 'tools) - -(defgroup magit-commands nil - "Options controlling behavior of certain commands." - :group 'magit) - -(defgroup magit-modes nil - "Modes used or provided by Magit." - :group 'magit) - -(defgroup magit-extensions nil - "Extensions to Magit." - :group 'magit) - -(defgroup magit-faces nil - "Faces used by Magit." - :group 'magit - :group 'faces) - -(custom-add-to-group 'magit-modes 'magit-popup 'custom-group) -(custom-add-to-group 'magit-faces 'magit-popup-faces 'custom-group) -(custom-add-to-group 'magit-modes 'git-commit 'custom-group) -(custom-add-to-group 'magit-faces 'git-commit-faces 'custom-group) -(custom-add-to-group 'magit-modes 'git-rebase 'custom-group) -(custom-add-to-group 'magit-faces 'git-rebase-faces 'custom-group) -(custom-add-to-group 'magit-process 'with-editor 'custom-group) - -(custom-add-to-group 'magit 'vc-follow-symlinks 'custom-variable) - -;;; magit-core.el ends soon -(provide 'magit-core) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-core.el ends here diff --git a/elpa/magit-20151119.202/magit-diff.el b/elpa/magit-20151119.202/magit-diff.el deleted file mode 100644 index e3f476c8..00000000 --- a/elpa/magit-20151119.202/magit-diff.el +++ /dev/null @@ -1,2079 +0,0 @@ -;;; magit-diff.el --- inspect Git diffs - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library implements support for looking at Git diffs and -;; commits. - -;;; Code: - -(require 'git-commit) -(require 'magit-core) - -;; For `magit-diff-popup' -(declare-function magit-stash-show 'magit-stash) -;; For `magit-diff-visit-file' -(declare-function magit-dired-jump 'magit) -(declare-function magit-find-file-noselect 'magit) -(declare-function magit-status-internal 'magit) -;; For `magit-diff-wash-revision' -(declare-function magit-insert-tags-header 'magit) -;; For `magit-diff-while-committing' -(declare-function magit-commit-message-buffer 'magit) -;; For `magit-show-commit' and `magit-diff-show-or-scroll' -(declare-function magit-blame-chunk-get 'magit-blame) -(declare-function magit-blame-mode 'magit-blame) -(defvar magit-blame-mode) -(defvar git-rebase-line) - -(require 'diff-mode) -(require 'smerge-mode) - -;;; Options -;;;; Diff Mode - -(defgroup magit-diff nil - "Inspect and manipulate Git diffs." - :group 'magit-modes) - -(custom-add-to-group 'magit-diff 'smerge-refine-ignore-whitespace - 'custom-variable) - -(defcustom magit-diff-mode-hook nil - "Hook run after entering Magit-Diff mode." - :group 'magit-diff - :type 'hook) - -(defcustom magit-diff-sections-hook - '(magit-insert-diff - magit-insert-xref-buttons) - "Hook run to insert sections into a `magit-diff-mode' buffer." - :package-version '(magit . "2.3.0") - :group 'magit-revision - :type 'hook) - -(defcustom magit-diff-expansion-threshold 1.0 - "After how many seconds not to expand anymore diffs. - -Except in status buffers, diffs are usually start out fully -expanded. Because that can take a long time, all diffs that -haven't been fontified during a refresh before the threshold -defined here are instead displayed with their bodies collapsed. - -Note that this can cause sections that were previously expanded -to be collapsed. So you should not pick a very low value here. - -The hook function `magit-diff-expansion-threshold' has to be a -member of `magit-section-set-visibility-hook' for this option -to have any effect" - :package-version '(magit . "2.1.0") - :group 'magit-diff - :type 'float) - -(defcustom magit-diff-highlight-hunk-body t - "Whether to highlight bodies of selected hunk sections. -This only has an effect if `magit-diff-highlight' is a -member of `magit-section-highlight-hook', which see." - :package-version '(magit . "2.1.0") - :group 'magit-diff - :type 'boolean) - -(defcustom magit-diff-show-lines-boundary t - "Whether to delimit hunk-internal region with thin lines. - -When a hunk-internal region (used to stage just the lines that -fall into the region instead of the complete hunk) only covers -context lines, then these lines are the only visual indicator -for the region. In character-only terminals it's not possible -to draw thin lines." - :package-version '(magit . "2.1.0") - :group 'magit-diff - :type 'boolean) - -(defcustom magit-diff-refine-hunk nil - "Whether to show word-granularity differences within diff hunks. - -nil never show fine differences. -t show fine differences for the current diff hunk only. -`all' show fine differences for all displayed diff hunks." - :group 'magit-diff - :safe (lambda (val) (memq val '(nil t all))) - :type '(choice (const :tag "Never" nil) - (const :tag "Current" t) - (const :tag "All" all))) - -(put 'magit-diff-refine-hunk 'permanent-local t) - -(defcustom magit-diff-paint-whitespace t - "Specify where to highlight whitespace errors. -See `magit-highlight-trailing-whitespace', -`magit-highlight-indentation'. The symbol t means in all diffs, -`status' means only in the status buffer, and nil means nowhere." - :group 'magit-diff - :safe (lambda (val) (memq val '(t nil status))) - :type '(choice (const :tag "Always" t) - (const :tag "Never" nil) - (const :tag "In status buffer" status))) - -(defcustom magit-diff-highlight-trailing t - "Whether to highlight whitespace at the end of a line in diffs. -Used only when `magit-diff-paint-whitespace' is non-nil." - :group 'magit-diff - :safe 'booleanp - :type 'boolean) - -(defcustom magit-diff-highlight-indentation nil - "Highlight the \"wrong\" indentation style. -Used only when `magit-diff-paint-whitespace' is non-nil. - -The value is a list of cons cells. The car is a regular -expression, and the cdr is the value that applies to repositories -whose directory matches the regular expression. If more than one -element matches, then the *last* element in the list applies. -The default value should therefore come first in the list. - -If the value is `tabs', highlight indentation with tabs. If the -value is an integer, highlight indentation with at least that -many spaces. Otherwise, highlight neither." - :group 'magit-diff - :type `(repeat (cons (string :tag "Directory regexp") - (choice (const :tag "Tabs" tabs) - (integer :tag "Spaces" :value ,tab-width) - (const :tag "Neither" nil))))) - -;;;; Revision Mode - -(defgroup magit-revision nil - "Inspect and manipulate Git commits." - :group 'magit-modes) - -(defcustom magit-revision-mode-hook nil - "Hook run after entering Magit-Revision mode." - :group 'magit-revision - :type 'hook) - -(defcustom magit-revision-sections-hook - '(magit-insert-revision-tag - magit-insert-revision-headers - magit-insert-revision-message - magit-insert-revision-notes - magit-insert-revision-diff - magit-insert-xref-buttons) - "Hook run to insert sections into a `magit-revision-mode' buffer." - :package-version '(magit . "2.3.0") - :group 'magit-revision - :type 'hook) - -(defcustom magit-revision-headers-format "\ -Author: %aN <%aE> -AuthorDate: %ad -Commit: %cN <%cE> -CommitDate: %cd -" - "Format string used to insert headers in revision buffers. - -All headers in revision buffers are inserted by the section -inserter `magit-insert-revision-headers'. Some of the headers -are created by calling `git show --format=FORMAT' where FORMAT -is the format specified here. Other headers are hard coded or -subject to option `magit-revision-insert-related-refs'." - :package-version '(magit . "2.3.0") - :group 'magit-revision - :type 'string) - -(defcustom magit-revision-insert-related-refs t - "Whether to show related refs in revision buffers." - :package-version '(magit . "2.1.0") - :group 'magit-revision - :type 'boolean) - -(defcustom magit-revision-show-gravatars nil - "Whether to show gravatar images in revision buffers. - -If non-nil, then the value has to be a cons-cell which specifies -where the gravatar images for the author and/or the committer are -inserted inside the text that was previously inserted according -to `magit-revision-header-format'. - -Both cells are regular expressions. The car specifies where to -insert the author gravatar image. The top halve of the image is -inserted right after the matched text, the bottom halve on the -next line at the same offset. The cdr specifies where to insert -the committer image, accordingly. Either the car or the cdr may -be nil." - :package-version '(magit . "2.3.0") - :group 'magit-revision - :type '(choice (const :tag "Don't show gravatars" nil) - (cons :tag "Show gravatars" - (regexp :tag "Author regexp" "^Author: ") - (regexp :tag "Committer regexp" "^Commit: ")))) - -(defcustom magit-revision-use-gravatar-kludge nil - "Whether to work around a bug which affects display of gravatars. - -Gravatar images are spliced into two halves which are then -displayed on separate lines. On OS X the splicing has a bug in -some Emacs builds, which causes the top and bottom halves to be -interchanged. Enabling this option works around this issue by -interchanging the halves once more, which cancels out the effect -of the bug. - -See https://github.com/magit/magit/issues/2265 -and https://debbugs.gnu.org/cgi/bugreport.cgi?bug=7847." - :package-version '(magit . "2.3.0") - :group 'magit-revision - :type 'boolean) - -;;; Faces - -(defface magit-diff-file-heading - '((t :weight bold)) - "Face for diff file headings." - :group 'magit-faces) - -(defface magit-diff-file-heading-highlight - '((t :inherit (magit-diff-file-heading magit-section-highlight))) - "Face for current diff file headings." - :group 'magit-faces) - -(defface magit-diff-file-heading-selection - '((((class color) (background light)) - :inherit magit-diff-file-heading-highlight - :foreground "salmon4") - (((class color) (background dark)) - :inherit magit-diff-file-heading-highlight - :foreground "LightSalmon3")) - "Face for selected diff file headings." - :group 'magit-faces) - -(defface magit-diff-hunk-heading - '((((class color) (background light)) - :background "grey80" - :foreground "grey30") - (((class color) (background dark)) - :background "grey25" - :foreground "grey70")) - "Face for diff hunk headings." - :group 'magit-faces) - -(defface magit-diff-hunk-heading-highlight - '((((class color) (background light)) - :background "grey75" - :foreground "grey30") - (((class color) (background dark)) - :background "grey35" - :foreground "grey70")) - "Face for current diff hunk headings." - :group 'magit-faces) - -(defface magit-diff-hunk-heading-selection - '((((class color) (background light)) - :inherit magit-diff-hunk-heading-highlight - :foreground "salmon4") - (((class color) (background dark)) - :inherit magit-diff-hunk-heading-highlight - :foreground "LightSalmon3")) - "Face for selected diff hunk headings." - :group 'magit-faces) - -(defface magit-diff-lines-heading - '((((class color) (background light)) - :inherit magit-diff-hunk-heading-highlight - :background "LightSalmon3") - (((class color) (background dark)) - :inherit magit-diff-hunk-heading-highlight - :foreground "grey80" - :background "salmon4")) - "Face for diff hunk heading when lines are marked." - :group 'magit-faces) - -(defface magit-diff-lines-boundary - '((t :inherit magit-diff-lines-heading)) - "Face for boundary of marked lines in diff hunk." - :group 'magit-faces) - -(defface magit-diff-conflict-heading - '((t :inherit magit-diff-hunk-heading)) - "Face for conflict markers." - :group 'magit-faces) - -(defface magit-diff-added - '((((class color) (background light)) - :background "#ddffdd" - :foreground "#22aa22") - (((class color) (background dark)) - :background "#335533" - :foreground "#ddffdd")) - "Face for lines in a diff that have been added." - :group 'magit-faces) - -(defface magit-diff-removed - '((((class color) (background light)) - :background "#ffdddd" - :foreground "#aa2222") - (((class color) (background dark)) - :background "#553333" - :foreground "#ffdddd")) - "Face for lines in a diff that have been removed." - :group 'magit-faces) - -(defface magit-diff-our - '((t :inherit magit-diff-removed)) - "Face for lines in a diff for our side in a conflict." - :group 'magit-faces) - -(defface magit-diff-base - '((((class color) (background light)) - :background "#ffffcc" - :foreground "#aaaa11") - (((class color) (background dark)) - :background "#555522" - :foreground "#ffffcc")) - "Face for lines in a diff for the base side in a conflict." - :group 'magit-faces) - -(defface magit-diff-their - '((t :inherit magit-diff-added)) - "Face for lines in a diff for their side in a conflict." - :group 'magit-faces) - -(defface magit-diff-context - '((((class color) (background light)) :foreground "grey50") - (((class color) (background dark)) :foreground "grey70")) - "Face for lines in a diff that are unchanged." - :group 'magit-faces) - -(defface magit-diff-added-highlight - '((((class color) (background light)) - :background "#cceecc" - :foreground "#22aa22") - (((class color) (background dark)) - :background "#336633" - :foreground "#cceecc")) - "Face for lines in a diff that have been added." - :group 'magit-faces) - -(defface magit-diff-removed-highlight - '((((class color) (background light)) - :background "#eecccc" - :foreground "#aa2222") - (((class color) (background dark)) - :background "#663333" - :foreground "#eecccc")) - "Face for lines in a diff that have been removed." - :group 'magit-faces) - -(defface magit-diff-our-highlight - '((t :inherit magit-diff-removed-highlight)) - "Face for lines in a diff for our side in a conflict." - :group 'magit-faces) - -(defface magit-diff-base-highlight - '((((class color) (background light)) - :background "#eeeebb" - :foreground "#aaaa11") - (((class color) (background dark)) - :background "#666622" - :foreground "#eeeebb")) - "Face for lines in a diff for the base side in a conflict." - :group 'magit-faces) - -(defface magit-diff-their-highlight - '((t :inherit magit-diff-added-highlight)) - "Face for lines in a diff for their side in a conflict." - :group 'magit-faces) - -(defface magit-diff-context-highlight - '((((class color) (background light)) - :background "grey95" - :foreground "grey50") - (((class color) (background dark)) - :background "grey20" - :foreground "grey70")) - "Face for lines in a diff that have been removed." - :group 'magit-faces) - -(defface magit-diff-whitespace-warning - '((t :inherit trailing-whitespace)) - "Face for highlighting whitespace errors added lines." - :group 'magit-faces) - -(defface magit-diffstat-added - '((((class color) (background light)) :foreground "#22aa22") - (((class color) (background dark)) :foreground "#448844")) - "Face for plus sign in diffstat." - :group 'magit-faces) - -(defface magit-diffstat-removed - '((((class color) (background light)) :foreground "#aa2222") - (((class color) (background dark)) :foreground "#aa4444")) - "Face for minus sign in diffstat." - :group 'magit-faces) - -;;; Commands - -(defconst magit-diff-popup-common - '(:variable magit-diff-arguments - :man-page "git-diff" - :options ((?f "Limit to files" "-- " magit-read-files) - (?u "Context lines" "-U" read-from-minibuffer) - (?m "Detect renames" "-M" read-from-minibuffer) - (?c "Detect copies" "-C" read-from-minibuffer) - (?a "Diff algorithm" "--diff-algorithm=" - magit-diff-select-algorithm)))) - -(defvar magit-diff-popup - `(,@magit-diff-popup-common - :switches ((?f "Show surrounding functions" "--function-context") - (?b "Ignore whitespace changes" "--ignore-space-change") - (?w "Ignore all whitespace" "--ignore-all-space") - (?x "Disallow external diff drivers" "--no-ext-diff") - (?s "Show stats" "--stat")) - :actions ((?d "Dwim" magit-diff-dwim) - (?u "Diff unstaged" magit-diff-unstaged) - (?c "Show commit" magit-show-commit) - (?r "Diff range" magit-diff) - (?s "Diff staged" magit-diff-staged) - (?t "Show stash" magit-stash-show) - (?p "Diff paths" magit-diff-paths) - (?w "Diff worktree" magit-diff-working-tree)) - :default-action magit-diff-dwim - :max-action-columns 3)) - -(defvar magit-diff-refresh-popup - `(,@magit-diff-popup-common - :switches ((?f "Show surrounding functions" "--function-context") - (?b "Ignore whitespace changes" "--ignore-space-change") - (?w "Ignore all whitespace" "--ignore-all-space") - (?x "Disallow external diff drivers" "--no-ext-diff")) - :actions ((?g "Refresh" magit-diff-refresh) - (?t "Toggle hunk refinement" magit-diff-toggle-refine-hunk) - (?s "Set defaults" magit-diff-set-default-arguments) nil - (?w "Save defaults" magit-diff-save-default-arguments)) - :max-action-columns 2)) - -(defvar magit-diff-mode-refresh-popup - `(,@magit-diff-popup-common - :switches ((?f "Show surrounding functions" "--function-context") - (?b "Ignore whitespace changes" "--ignore-space-change") - (?w "Ignore all whitespace" "--ignore-all-space") - (?x "Disallow external diff drivers" "--no-ext-diff") - (?s "Show stats" "--stat")) - :actions ((?g "Refresh" magit-diff-refresh) - (?t "Toggle hunk refinement" magit-diff-toggle-refine-hunk) - (?s "Set defaults" magit-diff-set-default-arguments) - (?r "Switch range type" magit-diff-switch-range-type) - (?w "Save defaults" magit-diff-save-default-arguments) - (?f "Flip revisions" magit-diff-flip-revs)) - :max-action-columns 2)) - -(defvar magit-revision-mode-refresh-popup - `(,@magit-diff-popup-common - :switches ((?f "Show surrounding functions" "--function-context") - (?b "Ignore whitespace changes" "--ignore-space-change") - (?w "Ignore all whitespace" "--ignore-all-space") - (?x "Disallow external diff drivers" "--no-ext-diff") - (?s "Show stats" "--stat")) - :actions ((?g "Refresh" magit-diff-refresh) - (?t "Toggle hunk refinement" magit-diff-toggle-refine-hunk) - (?s "Set defaults" magit-diff-set-default-arguments) nil - (?w "Save defaults" magit-diff-save-default-arguments)) - :max-action-columns 2)) - -(magit-define-popup-keys-deferred 'magit-diff-popup) -(magit-define-popup-keys-deferred 'magit-diff-refresh-popup) -(magit-define-popup-keys-deferred 'magit-diff-mode-refresh-popup) -(magit-define-popup-keys-deferred 'magit-revision-mode-refresh-popup) - -(defcustom magit-diff-arguments '("--stat" "--no-ext-diff") - "The diff arguments used in buffers whose mode derives from `magit-diff-mode'." - :group 'magit-diff - :group 'magit-commands - :type '(repeat (string :tag "Argument"))) - -(defcustom magit-diff-section-arguments '("--no-ext-diff") - "The diff arguments used in buffers that show other things besides diffs." - :group 'magit-diff - :group 'magit-status - :type '(repeat (string :tag "Argument"))) - -(defvar magit-diff-section-file-args nil) -(put 'magit-diff-section-file-args 'permanent-local t) -(put 'magit-diff-section-arguments 'permanent-local t) - -(defun magit-diff-arguments (&optional refresh) - (cond ((memq magit-current-popup '(magit-diff-popup magit-diff-refresh-popup)) - (magit-popup-export-file-args magit-current-popup-args)) - ((derived-mode-p 'magit-diff-mode) - (list (nth 2 magit-refresh-args) - (nth 3 magit-refresh-args))) - (refresh - (list magit-diff-section-arguments - magit-diff-section-file-args)) - (t - (-if-let (buffer (magit-mode-get-buffer 'magit-diff-mode)) - (with-current-buffer buffer - (list (nth 2 magit-refresh-args) - (nth 3 magit-refresh-args))) - (list (default-value 'magit-diff-arguments) nil))))) - -(defun magit-diff-popup (arg) - "Popup console for diff commands." - (interactive "P") - (let ((magit-diff-arguments - ;; We cannot possibly know what suffix command the user is - ;; about to invoke, so we also don't know from which buffer - ;; we should get the current values. However it is much - ;; more likely that we will end up updating the diff buffer, - ;; and we therefore use the value from that buffer. - (-if-let (buffer (magit-mode-get-buffer 'magit-diff-mode)) - (with-current-buffer buffer - (magit-popup-import-file-args (nth 2 magit-refresh-args) - (nth 3 magit-refresh-args))) - (default-value 'magit-diff-arguments)))) - (magit-invoke-popup 'magit-diff-popup nil arg))) - -(defun magit-diff-refresh-popup (arg) - "Popup console for changing diff arguments in the current buffer." - (interactive "P") - (let ((magit-diff-refresh-popup - (pcase major-mode - (`magit-revision-mode magit-revision-mode-refresh-popup) - (`magit-diff-mode magit-diff-mode-refresh-popup) - (_ magit-diff-refresh-popup))) - (magit-diff-arguments - (if (derived-mode-p 'magit-diff-mode) - (magit-popup-import-file-args (nth 2 magit-refresh-args) - (nth 3 magit-refresh-args)) - (magit-popup-import-file-args magit-diff-section-arguments - magit-diff-section-file-args)))) - (magit-invoke-popup 'magit-diff-refresh-popup nil arg))) - -(defun magit-diff-select-algorithm (&rest _ignore) - (magit-read-char-case nil t - (?d "[d]efault" "default") - (?m "[m]inimal" "minimal") - (?p "[p]atience" "patience") - (?h "[h]istogram" "histogram"))) - -;;;###autoload -(defun magit-diff-dwim (&optional args files) - "Show changes for the thing at point." - (interactive (magit-diff-arguments)) - (pcase (magit-diff--dwim) - (`unstaged (magit-diff-unstaged args files)) - (`staged (magit-diff-staged nil args files)) - (`(commit . ,value) - (magit-diff (format "%s^..%s" value value) args files)) - (`(stash . ,value) (magit-stash-show value args)) - ((and range (pred stringp)) - (magit-diff range args files)) - (_ - (call-interactively #'magit-diff)))) - -(defun magit-diff--dwim () - "Return information for performing DWIM diff. - -The information can be in three forms: -1. TYPE - A symbol describing a type of diff where no additional information - is needed to generate the diff. Currently, this includes `staged' - and `unstaged'. -2. (TYPE . VALUE) - Like #1 but the diff requires additional information, which is - given by VALUE. Currently, this includes `commit' and `stash', - where VALUE is the given commit or stash, respectively. -3. RANGE - A string indicating a diff range. - -If no DWIM context is found, nil is returned." - (cond - ((--when-let (magit-region-values 'commit 'branch) - (deactivate-mark) - (concat (car (last it)) ".." (car it)))) - (magit-buffer-refname - (cons 'commit magit-buffer-refname)) - ((derived-mode-p 'magit-revision-mode) - (cons 'commit (car magit-refresh-args))) - (t - (magit-section-case - ([* unstaged] 'unstaged) - ([* staged] 'staged) - (unpushed (format "%s...%s" - (magit-get-tracked-branch) - (magit-get-current-branch))) - (unpulled (format "%s...%s" - (magit-get-current-branch) - (magit-get-tracked-branch))) - (branch (let ((current (magit-get-current-branch)) - (atpoint (magit-section-value it))) - (if (equal atpoint current) - (--if-let (magit-get-tracked-branch) - (format "%s...%s" it current) - (if (magit-anything-modified-p) - current - (cons 'commit current))) - (format "%s..%s" atpoint current)))) - (commit (cons 'commit (magit-section-value it))) - (stash (cons 'stash (magit-section-value it))))))) - -(defun magit-diff-read-range-or-commit (prompt &optional secondary-default mbase) - "Read range or revision with special diff range treatment. -If MBASE is non-nil, prompt for which rev to place at the end of -a \"revA...revB\" range. Otherwise, always construct -\"revA..revB\" range." - (--if-let (magit-region-values 'commit 'branch) - (let ((revA (car (last it))) - (revB (car it))) - (deactivate-mark) - (if mbase - (let ((base (magit-git-string "merge-base" revA revB))) - (cond - ((string= (magit-rev-parse revA) base) - (format "%s..%s" revA revB)) - ((string= (magit-rev-parse revB) base) - (format "%s..%s" revB revA)) - (t - (let ((main (magit-completing-read "View changes along" - (list revA revB) - nil t nil nil revB))) - (format "%s...%s" - (if (string= main revB) revA revB) main))))) - (format "%s..%s" revA revB))) - (magit-read-range prompt - (or (pcase (magit-diff--dwim) - (`(commit . ,value) - (format "%s^..%s" value value)) - ((and range (pred stringp)) - range)) - secondary-default - (magit-get-current-branch))))) - -(defun magit-diff-setup (rev-or-range const args files) - (magit-mode-setup #'magit-diff-mode rev-or-range const args files)) - -;;;###autoload -(defun magit-diff (rev-or-range &optional args files) - "Show differences between two commits. - -REV-OR-RANGE should be a RANGE or a single revision. If it is a -revision, then show changes in the working tree relative to that -revision. If it is a range, but one side is omitted, then show -changes relative to `HEAD'. - -If the region is active, use the revisions on the first and last -line of the region as the two sides of the range. With a prefix -argument, instead of diffing the revisions, choose a revision to -view changes along, starting at the common ancestor of both -revisions (i.e., use a \"...\" range)." - (interactive (cons (magit-diff-read-range-or-commit "Diff for range" - nil current-prefix-arg) - (magit-diff-arguments))) - (magit-diff-setup rev-or-range nil args files)) - -;;;###autoload -(defun magit-diff-working-tree (&optional rev args files) - "Show changes between the current working tree and the `HEAD' commit. -With a prefix argument show changes between the working tree and -a commit read from the minibuffer." - (interactive - (cons (and current-prefix-arg - (magit-read-branch-or-commit "Diff working tree and commit")) - (magit-diff-arguments))) - (magit-diff-setup (or rev "HEAD") nil args files)) - -;;;###autoload -(defun magit-diff-staged (&optional rev args files) - "Show changes between the index and the `HEAD' commit. -With a prefix argument show changes between the index and -a commit read from the minibuffer." - (interactive - (cons (and current-prefix-arg - (magit-read-branch-or-commit "Diff index and commit")) - (magit-diff-arguments))) - (magit-diff-setup rev (list "--cached") args files)) - -;;;###autoload -(defun magit-diff-unstaged (&optional args files) - "Show changes between the working tree and the index." - (interactive (magit-diff-arguments)) - (magit-diff-setup nil nil args files)) - -;;;###autoload -(defun magit-diff-unpushed (&optional args files) - "Show unpushed changes." - (interactive (magit-diff-arguments)) - (-if-let (tracked (magit-get-tracked-ref)) - (magit-diff-setup (concat tracked "...") nil args files) - (user-error "No upstream set"))) - -;;;###autoload -(defun magit-diff-unpulled (&optional args files) - "Show unpulled changes." - (interactive (magit-diff-arguments)) - (-if-let (tracked (magit-get-tracked-ref)) - (magit-diff-setup (concat "..." tracked) nil args files) - (user-error "No upstream set"))) - -;;;###autoload -(defun magit-diff-while-committing (&optional args files) - "While committing, show the changes that are about to be committed. -While amending, invoking the command again toggles between -showing just the new changes or all the changes that will -be commited." - (interactive (magit-diff-arguments)) - (let ((toplevel (magit-toplevel)) - (diff-buf (magit-mode-get-buffer 'magit-diff-mode))) - (if (magit-commit-message-buffer) - (if (and (or ;; most likely an explicit amend - (not (magit-anything-staged-p)) - ;; explicitly toggled from within diff - (and (eq (current-buffer) diff-buf))) - (or (not diff-buf) - (with-current-buffer diff-buf - (or ;; default to include last commit - (not (equal (magit-toplevel) toplevel)) - ;; toggle to include last commit - (not (car magit-refresh-args)))))) - (magit-diff-while-amending args files) - (magit-diff-staged nil args files)) - (user-error "No commit in progress")))) - -(define-key git-commit-mode-map - (kbd "C-c C-d") 'magit-diff-while-committing) - -(defun magit-diff-while-amending (&optional args files) - (magit-diff-setup "HEAD^" (list "--cached") args files)) - -;;;###autoload -(defun magit-diff-paths (a b) - "Show changes between any two files on disk." - (interactive (list (read-file-name "First file: " nil nil t) - (read-file-name "Second file: " nil nil t))) - (magit-diff-setup nil (list "--no-index") - nil (list (expand-file-name a) - (expand-file-name b)))) - -(defvar-local magit-diff-hidden-files nil) -(put 'magit-diff-hidden-files 'permanent-local t) - -;;;###autoload -(defun magit-show-commit (rev &optional args files module) - "Show the revision at point. -If there is no revision at point or with a prefix argument prompt -for a revision." - (interactive - (let* ((mcommit (magit-section-when module-commit)) - (atpoint (or (and magit-blame-mode (magit-blame-chunk-get :hash)) - mcommit - (magit-branch-or-commit-at-point) - (magit-tag-at-point)))) - (nconc (cons (or (and (not current-prefix-arg) atpoint) - (magit-read-branch-or-commit "Show commit" atpoint)) - (magit-diff-arguments)) - (and mcommit (list (magit-section-parent-value - (magit-current-section))))))) - (magit-with-toplevel - (when module - (setq default-directory - (expand-file-name (file-name-as-directory module)))) - (unless (magit-rev-verify-commit rev) - (user-error "%s is not a commit" rev)) - (-when-let (buffer (magit-mode-get-buffer 'magit-revision-mode)) - (with-current-buffer buffer - (let ((prev (car magit-refresh-args))) - (unless (equal rev prev) - (dolist (child (cdr (magit-section-children magit-root-section))) - (when (eq (magit-section-type child) 'file) - (let ((file (magit-section-value child))) - (if (magit-section-hidden child) - (add-to-list 'magit-diff-hidden-files file) - (setq magit-diff-hidden-files - (delete file magit-diff-hidden-files)))))))))) - (magit-mode-setup #'magit-revision-mode rev nil args files))) - -(defun magit-diff-refresh (args files) - "Set the local diff arguments for the current buffer." - (interactive (magit-diff-arguments t)) - (cond ((derived-mode-p 'magit-diff-mode) - (setcdr (cdr magit-refresh-args) (list args files))) - (t - (setq-local magit-diff-section-arguments args) - (setq-local magit-diff-section-file-args files))) - (magit-refresh)) - -(defun magit-diff-set-default-arguments (args files) - "Set the global diff arguments for the current buffer." - (interactive (magit-diff-arguments t)) - (cond ((derived-mode-p 'magit-diff-mode) - (customize-set-variable 'magit-diff-arguments args) - (setcdr (cdr magit-refresh-args) (list args files))) - (t - (customize-set-variable 'magit-diff-section-arguments args) - (kill-local-variable 'magit-diff-section-arguments) - (kill-local-variable 'magit-diff-section-file-args))) - (magit-refresh)) - -(defun magit-diff-save-default-arguments (args files) - "Set and save the global diff arguments for the current buffer." - (interactive (magit-diff-arguments t)) - (cond ((derived-mode-p 'magit-diff-mode) - (customize-save-variable 'magit-diff-arguments args) - (setcdr (cdr magit-refresh-args) (list args files))) - (t - (customize-save-variable 'magit-diff-section-arguments args) - (kill-local-variable 'magit-diff-section-arguments) - (kill-local-variable 'magit-diff-section-file-args))) - (magit-refresh)) - -(defun magit-diff-switch-range-type () - "Convert diff range type. -Change \"revA..revB\" to \"revB...revA\", or vice versa." - (interactive) - (let ((range (car magit-refresh-args))) - (if (and range - (derived-mode-p 'magit-diff-mode) - (string-match magit-range-re range)) - (progn - (setcar magit-refresh-args - (concat (match-string 1 range) - (if (string= (match-string 2 range) "..") - "..." - "..") - (match-string 3 range))) - (magit-refresh)) - (user-error "No range to change")))) - -(defun magit-diff-flip-revs () - "Swap revisions in diff range. -Change \"revA..revB\" to \"revB..revA\"." - (interactive) - (let ((range (car magit-refresh-args))) - (if (and range - (derived-mode-p 'magit-diff-mode) - (string-match magit-range-re range)) - (progn - (setcar magit-refresh-args - (concat (match-string 3 range) - (match-string 2 range) - (match-string 1 range))) - (magit-refresh)) - (user-error "No range to swap")))) - -(defun magit-diff-less-context (&optional count) - "Decrease the context for diff hunks by COUNT lines." - (interactive "p") - (magit-diff-set-context `(lambda (cur) (max 0 (- (or cur 0) ,count))))) - -(defun magit-diff-more-context (&optional count) - "Increase the context for diff hunks by COUNT lines." - (interactive "p") - (magit-diff-set-context `(lambda (cur) (+ (or cur 0) ,count)))) - -(defun magit-diff-default-context () - "Reset context for diff hunks to the default height." - (interactive) - (magit-diff-set-context #'ignore)) - -(defun magit-diff-set-context (fn) - (let* ((def (--if-let (magit-get "diff.context") (string-to-number it) 3)) - (val (car (magit-diff-arguments t))) - (arg (--first (string-match "^-U\\([0-9]+\\)?$" it) val)) - (num (--if-let (and arg (match-string 1 arg)) (string-to-number it) def)) - (val (delete arg val)) - (num (funcall fn num)) - (arg (and num (not (= num def)) (format "-U%i" num))) - (val (if arg (cons arg val) val))) - (if (derived-mode-p 'magit-diff-mode) - (setcar (cddr magit-refresh-args) val) - (setq magit-diff-section-arguments val))) - (magit-refresh)) - -(defun magit-diff-context-p () - (--if-let (--first (string-match "^-U\\([0-9]+\\)$" it) - (car (magit-diff-arguments t))) - (not (equal "-U0" it)) - t)) - -(defun magit-diff-toggle-refine-hunk (&optional style) - "Turn diff-hunk refining on or off. - -If hunk refining is currently on, then hunk refining is turned off. -If hunk refining is off, then hunk refining is turned on, in -`selected' mode (only the currently selected hunk is refined). - -With a prefix argument, the \"third choice\" is used instead: -If hunk refining is currently on, then refining is kept on, but -the refining mode (`selected' or `all') is switched. -If hunk refining is off, then hunk refining is turned on, in -`all' mode (all hunks refined). - -Customize variable `magit-diff-refine-hunk' to change the default mode." - (interactive "P") - (setq-local magit-diff-refine-hunk - (if style - (if (eq magit-diff-refine-hunk 'all) t 'all) - (not magit-diff-refine-hunk))) - (magit-diff-update-hunk-refinement)) - -(defun magit-diff-visit-file (file &optional other-window force-worktree) - "From a diff, visit the corresponding file at the appropriate position. - -When the file is already being displayed in another window of the -same frame, then just select that window and adjust point. With -a prefix argument also display in another window. - -If the diff shows changes in the worktree, the index, or `HEAD', -then visit the actual file. Otherwise when the diff is about -an older commit, then visit the respective blob using -`magit-find-file'. Also see `magit-diff-visit-file-worktree' -which, as the name suggests always visits the actual file." - (interactive (list (--if-let (magit-file-at-point) - (expand-file-name it) - (user-error "No file at point")) - current-prefix-arg)) - (if (file-accessible-directory-p file) - (magit-diff-visit-directory file other-window) - (let ((current (magit-current-section)) - (rev (cond (force-worktree nil) - ((derived-mode-p 'magit-revision-mode) - (car magit-refresh-args)) - ((derived-mode-p 'magit-diff-mode) - (--when-let (car magit-refresh-args) - (and (string-match "\\.\\.\\([^.].*\\)?[ \t]*\\'" it) - (match-string 1 it)))))) - (unmerged-p (magit-anything-unmerged-p file)) - diff hunk line col buffer) - (when (and rev (magit-rev-head-p rev)) - (setq rev nil)) - (setq hunk - (pcase (magit-diff-scope) - ((or `hunk `region) current) - ((or `file `files) (car (magit-section-children current))) - (`list (car (magit-section-children - (car (magit-section-children current))))))) - (when hunk - (setq line (magit-diff-hunk-line hunk) - col (magit-diff-hunk-column hunk))) - (setq buffer (if rev - (magit-find-file-noselect rev file) - (or (get-file-buffer file) - (find-file-noselect file)))) - (magit-display-file-buffer buffer) - (when line - (goto-char (point-min)) - (forward-line (1- line)) - (when col - (move-to-column col))) - (when unmerged-p - (smerge-start-session))))) - -(defvar magit-display-file-buffer-function - 'magit-display-file-buffer-traditional - "The function used by `magit-diff-visit-file' to display blob buffers. - -Other commands such as `magit-find-file' do not use this -function. Instead they use high-level functions to select the -window to be used to display the buffer. This variable and the -related functions are an experimental feature and should be -treated as such.") - -(defun magit-display-file-buffer (buffer) - (funcall magit-display-file-buffer-function buffer)) - -(defun magit-display-file-buffer-traditional (buffer) - (if (or current-prefix-arg (get-buffer-window buffer)) - (pop-to-buffer buffer) - (switch-to-buffer buffer))) - -(defun magit-diff-visit-file-worktree (file &optional other-window) - "From a diff, visit the corresponding file at the appropriate position. - -When the file is already being displayed in another window of the -same frame, then just select that window and adjust point. With -a prefix argument also display in another window. - -The actual file in the worktree is visited. The positions in the -hunk headers get less useful the \"older\" the changes are, and -as a result, jumping to the appropriate position gets less -reliable. - -Also see `magit-diff-visit-file' which visits the respective -blob, unless the diff shows changes in the worktree, the index, -or `HEAD'." - (interactive (list (or (magit-file-at-point) - (user-error "No file at point")) - current-prefix-arg)) - (magit-diff-visit-file file other-window t)) - -(defun magit-diff-hunk-line (section) - (let* ((value (magit-section-value section)) - (prefix (- (length value) 2)) - (cpos (marker-position (magit-section-content section))) - (stop (line-number-at-pos)) - (cstart (save-excursion (goto-char cpos) (line-number-at-pos))) - (line (car (last value)))) - (string-match "^\\+\\([0-9]+\\)" line) - (setq line (string-to-number (match-string 1 line))) - (when (> cstart stop) - (save-excursion - (goto-char cpos) - (re-search-forward "^[-+]") - (setq stop (line-number-at-pos)))) - (save-excursion - (goto-char cpos) - (while (< (line-number-at-pos) stop) - (unless (string-match-p - "-" (buffer-substring (point) (+ (point) prefix))) - (cl-incf line)) - (forward-line))) - line)) - -(defun magit-diff-hunk-column (section) - (if (or (< (point) (magit-section-content section)) - (save-excursion (beginning-of-line) (looking-at-p "-"))) - 0 - (max 0 (- (+ (current-column) 2) - (length (magit-section-value section)))))) - -(defun magit-diff-visit-directory (directory &optional other-window) - (if (equal (magit-toplevel directory) - (magit-toplevel)) - (magit-dired-jump other-window) - (let ((display-buffer-overriding-action - (if other-window - '(nil (inhibit-same-window t)) - '(display-buffer-same-window)))) - (magit-status-internal directory)))) - -(defun magit-diff-show-or-scroll-up () - "Update the commit or diff buffer for the thing at point. - -Either show the commit or stash at point in the appropriate -buffer, or if that buffer is already being displayed in the -current frame and contains information about that commit or -stash, then instead scroll the buffer up. If there is no -commit or stash at point, then prompt for a commit." - (interactive) - (magit-diff-show-or-scroll 'scroll-up)) - -(defun magit-diff-show-or-scroll-down () - "Update the commit or diff buffer for the thing at point. - -Either show the commit or stash at point in the appropriate -buffer, or if that buffer is already being displayed in the -current frame and contains information about that commit or -stash, then instead scroll the buffer down. If there is no -commit or stash at point, then prompt for a commit." - (interactive) - (magit-diff-show-or-scroll 'scroll-down)) - -(defun magit-diff-show-or-scroll (fn) - (let (rev cmd buf win) - (cond - (magit-blame-mode - (setq rev (magit-blame-chunk-get :hash) - cmd 'magit-show-commit - buf (magit-mode-get-buffer 'magit-revision-mode))) - ((derived-mode-p 'git-rebase-mode) - (save-excursion - (goto-char (line-beginning-position)) - (--if-let (and (looking-at git-rebase-line) - (match-string 2)) - (setq rev it - cmd 'magit-show-commit - buf (magit-mode-get-buffer 'magit-revision-mode)) - (user-error "No commit on this line")))) - (t - (magit-section-case - ((commit branch) - (setq rev (magit-section-value it) - cmd 'magit-show-commit - buf (magit-mode-get-buffer 'magit-revision-mode))) - (stash - (setq rev (magit-section-value it) - cmd 'magit-stash-show - buf (magit-mode-get-buffer 'magit-diff-mode)))))) - (if rev - (if (and buf - (setq win (get-buffer-window buf)) - (with-current-buffer buf - (equal (if (eq cmd 'magit-stash-show) - (concat rev "^2^.." rev) - rev) - (car magit-refresh-args)))) - (with-selected-window win - (condition-case err - (funcall fn) - (error - (goto-char (pcase fn - (`scroll-up (point-min)) - (`scroll-down (point-max))))))) - (let ((magit-display-buffer-noselect t)) - (if (eq cmd 'magit-show-commit) - (apply #'magit-show-commit rev (magit-diff-arguments)) - (funcall cmd rev)))) - (call-interactively #'magit-show-commit)))) - -;;; Diff Mode - -(defvar magit-diff-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map magit-mode-map) - (define-key map "\C-c\C-d" 'magit-diff-while-committing) - (define-key map "\C-c\C-b" 'magit-go-backward) - (define-key map "\C-c\C-f" 'magit-go-forward) - (define-key map "\s" 'scroll-up) - (define-key map "\d" 'scroll-down) - (define-key map "j" 'magit-jump-to-diffstat-or-diff) - map) - "Keymap for `magit-diff-mode'.") - -(define-derived-mode magit-diff-mode magit-mode "Magit Diff" - "Mode for looking at a Git diff. - -This mode is documented in info node `(magit)Diff buffer'. - -\\\ -Type \\[magit-refresh] to refresh the current buffer. -Type \\[magit-section-toggle] to expand or hide the section at point. -Type \\[magit-visit-thing] to visit the hunk or file at point. - -Staging and applying changes is documented in info node -`(magit)Staging and unstaging' and info node `(magit)Applying'. - -\\Type \ -\\[magit-apply] to apply the change at point, \ -\\[magit-stage] to stage, -\\[magit-unstage] to unstage, \ -\\[magit-discard] to discard, or \ -\\[magit-reverse] to reverse it. - -\\{magit-diff-mode-map}" - :group 'magit-diff - (hack-dir-local-variables-non-file-buffer)) - -(defun magit-diff-refresh-buffer (rev-or-range const _args files) - "Refresh the current `magit-diff-mode' buffer. - -In such buffer the buffer-local value of `magit-refresh-args', -has the same form as the arguments of this function. The value -is set in `magit-mode-setup'." - (setq header-line-format - (propertize - (if (member "--no-index" const) - (apply #'format " Differences between %s and %s" files) - (concat (if rev-or-range - (if (string-match-p "\\.\\." rev-or-range) - (format " Changes in %s" rev-or-range) - (format " Changes from %s to working tree" rev-or-range)) - (if (member "--cached" const) - " Staged changes" - " Unstaged changes")) - (pcase (length files) - (0) - (1 (concat " in file " (car files))) - (_ (concat " in files " - (mapconcat #'identity files ", ")))))) - 'face 'magit-header-line)) - (magit-insert-section (diffbuf) - (run-hook-with-args 'magit-diff-sections-hook rev-or-range))) - -(defun magit-insert-diff (rev-or-range) - "Insert the diff into this `magit-diff-mode' buffer." - (magit-git-wash #'magit-diff-wash-diffs - "diff" rev-or-range "-p" "--no-prefix" - (and (member "--stat" (nth 2 magit-refresh-args)) "--numstat") - (nth 1 magit-refresh-args) - (nth 2 magit-refresh-args) "--" - (nth 3 magit-refresh-args))) - -(defvar magit-file-section-map - (let ((map (make-sparse-keymap))) - (define-key map [C-return] 'magit-diff-visit-file-worktree) - (define-key map "\C-j" 'magit-diff-visit-file-worktree) - (define-key map [remap magit-visit-thing] 'magit-diff-visit-file) - (define-key map [remap magit-delete-thing] 'magit-discard) - (define-key map "a" 'magit-apply) - (define-key map "C" 'magit-commit-add-log) - (define-key map "K" 'magit-file-untrack) - (define-key map "R" 'magit-file-rename) - (define-key map "s" 'magit-stage) - (define-key map "u" 'magit-unstage) - (define-key map "v" 'magit-reverse) - map) - "Keymap for `file' sections.") - -(defvar magit-hunk-section-map - (let ((map (make-sparse-keymap))) - (define-key map [C-return] 'magit-diff-visit-file-worktree) - (define-key map "\C-j" 'magit-diff-visit-file-worktree) - (define-key map [remap magit-visit-thing] 'magit-diff-visit-file) - (define-key map [remap magit-delete-thing] 'magit-discard) - (define-key map "a" 'magit-apply) - (define-key map "C" 'magit-commit-add-log) - (define-key map "s" 'magit-stage) - (define-key map "u" 'magit-unstage) - (define-key map "v" 'magit-reverse) - map) - "Keymap for `hunk' sections.") - -(defconst magit-diff-headline-re - (concat "^\\(@@@?\\|diff\\|Submodule\\|" - "\\* Unmerged path\\|merged\\|changed in both\\)")) - -(defconst magit-diff-statline-re - (concat "^ ?" - "\\(.*\\)" ; file - "\\( +| +\\)" ; separator - "\\([0-9]+\\|Bin\\(?: +[0-9]+ -> [0-9]+ bytes\\)?$\\) ?" - "\\(\\+*\\)" ; add - "\\(-*\\)$")) ; del - -(defconst magit-diff-submodule-re - (concat "^Submodule \\([^ ]+\\) \\(?:" - "\\([^ ]+ (new submodule)\\)\\|" - "\\([^ ]+ (submodule deleted)\\)\\|" - "\\(contains \\(?:modified\\|untracked\\) content\\)\\|" - "\\([^ :]+\\)\\( (rewind)\\)?:\\)$")) - -(defun magit-diff-wash-diffs (args &optional limit) - (when (member "--stat" args) - (magit-diff-wash-diffstat)) - (when (re-search-forward magit-diff-headline-re limit t) - (goto-char (line-beginning-position)) - (magit-wash-sequence (apply-partially 'magit-diff-wash-diff args)) - (insert ?\n))) - -(defun magit-jump-to-diffstat-or-diff () - "Jump to the diffstat or diff. -When point is on a file inside the diffstat section, then jump -to the respective diff section, otherwise jump to the diffstat -section or a child thereof." - (interactive) - (--if-let (magit-get-section - (append (magit-section-case - ([file diffstat] `((file . ,(magit-section-value it)))) - (file `((file . ,(magit-section-value it)) (diffstat))) - (t '((diffstat)))) - (magit-section-ident magit-root-section))) - (magit-section-goto it) - (user-error "No diffstat in this buffer"))) - -(defun magit-diff-wash-diffstat () - (let (heading (beg (point))) - (when (re-search-forward "^ ?\\([0-9]+ +files? change[^\n]*\n\\)" nil t) - (setq heading (match-string 1)) - (magit-delete-match) - (goto-char beg) - (magit-insert-section it (diffstat) - (insert (propertize heading 'face 'magit-diff-file-heading)) - (magit-insert-heading) - (let (files) - (while (looking-at "^[-0-9]+\t[-0-9]+\t\\(.+\\)$") - (push (magit-decode-git-path (match-string 1)) files) - (magit-delete-line)) - (setq files (nreverse files)) - (while (looking-at magit-diff-statline-re) - (magit-bind-match-strings (file sep cnt add del) nil - (magit-delete-line) - (when (string-match " +$" file) - (setq sep (concat (match-string 0 file) sep)) - (setq file (substring file 0 (match-beginning 0)))) - (let ((le (length file)) ld) - (setq file (magit-decode-git-path file)) - (setq ld (length file)) - (when (> le ld) - (setq sep (concat (make-string (- le ld) ?\s) sep)))) - (magit-insert-section (file (pop files)) - (insert (propertize file 'face 'magit-filename) sep cnt " ") - (when add - (insert (propertize add 'face 'magit-diffstat-added))) - (when del - (insert (propertize del 'face 'magit-diffstat-removed))) - (insert "\n"))))) - (if (looking-at "^$") (forward-line) (insert "\n")))))) - -(defun magit-diff-wash-diff (args) - (cond - ((looking-at magit-diff-submodule-re) - (magit-diff-wash-submodule)) - ((looking-at "^\\* Unmerged path \\(.*\\)") - (let ((file (magit-decode-git-path (match-string 1)))) - (magit-delete-line) - (unless (and (derived-mode-p 'magit-status-mode) - (not (member "--cached" args))) - (magit-insert-section (file file) - (insert (propertize - (format "unmerged %s%s" file - (pcase (cddr (car (magit-file-status file))) - (`(?D ?D) " (both deleted)") - (`(?D ?U) " (deleted by us)") - (`(?U ?D) " (deleted by them)") - (`(?A ?A) " (both added)") - (`(?A ?U) " (added by us)") - (`(?U ?A) " (added by them)") - (`(?U ?U) ""))) - 'face 'magit-diff-file-heading)) - (insert ?\n)))) - t) - ((looking-at "^\\(merged\\|changed in both\\)") - (let ((status (if (equal (match-string 1) "merged") 'merged 'conflict)) - file orig modes) - (magit-delete-line) - (while (looking-at - "^ \\([^ ]+\\) +[0-9]\\{6\\} \\([a-z0-9]\\{40\\}\\) \\(.+\\)$") - (magit-bind-match-strings (side blob name) nil - (pcase side - ("result" (setq file name)) - ("our" (setq orig name)) - ("their" (setq file name)))) - (magit-delete-line)) - (setq orig (magit-decode-git-path orig)) - (setq file (magit-decode-git-path file)) - (magit-diff-insert-file-section file orig status modes nil))) - ((looking-at - "^diff --\\(?:\\(git\\) \\(?:\\(.+?\\) \\2\\)?\\|\\(cc\\|combined\\) \\(.+\\)\\)") - (let ((status (cond ((equal (match-string 1) "git") "modified") - ((derived-mode-p 'magit-revision-mode) "resolved") - (t "unmerged"))) - (file (or (match-string 2) (match-string 4))) - (beg (point)) - orig header modes) - (save-excursion - (forward-line 1) - (setq header (buffer-substring - beg (if (re-search-forward magit-diff-headline-re nil t) - (match-beginning 0) - (point-max))))) - (magit-delete-line) - (while (not (or (eobp) (looking-at magit-diff-headline-re))) - (if (looking-at "^old mode \\([^\n]+\\)\nnew mode \\([^\n]+\\)\n") - (progn (setq modes (match-string 0)) - (magit-delete-match)) - (cond - ((looking-at "^--- \\([^/].*?\\)\t?$") ; i.e. not /dev/null - (setq orig (match-string 1))) - ((looking-at "^\\+\\+\\+ \\([^/].*?\\)\t?$") - (setq file (match-string 1))) - ((looking-at "^\\(copy\\|rename\\) from \\(.+\\)$") - (setq orig (match-string 2))) - ((looking-at "^\\(copy\\|rename\\) to \\(.+\\)$") - (setq file (match-string 2)) - (setq status (if (equal (match-string 1) "copy") "new file" "renamed"))) - ((looking-at "^\\(new file\\|deleted\\)") - (setq status (match-string 1)))) - (magit-delete-line))) - (when orig - (setq orig (magit-decode-git-path orig))) - (setq file (magit-decode-git-path file)) - ;; KLUDGE `git-log' ignores `--no-prefix' when `-L' is used. - (when (derived-mode-p 'magit-log-mode) - (setq file (substring file 2)) - (when orig - (setq orig (substring orig 2)))) - (magit-diff-insert-file-section file orig status modes header))))) - -(defun magit-diff-insert-file-section (file orig status modes header) - (magit-insert-section section - (file file (or (equal status "deleted") - (derived-mode-p 'magit-status-mode))) - (insert (propertize (format "%-10s %s\n" status - (if (or (not orig) (equal orig file)) - file - (format "%s -> %s" orig file))) - 'face 'magit-diff-file-heading)) - (magit-insert-heading) - (unless (equal orig file) - (setf (magit-section-source section) orig)) - (setf (magit-section-diff-header section) header) - (when modes - (magit-insert-section (hunk) - (insert modes))) - (magit-wash-sequence #'magit-diff-wash-hunk))) - -(defun magit-diff-wash-submodule () - (magit-bind-match-strings (module new deleted dirty range rewind) nil - (magit-delete-line) - (when (and dirty - (looking-at magit-diff-submodule-re) - (string= (match-string 1) module)) - (setq range (match-string 5)) - (magit-delete-line)) - (while (looking-at "^ \\([<>]\\) \\(.+\\)$") - (magit-delete-line)) - (if range - (let ((default-directory - (file-name-as-directory - (expand-file-name module (magit-toplevel))))) - (setf (magit-section-value - (magit-insert-section (file module t) - (magit-insert-heading - (concat (propertize (concat "modified " module) - 'face 'magit-diff-file-heading) - " (" - (if rewind "rewind" "new commits") - (and dirty ", modified content") - ")")) - (unless rewind - (magit-git-wash - (apply-partially 'magit-log-wash-log 'module) - "log" "--oneline" "--left-right" range) - (delete-char -1)))) - module)) - (magit-insert-section (file module) - (insert (propertize (if new - (concat "new module " module) - (concat "modified " module)) - 'face 'magit-diff-file-heading) - (cond (dirty " (modified content)") - (deleted " (deleted submodule)"))) - (insert ?\n))))) - -(defun magit-diff-wash-hunk () - (when (looking-at "^@\\{2,\\} \\(.+?\\) @\\{2,\\}\\(?: \\(.*\\)\\)?") - (let ((heading (match-string 0)) - (value (cons (match-string 2) (split-string (match-string 1))))) - (magit-delete-line) - (magit-insert-section it (hunk value) - (insert (propertize (concat heading "\n") 'face 'magit-diff-hunk-heading)) - (magit-insert-heading) - (while (not (or (eobp) (looking-at "^[^-+\s\\]"))) - (forward-line)) - (setf (magit-section-end it) (point)) - (setf (magit-section-washer it) #'magit-diff-paint-hunk))) - t)) - -(defun magit-diff-expansion-threshold (section) - "Keep new diff sections collapsed if washing takes too long." - (and (memq (magit-section-type section) '(file)) - (> (float-time (time-subtract (current-time) magit-refresh-start-time)) - magit-diff-expansion-threshold) - 'hide)) - -;;; Revision Mode - -(define-derived-mode magit-revision-mode magit-diff-mode "Magit Rev" - "Mode for looking at a Git commit. - -This mode is documented in info node `(magit)Revision buffer'. - -\\\ -Type \\[magit-refresh] to refresh the current buffer. -Type \\[magit-section-toggle] to expand or hide the section at point. -Type \\[magit-visit-thing] to visit the hunk or file at point. - -Staging and applying changes is documented in info node -`(magit)Staging and unstaging' and info node `(magit)Applying'. - -\\Type \ -\\[magit-apply] to apply the change at point, \ -\\[magit-stage] to stage, -\\[magit-unstage] to unstage, \ -\\[magit-discard] to discard, or \ -\\[magit-reverse] to reverse it. - -\\{magit-revision-mode-map}" - :group 'magit-revision - (hack-dir-local-variables-non-file-buffer)) - -(defun magit-revision-refresh-buffer (rev __const _args _files) - (setq header-line-format - (propertize (format " %s %s" (capitalize (magit-object-type rev)) rev) - 'face 'magit-header-line)) - (magit-insert-section (commitbuf) - (run-hook-with-args 'magit-revision-sections-hook rev))) - -(defun magit-insert-revision-diff (rev) - "Insert the diff into this `magit-revision-mode' buffer." - (magit-git-wash #'magit-diff-wash-diffs - "show" "-p" "--cc" "--format=" "--no-prefix" - (and (member "--stat" (nth 2 magit-refresh-args)) "--numstat") - (nth 2 magit-refresh-args) (concat rev "^{commit}") "--" - (nth 3 magit-refresh-args))) - -(defun magit-insert-revision-tag (rev) - "Insert tag message and headers into a revision buffer. -This function only inserts anything when `magit-show-commit' is -called with a tag as argument, when that is called with a commit -or a ref which is not a branch, then it inserts nothing." - (when (equal (magit-object-type rev) "tag") - (magit-insert-section (taginfo) - (let ((beg (point))) - (magit-git-insert "cat-file" "tag" rev) - (goto-char beg) - (forward-line 3) - (delete-region beg (point))) - (looking-at "^tagger \\([^<]+\\) <\\([^>]+\\)") - (let ((heading (format "Tagger: %s <%s>" - (match-string 1) - (match-string 2)))) - (magit-delete-line) - (insert (propertize heading 'face 'magit-section-secondary-heading))) - (magit-insert-heading) - (goto-char (point-max)) - (insert ?\n)))) - -(defun magit-insert-revision-message (rev) - "Insert the commit message into a revision buffer." - (magit-insert-section (message) - (let ((beg (point))) - (magit-rev-insert-format "%B" rev) - (if (= (point) (+ beg 2)) - (progn (backward-delete-char 2) - (insert "(no message)\n")) - (goto-char beg) - (forward-line) - (put-text-property beg (point) 'face 'magit-section-secondary-heading) - (magit-insert-heading) - (goto-char (point-max)))))) - -(defun magit-insert-revision-notes (rev) - "Insert commit notes into a revision buffer." - (magit-insert-section (notes) - (let ((beg (point))) - (magit-git-insert "notes" "show" rev) - (if (= (point) beg) - (magit-cancel-section) - (goto-char beg) - (forward-line) - (put-text-property beg (point) 'face 'magit-section-secondary-heading) - (magit-insert-heading) - (goto-char (point-max)) - (insert ?\n))))) - -(defun magit-insert-revision-headers (rev) - "Insert headers about the commit into a revision buffer." - (magit-insert-section (headers) - (--when-let (magit-rev-format "%D" rev "--decorate=full") - (insert (magit-format-ref-labels it) ?\s)) - (insert (propertize (magit-rev-parse (concat rev "^{commit}")) - 'face 'magit-hash)) - (magit-insert-heading) - (let ((beg (point))) - (magit-rev-insert-format magit-revision-headers-format rev) - (magit-insert-revision-gravatars rev beg)) - (when magit-revision-insert-related-refs - (dolist (parent (magit-commit-parents rev)) - (magit-insert-section (commit parent) - (let ((line (magit-rev-format "%h %s" parent))) - (string-match "^\\([^ ]+\\) \\(.*\\)" line) - (magit-bind-match-strings (hash msg) line - (insert "Parent: ") - (insert (propertize hash 'face 'magit-hash)) - (insert " " msg "\n"))))) - (-when-let (merged (magit-list-merged-branches rev)) - (insert "Merged: ") - (let (branch) - (while (and (< (+ (- (point) (line-beginning-position)) - (length (car merged)) 9) - (window-width)) - (setq branch (pop merged))) - (insert ?\s) - (magit-insert-section (branch branch) - (insert (propertize branch 'face 'magit-branch-local))))) - (when merged - (insert (format " (%s more)" (length merged)))) - (insert ?\n)) - (-when-let (containing (magit-list-containing-branches rev)) - (insert "Containing:") - (let (branch) - (while (and (< (+ (- (point) (line-beginning-position)) - (length (car containing)) 9) - (window-width)) - (setq branch (pop containing))) - (insert ?\s) - (magit-insert-section (branch branch) - (insert (propertize branch 'face 'magit-branch-local))))) - (when containing - (insert (format " (%s more)" (length containing)))) - (insert ?\n)) - (-when-let (follows (magit-get-current-tag rev t)) - (let ((tag (car follows)) - (cnt (cadr follows))) - (magit-insert-section (tag tag) - (insert (format "Follows: %s (%s)\n" - (propertize tag 'face 'magit-tag) - (propertize (number-to-string cnt) - 'face 'magit-branch-local)))))) - (-when-let (precedes (magit-get-next-tag rev t)) - (let ((tag (car precedes)) - (cnt (cadr precedes))) - (magit-insert-section (tag tag) - (insert (format "Precedes: %s (%s)\n" - (propertize tag 'face 'magit-tag) - (propertize (number-to-string cnt) - 'face 'magit-tag)))))) - (insert ?\n)))) - -(defun magit-insert-revision-gravatars (rev beg) - (when (and magit-revision-show-gravatars (window-system)) - (require 'gravatar) - (magit-insert-revision-gravatar beg (magit-rev-format "%aE" rev) - (car magit-revision-show-gravatars)) - (magit-insert-revision-gravatar beg (magit-rev-format "%cE" rev) - (cdr magit-revision-show-gravatars)) - (goto-char (point-max)))) - -(defun magit-insert-revision-gravatar (beg email regexp) - (when (and email (goto-char beg) (re-search-forward regexp nil t)) - (ignore-errors - (let* ((offset (length (match-string 0))) - (font-obj (query-font (font-at (point) (get-buffer-window)))) - (size (* 2 (+ (aref font-obj 4) (aref font-obj 5)))) - (align-to (+ offset (ceiling (/ size (aref font-obj 7) 1.0)))) - (gravatar-size (- size 2)) - (slice1 '(slice .0 .0 1.0 0.5)) - (slice2 '(slice .0 .5 1.0 1.0))) - (gravatar-retrieve - email - (lambda (image offset align-to slice1 slice2) - (unless (eq image 'error) - (insert (propertize " " 'display `((,@image :ascent center :relief 1) - ,slice1))) - (insert (propertize " " 'display `((space :align-to ,align-to)))) - (forward-line) - (forward-char offset) - (insert (propertize " " 'display `((,@image :ascent center :relief 1) - ,slice2))) - (insert (propertize " " 'display `((space :align-to ,align-to)))))) - (list offset align-to - (if magit-revision-use-gravatar-kludge slice2 slice1) - (if magit-revision-use-gravatar-kludge slice1 slice2))))))) - -(defun magit-revision-set-visibility (section) - "Preserve section visibility when displaying another commit." - (and (derived-mode-p 'magit-revision-mode) - (eq (magit-section-type section) 'file) - (member (magit-section-value section) magit-diff-hidden-files) - 'hide)) - -;;; Diff Sections - -(defvar magit-unstaged-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-visit-thing] 'magit-diff-unstaged) - (define-key map [remap magit-delete-thing] 'magit-discard) - (define-key map "s" 'magit-stage) - (define-key map "u" 'magit-unstage) - map) - "Keymap for the `unstaged' section.") - -(magit-define-section-jumper unstaged "Unstaged changes") - -(defun magit-insert-unstaged-changes () - "Insert section showing unstaged changes." - (magit-insert-section (unstaged) - (magit-insert-heading "Unstaged changes:") - (magit-git-wash #'magit-diff-wash-diffs - "diff" magit-diff-section-arguments "--no-prefix" - "--" magit-diff-section-file-args))) - -(defvar magit-staged-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-visit-thing] 'magit-diff-staged) - (define-key map [remap magit-delete-thing] 'magit-discard) - (define-key map "s" 'magit-stage) - (define-key map "u" 'magit-unstage) - (define-key map "v" 'magit-reverse) - map) - "Keymap for the `staged' section.") - -(magit-define-section-jumper staged "Staged changes") - -(defun magit-insert-staged-changes () - "Insert section showing staged changes." - (magit-insert-section (staged) - (magit-insert-heading "Staged changes:") - (magit-git-wash #'magit-diff-wash-diffs - "diff" "--cached" magit-diff-section-arguments "--no-prefix" - "--" magit-diff-section-file-args))) - -;;; Diff Type - -(defun magit-diff-type (&optional section) - "Return the diff type of SECTION. - -The returned type is one of the symbols `staged', `unstaged', -`committed', or `undefined'. This type serves a similar purpose -as the general type common to all sections (which is stored in -the `type' slot of the corresponding `magit-section' struct) but -takes additional information into account. When the SECTION -isn't related to diffs and the buffer containing it also isn't -a diff-only buffer, then return nil. - -Currently the type can also be one of `tracked' and `untracked' -but these values are not handled explicitly everywhere they -should be and a possible fix could be to just return nil here. - -The section has to be a `diff' or `hunk' section, or a section -whose children are of type `diff'. If optional SECTION is nil, -return the diff type for the current section. In buffers whose -major mode is `magit-diff-mode' SECTION is ignored and the type -is determined using other means. In `magit-revision-mode' -buffers the type is always `committed'. - -Do not confuse this with `magit-diff-scope' (which see)." - (--when-let (or section (magit-current-section)) - (cond ((derived-mode-p 'magit-revision-mode 'magit-stash-mode) 'committed) - ((derived-mode-p 'magit-diff-mode) - (let ((range (nth 0 magit-refresh-args)) - (const (nth 1 magit-refresh-args))) - (cond ((member "--no-index" const) 'undefined) - ((not range) - (if (member "--cached" const) - 'staged - 'unstaged)) - ((member "--cached" const) - (if (magit-rev-head-p range) - 'staged - 'undefined)) ; i.e. committed and staged - (t 'committed)))) - ((derived-mode-p 'magit-status-mode) - (let ((stype (magit-section-type it))) - (if (memq stype '(staged unstaged tracked untracked)) - stype - (pcase stype - (`file (let* ((parent (magit-section-parent it)) - (type (magit-section-type parent))) - (if (eq type 'file) - (magit-diff-type parent) - type))) - (`hunk (-> it magit-section-parent magit-section-parent - magit-section-type)))))) - ((derived-mode-p 'magit-log-mode) - (if (or (and (magit-section-match 'commit section) - (magit-section-children section)) - (magit-section-match [* file commit] section)) - 'committed - 'undefined)) - (t 'undefined)))) - -(cl-defun magit-diff-scope (&optional (section nil ssection) strict) - "Return the diff scope of SECTION or the selected section(s). - -A diff's \"scope\" describes what part of a diff is selected, it is -a symbol, one of `region', `hunk', `hunks', `file', `files', or -`list'. Do not confuse this with the diff \"type\", as returned by -`magit-diff-type'. - -If optional SECTION is non-nil, then return the scope of that, -ignoring the sections selected by the region. Otherwise return -the scope of the current section, or if the region is active and -selects a valid group of diff related sections, the type of these -sections, i.e. `hunks' or `files'. If SECTION, or if that is nil -the current section, is a `hunk' section; and the region region -starts and ends inside the body of a that section, then the type -is `region'. - -If optional STRICT is non-nil then return nil if the diff type of -the section at point is `untracked' or the section at point is not -actually a `diff' but a `diffstat' section." - (let ((siblings (and (not ssection) (magit-region-sections)))) - (setq section (or section (car siblings) (magit-current-section))) - (when (and section - (or (not strict) - (and (not (eq (magit-diff-type section) 'untracked)) - (not (eq (--when-let (magit-section-parent section) - (magit-section-type it)) - 'diffstat))))) - (pcase (list (magit-section-type section) - (and siblings t) - (and (region-active-p) t) - ssection) - (`(hunk nil t ,_) - (if (magit-section-internal-region-p section) 'region 'hunk)) - (`(hunk t t nil) 'hunks) - (`(hunk ,_ ,_ ,_) 'hunk) - (`(file t t nil) 'files) - (`(file ,_ ,_ ,_) 'file) - (`(,(or `staged `unstaged `untracked) - nil ,_ ,_) 'list))))) - -;;; Diff Highlight - -(defun magit-diff-unhighlight (section selection) - "Remove the highlighting of the diff-related SECTION." - (when (eq (magit-section-type section) 'hunk) - (magit-diff-paint-hunk section selection nil) - t)) - -(defun magit-diff-highlight (section selection) - "Highlight the diff-related SECTION and return t. -If SECTION is not a diff-related section, then do nothing and -return nil. If SELECTION is non-nil then it is a list of sections -selected by the region, including SECTION. All of these sections -are highlighted." - (if (and (magit-section-match 'commit section) - (magit-section-children section)) - (progn (if selection - (dolist (section selection) - (magit-diff-highlight-list section selection)) - (magit-diff-highlight-list section)) - t) - (-when-let (scope (magit-diff-scope section t)) - (cond ((eq scope 'region) - (magit-diff-paint-hunk section selection t)) - (selection - (dolist (section selection) - (magit-diff-highlight-recursive section selection))) - (t - (magit-diff-highlight-recursive section))) - t))) - -(defun magit-diff-highlight-recursive (section &optional selection) - (if (magit-section-match '(module-commit diffstat commit-header) section) - (magit-section-highlight section nil) - (pcase (magit-diff-scope section) - (`list (magit-diff-highlight-list section selection)) - (`file (magit-diff-highlight-file section selection)) - (`hunk (magit-diff-highlight-heading section selection) - (magit-diff-paint-hunk section selection t))))) - -(defun magit-diff-highlight-list (section &optional selection) - (let ((beg (magit-section-start section)) - (cnt (magit-section-content section)) - (end (magit-section-end section))) - (unless (and (region-active-p) - (= end (1+ (region-end)))) - (magit-section-make-overlay beg cnt 'magit-section-highlight) - (unless (magit-section-hidden section) - (dolist (child (magit-section-children section)) - (magit-diff-highlight-recursive child selection)))) - (when magit-diff-highlight-hunk-body - (magit-section-make-overlay (1- end) end 'magit-section-highlight)))) - -(defun magit-diff-highlight-file (section &optional selection) - (magit-diff-highlight-heading section selection) - (unless (magit-section-hidden section) - (dolist (child (magit-section-children section)) - (magit-diff-highlight-recursive child selection)))) - -(defun magit-diff-highlight-heading (section &optional selection) - (magit-section-make-overlay - (magit-section-start section) - (or (magit-section-content section) - (magit-section-end section)) - (pcase (list (magit-section-type section) - (and (member section selection) t)) - (`(file t) 'magit-diff-file-heading-selection) - (`(file nil) 'magit-diff-file-heading-highlight) - (`(hunk t) 'magit-diff-hunk-heading-selection) - (`(hunk nil) 'magit-diff-hunk-heading-highlight)))) - -;;; Hunk Paint - -(cl-defun magit-diff-paint-hunk - (section &optional selection - (highlight (magit-section-selected-p section selection))) - (let (paint) - (unless magit-diff-highlight-hunk-body - (setq highlight nil)) - (cond (highlight - (unless (magit-section-hidden section) - (add-to-list 'magit-section-highlighted-sections section) - (cond ((memq section magit-section-unhighlight-sections) - (setq magit-section-unhighlight-sections - (delq section magit-section-unhighlight-sections))) - (magit-diff-highlight-hunk-body - (setq paint t))))) - (t - (cond ((and (magit-section-hidden section) - (memq section magit-section-unhighlight-sections)) - (add-to-list 'magit-section-highlighted-sections section) - (setq magit-section-unhighlight-sections - (delq section magit-section-unhighlight-sections))) - (t - (setq paint t))))) - (when paint - (save-excursion - (goto-char (magit-section-start section)) - (let ((end (magit-section-end section)) - (merging (looking-at "@@@")) - (stage nil)) - (forward-line) - (while (< (point) end) - (put-text-property - (point) (1+ (line-end-position)) 'face - (cond - ((looking-at "^\\+\\+?\\([<=|>]\\)\\{7\\}") - (setq stage (pcase (list (match-string 1) highlight) - (`("<" nil) 'magit-diff-our) - (`("<" t) 'magit-diff-our-highlight) - (`("|" nil) 'magit-diff-base) - (`("|" t) 'magit-diff-base-highlight) - (`("=" nil) 'magit-diff-their) - (`("=" t) 'magit-diff-their-highlight) - (`(">" nil) nil))) - 'magit-diff-conflict-heading) - ((looking-at (if merging "^\\(\\+\\| \\+\\)" "^\\+")) - (magit-diff-paint-whitespace merging) - (or stage - (if highlight 'magit-diff-added-highlight 'magit-diff-added))) - ((looking-at (if merging "^\\(-\\| -\\)" "^-")) - (if highlight 'magit-diff-removed-highlight 'magit-diff-removed)) - (t - (if highlight 'magit-diff-context-highlight 'magit-diff-context)))) - (forward-line)))))) - (magit-diff-update-hunk-refinement section)) - -(defun magit-diff-paint-whitespace (merging) - (when (and magit-diff-paint-whitespace - (or (derived-mode-p 'magit-status-mode) - (not (eq magit-diff-paint-whitespace 'status)))) - (let ((prefix (if merging "^[-\\+\s]\\{2\\}" "^[-\\+]")) - (indent - (if (local-variable-p 'magit-diff-highlight-indentation) - magit-diff-highlight-indentation - (setq-local - magit-diff-highlight-indentation - (cdr (--first (string-match-p (car it) default-directory) - (nreverse - (default-value - 'magit-diff-highlight-indentation)))))))) - (when (and magit-diff-highlight-trailing - (looking-at (concat prefix ".*?\\([ \t]+\\)$"))) - (let ((ov (make-overlay (match-beginning 1) (match-end 1) nil t))) - (overlay-put ov 'face 'magit-diff-whitespace-warning) - (overlay-put ov 'evaporate t))) - (when (or (and (eq indent 'tabs) - (looking-at (concat prefix "\\( *\t[ \t]*\\)"))) - (and (integerp indent) - (looking-at (format "%s\\([ \t]* \\{%s,\\}[ \t]*\\)" - prefix indent)))) - (let ((ov (make-overlay (match-beginning 1) (match-end 1) nil t))) - (overlay-put ov 'face 'magit-diff-whitespace-warning) - (overlay-put ov 'evaporate t)))))) - -(defun magit-diff-update-hunk-refinement (&optional section) - (if section - (unless (magit-section-hidden section) - (pcase (list magit-diff-refine-hunk - (magit-section-refined section) - (eq section (magit-current-section))) - ((or `(all nil ,_) `(t nil t)) - (setf (magit-section-refined section) t) - (save-excursion - (goto-char (magit-section-start section)) - ;; `diff-refine-hunk' does not handle combined diffs. - (unless (looking-at "@@@") - (diff-refine-hunk)))) - ((or `(nil t ,_) `(t t nil)) - (setf (magit-section-refined section) nil) - (remove-overlays (magit-section-start section) - (magit-section-end section) - 'diff-mode 'fine)))) - (cl-labels ((recurse (section) - (if (magit-section-match 'hunk section) - (magit-diff-update-hunk-refinement section) - (--each (magit-section-children section) - (recurse it))))) - (recurse magit-root-section)))) - - -;;; Highlight Region - -(defvar magit-diff-unmarked-lines-keep-foreground t) - -(defun magit-diff-update-hunk-region (section) - (when (and (eq (magit-diff-scope section t) 'region) - (not (and (eq this-command 'mouse-drag-region) - (eq (mark) (point))))) - (let ((sbeg (magit-section-start section)) - (cbeg (magit-section-content section)) - (rbeg (save-excursion (goto-char (region-beginning)) - (line-beginning-position))) - (rend (save-excursion (goto-char (region-end)) - (line-end-position))) - (send (magit-section-end section)) - (face (if magit-diff-highlight-hunk-body - 'magit-diff-context-highlight - 'magit-diff-context))) - (when magit-diff-unmarked-lines-keep-foreground - (setq face (list :background (face-attribute face :background)))) - (cl-flet ((ov (start end &rest args) - (let ((ov (make-overlay start end nil t))) - (overlay-put ov 'evaporate t) - (while args (overlay-put ov (pop args) (pop args))) - (push ov magit-region-overlays) - ov))) - (ov sbeg cbeg 'face 'magit-diff-lines-heading - 'display (concat (magit-diff-hunk-region-header section) "\n")) - (ov cbeg rbeg 'face face 'priority 2) - (when (and (window-system) magit-diff-show-lines-boundary) - (ov rbeg (1+ rbeg) 'before-string - (propertize (concat (propertize "\s" 'display '(space :height (1))) - (propertize "\n" 'line-height t)) - 'face 'magit-diff-lines-boundary)) - (ov rend (1+ rend) 'after-string - (propertize (concat (propertize "\s" 'display '(space :height (1))) - (propertize "\n" 'line-height t)) - 'face 'magit-diff-lines-boundary))) - (ov (1+ rend) send 'face face 'priority 2))))) - -;;; Diff Extract - -(defun magit-diff-file-header (section) - (when (eq (magit-section-type section) 'hunk) - (setq section (magit-section-parent section))) - (when (eq (magit-section-type section) 'file) - (magit-section-diff-header section))) - -(defun magit-diff-hunk-region-header (section) - (let ((patch (magit-diff-hunk-region-patch section))) - (string-match "\n" patch) - (substring patch 0 (1- (match-end 0))))) - -(defun magit-diff-hunk-region-patch (section &optional args) - (let ((op (if (member "--reverse" args) "+" "-")) - (sbeg (magit-section-start section)) - (rbeg (save-excursion - (goto-char (region-beginning)) - (line-beginning-position))) - (rend (region-end)) - (send (magit-section-end section)) - (patch nil)) - (save-excursion - (goto-char sbeg) - (while (< (point) send) - (looking-at "\\(.\\)\\([^\n]*\n\\)") - (cond ((or (string-match-p "[@ ]" (match-string-no-properties 1)) - (and (>= (point) rbeg) - (<= (point) rend))) - (push (match-string-no-properties 0) patch)) - ((equal op (match-string-no-properties 1)) - (push (concat " " (match-string-no-properties 2)) patch))) - (forward-line))) - (with-temp-buffer - (insert (mapconcat 'identity (reverse patch) "")) - (diff-fixup-modifs (point-min) (point-max)) - (setq patch (buffer-string))) - patch)) - -;;; magit-diff.el ends soon -(provide 'magit-diff) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-diff.el ends here diff --git a/elpa/magit-20151119.202/magit-ediff.el b/elpa/magit-20151119.202/magit-ediff.el deleted file mode 100644 index a1766891..00000000 --- a/elpa/magit-20151119.202/magit-ediff.el +++ /dev/null @@ -1,431 +0,0 @@ -;;; magit-ediff.el --- Ediff extension for Magit - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library provides basic support for Ediff. - -;;; Code: - -(require 'magit) - -(require 'ediff) -(require 'smerge-mode) - -(defvar smerge-ediff-buf) -(defvar smerge-ediff-windows) - -(defgroup magit-ediff nil - "Ediff support for Magit." - :group 'magit-extensions) - -(unless (find-lisp-object-file-name 'magit-ediff-quit-hook 'defvar) - (add-hook 'magit-ediff-quit-hook 'magit-ediff-restore-previous-winconf) - (add-hook 'magit-ediff-quit-hook 'magit-ediff-cleanup-auxiliary-buffers)) -(defcustom magit-ediff-quit-hook - '(magit-ediff-cleanup-auxiliary-buffers - magit-ediff-restore-previous-winconf) - "Hooks to run after finishing Ediff, when that was invoked using Magit. -The hooks are run in the Ediff control buffer. This is similar -to `ediff-quit-hook' but takes the needs of Magit into account. -The `ediff-quit-hook' is ignored by Ediff sessions which were -invoked using Magit." - :package-version '(magit . "2.2.0") - :group 'magit-ediff - :type 'hook - :options '(magit-ediff-cleanup-auxiliary-buffers - magit-ediff-restore-previous-winconf)) - -(defcustom magit-ediff-dwim-show-on-hunks nil - "Whether `magit-ediff-dwim' runs show variants on hunks. -If non-nil, `magit-ediff-show-staged' or -`magit-ediff-show-unstaged' are called based on what section the -hunk is in. Otherwise, `magit-ediff-dwim' runs -`magit-ediff-stage' when point is on an uncommitted hunk." - :package-version '(magit . "2.2.0") - :group 'magit-ediff - :type 'boolean) - -(defvar magit-ediff-previous-winconf nil) - -;;;###autoload (autoload 'magit-ediff-popup "magit-ediff" nil t) -(magit-define-popup magit-ediff-popup - "Popup console for ediff commands." - 'magit-diff nil nil - :actions '((?E "Dwim" magit-ediff-dwim) - (?u "Show unstaged" magit-ediff-show-unstaged) - (?s "Stage" magit-ediff-stage) - (?i "Show staged" magit-ediff-show-staged) - (?m "Resolve" magit-ediff-resolve) - (?w "Show worktree" magit-ediff-show-working-tree) - (?r "Diff range" magit-ediff-compare) - (?c "Show commit" magit-ediff-show-commit)) - :max-action-columns 2) - -;;;###autoload -(defun magit-ediff-resolve (file) - "Resolve outstanding conflicts in FILE using Ediff. -FILE has to be relative to the top directory of the repository. - -In the rare event that you want to manually resolve all -conflicts, including those already resolved by Git, use -`ediff-merge-revisions-with-ancestor'." - (interactive - (let ((current (magit-current-file)) - (unmerged (magit-unmerged-files))) - (unless unmerged - (user-error "There are no unresolved conflicts")) - (list (magit-completing-read "Resolve file" unmerged nil t nil nil - (car (member current unmerged)))))) - (magit-with-toplevel - (with-current-buffer (find-file-noselect file) - (smerge-ediff) - (setq-local - ediff-quit-hook - (lambda () - (let ((bufC ediff-buffer-C) - (bufS smerge-ediff-buf)) - (with-current-buffer bufS - (when (yes-or-no-p (format "Conflict resolution finished; save %s?" - buffer-file-name)) - (erase-buffer) - (insert-buffer-substring bufC) - (save-buffer)))) - (when (buffer-live-p ediff-buffer-A) (kill-buffer ediff-buffer-A)) - (when (buffer-live-p ediff-buffer-B) (kill-buffer ediff-buffer-B)) - (when (buffer-live-p ediff-buffer-C) (kill-buffer ediff-buffer-C)) - (when (buffer-live-p ediff-ancestor-buffer) - (kill-buffer ediff-ancestor-buffer)) - (let ((magit-ediff-previous-winconf smerge-ediff-windows)) - (run-hooks 'magit-ediff-quit-hook))))))) - -;;;###autoload -(defun magit-ediff-stage (file) - "Stage and unstage changes to FILE using Ediff. -FILE has to be relative to the top directory of the repository." - (interactive - (list (magit-completing-read "Selectively stage file" nil - (magit-tracked-files) nil nil nil - (magit-current-file)))) - (magit-with-toplevel - (let* ((conf (current-window-configuration)) - (bufA (magit-get-revision-buffer "HEAD" file)) - (bufB (get-buffer (concat file ".~{index}~"))) - (bufBrw (and bufB (with-current-buffer bufB (not buffer-read-only)))) - (bufC (get-file-buffer file))) - (ediff-buffers3 - (or bufA (magit-find-file-noselect "HEAD" file)) - (with-current-buffer (magit-find-file-index-noselect file t) - (setq buffer-read-only nil) - (current-buffer)) - (or bufC (find-file-noselect file)) - `((lambda () - (setq-local - ediff-quit-hook - (lambda () - (and (buffer-live-p ediff-buffer-B) - (buffer-modified-p ediff-buffer-B) - (with-current-buffer ediff-buffer-B - (magit-update-index))) - (and (buffer-live-p ediff-buffer-C) - (buffer-modified-p ediff-buffer-C) - (with-current-buffer ediff-buffer-C - (when (y-or-n-p - (format "Save file %s? " buffer-file-name)) - (save-buffer)))) - ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) - ,@(if bufB - (unless bufBrw '((with-current-buffer ediff-buffer-B - (setq buffer-read-only t)))) - '((ediff-kill-buffer-carefully ediff-buffer-B))) - ,@(unless bufC '((ediff-kill-buffer-carefully ediff-buffer-C))) - (let ((magit-ediff-previous-winconf ,conf)) - (run-hooks 'magit-ediff-quit-hook)))))) - 'ediff-buffers3)))) - -;;;###autoload -(defun magit-ediff-compare (revA revB fileA fileB) - "Compare REVA:FILEA with REVB:FILEB using Ediff. - -FILEA and FILEB have to be relative to the top directory of the -repository. If REVA or REVB is nil then this stands for the -working tree state. - -If the region is active, use the revisions on the first and last -line of the region. With a prefix argument, instead of diffing -the revisions, choose a revision to view changes along, starting -at the common ancestor of both revisions (i.e., use a \"...\" -range)." - (interactive (-let [(revA revB) (magit-ediff-compare--read-revisions - nil current-prefix-arg)] - (nconc (list revA revB) - (magit-ediff-compare--read-files revA revB)))) - (magit-with-toplevel - (let ((conf (current-window-configuration)) - (bufA (if revA - (magit-get-revision-buffer revA fileA) - (get-file-buffer fileA))) - (bufB (if revB - (magit-get-revision-buffer revB fileB) - (get-file-buffer fileB)))) - (ediff-buffers - (or bufA (if revA - (magit-find-file-noselect revA fileA) - (find-file-noselect fileA))) - (or bufB (if revB - (magit-find-file-noselect revB fileB) - (find-file-noselect fileB))) - `((lambda () - (setq-local - ediff-quit-hook - (lambda () - ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) - ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) - (let ((magit-ediff-previous-winconf ,conf)) - (run-hooks 'magit-ediff-quit-hook)))))) - 'ediff-revision)))) - -(defun magit-ediff-compare--read-revisions (&optional arg mbase) - (let ((input (or arg (magit-diff-read-range-or-commit "Compare range or commit" - nil mbase))) - revA revB) - (if (string-match magit-range-re input) - (progn (setq revA (or (match-string 1 input) "HEAD") - revB (or (match-string 3 input) "HEAD")) - (when (string= (match-string 2 input) "...") - (setq revA (magit-git-string "merge-base" revA revB)))) - (setq revA input)) - (list revA revB))) - -(defun magit-ediff-compare--read-files (revA revB &optional fileB) - (unless fileB - (setq fileB (magit-read-file-choice - (format "File to compare between %s and %s" - revA (or revB "the working tree")) - (magit-changed-files revA revB) - (format "No changed files between %s and %s" - revA (or revB "the working tree"))))) - (list (or (car (member fileB (magit-revision-files revA))) - (cdr (assoc fileB (magit-renamed-files revB revA))) - (magit-read-file-choice - (format "File in %s to compare with %s in %s" - revA fileB (or revB "the working tree")) - (magit-changed-files revB revA) - (format "File in %s to compare with %s in %s" - revA fileB (or revB "the working tree")))) - fileB)) - -;;;###autoload -(defun magit-ediff-dwim () - "Compare, stage, or resolve using Ediff. -This command tries to guess what file, and what commit or range -the user wants to compare, stage, or resolve using Ediff. It -might only be able to guess either the file, or range or commit, -in which case the user is asked about the other. It might not -always guess right, in which case the appropriate `magit-ediff-*' -command has to be used explicitly. If it cannot read the user's -mind at all, then it asks the user for a command to run." - (interactive) - (magit-section-case - (hunk (save-excursion - (goto-char (magit-section-start (magit-section-parent it))) - (magit-ediff-dwim))) - (t - (let ((range (magit-diff--dwim)) - (file (magit-current-file)) - command revA revB) - (pcase range - ((and (guard (not magit-ediff-dwim-show-on-hunks)) - (or `unstaged `staged)) - (setq command (if (magit-anything-unmerged-p) - #'magit-ediff-resolve - #'magit-ediff-stage))) - (`unstaged (setq command #'magit-ediff-show-unstaged)) - (`staged (setq command #'magit-ediff-show-staged)) - (`(commit . ,value) - (setq command #'magit-ediff-show-commit - revB value)) - ((pred stringp) - (-let [(a b) (magit-ediff-compare--read-revisions range)] - (setq command #'magit-ediff-compare - revA a - revB b))) - (_ - (when (derived-mode-p 'magit-diff-mode) - (pcase (magit-diff-type) - (`committed (-let [(a b) (magit-ediff-compare--read-revisions - (car magit-refresh-args))] - (setq revA a revB b))) - ((guard (not magit-ediff-dwim-show-on-hunks)) - (setq command #'magit-ediff-stage)) - (`unstaged (setq command #'magit-ediff-show-unstaged)) - (`staged (setq command #'magit-ediff-show-staged)) - (`undefined (setq command nil)) - (_ (setq command nil)))))) - (cond ((not command) - (call-interactively - (magit-read-char-case - "Failed to read your mind; do you want to " t - (?c "[c]ommit" 'magit-ediff-show-commit) - (?r "[r]ange" 'magit-ediff-compare) - (?s "[s]tage" 'magit-ediff-stage) - (?v "resol[v]e" 'magit-ediff-resolve)))) - ((eq command 'magit-ediff-compare) - (apply 'magit-ediff-compare revA revB - (magit-ediff-compare--read-files revA revB file))) - ((eq command 'magit-ediff-show-commit) - (magit-ediff-show-commit revB)) - (file - (funcall command file)) - (t - (call-interactively command))))))) - -;;;###autoload -(defun magit-ediff-show-staged (file) - "Show staged changes using Ediff. - -This only allows looking at the changes; to stage, unstage, -and discard changes using Ediff, use `magit-ediff-stage'. - -FILE must be relative to the top directory of the repository." - (interactive - (list (magit-read-file-choice "Show staged changes for file" - (magit-staged-files) - "No staged files"))) - (let ((conf (current-window-configuration)) - (bufA (magit-get-revision-buffer "HEAD" file)) - (bufB (get-buffer (concat file ".~{index}~")))) - (ediff-buffers - (or bufA (magit-find-file-noselect "HEAD" file)) - (or bufB (magit-find-file-index-noselect file t)) - `((lambda () - (setq-local - ediff-quit-hook - (lambda () - ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) - ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) - (let ((magit-ediff-previous-winconf ,conf)) - (run-hooks 'magit-ediff-quit-hook)))))) - 'ediff-buffers))) - -;;;###autoload -(defun magit-ediff-show-unstaged (file) - "Show unstaged changes using Ediff. - -This only allows looking at the changes; to stage, unstage, -and discard changes using Ediff, use `magit-ediff-stage'. - -FILE must be relative to the top directory of the repository." - (interactive - (list (magit-read-file-choice "Show unstaged changes for file" - (magit-modified-files) - "No unstaged files"))) - (magit-with-toplevel - (let ((conf (current-window-configuration)) - (bufA (get-buffer (concat file ".~{index}~"))) - (bufB (get-file-buffer file))) - (ediff-buffers - (or bufA (magit-find-file-index-noselect file t)) - (or bufB (find-file-noselect file)) - `((lambda () - (setq-local - ediff-quit-hook - (lambda () - ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) - ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) - (let ((magit-ediff-previous-winconf ,conf)) - (run-hooks 'magit-ediff-quit-hook)))))) - 'ediff-buffers)))) - -;;;###autoload -(defun magit-ediff-show-working-tree (file) - "Show changes between HEAD and working tree using Ediff. -FILE must be relative to the top directory of the repository." - (interactive - (list (magit-read-file-choice "Show changes in file" - (magit-changed-files "HEAD") - "No changed files"))) - (magit-with-toplevel - (let ((conf (current-window-configuration)) - (bufA (magit-get-revision-buffer "HEAD" file)) - (bufB (get-file-buffer file))) - (ediff-buffers - (or bufA (magit-find-file-noselect "HEAD" file)) - (or bufB (find-file-noselect file)) - `((lambda () - (setq-local - ediff-quit-hook - (lambda () - ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) - ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) - (let ((magit-ediff-previous-winconf ,conf)) - (run-hooks 'magit-ediff-quit-hook)))))) - 'ediff-buffers)))) - -;;;###autoload -(defun magit-ediff-show-commit (commit) - "Show changes introduced by COMMIT using Ediff." - (interactive (list (magit-read-branch-or-commit "Revision"))) - (let ((revA (concat commit "^")) - (revB commit)) - (apply #'magit-ediff-compare - revA revB - (magit-ediff-compare--read-files revA revB (magit-current-file))))) - -(defun magit-ediff-cleanup-auxiliary-buffers () - (let* ((ctl-buf ediff-control-buffer) - (ctl-win (ediff-get-visible-buffer-window ctl-buf)) - (ctl-frm ediff-control-frame) - (main-frame (cond ((window-live-p ediff-window-A) - (window-frame ediff-window-A)) - ((window-live-p ediff-window-B) - (window-frame ediff-window-B))))) - (ediff-kill-buffer-carefully ediff-diff-buffer) - (ediff-kill-buffer-carefully ediff-custom-diff-buffer) - (ediff-kill-buffer-carefully ediff-fine-diff-buffer) - (ediff-kill-buffer-carefully ediff-tmp-buffer) - (ediff-kill-buffer-carefully ediff-error-buffer) - (ediff-kill-buffer-carefully ediff-msg-buffer) - (ediff-kill-buffer-carefully ediff-debug-buffer) - (when (boundp 'ediff-patch-diagnostics) - (ediff-kill-buffer-carefully ediff-patch-diagnostics)) - (cond ((and (ediff-window-display-p) - (frame-live-p ctl-frm)) - (delete-frame ctl-frm)) - ((window-live-p ctl-win) - (delete-window ctl-win))) - (unless (ediff-multiframe-setup-p) - (ediff-kill-bottom-toolbar)) - (ediff-kill-buffer-carefully ctl-buf) - (when (frame-live-p main-frame) - (select-frame main-frame)))) - -(defun magit-ediff-restore-previous-winconf () - (set-window-configuration magit-ediff-previous-winconf)) - -;;; magit-ediff.el ends soon -(provide 'magit-ediff) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-ediff.el ends here diff --git a/elpa/magit-20151119.202/magit-extras.el b/elpa/magit-20151119.202/magit-extras.el deleted file mode 100644 index db23a8e6..00000000 --- a/elpa/magit-20151119.202/magit-extras.el +++ /dev/null @@ -1,204 +0,0 @@ -;;; magit-extras.el --- additional functionality for Magit - -;; Copyright (C) 2008-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; 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: - -;; Additional functionality for Magit. - -;;; Code: - -(require 'magit) - -(defgroup magit-extras nil - "Additional functionality for Magit." - :group 'magit-extensions) - -;;; External Tools - -(defcustom magit-gitk-executable - (or (and (eq system-type 'windows-nt) - (let ((exe (expand-file-name - "gitk" (file-name-nondirectory magit-git-executable)))) - (and (file-executable-p exe) exe))) - (executable-find "gitk") "gitk") - "The Gitk executable." - :group 'magit-extras - :set-after '(magit-git-executable) - :type 'string) - -;;;###autoload -(defun magit-run-git-gui () - "Run `git gui' for the current git repository." - (interactive) - (magit-with-toplevel - (call-process magit-git-executable nil 0 nil "gui"))) - -;;;###autoload -(defun magit-run-git-gui-blame (commit filename &optional linenum) - "Run `git gui blame' on the given FILENAME and COMMIT. -Interactively run it for the current file and the HEAD, with a -prefix or when the current file cannot be determined let the user -choose. When the current buffer is visiting FILENAME instruct -blame to center around the line point is on." - (interactive - (let (revision filename) - (when (or current-prefix-arg - (not (setq revision "HEAD" - filename (magit-file-relative-name nil 'tracked)))) - (setq revision (magit-read-branch-or-commit "Blame from revision") - filename (magit-read-file-from-rev revision "Blame file"))) - (list revision filename - (and (equal filename - (ignore-errors - (magit-file-relative-name buffer-file-name))) - (line-number-at-pos))))) - (magit-with-toplevel - (apply #'call-process magit-git-executable nil 0 nil "gui" "blame" - `(,@(and linenum (list (format "--line=%d" linenum))) - ,commit - ,filename)))) - -;;;###autoload -(defun magit-run-gitk () - "Run `gitk' in the current repository." - (interactive) - (call-process magit-gitk-executable nil 0)) - -;;;###autoload -(defun magit-run-gitk-branches () - "Run `gitk --branches' in the current repository." - (interactive) - (call-process magit-gitk-executable nil 0 nil "--branches")) - -;;;###autoload -(defun magit-run-gitk-all () - "Run `gitk --all' in the current repository." - (interactive) - (call-process magit-gitk-executable nil 0 nil "--all")) - -;;; Clean - -;;;###autoload -(defun magit-clean (&optional arg) - "Remove untracked files from the working tree. -With a prefix argument also remove ignored files, -with two prefix arguments remove ignored files only. -\n(git clean -f -d [-x|-X])" - (interactive "p") - (when (yes-or-no-p (format "Remove %s files? " - (pcase arg - (1 "untracked") - (4 "untracked and ignored") - (_ "ignored")))) - (magit-wip-commit-before-change) - (magit-run-git "clean" "-f" "-d" (pcase arg (4 "-x") (16 "-X"))))) - -(put 'magit-clean 'disabled t) - -;;; Gitignore - -;;;###autoload -(defun magit-gitignore (file-or-pattern &optional local) - "Instruct Git to ignore FILE-OR-PATTERN. -With a prefix argument only ignore locally." - (interactive (magit-gitignore-read-args current-prefix-arg)) - (let ((gitignore - (if local - (magit-git-dir (convert-standard-filename "info/exclude")) - (expand-file-name ".gitignore" (magit-toplevel))))) - (make-directory (file-name-directory gitignore) t) - (with-temp-buffer - (when (file-exists-p gitignore) - (insert-file-contents gitignore)) - (goto-char (point-max)) - (unless (bolp) - (insert "\n")) - (insert (replace-regexp-in-string "\\(\\\\*\\)" "\\1\\1" file-or-pattern)) - (insert "\n") - (write-region nil nil gitignore)) - (if local - (magit-refresh) - (magit-run-git "add" ".gitignore")))) - -;;;###autoload -(defun magit-gitignore-locally (file-or-pattern &optional local) - "Instruct Git to locally ignore FILE-OR-PATTERN. -\n(fn FILE-OR-PATTERN)" - (interactive (magit-gitignore-read-args t)) - (magit-gitignore file-or-pattern t)) - -(defun magit-gitignore-read-args (local) - (let* ((default (magit-current-file)) - (choices - (delete-dups - (--mapcat - (cons (concat "/" it) - (-when-let (ext (file-name-extension it)) - (list (concat "/" (file-name-directory "foo") "*." ext) - (concat "*." ext)))) - (magit-untracked-files))))) - (when default - (setq default (concat "/" default)) - (unless (member default choices) - (setq default (concat "*." (file-name-extension default))) - (unless (member default choices) - (setq default nil)))) - (list (magit-completing-read - (concat "File or pattern to ignore" (and local " locally")) - choices nil nil nil nil default) - local))) - -;;; ChangeLog - -;;;###autoload -(defun magit-add-change-log-entry (&optional whoami file-name other-window) - "Find change log file and add date entry and item for current change. -This differs from `add-change-log-entry' (which see) in that -it acts on the current hunk in a Magit buffer instead of on -a position in a file-visiting buffer." - (interactive (list current-prefix-arg - (prompt-for-change-log-name))) - (let (buf pos) - (save-window-excursion - (call-interactively #'magit-diff-visit-file) - (setq buf (current-buffer) - pos (point))) - (save-excursion - (with-current-buffer buf - (goto-char pos) - (add-change-log-entry whoami file-name other-window))))) - -;;;###autoload -(defun magit-add-change-log-entry-other-window (&optional whoami file-name) - "Find change log file in other window and add entry and item. -This differs from `add-change-log-entry-other-window' (which see) -in that it acts on the current hunk in a Magit buffer instead of -on a position in a file-visiting buffer." - (interactive (and current-prefix-arg - (list current-prefix-arg - (prompt-for-change-log-name)))) - (magit-add-change-log-entry whoami file-name t)) - -;;; magit-extras.el ends soon -(provide 'magit-extras) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-extras.el ends here diff --git a/elpa/magit-20151119.202/magit-git.el b/elpa/magit-20151119.202/magit-git.el deleted file mode 100644 index dfdd6583..00000000 --- a/elpa/magit-20151119.202/magit-git.el +++ /dev/null @@ -1,1184 +0,0 @@ -;;; magit-git.el --- Git functionality - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library implements wrappers for various Git plumbing commands. - -;;; Code: - -(require 'cl-lib) -(require 'dash) - -(require 'magit-utils) -(require 'magit-section) - -(declare-function magit-process-buffer 'magit-process) -(declare-function magit-process-file 'magit-process) -(declare-function magit-process-insert-section 'magit-process) -(defvar magit-process-error-message-re) -(defvar magit-refresh-args) ; from `magit-mode' for `magit-current-file' - -(defvar magit-tramp-process-environment nil) - -(require 'crm) - -;;; Options - -;; For now this is shared between `magit-process' and `magit-git'. -(defgroup magit-process nil - "Git and other external processes used by Magit." - :group 'magit) - -(defvar magit-git-environment nil - "Prepended to `process-environment' while running git.") - -(defcustom magit-git-executable - ;; Git might be installed in a different location on a remote, so - ;; it is better not to use the full path to the executable, except - ;; on Window were we would otherwise end up using one one of the - ;; wrappers "cmd/git.exe" or "cmd/git.cmd", which are much slower - ;; than using "bin/git.exe" directly. - (or (and (eq system-type 'windows-nt) - (--when-let (executable-find "git.exe") - (or (with-temp-buffer - (when (save-excursion - (= (call-process - it nil '(t t) nil "-c" - "alias.exe=!which git | cygpath -wf -" "exe") 0)) - (prog1 (delete-and-extract-region 1 (line-end-position)) - (save-excursion - (insert "PATH=") - (call-process - it nil '(t t) nil "-c" - "alias.path=!cygpath -wp \"$PATH\"" "path")) - (setq magit-git-environment - (list (buffer-substring-no-properties - (point) (line-end-position))))))) - (let ((alt (directory-file-name (file-name-directory it)))) - (if (and (equal (file-name-nondirectory alt) "cmd") - (setq alt (expand-file-name - (convert-standard-filename "bin/git.exe") - (file-name-directory alt))) - (file-executable-p alt)) - alt - it))))) - "git") - "The Git executable used by Magit." - :group 'magit-process - :type 'string) - -(defcustom magit-git-global-arguments - '("--no-pager" "--literal-pathspecs" "-c" "core.preloadindex=true") - "Global git arguments. - -The arguments set here are used every time the git executable is -run as a subprocess. They are placed right after the executable -itself and before the git command - as in `git HERE... COMMAND -REST'. See the manpage `git(1)' for valid arguments. - -Be careful what you add here, especially if you are using Tramp -to connect to servers with ancient Git versions. Never remove -anything that is part of the default value, unless you really -know what you are doing. And think very hard before adding -something; it will be used every time Magit runs Git for any -purpose." - :package-version '(magit . "2.1.0") - :group 'magit - :type '(repeat string)) - -(define-obsolete-variable-alias 'magit-git-standard-options - 'magit-git-global-arguments "2.1.0") - -(defcustom magit-git-debug nil - "Whether to enable additional reporting of git errors. - -Magit basically calls git for one of these two reasons: for -side-effects or to do something with its standard output. - -When git is run for side-effects then its output, including error -messages, go into the process buffer which is shown when using \ -\\\\[magit-process]. - -When git's output is consumed in some way, then it would be too -expensive to also insert it into this buffer, but when this -option is non-nil and git returns with a non-zero exit status, -then at least its standard error is inserted into this buffer. - -This is only intended for debugging purposes. Do not enable this -permanently, that would negatively affect performance" - :group 'magit - :group 'magit-process - :type 'boolean) - -(defcustom magit-ref-namespaces - '(("^@$" magit-head nil) - ("^refs/tags/\\(.+\\)" magit-tag nil) - ("^refs/heads/\\(.+\\)" magit-branch-local nil) - ("^refs/remotes/\\(.+\\)" magit-branch-remote nil) - ("^refs/bisect/\\(bad\\)" magit-bisect-bad nil) - ("^refs/bisect/\\(skip.*\\)" magit-bisect-skip nil) - ("^refs/bisect/\\(good.*\\)" magit-bisect-good nil) - ("^refs/stash$" magit-refname-stash nil) - ("^refs/wip/\\(.+\\)" magit-refname-wip nil) - ("^\\(bad\\):" magit-bisect-bad nil) - ("^\\(skip\\):" magit-bisect-skip nil) - ("^\\(good\\):" magit-bisect-good nil) - ("\\(.+\\)" magit-refname nil)) - "How refs are formatted for display. - -Each entry controls how a certain type of ref is displayed, and -has the form (REGEXP FACE FORMATTER). REGEXP is a regular -expression used to match full refs. The first entry whose REGEXP -matches the reference is used. The first regexp submatch becomes -the \"label\" that represents the ref and is propertized with -font FONT. If FORMATTER is non-nil it should be a function that -takes two arguments, the full ref and the face. It is supposed -to return a propertized label that represents the ref." - :package-version '(magit . "2.1.0") - :group 'magit-modes - :type '(repeat - (list regexp - face - (choice (const :tag "first submatch is label" nil) - (function :tag "format using function"))))) - -;;; Git - -(defun magit-process-git-arguments (args) - "Prepare ARGS for a function that invokes Git. - -Magit has many specialized functions for running Git; they all -pass arguments through this function before handing them to Git, -to do the following. - -* Flatten ARGS, removing nil arguments. -* Prepend `magit-git-global-arguments' to ARGS." - (append magit-git-global-arguments (-flatten args))) - -(defun magit-git-exit-code (&rest args) - "Execute Git with ARGS, returning its exit code." - (apply #'magit-process-file magit-git-executable nil nil nil - (magit-process-git-arguments args))) - -(defun magit-git-success (&rest args) - "Execute Git with ARGS, returning t if its exit code is 0." - (= (magit-git-exit-code args) 0)) - -(defun magit-git-failure (&rest args) - "Execute Git with ARGS, returning t if its exit code is 1." - (= (magit-git-exit-code args) 1)) - -(defun magit-git-str (&rest args) - "Execute Git with ARGS, returning the first line of its output. -If there is no output return nil. If the output begins with a -newline return an empty string. Like `magit-git-string' but -ignore `magit-git-debug'." - (with-temp-buffer - (apply #'magit-process-file magit-git-executable nil (list t nil) nil - (magit-process-git-arguments args)) - (unless (bobp) - (goto-char (point-min)) - (buffer-substring-no-properties (point) (line-end-position))))) - -(defun magit-git-true (&rest args) - "Execute Git with ARGS, returning t if it prints \"true\". -Return t if the first (and usually only) output line is the -string \"true\", otherwise return nil." - (equal (magit-git-str args) "true")) - -(defun magit-git-false (&rest args) - "Execute Git with ARGS, returning t if it prints \"false\". -Return t if the first (and usually only) output line is the -string \"false\", otherwise return nil." - (equal (magit-git-str args) "false")) - -(defun magit-git-insert (&rest args) - "Execute Git with ARGS, inserting its output at point. -If Git exits with a non-zero exit status, then show a message and -add a section in the respective process buffer." - (setq args (magit-process-git-arguments args)) - (if magit-git-debug - (let (log) - (unwind-protect - (progn - (setq log (make-temp-file "magit-stderr")) - (delete-file log) - (let ((exit (apply #'magit-process-file magit-git-executable - nil (list t log) nil args))) - (when (> exit 0) - (let ((msg "Git failed")) - (when (file-exists-p log) - (setq msg (with-temp-buffer - (insert-file-contents log) - (goto-char (point-max)) - (and (re-search-backward - magit-process-error-message-re nil t) - (match-string 1)))) - (let ((magit-git-debug nil)) - (with-current-buffer (magit-process-buffer t) - (magit-process-insert-section default-directory - magit-git-executable - args exit log)))) - (message "%s" msg))) - exit)) - (ignore-errors (delete-file log)))) - (apply #'magit-process-file magit-git-executable - nil (list t nil) nil args))) - -(defun magit-git-string (&rest args) - "Execute Git with ARGS, returning the first line of its output. -If there is no output return nil. If the output begins with a -newline return an empty string." - (with-temp-buffer - (apply #'magit-git-insert args) - (unless (bobp) - (goto-char (point-min)) - (buffer-substring-no-properties (point) (line-end-position))))) - -(defun magit-git-lines (&rest args) - "Execute Git with ARGS, returning its output as a list of lines. -Empty lines anywhere in the output are omitted. - -If Git exits with a non-zero exit status, then report show a -message and add a section in the respective process buffer." - (with-temp-buffer - (apply #'magit-git-insert args) - (split-string (buffer-string) "\n" t))) - -(defun magit-git-items (&rest args) - "Execute Git with ARGS, returning its null-separated output as a list. -Empty items anywhere in the output are omitted. - -If Git exits with a non-zero exit status, then report show a -message and add a section in the respective process buffer." - (with-temp-buffer - (apply #'magit-git-insert args) - (split-string (buffer-string) "\0" t))) - -(defun magit-git-wash (washer &rest args) - "Execute Git with ARGS, inserting washed output at point. -Actually first insert the raw output at point. If there is no -output call `magit-cancel-section'. Otherwise temporarily narrow -the buffer to the inserted text, move to its beginning, and then -call function WASHER with no argument." - (declare (indent 1)) - (let ((beg (point))) - (setq args (-flatten args)) - (magit-git-insert args) - (if (= (point) beg) - (magit-cancel-section) - (unless (bolp) - (insert "\n")) - (save-restriction - (narrow-to-region beg (point)) - (goto-char beg) - (funcall washer args)) - (when (or (= (point) beg) - (= (point) (1+ beg))) - (magit-cancel-section))))) - -;;; Files - -(defmacro magit--with-safe-default-directory (file &rest body) - (declare (indent 1) (debug (form body))) - `(catch 'unsafe-default-dir - (let ((default-directory (file-name-as-directory - (expand-file-name - (or ,file default-directory)))) - previous) - (while (not (file-accessible-directory-p default-directory)) - (setq default-directory - (file-name-directory - (directory-file-name default-directory))) - (when (equal default-directory previous) - (throw 'unsafe-default-dir nil)) - (setq previous default-directory)) - ,@body))) - -(defun magit-git-dir (&optional path) - "Return absolute path to the control directory of the current repository. - -All symlinks are followed. If optional PATH is non-nil, then -it has to be a path relative to the control directory and its -absolute path is returned." - (magit--with-safe-default-directory nil - (--when-let (magit-rev-parse-safe "--git-dir") - (setq it (file-name-as-directory (magit-expand-git-file-name it))) - (if path (expand-file-name (convert-standard-filename path) it) it)))) - -(defun magit-toplevel (&optional directory) - "Return the absolute path to the toplevel of the current repository. - -From within the working tree or control directory of a repository -return the absolute path to the toplevel directory of the working -tree. As a special case, from within a bare repository return -the control directory instead. When called outside a repository -then return nil. - -When optional DIRECTORY is non-nil then return the toplevel for -that directory instead of the one for `default-directory'. - -Try to respect the option `find-file-visit-truename', i.e. when -the value of that option is nil, then avoid needlessly returning -the truename. When a symlink to a sub-directory of the working -tree is involved, or when called from within a sub-directory of -the gitdir or from the toplevel of a gitdir, which itself is not -located within the working tree, then it is not possible to avoid -returning the truename." - (magit--with-safe-default-directory directory - (-if-let (topdir (magit-rev-parse-safe "--show-toplevel")) - (let (updir) - (setq topdir (magit-expand-git-file-name topdir)) - (if (and - ;; Always honor these settings. - (not find-file-visit-truename) - (not (getenv "GIT_WORK_TREE")) - ;; `--show-cdup' is the relative path to the toplevel - ;; from `(file-truename default-directory)'. Here we - ;; pretend it is relative to `default-directory', and - ;; go to that directory. Then we check whether - ;; `--show-toplevel' still returns the same value and - ;; whether `--show-cdup' now is the empty string. If - ;; both is the case, then we are at the toplevel of - ;; the same working tree, but also avoided needlessly - ;; following any symlinks. - (progn - (setq updir (file-name-as-directory - (magit-rev-parse-safe "--show-cdup"))) - (setq updir (if (file-name-absolute-p updir) - (concat (file-remote-p default-directory) updir) - (expand-file-name updir))) - (let ((default-directory updir)) - (and (string-equal (magit-rev-parse-safe "--show-cdup") "") - (--when-let (magit-rev-parse-safe "--show-toplevel") - (string-equal (magit-expand-git-file-name it) - topdir)))))) - updir - (concat (file-remote-p default-directory) - (file-name-as-directory topdir)))) - (-when-let (gitdir (magit-rev-parse-safe "--git-dir")) - (setq gitdir (file-name-as-directory - (if (file-name-absolute-p gitdir) - ;; We might have followed a symlink. - (concat (file-remote-p default-directory) - (magit-expand-git-file-name gitdir)) - (expand-file-name gitdir)))) - (if (magit-bare-repo-p) - gitdir - (let* ((link (expand-file-name "gitdir" gitdir)) - (wtree (and (file-exists-p link) - (magit-file-line link)))) - (if (and wtree - ;; Ignore .git/gitdir files that result from a - ;; Git bug. See #2364. - (not (equal wtree ".git"))) - ;; Return the linked working tree. - (file-name-directory wtree) - ;; Step outside the control directory to enter the working tree. - (file-name-directory (directory-file-name gitdir))))))))) - -(defmacro magit-with-toplevel (&rest body) - (declare (indent defun) (debug (body))) - (let ((toplevel (cl-gensym "toplevel"))) - `(let ((,toplevel (magit-toplevel))) - (if ,toplevel - (let ((default-directory ,toplevel)) - ,@body) - (error "Not inside a Git repository: %s" default-directory))))) - -(defun magit-inside-gitdir-p () - "Return t if `default-directory' is below a repository directory." - (magit-rev-parse-p "--is-inside-git-dir")) - -(defun magit-inside-worktree-p () - "Return t if `default-directory' is below the work tree of a repository." - (magit-rev-parse-p "--is-inside-work-tree")) - -(defun magit-bare-repo-p () - "Return t if the current repository is bare." - (magit-rev-parse-p "--is-bare-repository")) - -(defun magit-git-repo-p (directory &optional non-bare) - "Return t if DIRECTORY is a Git repository. -When optional NON-BARE is non-nil also return nil if DIRECTORY is -a bare repositories." - (or (file-regular-p (expand-file-name ".git" directory)) - (file-directory-p (expand-file-name ".git" directory)) - (and (not non-bare) - (file-regular-p (expand-file-name "HEAD" directory)) - (file-directory-p (expand-file-name "refs" directory)) - (file-directory-p (expand-file-name "objects" directory))))) - -(defvar-local magit-buffer-revision nil) -(defvar-local magit-buffer-refname nil) -(defvar-local magit-buffer-file-name nil) -(put 'magit-buffer-revision 'permanent-local t) -(put 'magit-buffer-refname 'permanent-local t) -(put 'magit-buffer-file-name 'permanent-local t) - -(defun magit-file-relative-name (&optional file tracked) - "Return the path of FILE relative to the repository root. - -If optional FILE is nil or omitted return the relative path of -the file being visited in the current buffer, if any, else nil. -If the file is not inside a Git repository then return nil. - -If TRACKED is non-nil, return the path only if it matches a -tracked file." - (unless file - (with-current-buffer (or (buffer-base-buffer) - (current-buffer)) - (setq file (or magit-buffer-file-name buffer-file-name)))) - (when (and file (or (not tracked) - (magit-file-tracked-p (file-relative-name file)))) - (--when-let (magit-toplevel (magit--with-safe-default-directory file - default-directory)) - (file-relative-name file it)))) - -(defun magit-file-tracked-p (file) - (magit-git-success "ls-files" "--error-unmatch" file)) - -(defun magit-list-files (&rest args) - (apply #'magit-git-items "ls-files" "-z" "--full-name" args)) - -(defun magit-tracked-files () - (magit-list-files "--cached")) - -(defun magit-untracked-files (&optional all files) - (magit-list-files "--other" (unless all "--exclude-standard") "--" files)) - -(defun magit-modified-files (&optional nomodules) - (magit-git-items "diff-files" "-z" "--name-only" - (and nomodules "--ignore-submodules"))) - -(defun magit-staged-files (&optional nomodules) - (magit-git-items "diff-index" "-z" "--name-only" "--cached" - (and nomodules "--ignore-submodules") - (magit-headish))) - -(defun magit-staged-binary-files () - (--mapcat (and (string-match "^-\t-\t\\(.+\\)" it) - (list (match-string 1 it))) - (magit-git-items "diff" "-z" "--cached" - "--numstat" "--ignore-submodules"))) - -(defun magit-unmerged-files () - (magit-git-items "diff-files" "-z" "--name-only" "--diff-filter=U")) - -(defun magit-revision-files (rev) - (magit-with-toplevel - (magit-git-items "ls-tree" "-z" "-r" "--name-only" rev))) - -(defun magit-changed-files (rev-or-range &optional other-rev) - "Return list of files the have changed between two revisions. -If OTHER-REV is non-nil, REV-OR-RANGE should be a revision, not a -range. Otherwise, it can be any revision or range accepted by -\"git diff\" (i.e., , .., or ...)." - (magit-with-toplevel - (magit-git-items "diff" "-z" "--name-only" rev-or-range other-rev))) - -(defun magit-renamed-files (revA revB) - (--map (cons (nth 1 it) (nth 2 it)) - (-partition 3 (magit-git-items - "diff-tree" "-r" "--diff-filter=R" "-z" "-M" - revA revB)))) - -(defun magit-file-status (&rest args) - (with-temp-buffer - (save-excursion (magit-git-insert "status" "-z" args)) - (let ((pos (point)) status) - (while (> (skip-chars-forward "[:print:]") 0) - (let ((x (char-after pos)) - (y (char-after (1+ pos))) - (file (buffer-substring (+ pos 3) (point)))) - (forward-char) - (if (memq x '(?R ?C)) - (progn - (setq pos (point)) - (skip-chars-forward "[:print:]") - (push (list file (buffer-substring pos (point)) x y) status) - (forward-char)) - (push (list file nil x y) status))) - (setq pos (point))) - status))) - -(defcustom magit-cygwin-mount-points - (when (eq system-type 'windows-nt) - (cl-sort (--map (if (string-match "^\\(.*\\) on \\(.*\\) type" it) - (cons (file-name-as-directory (match-string 2 it)) - (file-name-as-directory (match-string 1 it))) - (lwarn '(magit) :error - "Failed to parse Cygwin mount: %S" it)) - (ignore-errors (process-lines "mount"))) - #'> :key (-lambda ((cyg . win)) (length cyg)))) - "Alist of (CYGWIN . WIN32) directory names. -Sorted from longest to shortest CYGWIN name." - :package-version '(magit . "2.3.0") - :group 'magit-process - :type '(alist :key-type string :value-type directory)) - -(defun magit-expand-git-file-name (filename) - (unless (file-name-absolute-p filename) - (setq filename (expand-file-name filename))) - (-if-let ((cyg . win) - (cl-assoc filename magit-cygwin-mount-points - :test (lambda (f cyg) (string-prefix-p cyg f)))) - (concat win (substring filename (length cyg))) - filename)) - -(defun magit-convert-git-filename (filename) - (-if-let ((cyg . win) - (cl-rassoc filename magit-cygwin-mount-points - :test (lambda (f win) (string-prefix-p win f)))) - (concat cyg (substring filename (length win))) - filename)) - -(defun magit-decode-git-path (path) - (if (eq (aref path 0) ?\") - (string-as-multibyte (read path)) - path)) - -(defun magit-file-at-point () - (magit-section-case - (file (magit-section-value it)) - (hunk (magit-section-parent-value it)))) - -(defun magit-current-file () - (or (magit-file-relative-name) - (magit-file-at-point) - (and (derived-mode-p 'magit-log-mode) - (nth 3 magit-refresh-args)))) - -;;; Predicates - -(defun magit-no-commit-p () - "Return t if there is no commit in the current Git repository." - (not (magit-rev-verify "HEAD"))) - -(defun magit-anything-staged-p (&optional ignore-submodules &rest files) - "Return t if there are any staged changes. -If optional FILES is non-nil, then only changes to those files -are considered." - (magit-git-failure "diff" "--quiet" "--cached" - (and ignore-submodules "--ignore-submodules") - "--" files)) - -(defun magit-anything-unstaged-p (&optional ignore-submodules &rest files) - "Return t if there are any unstaged changes. -If optional FILES is non-nil, then only changes to those files -are considered." - (magit-git-failure "diff" "--quiet" - (and ignore-submodules "--ignore-submodules") - "--" files)) - -(defun magit-anything-modified-p (&optional ignore-submodules &rest files) - "Return t if there are any staged or unstaged changes. -If optional FILES is non-nil, then only changes to those files -are considered." - (or (apply 'magit-anything-staged-p ignore-submodules files) - (apply 'magit-anything-unstaged-p ignore-submodules files))) - -(defun magit-anything-unmerged-p (&rest files) - "Return t if there are any merge conflicts. -If optional FILES is non-nil, then only conflicts in those files -are considered." - (and (magit-git-string "ls-files" "--unmerged" files) t)) - -;;; Revisions and References - -(defun magit-rev-parse (&rest args) - "Execute `git rev-parse ARGS', returning first line of output. -If there is no output return nil." - (apply #'magit-git-string "rev-parse" args)) - -(defun magit-rev-parse-safe (&rest args) - "Execute `git rev-parse ARGS', returning first line of output. -If there is no output return nil. Like `magit-rev-parse' but -ignore `magit-git-debug'." - (apply #'magit-git-str "rev-parse" args)) - -(defun magit-rev-parse-p (&rest args) - "Execute `git rev-parse ARGS', returning t if it prints \"true\". -Return t if the first (and usually only) output line is the -string \"true\", otherwise return nil." - (magit-git-true "rev-parse" args)) - -(defun magit-rev-verify (rev) - (magit-rev-parse-safe "--verify" rev)) - -(defun magit-rev-verify-commit (rev) - "Return full hash for REV if it names an existing commit." - (magit-rev-verify (concat rev "^{commit}"))) - -(defun magit-rev-equal (a b) - (magit-git-success "diff" "--quiet" a b)) - -(defun magit-rev-head-p (rev) - (or (equal rev "HEAD") - (and rev - (not (string-match-p "\\.\\." rev)) - (equal (magit-rev-parse rev) - (magit-rev-parse "HEAD"))))) - -(defun magit-rev-name (rev &optional pattern) - (magit-git-string "name-rev" "--name-only" "--no-undefined" - (and pattern (concat "--refs=" pattern)) - rev)) - -(defun magit-rev-branch (rev) - (--when-let (magit-rev-name rev "refs/heads/*") - (unless (string-match-p "~" it) it))) - -(defun magit-get-shortname (rev) - (let ((fn (apply-partially 'magit-git-string "name-rev" - "--name-only" "--no-undefined" rev))) - (setq rev (or (funcall fn "--refs=refs/tags/*") - (funcall fn "--refs=refs/heads/*") - (funcall fn "--refs=refs/remotes/*" "--always"))) - (if (and (string-match "^\\(?:tags\\|remotes\\)/\\(.+\\)" rev) - (magit-ref-fullname (match-string 1 rev))) - (match-string 1 rev) - rev))) - -(defun magit-ref-fullname (name) - (magit-rev-parse "--symbolic-full-name" name)) - -(defun magit-ref-exists-p (ref) - (magit-git-success "show-ref" "--verify" ref)) - -(defun magit-headish () - "Return \"HEAD\" or if that doesn't exist the hash of the empty tree." - (if (magit-no-commit-p) - (magit-git-string "mktree") - "HEAD")) - -(defun magit-branch-at-point () - (magit-section-when branch)) - -(defun magit-local-branch-at-point () - (magit-section-when branch - (let ((branch (magit-section-value it))) - (when (member branch (magit-list-local-branch-names)) - branch)))) - -(defun magit-commit-at-point () - (or (magit-section-when commit) - (and (derived-mode-p 'magit-revision-mode) - (car magit-refresh-args)))) - -(defun magit-branch-or-commit-at-point () - (or (magit-section-case - (branch (magit-section-value it)) - (commit (magit-get-shortname (magit-section-value it)))) - (and (derived-mode-p 'magit-revision-mode) - (car magit-refresh-args)))) - - -(defun magit-tag-at-point () - (magit-section-when tag)) - -(defun magit-stash-at-point () - (magit-section-when stash)) - -(defun magit-remote-at-point () - (magit-section-case - (remote (magit-section-value it)) - (branch (magit-section-parent-value it)))) - -(defun magit-get-current-branch () - "Return the refname of the currently checked out branch. -Return nil if no branch is currently checked out." - (magit-git-string "symbolic-ref" "--short" "HEAD")) - -(defun magit-get-previous-branch () - "Return the refname of the previously checked out branch. -Return nil if no branch can be found in the `HEAD' reflog -which is different from the current branch and still exists." - (let ((current (magit-get-current-branch)) - (i 1) prev) - (while (and (setq prev (magit-rev-verify (format "@{-%i}" i))) - (or (not (setq prev (magit-rev-branch prev))) - (equal prev current))) - (cl-incf i)) - prev)) - -(cl-defun magit-get-tracked-ref - (&optional (branch (magit-get-current-branch))) - (when branch - (let ((remote (magit-get "branch" branch "remote")) - (merge (magit-get "branch" branch "merge"))) - (when (and remote merge) - (cond ((string-equal remote ".") merge) - ((string-prefix-p "refs/heads/" merge) - (concat "refs/remotes/" remote "/" (substring merge 11)))))))) - -(cl-defun magit-get-tracked-branch - (&optional (branch (magit-get-current-branch))) - (when branch - (let ((remote (magit-get "branch" branch "remote")) - (merge (magit-get "branch" branch "merge"))) - (when (and remote merge (string-prefix-p "refs/heads/" merge)) - (setq merge (substring merge 11)) - (if (string-equal remote ".") - merge - (concat remote "/" merge)))))) - -(cl-defun magit-get-push-branch - (&optional (branch (magit-get-current-branch))) - (when branch - (-when-let (remote (or (magit-get "branch" branch "pushRemote") - (magit-get "remote.pushDefault"))) - (concat remote "/" branch)))) - -(defun magit-get-remote (&optional branch) - (when (or branch (setq branch (magit-get-current-branch))) - (let ((remote (magit-get "branch" branch "remote"))) - (unless (equal remote ".") - remote)))) - -(defun magit-get-remote-branch (&optional branch) - (-when-let (local (or branch (magit-get-current-branch))) - (let ((remote (magit-get-remote local)) - (branch (magit-get "branch" local "merge"))) - (when (and remote branch (string-match "^refs/heads/\\(.+\\)" branch)) - (cons remote (match-string 1 branch)))))) - -(defun magit-get-current-tag (&optional rev with-distance) - "Return the closest tag reachable from REV. - -If optional REV is nil then default to \"HEAD\". -If optional WITH-DISTANCE is non-nil then return (TAG COMMITS), -if it is `dirty' return (TAG COMMIT DIRTY). COMMITS is the number -of commits in \"HEAD\" but not in TAG and DIRTY is t if there are -uncommitted changes, nil otherwise." - (--when-let (magit-git-str "describe" "--long" "--tags" - (and (eq with-distance 'dirty) "--dirty") rev) - (save-match-data - (string-match - "\\(.+\\)-\\(?:0[0-9]*\\|\\([0-9]+\\)\\)-g[0-9a-z]+\\(-dirty\\)?$" it) - (if with-distance - `(,(match-string 1 it) - ,(string-to-number (or (match-string 2 it) "0")) - ,@(and (match-string 3 it) (list t))) - (match-string 1 it))))) - -(defun magit-get-next-tag (&optional rev with-distance) - "Return the closest tag from which REV is reachable. - -If optional REV is nil then default to \"HEAD\". -If no such tag can be found or if the distance is 0 (in which -case it is the current tag, not the next) return nil instead. -If optional WITH-DISTANCE is non-nil then return (TAG COMMITS) -where COMMITS is the number of commits in TAG but not in REV." - (--when-let (magit-git-string "describe" "--contains" (or rev "HEAD")) - (save-match-data - (when (string-match "^[^^~]+" it) - (setq it (match-string 0 it)) - (unless (equal it (magit-get-current-tag rev)) - (if with-distance - (list it (car (magit-rev-diff-count it rev))) - it)))))) - -(defvar magit-list-refs-namespaces - '("refs/heads" "refs/remotes" "refs/tags" "refs/pull")) - -(defun magit-list-refs (&rest args) - (magit-git-lines "for-each-ref" "--format=%(refname)" - (or args magit-list-refs-namespaces))) - -(defun magit-list-branches () - (magit-list-refs "refs/heads" "refs/remotes")) - -(defun magit-list-local-branches () - (magit-list-refs "refs/heads")) - -(defun magit-list-remote-branches (&optional remote) - (magit-list-refs (concat "refs/remotes/" remote))) - -(defun magit-list-containing-branches (&optional commit) - (--map (substring it 2) (magit-git-lines "branch" "--contains" commit))) - -(defun magit-list-merged-branches (&optional commit) - (--map (substring it 2) (magit-git-lines "branch" "--merged" commit))) - -(defun magit-list-unmerged-branches (&optional commit) - (--map (substring it 2) (magit-git-lines "branch" "--no-merged" commit))) - -(defun magit-list-unmerged-to-upstream-branches () - (--filter (-when-let (upstream (magit-get-tracked-branch it)) - (member it (magit-list-unmerged-branches upstream))) - (magit-list-local-branch-names))) - -(defun magit-list-refnames (&rest args) - (magit-git-lines "for-each-ref" "--format=%(refname:short)" - (or args magit-list-refs-namespaces))) - -(defun magit-list-branch-names () - (magit-list-refnames "refs/heads" "refs/remotes")) - -(defun magit-list-local-branch-names () - (magit-list-refnames "refs/heads")) - -(defun magit-list-remote-branch-names (&optional remote relative) - (if (and remote relative) - (let ((regexp (format "^refs/remotes/%s/\\(.+\\)" remote))) - (--mapcat (when (string-match regexp it) - (list (match-string 1 it))) - (magit-list-remote-branches remote))) - (magit-list-refnames (concat "refs/remotes/" remote)))) - -(defun magit-format-refs (format &rest args) - (let ((lines (magit-git-lines - "for-each-ref" (concat "--format=" format) - (or args (list "refs/heads" "refs/remotes" "refs/tags"))))) - (if (string-match-p "\f" format) - (--map (split-string it "\f") lines) - lines))) - -(defun magit-list-remotes () - (magit-git-lines "remote")) - -(defun magit-list-tags () - (magit-git-lines "tag")) - -(defun magit-list-notes-refnames () - (--map (substring it 6) (magit-list-refnames "refs/notes"))) - -(defun magit-list-remote-tags (remote) - (--map (substring it 51) - (--filter (not (string-match-p "\\^{}$" it)) - (magit-git-lines "ls-remote" "--tags" remote)))) - -(defun magit-get-submodules () - (--mapcat (and (string-match "^160000 [0-9a-z]\\{40\\} 0\t\\(.+\\)$" it) - (list (match-string 1 it))) - (magit-git-items "ls-files" "-z" "--stage"))) - -(defun magit-branch-p (string) - (and (or (member string (magit-list-branches)) - (member string (magit-list-branch-names))) t)) - -(defun magit-remote-p (string) - (car (member string (magit-list-remotes)))) - -(defun magit-rev-diff-count (a b) - "Return the commits in A but not B and vice versa. -Return a list of two integers: (A>B B>A)." - (mapcar 'string-to-number - (split-string (magit-git-string "rev-list" - "--count" "--left-right" - (concat a "..." b)) - "\t"))) - -(defun magit-abbrev-length () - (string-to-number (or (magit-get "core.abbrev") "7"))) - -(defun magit-abbrev-arg () - (format "--abbrev=%d" (magit-abbrev-length))) - -(defun magit-commit-children (commit &optional args) - (-map #'car - (--filter (member commit (cdr it)) - (--map (split-string it " ") - (magit-git-lines - "log" "--format=%H %P" - (or args (list "--branches" "--tags" "--remotes")) - "--not" commit))))) - -(defun magit-commit-parents (commit) - (--when-let (magit-git-string "rev-list" "-1" "--parents" commit) - (cdr (split-string it)))) - -(defun magit-assert-one-parent (commit command) - (when (> (length (magit-commit-parents commit)) 1) - (user-error "Cannot %s a merge commit" command))) - -(defun magit-patch-id (rev) - (with-temp-buffer - (magit-process-file - shell-file-name nil '(t nil) nil shell-command-switch - (let ((exec (shell-quote-argument magit-git-executable))) - (format "%s diff-tree -u %s | %s patch-id" exec rev exec))) - (car (split-string (buffer-string))))) - -(defun magit-reflog-enable (ref &optional stashish) - (let ((oldrev (magit-rev-verify ref)) - (logfile (magit-git-dir (concat "logs/" ref)))) - (unless (file-exists-p logfile) - (when oldrev - (magit-git-success "update-ref" "-d" ref oldrev)) - (make-directory (file-name-directory logfile) t) - (with-temp-file logfile) - (when (and oldrev (not stashish)) - (magit-git-success "update-ref" "-m" "enable reflog" ref oldrev ""))))) - -(defun magit-rev-format (format &optional rev args) - (let ((str (magit-git-string "show" "--no-patch" - (concat "--format=" format) args - (if rev (concat rev "^{commit}") "HEAD") "--"))) - (unless (string-equal str "") - str))) - -(defun magit-rev-insert-format (format &optional rev args) - (magit-git-insert "show" "--no-patch" - (concat "--format=" format) args - (if rev (concat rev "^{commit}") "HEAD") "--")) - -(defun magit-format-rev-summary (rev) - (--when-let (magit-rev-format "%h %s" rev) - (string-match " " it) - (put-text-property 0 (match-beginning 0) 'face 'magit-hash it) - it)) - -(defun magit-format-ref-label (ref &optional head) - (-let [(re face fn) (--first (string-match (car it) ref) magit-ref-namespaces)] - (if fn - (funcall fn ref face) - (propertize (or (match-string 1 ref) ref) - 'face (if (equal ref head) 'magit-branch-current face))))) - -(defun magit-format-ref-labels (string) - (save-match-data - (let ((regexp "\\(, \\|tag: \\| -> \\|[()]\\)") head names) - (if (and (derived-mode-p 'magit-log-mode) - (member "--simplify-by-decoration" (cadr magit-refresh-args))) - (let ((branches (magit-list-local-branch-names)) - (re (format "^%s/.+" (regexp-opt (magit-list-remotes))))) - (setq names - (--map (cond ((string-equal it "HEAD") it) - ((string-prefix-p "refs/" it) it) - ((member it branches) (concat "refs/heads/" it)) - ((string-match re it) (concat "refs/remotes/" it)) - (t (concat "refs/" it))) - (split-string - (replace-regexp-in-string "tag: " "refs/tags/" string) - regexp t)))) - (setq names (split-string string regexp t))) - (when (member "HEAD" names) - (setq head (magit-git-string "symbolic-ref" "HEAD") - names (cons (or head "@") (delete head (delete "HEAD" names))))) - (mapconcat (lambda (it) (magit-format-ref-label it head)) names " ")))) - -(defun magit-object-type (object) - (magit-git-string "cat-file" "-t" object)) - -(defmacro magit-with-blob (commit file &rest body) - (declare (indent 2) - (debug (form form body))) - `(with-temp-buffer - (let ((buffer-file-name ,file)) - (save-excursion - (magit-git-insert "cat-file" "-p" - (concat ,commit ":" buffer-file-name))) - (decode-coding-inserted-region - (point-min) (point-max) buffer-file-name t nil nil t) - ,@body))) - -(defmacro magit-with-temp-index (tree arg &rest body) - (declare (indent 2) (debug (form form body))) - (let ((file (cl-gensym "file"))) - `(let ((,file (magit-git-dir (make-temp-name "index.magit.")))) - (setq ,file (or (file-remote-p ,file 'localname) ,file)) - (unwind-protect - (progn (--when-let ,tree - (or (magit-git-success "read-tree" ,arg it - (concat "--index-output=" ,file)) - (error "Cannot read tree %s" it))) - (if (file-remote-p default-directory) - (let ((magit-tramp-process-environment - (setenv-internal magit-tramp-process-environment - "GIT_INDEX_FILE" ,file t))) - ,@body) - (let ((process-environment process-environment)) - (setenv "GIT_INDEX_FILE" ,file) - ,@body))) - (ignore-errors - (delete-file (concat (file-remote-p default-directory) ,file))))))) - -(defun magit-commit-tree (message &optional tree &rest parents) - (magit-git-string "commit-tree" "-m" message - (--mapcat (list "-p" it) (delq nil parents)) - (or tree (magit-git-string "write-tree")))) - -(defun magit-commit-worktree (message &optional arg &rest other-parents) - (magit-with-temp-index "HEAD" arg - (and (magit-update-files (magit-modified-files)) - (apply #'magit-commit-tree message nil "HEAD" other-parents)))) - -(defun magit-update-files (files) - (magit-git-success "update-index" "--add" "--remove" "--" files)) - -(defconst magit-range-re - (concat "\\`\\([^ \t]*[^.]\\)?" ; revA - "\\(\\.\\.\\.?\\)" ; range marker - "\\([^.][^ \t]*\\)?\\'")) ; revB - -;;; Completion - -(defvar magit-revision-history nil) - -(defun magit-read-branch (prompt &optional default) - (magit-completing-read prompt (magit-list-branch-names) - nil t nil 'magit-revision-history - (or (magit-branch-at-point) - default (magit-get-current-branch)))) - -(defun magit-read-branch-or-commit (prompt &optional secondary-default) - (or (magit-completing-read prompt (cons "HEAD" (magit-list-refnames)) - nil nil nil 'magit-revision-history - (or (magit-branch-or-commit-at-point) - secondary-default - (magit-get-current-branch))) - (user-error "Nothing selected"))) - -(defun magit-read-range-or-commit (prompt &optional secondary-default) - (magit-read-range - prompt - (or (--when-let (magit-region-values 'commit 'branch) - (deactivate-mark) - (concat (car (last it)) ".." (car it))) - (magit-branch-or-commit-at-point) - secondary-default - (magit-get-current-branch)))) - -(defun magit-read-range (prompt &optional default) - (let* ((choose-completion-string-functions - '(crm--choose-completion-string)) - (minibuffer-completion-table #'crm--collection-fn) - (minibuffer-completion-confirm t) - (crm-completion-table (magit-list-refnames)) - (crm-separator "\\.\\.\\.?") - (input (read-from-minibuffer - (concat prompt (and default (format " (%s)" default)) ": ") - nil crm-local-completion-map - nil 'magit-revision-history - default))) - (when (string-equal input "") - (or (setq input default) - (user-error "Nothing selected"))) - input)) - -(defun magit-read-remote-branch - (prompt &optional remote default local-branch require-match) - (when (consp default) - (setq default (concat (car default) "/" (cdr default)))) - (let ((branch (magit-completing-read - prompt - (nconc (and local-branch - (if remote - (concat remote "/" local-branch) - (--map (concat it "/" local-branch) - (magit-list-remotes)))) - (magit-list-remote-branch-names remote t)) - nil require-match nil 'magit-revision-history default))) - (string-match "^\\([^/]+\\)/\\(.+\\)" branch) - (cons (match-string 1 branch) - (match-string 2 branch)))) - -(defun magit-read-local-branch (prompt &optional secondary-default) - (magit-completing-read prompt (magit-list-local-branch-names) - nil t nil 'magit-revision-history - (or (magit-branch-at-point) - secondary-default - (magit-get-current-branch)))) - -(defun magit-read-local-branch-or-ref (prompt &optional secondary-default) - (magit-completing-read prompt (nconc (magit-list-local-branch-names) - (magit-list-refs "refs/")) - nil t nil 'magit-revision-history - (or (magit-branch-at-point) - secondary-default - (magit-get-current-branch)))) - -(defun magit-read-other-branch (prompt &optional exclude secondary-default) - (let* ((current (magit-get-current-branch)) - (atpoint (magit-branch-at-point)) - (exclude (or exclude current)) - (default (or (and (not (equal atpoint exclude)) atpoint) - (and (not (equal current exclude)) current) - secondary-default (magit-get-previous-branch)))) - (magit-completing-read prompt (delete exclude (magit-list-branch-names)) - nil t nil 'magit-revision-history default))) - -(defun magit-read-other-branch-or-commit - (prompt &optional exclude secondary-default) - (let* ((current (magit-get-current-branch)) - (atpoint (magit-branch-or-commit-at-point)) - (exclude (or exclude current)) - (default (or (and (not (equal atpoint exclude)) atpoint) - (and (not (equal current exclude)) current) - secondary-default (magit-get-previous-branch)))) - (or (magit-completing-read prompt (delete exclude (magit-list-refnames)) - nil nil nil 'magit-revision-history default) - (user-error "Nothing selected")))) - -(defun magit-read-tag (prompt &optional require-match) - (magit-completing-read prompt (magit-list-tags) nil - require-match nil 'magit-revision-history - (magit-tag-at-point))) - -(defun magit-read-stash (prompt &optional use-at-point) - (let ((atpoint (magit-stash-at-point))) - (or (and use-at-point atpoint) - (let ((stashes (magit-git-lines "stash" "list" "--format=%gd"))) - (magit-completing-read prompt stashes nil t nil nil - (or atpoint (car stashes))))))) - -(defun magit-read-remote (prompt &optional default use-only) - (let ((remotes (magit-list-remotes))) - (if (and use-only (= (length remotes) 1)) - (car remotes) - (magit-completing-read prompt remotes - nil t nil nil - (or default - (magit-remote-at-point) - (magit-get-remote)))))) - -;;; Variables - -(defun magit-get (&rest keys) - "Return the value of Git config entry specified by KEYS." - (magit-git-str "config" (mapconcat 'identity keys "."))) - -(defun magit-get-all (&rest keys) - "Return all values of the Git config entry specified by KEYS." - (let ((magit-git-debug nil)) - (magit-git-lines "config" "--get-all" (mapconcat 'identity keys ".")))) - -(defun magit-get-boolean (&rest keys) - "Return the boolean value of Git config entry specified by KEYS." - (magit-git-true "config" "--bool" (mapconcat 'identity keys "."))) - -(defun magit-set (val &rest keys) - "Set Git config settings specified by KEYS to VAL." - (if val - (magit-git-string "config" (mapconcat 'identity keys ".") val) - (magit-git-string "config" "--unset" (mapconcat 'identity keys ".")))) - -;;; magit-git.el ends soon -(provide 'magit-git) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-git.el ends here diff --git a/elpa/magit-20151119.202/magit-log.el b/elpa/magit-20151119.202/magit-log.el deleted file mode 100644 index 5023129e..00000000 --- a/elpa/magit-20151119.202/magit-log.el +++ /dev/null @@ -1,1454 +0,0 @@ -;;; magit-log.el --- inspect Git history - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library implements support for looking at Git logs, including -;; special logs like reflogs and cherry-logs, as well as for selecting -;; a commit from a log. - -;;; Code: - -(require 'magit-core) -(require 'magit-diff) - -(declare-function magit-blame-chunk-get 'magit-blame) -(declare-function magit-blob-visit 'magit) -(declare-function magit-find-file-noselect 'magit) -(declare-function magit-insert-head-branch-header 'magit) -(declare-function magit-insert-pull-branch-header 'magit) -(declare-function magit-read-file-from-rev 'magit) -(declare-function magit-show-commit 'magit) -(defvar magit-refs-indent-cherry-lines) -(defvar magit-refs-show-commit-count) - -(require 'ansi-color) -(require 'crm) - -;;; Options -;;;; Log Mode - -(defgroup magit-log nil - "Inspect and manipulate Git history." - :group 'magit-modes) - -(defcustom magit-log-mode-hook nil - "Hook run after entering Magit-Log mode." - :group 'magit-log - :type 'hook) - -(defcustom magit-log-arguments '("-n256" "--graph" "--decorate") - "The log arguments used in `magit-log-mode' buffers." - :package-version '(magit . "2.3.0") - :group 'magit-log - :group 'magit-commands - :type '(repeat (string :tag "Argument"))) - -(defcustom magit-log-remove-graph-args '("--follow" "--grep" "-G" "-S" "-L") - "The log arguments that cause the `--graph' argument to be dropped." - :package-version '(magit . "2.3.0") - :group 'magit-log - :type '(repeat (string :tag "Argument")) - :options '("--follow" "--grep" "-G" "-S" "-L")) - -(defcustom magit-log-revision-headers-format "\ -%+b -Author: %aN <%aE> -Committer: %cN <%cE>" - "Additional format string used with the `++header' argument." - :package-version '(magit . "2.3.0") - :group 'magit-log - :type 'string) - -(defcustom magit-log-auto-more nil - "Insert more log entries automatically when moving past the last entry. -Only considered when moving past the last entry with -`magit-goto-*-section' commands." - :group 'magit-log - :type 'boolean) - -(defcustom magit-log-show-margin t - "Whether to initially show the margin in log buffers. - -When non-nil the author name and date are initially displayed in -the margin of log buffers. The margin can be shown or hidden in -the current buffer using the command `magit-toggle-margin'. In -status buffers this option is ignored but it is possible to show -the margin using the mentioned command." - :package-version '(magit . "2.1.0") - :group 'magit-log - :type 'boolean) - -(defcustom magit-duration-spec - `((?Y "year" "years" ,(round (* 60 60 24 365.2425))) - (?M "month" "months" ,(round (* 60 60 24 30.436875))) - (?w "week" "weeks" ,(* 60 60 24 7)) - (?d "day" "days" ,(* 60 60 24)) - (?h "hour" "hours" ,(* 60 60)) - (?m "minute" "minutes" 60) - (?s "second" "seconds" 1)) - "Units used to display durations in a human format. -The value is a list of time units, beginning with the longest. -Each element has the form (CHAR UNIT UNITS SECONDS). UNIT is the -time unit, UNITS is the plural of that unit. CHAR is a character -abbreviation. And SECONDS is the number of seconds in one UNIT. -Also see option `magit-log-margin-spec'." - :package-version '(magit . "2.1.0") - :group 'magit-log - :type '(repeat (list (character :tag "Unit character") - (string :tag "Unit singular string") - (string :tag "Unit plural string") - (integer :tag "Seconds in unit")))) - -(defcustom magit-log-margin-spec '(28 7 magit-duration-spec) - "How to format the log margin. - -The log margin is used to display each commit's author followed -by the commit's age. This option controls the total width of the -margin and how time units are formatted, the value has the form: - - (WIDTH UNIT-WIDTH DURATION-SPEC) - -WIDTH specifies the total width of the log margin. UNIT-WIDTH is -either the integer 1, in which case time units are displayed as a -single characters, leaving more room for author names; or it has -to be the width of the longest time unit string in DURATION-SPEC. -DURATION-SPEC has to be a variable, its value controls which time -units, in what language, are being used." - :package-version '(magit . "2.1.0") - :group 'magit-log - :set-after '(magit-duration-spec) - :type '(list (integer :tag "Margin width") - (choice :tag "Time unit style" - (const :format "%t\n" - :tag "abbreviate to single character" 1) - (integer :format "%t\n" - :tag "show full name" 7)) - (variable :tag "Duration spec variable"))) - -(defcustom magit-log-show-refname-after-summary nil - "Whether to show refnames after commit summaries. -This is useful if you use really long branch names." - :package-version '(magit . "2.2.0") - :group 'magit-log - :type 'boolean) - -(defface magit-log-graph - '((((class color) (background light)) :foreground "grey30") - (((class color) (background dark)) :foreground "grey80")) - "Face for the graph part of the log output." - :group 'magit-faces) - -(defface magit-log-author - '((((class color) (background light)) :foreground "firebrick") - (((class color) (background dark)) :foreground "tomato")) - "Face for the author part of the log output." - :group 'magit-faces) - -(defface magit-log-date - '((((class color) (background light)) :foreground "grey30") - (((class color) (background dark)) :foreground "grey80")) - "Face for the date part of the log output." - :group 'magit-faces) - -;;;; Select Mode - -(defcustom magit-log-select-arguments '("-n256" "--decorate") - "The log arguments used in `magit-log-select-mode' buffers." - :package-version '(magit . "2.3.0") - :group 'magit-log - :type '(repeat (string :tag "Argument"))) - -(defcustom magit-log-select-show-usage 'both - "Whether to show usage information when selecting a commit from a log. -The message can be shown in the `echo-area' or the `header-line', or in -`both' places. If the value isn't one of these symbols, then it should -be nil, in which case no usage information is shown." - :package-version '(magit . "2.1.0") - :group 'magit-log - :type '(choice (const :tag "in echo-area" echo-area) - (const :tag "in header-line" header-line) - (const :tag "in both places" both) - (const :tag "nowhere"))) - -;;;; Cherry Mode - -(defcustom magit-cherry-sections-hook - '(magit-insert-cherry-headers - magit-insert-cherry-commits) - "Hook run to insert sections into the cherry buffer." - :package-version '(magit . "2.1.0") - :group 'magit-log - :type 'hook) - -;;;; Reflog Mode - -(defcustom magit-reflog-arguments '("-n256") - "The log arguments used in `magit-reflog-mode' buffers." - :package-version '(magit . "2.3.0") - :group 'magit-log - :group 'magit-commands - :type '(repeat (string :tag "Argument"))) - -(defcustom magit-reflog-show-margin t - "Whether to initially show the margin in reflog buffers. - -When non-nil the author name and date are initially displayed in -the margin of reflog buffers. The margin can be shown or hidden -in the current buffer using the command `magit-toggle-margin'." - :package-version '(magit . "2.1.0") - :group 'magit-log - :type 'boolean) - -(defface magit-reflog-commit '((t :foreground "green")) - "Face for commit commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-amend '((t :foreground "magenta")) - "Face for amend commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-merge '((t :foreground "green")) - "Face for merge, checkout and branch commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-checkout '((t :foreground "blue")) - "Face for checkout commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-reset '((t :foreground "red")) - "Face for reset commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-rebase '((t :foreground "magenta")) - "Face for rebase commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-cherry-pick '((t :foreground "green")) - "Face for cherry-pick commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-remote '((t :foreground "cyan")) - "Face for pull and clone commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-other '((t :foreground "cyan")) - "Face for other commands in reflogs." - :group 'magit-faces) - -;;;; Log Sections - -(defcustom magit-log-section-commit-count 10 - "How many recent commits to show in certain log sections. -How many recent commits `magit-insert-recent-commits' and -`magit-insert-unpulled-or-recent-commits' (provided there -are no unpulled commits) show." - :package-version '(magit . "2.1.0") - :group 'magit-status - :type 'number) - -(defcustom magit-log-section-arguments '("--decorate") - "The log arguments used in buffers that show other things besides logs." - :package-version '(magit . "2.2.0") - :group 'magit-log - :group 'magit-status - :type '(repeat (string :tag "Argument"))) - -(define-obsolete-variable-alias 'magit-log-section-args - 'magit-log-section-arguments "2.2.0") - -;;; Commands - -(defvar magit-log-popup - '(:variable magit-log-arguments - :man-page "git-log" - :switches ((?g "Show graph" "--graph") - (?c "Show graph in color" "--color") - (?d "Show refnames" "--decorate") - (?S "Show signatures" "--show-signature") - (?u "Show diffs" "--patch") - (?s "Show diffstats" "--stat") - (?h "Show header" "++header") - (?D "Simplify by decoration" "--simplify-by-decoration") - (?f "Follow renames when showing single-file log" "--follow")) - :options ((?n "Limit number of commits" "-n" read-from-minibuffer) - (?f "Limit to files" "-- " magit-read-files) - (?a "Limit to author" "--author=" read-from-minibuffer) - (?g "Search messages" "--grep=" read-from-minibuffer) - (?G "Search changes" "-G" read-from-minibuffer) - (?S "Search occurences" "-S" read-from-minibuffer) - (?L "Trace line evolution" "-L" magit-read-file-trace)) - :actions ((?l "Log current" magit-log-current) - (?L "Log local branches" magit-log-branches) - (?r "Reflog current" magit-reflog-current) - (?o "Log other" magit-log) - (?b "Log all branches" magit-log-all-branches) - (?O "Reflog other" magit-reflog) - (?h "Log HEAD" magit-log-head) - (?a "Log all references" magit-log-all) - (?H "Reflog HEAD" magit-reflog-head)) - :default-action magit-log-current - :max-action-columns 3)) - -(defvar magit-log-mode-refresh-popup - '(:variable magit-log-arguments - :man-page "git-log" - :switches ((?g "Show graph" "--graph") - (?c "Show graph in color" "--color") - (?d "Show refnames" "--decorate") - (?S "Show signatures" "--show-signature") - (?u "Show diffs" "--patch") - (?s "Show diffstats" "--stat") - (?D "Simplify by decoration" "--simplify-by-decoration") - (?f "Follow renames when showing single-file log" "--follow")) - :options ((?n "Limit number of commits" "-n" read-from-minibuffer) - (?f "Limit to files" "-- " magit-read-files) - (?a "Limit to author" "--author=" read-from-minibuffer) - (?g "Search messages" "--grep=" read-from-minibuffer) - (?G "Search changes" "-G" read-from-minibuffer) - (?S "Search occurences" "-S" read-from-minibuffer) - (?L "Trace line evolution" "-L" magit-read-file-trace)) - :actions ((?g "Refresh" magit-log-refresh) - (?t "Toggle margin" magit-toggle-margin) - (?s "Set defaults" magit-log-set-default-arguments) nil - (?w "Save defaults" magit-log-save-default-arguments)) - :max-action-columns 2)) - -(defvar magit-reflog-mode-refresh-popup - '(:variable magit-reflog-arguments - :man-page "git-reflog" - :options ((?n "Limit number of commits" "-n" read-from-minibuffer)))) - -(defvar magit-log-refresh-popup - '(:variable magit-log-arguments - :man-page "git-log" - :switches ((?g "Show graph" "--graph") - (?c "Show graph in color" "--color") - (?d "Show refnames" "--decorate")) - :actions ((?g "Refresh" magit-log-refresh) - (?t "Toggle margin" magit-toggle-margin) - (?s "Set defaults" magit-log-set-default-arguments) nil - (?w "Save defaults" magit-log-save-default-arguments)) - :max-action-columns 2)) - -(magit-define-popup-keys-deferred 'magit-log-popup) -(magit-define-popup-keys-deferred 'magit-log-mode-refresh-popup) -(magit-define-popup-keys-deferred 'magit-log-refresh-popup) - -(defun magit-read-file-trace (&rest ignored) - (let ((file (magit-read-file-from-rev "HEAD" "File")) - (trace (magit-read-string "Trace"))) - (if (string-match - "^\\(/.+/\\|:[^:]+\\|[0-9]+,[-+]?[0-9]+\\)\\(:\\)?$" trace) - (concat trace (or (match-string 2 trace) ":") file) - (user-error "Trace is invalid, see man git-log")))) - -(defun magit-log-arguments (&optional refresh) - (cond ((memq magit-current-popup - '(magit-log-popup magit-log-refresh-popup)) - (magit-popup-export-file-args magit-current-popup-args)) - ((derived-mode-p 'magit-log-mode) - (list (nth 1 magit-refresh-args) - (nth 2 magit-refresh-args))) - (refresh - (list magit-log-section-arguments nil)) - (t - (-if-let (buffer (magit-mode-get-buffer 'magit-log-mode)) - (with-current-buffer buffer - (list (nth 1 magit-refresh-args) - (nth 2 magit-refresh-args))) - (list (default-value 'magit-log-arguments) nil))))) - -(defun magit-log-popup (arg) - "Popup console for log commands." - (interactive "P") - (let ((magit-log-refresh-popup - (pcase major-mode - (`magit-log-mode magit-log-mode-refresh-popup) - (_ magit-log-refresh-popup))) - (magit-log-arguments - (-if-let (buffer (magit-mode-get-buffer 'magit-log-mode)) - (with-current-buffer buffer - (magit-popup-import-file-args (nth 1 magit-refresh-args) - (nth 2 magit-refresh-args))) - (default-value 'magit-log-arguments)))) - (magit-invoke-popup 'magit-log-popup nil arg))) - -(defun magit-log-refresh-popup (arg) - "Popup console for changing log arguments in the current buffer." - (interactive "P") - (magit-log-refresh-assert) - (let ((magit-log-refresh-popup - (cond ((derived-mode-p 'magit-log-select-mode) - magit-log-refresh-popup) - ((derived-mode-p 'magit-log-mode) - (let ((def (copy-sequence magit-log-refresh-popup))) - (plist-put def :switches (plist-get magit-log-popup :switches)) - (plist-put def :options (plist-get magit-log-popup :options)) - def)) - (t - magit-log-refresh-popup))) - (magit-log-arguments - (cond ((derived-mode-p 'magit-log-select-mode) - (cadr magit-refresh-args)) - ((derived-mode-p 'magit-log-mode) - (magit-popup-import-file-args (nth 1 magit-refresh-args) - (nth 2 magit-refresh-args))) - (t - magit-log-section-arguments)))) - (magit-invoke-popup 'magit-log-refresh-popup nil arg))) - -(defun magit-log-refresh (args files) - "Set the local log arguments for the current buffer." - (interactive (magit-log-arguments t)) - (magit-log-refresh-assert) - (cond ((derived-mode-p 'magit-log-select-mode) - (setcar (cdr magit-refresh-args) args)) - ((derived-mode-p 'magit-log-mode) - (setcdr magit-refresh-args (list args files))) - (t - (setq-local magit-log-section-arguments args))) - (magit-refresh)) - -(defun magit-log-set-default-arguments (args files) - "Set the global log arguments for the current buffer." - (interactive (magit-log-arguments t)) - (magit-log-refresh-assert) - (cond ((derived-mode-p 'magit-log-select-mode) - (customize-set-variable 'magit-log-select-arguments args) - (setcar (cdr magit-refresh-args) args)) - ((derived-mode-p 'magit-log-mode) - (customize-set-variable 'magit-log-arguments args) - (setcdr magit-refresh-args (list args files))) - (t - (customize-set-variable 'magit-log-section-arguments args) - (kill-local-variable 'magit-log-section-arguments))) - (magit-refresh)) - -(defun magit-log-save-default-arguments (args files) - "Set and save the global log arguments for the current buffer." - (interactive (magit-log-arguments t)) - (magit-log-refresh-assert) - (cond ((derived-mode-p 'magit-log-select-mode) - (customize-save-variable 'magit-log-select-arguments args) - (setcar (cdr magit-refresh-args) args)) - ((derived-mode-p 'magit-log-mode) - (customize-save-variable 'magit-log-arguments args) - (setcdr magit-refresh-args (list args files))) - (t - (customize-save-variable 'magit-log-section-arguments args) - (kill-local-variable 'magit-log-section-arguments))) - (magit-refresh)) - -(defun magit-log-refresh-assert () - (cond ((derived-mode-p 'magit-reflog-mode) - (user-error "Cannot change log arguments in reflog buffers")) - ((derived-mode-p 'magit-cherry-mode) - (user-error "Cannot change log arguments in cherry buffers")))) - -(defvar magit-log-read-revs-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map crm-local-completion-map) - (define-key map "\s" 'self-insert-command) - map)) - -(defun magit-log-read-revs (&optional use-current) - (or (and use-current (--when-let (magit-get-current-branch) (list it))) - (let* ((choose-completion-string-functions - '(crm--choose-completion-string)) - (minibuffer-completion-table #'crm--collection-fn) - (minibuffer-completion-confirm t) - (crm-completion-table - `(,@(and (file-exists-p (magit-git-dir "FETCH_HEAD")) - (list "FETCH_HEAD")) - ,@(magit-list-branch-names))) - (crm-separator "\\(\\.\\.\\.?\\|[, ]\\)") - (default (or (magit-branch-or-commit-at-point) - (unless use-current - (magit-get-previous-branch)))) - (input (read-from-minibuffer - (format "Log rev,s%s: " - (if default (format " (%s)" default) "")) - nil magit-log-read-revs-map - nil 'magit-revision-history default))) - (when (string-equal input "") - (or (setq input default) - (user-error "Nothing selected"))) - (split-string input "[, ]" t)))) - -;;;###autoload -(defun magit-log-current (revs &optional args files) - "Show log for the current branch. -When `HEAD' is detached or with a prefix argument show log for -one or more revs read from the minibuffer." - (interactive (cons (magit-log-read-revs t) - (magit-log-arguments))) - (magit-log revs args files)) - -;;;###autoload -(defun magit-log (revs &optional args files) - "Show log for one or more revs read from the minibuffer. -The user can input any revision or revisions separated by a -space, or even ranges, but only branches and tags, and a -representation of the commit at point, are available as -completion candidates." - (interactive (cons (magit-log-read-revs) - (magit-log-arguments))) - (magit-mode-setup #'magit-log-mode revs args files) - (magit-log-goto-same-commit)) - -;;;###autoload -(defun magit-log-head (&optional args files) - "Show log for `HEAD'." - (interactive (magit-log-arguments)) - (magit-log (list "HEAD") args files)) - -;;;###autoload -(defun magit-log-branches (&optional args files) - "Show log for all local branches and `HEAD'." - (interactive (magit-log-arguments)) - (magit-log (if (magit-get-current-branch) - (list "--branches") - (list "HEAD" "--branches")) - args files)) - -;;;###autoload -(defun magit-log-all-branches (&optional args files) - "Show log for all local and remote branches and `HEAD'." - (interactive (magit-log-arguments)) - (magit-log (if (magit-get-current-branch) - (list "--branches" "--remotes") - (list "HEAD" "--branches" "--remotes")) - args files)) - -;;;###autoload -(defun magit-log-all (&optional args files) - "Show log for all references and `HEAD'." - (interactive (magit-log-arguments)) - (magit-log (if (magit-get-current-branch) - (list "--all") - (list "HEAD" "--all")) - args files)) - -;;;###autoload -(defun magit-log-buffer-file (&optional follow beg end) - "Show log for the blob or file visited in the current buffer. -With a prefix argument or when `--follow' is part of -`magit-log-arguments', then follow renames." - (interactive (if (region-active-p) - (list current-prefix-arg - (1- (line-number-at-pos (region-beginning))) - (1- (line-number-at-pos (region-end)))) - (list current-prefix-arg))) - (-if-let (file (magit-file-relative-name)) - (magit-mode-setup #'magit-log-mode - (list (or magit-buffer-refname - (magit-get-current-branch) "HEAD")) - (let ((args (car (magit-log-arguments)))) - (when (and follow (not (member "--follow" args))) - (push "--follow" args)) - (when (and beg end) - (setq args (cons (format "-L%s,%s:%s" beg end file) - (cl-delete "-L" args :test - 'string-prefix-p))) - (setq file nil)) - args) - (and file (list file))) - (user-error "Buffer isn't visiting a file")) - (magit-log-goto-same-commit)) - -;;;###autoload -(defun magit-reflog-current () - "Display the reflog of the current branch." - (interactive) - (magit-reflog (magit-get-current-branch))) - -;;;###autoload -(defun magit-reflog (ref) - "Display the reflog of a branch." - (interactive (list (magit-read-local-branch-or-ref "Show reflog for"))) - (magit-mode-setup #'magit-reflog-mode ref magit-reflog-arguments)) - -;;;###autoload -(defun magit-reflog-head () - "Display the `HEAD' reflog." - (interactive) - (magit-reflog "HEAD")) - -(defun magit-log-toggle-commit-limit () - "Toggle the number of commits the current log buffer is limited to. -If the number of commits is currently limited, then remove that -limit. Otherwise set it to 256." - (interactive) - (magit-log-set-commit-limit (lambda (&rest _) nil))) - -(defun magit-log-double-commit-limit () - "Double the number of commits the current log buffer is limited to." - (interactive) - (magit-log-set-commit-limit '*)) - -(defun magit-log-half-commit-limit () - "Half the number of commits the current log buffer is limited to." - (interactive) - (magit-log-set-commit-limit '/)) - -(defun magit-log-set-commit-limit (fn) - (let* ((val (car (magit-log-arguments t))) - (arg (--first (string-match "^-n\\([0-9]+\\)?$" it) val)) - (num (and arg (string-to-number (match-string 1 arg)))) - (num (if num (funcall fn num 2) 256))) - (setq val (delete arg val)) - (setcar (cdr magit-refresh-args) - (if (and num (> num 0)) - (cons (format "-n%i" num) val) - val))) - (magit-refresh)) - -(defun magit-log-get-commit-limit () - (--when-let (--first (string-match "^-n\\([0-9]+\\)?$" it) - (car (magit-log-arguments t))) - (string-to-number (match-string 1 it)))) - -(defun magit-log-bury-buffer (&optional arg) - "Bury the current buffer or the revision buffer in the same frame. -Like `magit-mode-bury-buffer' (which see) but with a negative -prefix argument instead bury the revision buffer, provided it -is displayed in the current frame." - (interactive "p") - (if (< arg 0) - (let* ((buf (magit-mode-get-buffer 'magit-revision-mode)) - (win (and buf (get-buffer-window buf (selected-frame))))) - (if win - (with-selected-window win - (with-current-buffer buf - (magit-mode-bury-buffer (> (abs arg) 1)))) - (user-error "No revision buffer in this frame"))) - (magit-mode-bury-buffer (> arg 1)))) - -;;; Log Mode - -(defvar magit-log-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map magit-mode-map) - (define-key map "\C-c\C-b" 'magit-go-backward) - (define-key map "\C-c\C-f" 'magit-go-forward) - (define-key map "=" 'magit-log-toggle-commit-limit) - (define-key map "+" 'magit-log-double-commit-limit) - (define-key map "-" 'magit-log-half-commit-limit) - (define-key map "q" 'magit-log-bury-buffer) - map) - "Keymap for `magit-log-mode'.") - -(define-derived-mode magit-log-mode magit-mode "Magit Log" - "Mode for looking at Git log. - -This mode is documented in info node `(magit)Log Buffer'. - -\\\ -Type \\[magit-refresh] to refresh the current buffer. -Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ -to visit the commit at point. - -Type \\[magit-branch-popup] to see available branch commands. -Type \\[magit-merge-popup] to merge the branch or commit at point. -Type \\[magit-cherry-pick-popup] to apply the commit at point. -Type \\[magit-reset] to reset HEAD to the commit at point. - -\\{magit-log-mode-map}" - :group 'magit-log - (hack-dir-local-variables-non-file-buffer)) - -(defvar magit-log-disable-graph-hack-args - '("-G" "--grep" "--author") - "Arguments which disable the graph speedup hack.") - -(defun magit-log-refresh-buffer (revs args files) - (setq header-line-format - (propertize - (concat " Commits in " (mapconcat 'identity revs " ") - (and files (concat " touching " - (mapconcat 'identity files " ")))) - 'face 'magit-header-line)) - (unless (= (length files) 1) - (setq args (remove "--follow" args))) - (when (--any-p (string-match-p - (concat "^" (regexp-opt magit-log-remove-graph-args)) it) - args) - (setq args (remove "--graph" args))) - (unless (member "--graph" args) - (setq args (remove "--color" args))) - (-when-let* ((limit (magit-log-get-commit-limit)) - (limit (* 2 limit)) ; increase odds for complete graph - (count (and (= (length revs) 1) - (> limit 1024) ; otherwise it's fast enough - (setq revs (car revs)) - (not (string-match-p "\\.\\." revs)) - (not (member revs '("--all" "--branches"))) - (-none-p (lambda (arg) - (--any-p (string-prefix-p it arg) - magit-log-disable-graph-hack-args)) - args) - (magit-git-string "rev-list" "--count" - "--first-parent" args revs)))) - (setq revs (if (< (string-to-number count) limit) - revs - (format "%s~%s..%s" revs limit revs)))) - (magit-insert-section (logbuf) - (magit-insert-log revs args files))) - -(defun magit-insert-log (revs &optional args files) - "Insert a log section. -Do not add this to a hook variable." - (magit-git-wash (apply-partially #'magit-log-wash-log 'log) - "log" - (format "--format=%%h%s %s[%%aN][%%at]%%s%s" - (if (member "--decorate" args) "%d" "") - (if (member "--show-signature" args) - (progn (setq args (remove "--show-signature" args)) "%G?") - "") - (if (member "++header" args) - (if (member "--graph" (setq args (delete "++header" args))) - (concat "\n" magit-log-revision-headers-format "\n") - (concat "\n" magit-log-revision-headers-format "\n")) - "")) - (if (member "--decorate" args) - (cons "--decorate=full" (remove "--decorate" args)) - args) - "--use-mailmap" "--no-prefix" revs "--" files)) - -(defvar magit-commit-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-visit-thing] 'magit-show-commit) - (define-key map "a" 'magit-cherry-apply) - (define-key map "v" 'magit-revert-no-commit) - map) - "Keymap for `commit' sections.") - -(defvar magit-module-commit-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-visit-thing] 'magit-show-commit) - map) - "Keymap for `module-commit' sections.") - -(defconst magit-log-heading-re - (concat "^" - "\\(?4:[-_/|\\*o. ]*\\)" ; graph - "\\(?1:[0-9a-fA-F]+\\) " ; sha1 - "\\(?:\\(?3:([^()]+)\\) \\)?" ; refs - "\\(?7:[BGUN]\\)?" ; gpg - "\\[\\(?5:[^]]*\\)\\]" ; author - "\\[\\(?6:[^]]*\\)\\]" ; date - "\\(?2:.*\\)$")) ; msg - -(defconst magit-log-cherry-re - (concat "^" - "\\(?8:[-+]\\) " ; cherry - "\\(?1:[0-9a-fA-F]+\\) " ; sha1 - "\\(?2:.*\\)$")) ; msg - -(defconst magit-log-module-re - (concat "^" - "\\(?:\\(?11:[<>]\\) \\)?" ; side - "\\(?1:[0-9a-fA-F]+\\) " ; sha1 - "\\(?2:.*\\)$")) ; msg - -(defconst magit-log-bisect-vis-re - (concat "^" - "\\(?1:[0-9a-fA-F]+\\) " ; sha1 - "\\(?:\\(?3:([^()]+)\\) \\)?" ; refs - "\\(?2:.*\\)$")) ; msg - -(defconst magit-log-bisect-log-re - (concat "^# " - "\\(?3:bad:\\|skip:\\|good:\\) " ; "refs" - "\\[\\(?1:[^]]+\\)\\] " ; sha1 - "\\(?2:.*\\)$")) ; msg - -(defconst magit-log-reflog-re - (concat "^" - "\\(?1:[^ ]+\\) " ; sha1 - "\\(?:\\(?:[^@]+@{\\(?6:[^}]+\\)} " ; date - "\\(?10:merge \\|autosave \\|restart \\|[^:]+: \\)?" ; refsub - "\\(?2:.*\\)?\\)\\| \\)$")) ; msg - -(defconst magit-reflog-subject-re - (concat "\\(?1:[^ ]+\\) ?" ; command - "\\(?2:\\(?: ?-[^ ]+\\)+\\)?" ; option - "\\(?: ?(\\(?3:[^)]+\\))\\)?")) ; type - -(defconst magit-log-stash-re - (concat "^" - "\\(?1:[^ ]+\\)" ; "sha1" - "\\(?5: \\)" ; "author" - "\\(?6:[^ ]+\\) " ; date - "\\(?2:.*\\)$")) ; msg - -(defvar magit-log-count nil) - -(defun magit-log-wash-log (style args) - (setq args (-flatten args)) - (when (and (member "--graph" args) - (member "--color" args)) - (let ((ansi-color-apply-face-function - (lambda (beg end face) - (put-text-property beg end 'font-lock-face - (or face 'magit-log-graph))))) - (ansi-color-apply-on-region (point-min) (point-max)))) - (when (eq style 'cherry) - (reverse-region (point-min) (point-max))) - (let ((magit-log-count 0) - (abbrev (magit-abbrev-length))) - (magit-wash-sequence (apply-partially 'magit-log-wash-rev style abbrev)) - (if (derived-mode-p 'magit-log-mode) - (when (eq magit-log-count (magit-log-get-commit-limit)) - (magit-insert-section (longer) - (insert-text-button - (substitute-command-keys - (format "Type \\<%s>\\[%s] to show more history" - 'magit-log-mode-map - 'magit-log-double-commit-limit)) - 'action (lambda (button) - (magit-log-double-commit-limit)) - 'follow-link t - 'mouse-face 'magit-section-highlight))) - (unless (equal (car args) "cherry") - (insert ?\n))))) - -(defun magit-log-wash-rev (style abbrev) - (when (derived-mode-p 'magit-log-mode) - (cl-incf magit-log-count)) - (looking-at (pcase style - (`log magit-log-heading-re) - (`cherry magit-log-cherry-re) - (`module magit-log-module-re) - (`reflog magit-log-reflog-re) - (`stash magit-log-stash-re) - (`bisect-vis magit-log-bisect-vis-re) - (`bisect-log magit-log-bisect-log-re))) - (magit-bind-match-strings - (hash msg refs graph author date gpg cherry _ refsub side) nil - (let ((align (not (member "--stat" (cadr magit-refresh-args))))) - (magit-delete-line) - (magit-insert-section section (commit hash) - (pcase style - (`stash (setf (magit-section-type section) 'stash)) - (`module (setf (magit-section-type section) 'module-commit)) - (`bisect-log (setq hash (magit-rev-parse "--short" hash)))) - (when cherry - (when (and (derived-mode-p 'magit-refs-mode) - magit-refs-show-commit-count) - (insert (make-string magit-refs-indent-cherry-lines ?\s))) - (insert (propertize cherry 'face (if (string= cherry "-") - 'magit-cherry-equivalent - 'magit-cherry-unmatched))) - (insert ?\s)) - (when side - (insert (propertize side 'face (if (string= side "<") - 'magit-diff-removed - 'magit-diff-added))) - (insert ?\s)) - (when align - (insert (propertize hash 'face 'magit-hash) ?\s)) - (when graph - (insert graph)) - (unless align - (insert (propertize hash 'face 'magit-hash) ?\s)) - (when (and refs (not magit-log-show-refname-after-summary)) - (insert (magit-format-ref-labels refs) ?\s)) - (when refsub - (insert (format "%-2s " (1- magit-log-count))) - (insert (magit-reflog-format-subject - (substring refsub 0 (if (string-match-p ":" refsub) -2 -1))))) - (when msg - (insert (propertize msg 'face - (pcase (and gpg (aref gpg 0)) - (?G 'magit-signature-good) - (?B 'magit-signature-bad) - (?U 'magit-signature-untrusted)))) - (insert ?\s)) - (when (and refs magit-log-show-refname-after-summary) - (insert ?\s) - (insert (magit-format-ref-labels refs))) - (insert ?\n) - (when (memq style '(log reflog stash)) - (goto-char (line-beginning-position)) - (when (and refsub - (string-match "\\`\\([^ ]\\) \\+\\(..\\)\\(..\\)" date)) - (setq date (+ (string-to-number (match-string 1 date)) - (* (string-to-number (match-string 2 date)) 60 60) - (* (string-to-number (match-string 3 date)) 60)))) - (save-excursion - (backward-char) - (magit-format-log-margin author date))) - (when (and (eq style 'log) - (not (or (eobp) (looking-at magit-log-heading-re)))) - (when (looking-at "") - (magit-insert-heading) - (delete-char 1) - (magit-insert-section (commit-header) - (forward-line) - (magit-insert-heading) - (re-search-forward "") - (backward-delete-char 1) - (forward-char) - (insert ?\n)) - (delete-char 1)) - (if (looking-at "^\\(---\\|\n\s\\|\ndiff\\)") - (let ((limit (save-excursion - (and (re-search-forward magit-log-heading-re nil t) - (match-beginning 0))))) - (unless (magit-section-content magit-insert-section--current) - (magit-insert-heading)) - (delete-char (if (looking-at "\n") 1 4)) - (magit-diff-wash-diffs (list "--stat") limit)) - (when align - (setq align (make-string (1+ abbrev) ? ))) - (when (and (not (eobp)) (not (looking-at magit-log-heading-re))) - (when align - (setq align (make-string (1+ abbrev) ? ))) - (while (and (not (eobp)) (not (looking-at magit-log-heading-re))) - (when align - (save-excursion (insert align))) - (magit-format-log-margin) - (forward-line)) - ;; When `--format' is used and its value isn't one of the - ;; predefined formats, then `git-log' does not insert a - ;; separator line. - (save-excursion - (forward-line -1) - (looking-at "[-_/|\\*o. ]*")) - (setq graph (match-string 0)) - (unless (string-match-p "[/\\]" graph) - (insert graph ?\n)))))))) - t) - -(defun magit-format-log-margin (&optional author date) - (-let [(width unit-width duration-spec) magit-log-margin-spec] - (when (and date (not author)) - (setq width (+ (if (= unit-width 1) 1 (1+ unit-width)) - (if (derived-mode-p 'magit-log-mode) 1 0)))) - (if date - (magit-make-margin-overlay - (and author - (concat (propertize (truncate-string-to-width - (or author "") - (- width 1 3 ; gap, digits - (if (= unit-width 1) 1 (1+ unit-width)) - (if (derived-mode-p 'magit-log-mode) 1 0)) - nil ?\s (make-string 1 magit-ellipsis)) - 'face 'magit-log-author) - " ")) - (propertize (magit-format-duration - (abs (truncate (- (float-time) - (string-to-number date)))) - (symbol-value duration-spec) - unit-width) - 'face 'magit-log-date) - (and (derived-mode-p 'magit-log-mode) - (propertize " " 'face 'fringe))) - (magit-make-margin-overlay - (propertize (make-string (1- width) ?\s) 'face 'default) - (propertize " " 'face 'fringe))))) - -(defun magit-format-duration (duration spec &optional width) - (-let [(char unit units weight) (car spec)] - (let ((cnt (round (/ duration weight 1.0)))) - (if (or (not (cdr spec)) - (>= (/ duration weight) 1)) - (if (eq width 1) - (format "%3i%c" cnt char) - (format (if width (format "%%3i %%-%is" width) "%i %s") - cnt (if (= cnt 1) unit units))) - (magit-format-duration duration (cdr spec) width))))) - -(defun magit-log-maybe-show-more-commits (section) - "Automatically insert more commit sections in a log. -Only do so if `point' is on the \"show more\" section, -and `magit-log-auto-more' is non-nil." - (when (and (eq (magit-section-type section) 'longer) - magit-log-auto-more) - (magit-log-double-commit-limit) - (forward-line -1) - (magit-section-forward))) - -(defvar magit--update-revision-buffer nil) - -(defun magit-log-maybe-update-revision-buffer (&optional _) - "When moving in the log buffer, update the revision buffer. -If there is no revision buffer in the same frame, then do nothing." - (when (derived-mode-p 'magit-log-mode) - (magit-log-maybe-update-revision-buffer-1))) - -(defun magit-log-maybe-update-revision-buffer-1 () - (unless magit--update-revision-buffer - (-when-let* ((commit (magit-section-when 'commit)) - (buffer (magit-mode-get-buffer 'magit-revision-mode nil t))) - (setq magit--update-revision-buffer (list commit buffer)) - (run-with-idle-timer - magit-update-other-window-delay nil - (lambda () - (-let [(rev buf) magit--update-revision-buffer] - (setq magit--update-revision-buffer nil) - (when (buffer-live-p buf) - (let ((magit-display-buffer-noselect t)) - (apply #'magit-show-commit rev (magit-diff-arguments))))) - (setq magit--update-revision-buffer nil)))))) - -(defvar magit--update-blob-buffer nil) - -(defun magit-log-maybe-update-blob-buffer (&optional _) - "When moving in the log buffer, update the blob buffer. -If there is no blob buffer in the same frame, then do nothing." - (when (derived-mode-p 'magit-log-mode) - (magit-log-maybe-update-blob-buffer-1))) - -(defun magit-log-maybe-update-blob-buffer-1 () - (unless magit--update-revision-buffer - (-when-let* ((commit (magit-section-when 'commit)) - (buffer (--first (with-current-buffer it magit-buffer-revision) - (-map #'window-buffer (window-list))))) - (setq magit--update-blob-buffer (list commit buffer)) - (run-with-idle-timer - magit-update-other-window-delay nil - (lambda () - (-let [(rev buf) magit--update-blob-buffer] - (setq magit--update-blob-buffer nil) - (when (buffer-live-p buf) - (save-excursion - (with-selected-window (get-buffer-window buf) - (with-current-buffer buf - (magit-blob-visit (list (magit-rev-parse rev) - (magit-file-relative-name - magit-buffer-file-name)) - (line-number-at-pos)))))))))))) - -(defun magit-log-goto-same-commit () - (-when-let* ((prev magit-previous-section) - (rev (cond ((magit-section-match 'commit prev) - (magit-section-value prev)) - ((magit-section-match 'branch prev) - (magit-rev-format - "%h" (magit-section-value prev))))) - (same (--first (equal (magit-section-value it) rev) - (magit-section-children magit-root-section)))) - (goto-char (magit-section-start same)))) - -;;; Select Mode - -(defvar magit-log-select-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map magit-log-mode-map) - (define-key map "\C-c\C-b" 'undefined) - (define-key map "\C-c\C-f" 'undefined) - (define-key map "." 'magit-log-select-pick) - (define-key map "e" 'magit-log-select-pick) - (define-key map "\C-c\C-c" 'magit-log-select-pick) - (define-key map "q" 'magit-log-select-quit) - (define-key map "\C-c\C-k" 'magit-log-select-quit) - map) - "Keymap for `magit-log-select-mode'.") - -(put 'magit-log-select-pick :advertised-binding [?\C-c ?\C-c]) -(put 'magit-log-select-quit :advertised-binding [?\C-c ?\C-k]) - -(define-derived-mode magit-log-select-mode magit-log-mode "Magit Select" - "Mode for selecting a commit from history. - -This mode is documented in info node `(magit)Select from log'. - -\\\ -Type \\[magit-refresh] to refresh the current buffer. -Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ -to visit the commit at point. - -\\\ -Type \\[magit-log-select-pick] to select the commit at point. -Type \\[magit-log-select-quit] to abort without selecting a commit." - :group 'magit-log - (hack-dir-local-variables-non-file-buffer)) - -(defun magit-log-select-refresh-buffer (rev args) - (magit-insert-section (logbuf) - (magit-insert-log rev args))) - -(defvar-local magit-log-select-pick-function nil) -(defvar-local magit-log-select-quit-function nil) - -(defun magit-log-select (pick &optional msg quit branch) - (declare (indent defun)) - (magit-mode-setup #'magit-log-select-mode - (or branch (magit-get-current-branch) "HEAD") - magit-log-select-arguments) - (magit-log-goto-same-commit) - (setq magit-log-select-pick-function pick) - (setq magit-log-select-quit-function quit) - (when magit-log-select-show-usage - (setq msg (substitute-command-keys - (format-spec - (if msg - (if (string-suffix-p "," msg) - (concat msg " or %q to abort") - msg) - "Type %p to select commit at point, or %q to abort") - '((?p . "\\[magit-log-select-pick]") - (?q . "\\[magit-log-select-quit]"))))) - (when (memq magit-log-select-show-usage '(both header-line)) - (setq header-line-format (propertize (concat " " msg) 'face 'bold))) - (when (memq magit-log-select-show-usage '(both echo-area)) - (message "%s" msg)))) - -(defun magit-log-select-pick () - "Select the commit at point and act on it. -Call `magit-log-select-pick-function' with the selected -commit as argument." - (interactive) - (let ((fun magit-log-select-pick-function) - (rev (magit-commit-at-point))) - (kill-buffer (current-buffer)) - (funcall fun rev))) - -(defun magit-log-select-quit () - "Abort selecting a commit, don't act on any commit." - (interactive) - (kill-buffer (current-buffer)) - (when magit-log-select-quit-function - (funcall magit-log-select-quit-function))) - -;;; Cherry Mode - -(defvar magit-cherry-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map magit-mode-map) - (define-key map "q" 'magit-log-bury-buffer) - (define-key map "L" 'magit-toggle-margin) - map) - "Keymap for `magit-cherry-mode'.") - -(define-derived-mode magit-cherry-mode magit-mode "Magit Cherry" - "Mode for looking at commits not merged upstream. - -\\\ -Type \\[magit-refresh] to refresh the current buffer. -Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ -to visit the commit at point. - -Type \\[magit-cherry-pick-popup] to apply the commit at point. - -\\{magit-cherry-mode-map}" - :group 'magit-log - (hack-dir-local-variables-non-file-buffer)) - -;;;###autoload -(defun magit-cherry (head upstream) - "Show commits in a branch that are not merged in the upstream branch." - (interactive - (let ((head (magit-read-branch "Cherry head"))) - (list head (magit-read-other-branch "Cherry upstream" head - (magit-get-tracked-branch head))))) - (magit-mode-setup #'magit-cherry-mode upstream head)) - -(defun magit-cherry-refresh-buffer (_upstream _head) - (magit-insert-section (cherry) - (run-hooks 'magit-cherry-sections-hook))) - -(defun magit-insert-cherry-headers () - "Insert headers appropriate for `magit-cherry-mode' buffers." - (magit-insert-head-branch-header (nth 1 magit-refresh-args)) - (magit-insert-pull-branch-header (nth 1 magit-refresh-args) - (nth 0 magit-refresh-args) - "Upstream: ") - (insert ?\n)) - -(defun magit-insert-cherry-commits () - "Insert commit sections into a `magit-cherry-mode' buffer." - (magit-insert-section (cherries) - (magit-insert-heading "Cherry commits:") - (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) - "cherry" "-v" "--abbrev" magit-refresh-args))) - -;;; Reflog Mode - -(defvar magit-reflog-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map magit-log-mode-map) - (define-key map "L" 'magit-toggle-margin) - map) - "Keymap for `magit-reflog-mode'.") - -(define-derived-mode magit-reflog-mode magit-log-mode "Magit Reflog" - "Mode for looking at Git reflog. - -This mode is documented in info node `(magit)Reflog'. - -\\\ -Type \\[magit-refresh] to refresh the current buffer. -Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ -to visit the commit at point. - -Type \\[magit-cherry-pick-popup] to apply the commit at point. -Type \\[magit-reset] to reset HEAD to the commit at point. - -\\{magit-reflog-mode-map}" - :group 'magit-log - (hack-dir-local-variables-non-file-buffer)) - -(defun magit-reflog-refresh-buffer (ref args) - (setq header-line-format - (propertize (concat " Reflog for " ref) 'face 'magit-header-line)) - (magit-insert-section (reflogbuf) - (magit-git-wash (apply-partially 'magit-log-wash-log 'reflog) - "reflog" "show" "--format=%h %gd %gs" "--date=raw" args ref))) - -(defvar magit-reflog-labels - '(("commit" . magit-reflog-commit) - ("amend" . magit-reflog-amend) - ("merge" . magit-reflog-merge) - ("checkout" . magit-reflog-checkout) - ("branch" . magit-reflog-checkout) - ("reset" . magit-reflog-reset) - ("rebase" . magit-reflog-rebase) - ("cherry-pick" . magit-reflog-cherry-pick) - ("initial" . magit-reflog-commit) - ("pull" . magit-reflog-remote) - ("clone" . magit-reflog-remote) - ("autosave" . magit-reflog-commit) - ("restart" . magit-reflog-reset))) - -(defun magit-reflog-format-subject (subject) - (let* ((match (string-match magit-reflog-subject-re subject)) - (command (and match (match-string 1 subject))) - (option (and match (match-string 2 subject))) - (type (and match (match-string 3 subject))) - (label (if (string= command "commit") - (or type command) - command)) - (text (if (string= command "commit") - label - (mapconcat #'identity - (delq nil (list command option type)) - " ")))) - (format "%-16s " - (propertize text 'face - (or (cdr (assoc label magit-reflog-labels)) - 'magit-reflog-other))))) - -;;; Log Sections -;;;; Standard Log Sections - -(defvar magit-unpulled-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-visit-thing] 'magit-diff-unpulled) - map) - "Keymap for the `unpulled' section.") - -(magit-define-section-jumper unpulled "Unpulled commits") - -(defun magit-insert-unpulled-commits () - "Insert section showing unpulled commits." - (-when-let (tracked (magit-get-tracked-ref)) - (magit-insert-section (unpulled) - (magit-insert-heading "Unpulled commits:") - (magit-insert-log (concat "HEAD.." tracked) - magit-log-section-arguments)))) - -(defvar magit-unpushed-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-visit-thing] 'magit-diff-unpushed) - map) - "Keymap for the `unpushed' section.") - -(magit-define-section-jumper unpushed "Unpushed commits") - -(defun magit-insert-unpushed-commits () - "Insert section showing unpushed commits." - (-when-let (tracked (magit-get-tracked-ref)) - (magit-insert-section (unpushed) - (magit-insert-heading "Unpushed commits:") - (magit-insert-log (concat tracked "..HEAD") - magit-log-section-arguments)))) - -;;;; Auxiliary Log Sections - -(defun magit-insert-recent-commits (&optional collapse) - "Insert section showing recent commits. -Show the last `magit-log-section-commit-count' commits." - (magit-insert-section (recent nil collapse) - (magit-insert-heading "Recent commits:") - (magit-insert-log - (let ((beg (format "HEAD~%s" magit-log-section-commit-count))) - (and (magit-rev-verify beg) - (concat beg "..HEAD"))) - (cons (format "-%d" magit-log-section-commit-count) - magit-log-section-arguments)))) - -(defun magit-insert-unpulled-or-recent-commits () - "Insert section showing unpulled or recent commits. -If an upstream is configured for the current branch and it is -ahead of the current branch, then show the missing commits, -otherwise show the last `magit-log-section-commit-count' -commits." - (let ((tracked (magit-get-tracked-ref))) - (if (and tracked (not (equal (magit-rev-parse "HEAD") - (magit-rev-parse tracked)))) - (magit-insert-unpulled-commits) - (magit-insert-recent-commits t)))) - -(defun magit-insert-unpulled-cherries () - "Insert section showing unpulled commits. -Like `magit-insert-unpulled-commits' but prefix each commit -which has not been applied yet (i.e. a commit with a patch-id -not shared with any local commit) with \"+\", and all others -with \"-\"." - (-when-let (tracked (magit-get-tracked-ref)) - (magit-insert-section (unpulled) - (magit-insert-heading "Unpulled commits:") - (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) - "cherry" "-v" (magit-abbrev-arg) (magit-get-current-branch) tracked)))) - -(defun magit-insert-unpushed-cherries () - "Insert section showing unpushed commits. -Like `magit-insert-unpushed-commits' but prefix each commit -which has not been applied to upstream yet (i.e. a commit with -a patch-id not shared with any upstream commit) with \"+\", and -all others with \"-\"." - (-when-let (tracked (magit-get-tracked-ref)) - (magit-insert-section (unpushed) - (magit-insert-heading "Unpushed commits:") - (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) - "cherry" "-v" (magit-abbrev-arg) tracked)))) - -;;;; Submodule Sections - -(defun magit-insert-submodule-commits (section range) - "For internal use, don't add to a hook." - (if (magit-section-hidden section) - (setf (magit-section-washer section) - (apply-partially #'magit-insert-submodule-commits section range)) - (magit-git-wash (apply-partially 'magit-log-wash-log 'module) - "log" "--oneline" range) - (when (> (point) (magit-section-content section)) - (delete-char -1)))) - -(defun magit-insert-unpulled-module-commits () - "Insert sections for all submodules with unpulled commits. -These sections can be expanded to show the respective commits." - (-when-let (modules (magit-get-submodules)) - (magit-insert-section section (unpulled-modules) - (magit-insert-heading "Unpulled modules:") - (magit-with-toplevel - (dolist (module modules) - (let ((default-directory - (expand-file-name (file-name-as-directory module)))) - (-when-let (tracked (magit-get-tracked-ref)) - (magit-insert-section sec (file module t) - (magit-insert-heading - (concat (propertize module 'face 'magit-diff-file-heading) ":")) - (magit-insert-submodule-commits - section (concat "HEAD.." tracked))))))) - (if (> (point) (magit-section-content section)) - (insert ?\n) - (magit-cancel-section))))) - -(defun magit-insert-unpushed-module-commits () - "Insert sections for all submodules with unpushed commits. -These sections can be expanded to show the respective commits." - (-when-let (modules (magit-get-submodules)) - (magit-insert-section section (unpushed-modules) - (magit-insert-heading "Unpushed modules:") - (magit-with-toplevel - (dolist (module modules) - (let ((default-directory - (expand-file-name (file-name-as-directory module)))) - (-when-let (tracked (magit-get-tracked-ref)) - (magit-insert-section sec (file module t) - (magit-insert-heading - (concat (propertize module 'face 'magit-diff-file-heading) ":")) - (magit-insert-submodule-commits - section (concat tracked "..HEAD"))))))) - (if (> (point) (magit-section-content section)) - (insert ?\n) - (magit-cancel-section))))) - -;;; Buffer Margins - -(defvar-local magit-set-buffer-margin-refresh nil) - -(defvar-local magit-show-margin nil) -(put 'magit-show-margin 'permanent-local t) - -(defun magit-toggle-margin () - "Show or hide the Magit margin." - (interactive) - (unless (derived-mode-p 'magit-log-mode 'magit-status-mode 'magit-refs-mode) - (user-error "Buffer doesn't contain any logs")) - (magit-set-buffer-margin (not (cdr (window-margins))))) - -(defun magit-maybe-show-margin () - "Maybe show the margin, depending on the major-mode and an option. -Supported modes are `magit-log-mode' and `magit-reflog-mode', -and the respective options are `magit-log-show-margin' and -`magit-reflog-show-margin'." - (pcase major-mode - (`magit-log-mode (magit-set-buffer-margin magit-log-show-margin)) - (`magit-reflog-mode (magit-set-buffer-margin magit-reflog-show-margin)))) - -(defun magit-set-buffer-margin (enable) - (let ((width (cond ((not enable) nil) - ((derived-mode-p 'magit-reflog-mode) - (+ (cadr magit-log-margin-spec) 5)) - (t (car magit-log-margin-spec))))) - (setq magit-show-margin width) - (when (and enable magit-set-buffer-margin-refresh) - (magit-refresh)) - (-when-let (window (get-buffer-window)) - (with-selected-window window - (set-window-margins nil (car (window-margins)) width) - (if enable - (add-hook 'window-configuration-change-hook - 'magit-set-buffer-margin-1 nil t) - (remove-hook 'window-configuration-change-hook - 'magit-set-buffer-margin-1 t)))))) - -(defun magit-set-buffer-margin-1 () - (-when-let (window (get-buffer-window)) - (with-selected-window window - (set-window-margins nil (car (window-margins)) magit-show-margin)))) - -(defun magit-make-margin-overlay (&rest strings) - ;; Don't put the overlay on the complete line to work around #1880. - (let ((o (make-overlay (1+ (line-beginning-position)) - (line-end-position) - nil t))) - (overlay-put o 'evaporate t) - (overlay-put o 'before-string - (propertize "o" 'display - (list '(margin right-margin) - (apply #'concat strings)))))) - -;;; magit-log.el ends soon -(provide 'magit-log) -;; Local Variables: -;; coding: utf-8 -;; indent-tabs-mode: nil -;; End: -;;; magit-log.el ends here diff --git a/elpa/magit-20151119.202/magit-mode.el b/elpa/magit-20151119.202/magit-mode.el deleted file mode 100644 index 37ccc166..00000000 --- a/elpa/magit-20151119.202/magit-mode.el +++ /dev/null @@ -1,1098 +0,0 @@ -;;; magit-mode.el --- create and refresh Magit buffers - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library implements the abstract major-mode `magit-mode' from -;; which almost all other Magit major-modes derive. The code in here -;; is mostly concerned with creating and refreshing Magit buffers. - -;;; Code: - -(require 'cl-lib) -(require 'dash) - -(require 'magit-section) -(require 'magit-git) - -;; For `magit-xref-insert-buttons' from `magit' -(defvar magit-diff-show-xref-buttons) -(defvar magit-revision-show-xref-buttons) -;; For `magit-revert-buffers' -(declare-function magit-blame-mode 'magit-blame) -(defvar magit-blame-mode) - -(require 'format-spec) -(require 'help-mode) - -;;; Options - -(defcustom magit-mode-hook - '(magit-load-config-extensions - magit-xref-setup) - "Hook run when entering a mode derived from Magit mode." - :group 'magit-modes - :type 'hook - :options '(magit-load-config-extensions - magit-xref-setup - bug-reference-mode)) - -(defcustom magit-mode-setup-hook - '(magit-maybe-save-repository-buffers - magit-maybe-show-margin) - "Hook run by `magit-mode-setup'." - :package-version '(magit . "2.3.0") - :group 'magit-modes - :type 'hook - :options '(magit-maybe-save-repository-buffers - magit-maybe-show-margin)) - -(defcustom magit-display-buffer-function 'magit-display-buffer-traditional - "The function used display a Magit buffer. - -All Magit buffers (buffers whose major-modes derive from -`magit-mode') are displayed using `magit-display-buffer', -which in turn uses the function specified here." - :package-version '(magit . "2.3.0") - :group 'magit-modes - :type '(radio (function-item magit-display-buffer-traditional) - (function-item display-buffer) - (function :tag "Function"))) - -(unless (find-lisp-object-file-name 'magit-pre-display-buffer-hook 'defvar) - (add-hook 'magit-pre-display-buffer-hook 'magit-save-window-configuration)) -(defcustom magit-pre-display-buffer-hook '(magit-save-window-configuration) - "Hook run by `magit-display-buffer' before displaying the buffer." - :package-version '(magit . "2.3.0") - :group 'magit-modes - :type 'hook - :options '(magit-save-window-configuration)) - -(unless (find-lisp-object-file-name 'magit-post-display-buffer-hook 'defvar) - (add-hook 'magit-post-display-buffer-hook 'magit-maybe-set-dedicated)) -(defcustom magit-post-display-buffer-hook '(magit-maybe-set-dedicated) - "Hook run by `magit-display-buffer' after displaying the buffer." - :package-version '(magit . "2.3.0") - :group 'magit-modes - :type 'hook - :options '(magit-maybe-set-dedicated)) - -(defcustom magit-generate-buffer-name-function - 'magit-generate-buffer-name-default-function - "The function used to generate the name for a Magit buffer." - :package-version '(magit . "2.3.0") - :group 'magit-modes - :type '(radio (function-item magit-generate-buffer-name-default-function) - (function :tag "Function"))) - -(defcustom magit-buffer-name-format "*%M%v: %t" - "The format string used to name Magit buffers. - -The following %-sequences are supported: - -`%m' The name of the major-mode, but with the `-mode' suffix - removed. - -`%M' Like \"%m\" but abbreviate `magit-status-mode' as `magit'. - -`%v' The value the buffer is locked to, in parentheses, or an empty - string if the buffer is not locked to a value. - -`%V' Like \"%v\", but the string is prefixed with a space, unless it - is an empty string. - -`%t' The top-level directory of the working tree of the - repository, or if `magit-uniquify-buffer-names' is non-nil - an abbreviation of that. - -The value should always contain either \"%m\" or \"%M\" as well as -\"%t\". If `magit-uniquify-buffer-names' is non-nil, then the -value must end with \"%t\". - -This is used by `magit-generate-buffer-name-default-function'. -If another `magit-generate-buffer-name-function' is used, then -it may not respect this option, or on the contrary it may -support additional %-sequences." - :package-version '(magit . "2.3.0") - :group 'magit-modes - :type 'string) - -(defcustom magit-uniquify-buffer-names t - "Whether to uniquify the names of Magit buffers." - :package-version '(magit . "2.3.0") - :group 'magit-modes - :type 'boolean) - -(defcustom magit-bury-buffer-function 'magit-restore-window-configuration - "The function used to bury or kill the current Magit buffer." - :package-version '(magit . "2.3.0") - :group 'magit-modes - :type '(radio (function-item quit-window) - (function-item magit-mode-quit-window) - (function-item magit-restore-window-configuration) - (function :tag "Function"))) - -(defcustom magit-region-highlight-hook - '(magit-section-update-region magit-diff-update-hunk-region) - "Functions used to highlight the region. -Each function is run with the current section as only argument -until one of them returns non-nil. When multiple sections are -selected, then this hook does not run and the region is not -displayed. Otherwise fall back to regular region highlighting." - :package-version '(magit . "2.1.0") - :group 'magit-modes - :type 'hook - :options '(magit-section-update-region magit-diff-update-hunk-region)) - -(defcustom magit-refresh-verbose nil - "Whether to revert Magit buffers verbosely." - :package-version '(magit . "2.1.0") - :group 'magit-modes - :type 'boolean) - -(defcustom magit-refresh-buffer-hook nil - "Normal hook for `magit-refresh-buffer' to run after refreshing." - :package-version '(magit . "2.1.0") - :group 'magit-modes - :type 'hook) - -(defvar magit-revert-buffers-timer nil) - -(defun magit-revert-buffers-set-timer () - (when (timerp magit-revert-buffers-timer) - (cancel-timer magit-revert-buffers-timer)) - (setq magit-revert-buffers-timer - (and (boundp 'magit-revert-buffers) - (numberp magit-revert-buffers) - (run-with-timer 0 magit-revert-buffers - 'magit-revert-buffers-async)))) - -(defcustom magit-revert-buffers 'usage - "How file-visiting buffers in the current repository are reverted. - -After running certain commands, after refreshing the current -Magit buffer, unmodified buffers visiting files belonging to -the current repository may optionally be reverted. - -`nil' Don't revert any buffers. - -`ask' List the buffers which might potentially have to be - reverted and ask the user whether she wants to revert - them. If so, then do it synchronously. - -`t' Revert the buffers synchronously, mentioning each one - as it is being reverted and then also show a summary. - -`usage' Like `t' but include usage information in the summary. - This is the default so that users come here and pick - what is right for them. - -`silent' Revert the buffers synchronously and be quiet about it. - This is the recommended setting, because for the other - values the revert messages might prevent you from - seeing other, more important, messages in the echo - area. - -NUMBER An integer or float. Revert the buffers asynchronously, - mentioning each one as it is being reverted. If user - input arrives, then stop reverting. After NUMBER - seconds resume reverting." - :package-version '(magit . "2.1.0") - :group 'magit - :type '(choice - (const :tag "Don't revert" nil) - (const :tag "Ask whether to revert" ask) - (const :tag "Revert synchronously" t) - (const :tag "Revert synchronously but in silence" silent) - (const :tag "Revert synchronously with usage information" usage) - (integer :tag "Revert asynchronously (interval in seconds)")) - :set (lambda (var val) - (set-default var val) - (magit-revert-buffers-set-timer))) - -(defcustom magit-after-revert-hook '(magit-refresh-vc-mode-line) - "Normal hook for `magit-revert-buffer' to run after reverting. - -This hook is only run for buffers that were actually reverted. -For other buffers `magit-not-reverted-hook' is run instead." - :package-version '(magit . "2.1.0") - :group 'magit-modes - :type 'hook - :options '(magit-refresh-vc-mode-line)) - -(defcustom magit-not-reverted-hook '(magit-refresh-vc-mode-line) - "Normal hook for `magit-revert-buffer' to run instead of reverting. - -This hook is only run for buffers which might have been reverted -but were not actually reverted, because that was not necessary. -For other buffers `magit-after-revert-hook' is run instead." - :package-version '(magit . "2.1.0") - :group 'magit-modes - :type 'hook - :options '(magit-refresh-vc-mode-line)) - -(defcustom magit-save-repository-buffers t - "Whether to save file-visiting buffers when appropriate. - -If this is non-nil then all modified file-visiting buffers -belonging to the current repository may be saved before running -commands, before creating new Magit buffers, and before -explicitly refreshing such buffers. If this is `dontask' then -this is done without user intervention, if it is t then the user -has to confirm each save. `dontask' is the recommended setting." - :group 'magit - :type '(choice (const :tag "Never" nil) - (const :tag "Ask" t) - (const :tag "Save without asking" dontask))) - -(defcustom magit-keep-region-overlay nil - "Whether to keep the region overlay when there is a valid selection. - -By default Magit removes the regular region overlay if, and only -if, that region constitutes a valid selection as understood by -Magit commands. Otherwise it does not remove that overlay, and -the region looks like it would in other buffers. - -There are two types of such valid selections: hunk-internal -regions and regions that select two or more sibling sections. -In such cases Magit removes the region overlay and instead -highlights a slightly larger range. All text (for hunk-internal -regions) or the headings of all sections (for sibling selections) -that are inside that range (not just inside the region) are acted -on by commands such as the staging command. This buffer range -begins at the beginning of the line on which the region begins -and ends at the end of the line on which the region ends. - -Because Magit acts on this larger range and not the region, it is -actually quite important to visualize that larger range. If we -don't do that, then one might think that these commands act on -the region instead. If you want to *also* visualize the region, -then set this option to t. But please note that when the region -does *not* constitute a valid selection, then the region is -*always* visualized as usual, and that it is usually under such -circumstances that you want to use a non-magit command to act on -the region. - -Besides keeping the region overlay, setting this option to t also -causes all face properties, except for `:foreground', to be -ignored for the faces used to highlight headings of selected -sections. This avoids the worst conflicts that result from -displaying the region and the selection overlays at the same -time. We are not interested in dealing with other conflicts. -In fact we *already* provide a way to avoid all of these -conflicts: *not* changing the value of this option. - -It should be clear by now that we consider it a mistake to set -this to display the region when the Magit selection is also -visualized, but since it has been requested a few times and -because it doesn't cost much to offer this option we do so. -However that might change. If the existance of this option -starts complicating other things, then it will be removed." - :package-version '(magit . "2.3.0") - :group 'magit-modes - :type 'boolean) - -;;; Magit Mode - -(defvar magit-mode-map - (let ((map (make-keymap))) - (suppress-keymap map t) - (define-key map "\t" 'magit-section-toggle) - (define-key map [C-tab] 'magit-section-cycle) - (define-key map [M-tab] 'magit-section-cycle-diffs) - (define-key map [s-tab] 'magit-section-cycle-global) - (define-key map "^" 'magit-section-up) - (define-key map "n" 'magit-section-forward) - (define-key map "p" 'magit-section-backward) - (define-key map "\M-n" 'magit-section-forward-sibling) - (define-key map "\M-p" 'magit-section-backward-sibling) - (define-key map "+" 'magit-diff-more-context) - (define-key map "-" 'magit-diff-less-context) - (define-key map "0" 'magit-diff-default-context) - (define-key map "1" 'magit-section-show-level-1) - (define-key map "2" 'magit-section-show-level-2) - (define-key map "3" 'magit-section-show-level-3) - (define-key map "4" 'magit-section-show-level-4) - (define-key map "\M-1" 'magit-section-show-level-1-all) - (define-key map "\M-2" 'magit-section-show-level-2-all) - (define-key map "\M-3" 'magit-section-show-level-3-all) - (define-key map "\M-4" 'magit-section-show-level-4-all) - (define-key map "g" 'magit-refresh) - (define-key map "G" 'magit-refresh-all) - (define-key map "q" 'magit-mode-bury-buffer) - (define-key map "$" 'magit-process-buffer) - (define-key map "a" 'magit-cherry-apply) - (define-key map "A" 'magit-cherry-pick-popup) - (define-key map "b" 'magit-branch-popup) - (define-key map "B" 'magit-bisect-popup) - (define-key map "c" 'magit-commit-popup) - (define-key map "d" 'magit-diff-popup) - (define-key map "D" 'magit-diff-refresh-popup) - (define-key map "h" 'magit-dispatch-popup) - (define-key map "?" 'magit-dispatch-popup) - (define-key map "\C-c\C-c" 'magit-dispatch-popup) - (define-key map "\C-c\C-e" 'magit-dispatch-popup) - (define-key map "e" 'magit-ediff-dwim) - (define-key map "E" 'magit-ediff-popup) - (define-key map "f" 'magit-fetch-popup) - (define-key map "F" 'magit-pull-popup) - (define-key map "i" 'magit-gitignore) - (define-key map "I" 'magit-gitignore-locally) - (define-key map "k" 'magit-delete-thing) - (define-key map "K" 'magit-file-untrack) - (define-key map "l" 'magit-log-popup) - (define-key map "L" 'magit-log-refresh-popup) - (define-key map "m" 'magit-merge-popup) - (define-key map "M" 'magit-remote-popup) - (define-key map "o" 'magit-submodule-popup) - (define-key map "P" 'magit-push-popup) - (define-key map "r" 'magit-rebase-popup) - (define-key map "R" 'magit-file-rename) - (define-key map "t" 'magit-tag-popup) - (define-key map "T" 'magit-notes-popup) - (define-key map "\r" 'magit-visit-thing) - (define-key map [C-return] 'magit-visit-thing) - (define-key map [M-return] 'magit-dired-jump) - (define-key map "\s" 'magit-diff-show-or-scroll-up) - (define-key map "\d" 'magit-diff-show-or-scroll-down) - (define-key map "s" 'magit-stage-file) - (define-key map "S" 'magit-stage-modified) - (define-key map "u" 'magit-unstage-file) - (define-key map "U" 'magit-unstage-all) - (define-key map "v" 'magit-revert-no-commit) - (define-key map "V" 'magit-revert-popup) - (define-key map "w" 'magit-am-popup) - (define-key map "W" 'magit-patch-popup) - (define-key map "x" 'magit-reset) - (define-key map "y" 'magit-show-refs-popup) - (define-key map "Y" 'magit-cherry) - (define-key map "z" 'magit-stash-popup) - (define-key map "Z" 'magit-stash-popup) - (define-key map ":" 'magit-git-command) - (define-key map "!" 'magit-run-popup) - (define-key map "\C-xa" 'magit-add-change-log-entry) - (define-key map "\C-x4a" 'magit-add-change-log-entry-other-window) - (define-key map "\C-w" 'magit-copy-section-value) - (define-key map "\M-w" 'magit-copy-buffer-revision) - (define-key map [remap evil-previous-line] 'evil-previous-visual-line) - (define-key map [remap evil-next-line] 'evil-next-visual-line) - map) - "Parent keymap for all keymaps of modes derived from `magit-mode'.") - -(defun magit-delete-thing () - "This is a placeholder command. -Where applicable, section-specific keymaps bind another command -which deletes the thing at point." - (interactive) - (user-error "There is no thing at point that could be deleted")) - -(defun magit-visit-thing () - "This is a placeholder command. -Where applicable, section-specific keymaps bind another command -which visits the thing at point." - (interactive) - (user-error "There is no thing at point that could be visited")) - -(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 t] - ["Stage modified" magit-stage-modified t] - ["Unstage" magit-unstage t] - ["Reset index" magit-reset-index t] - ["Commit" magit-commit-popup t] - ["Add log entry" magit-commit-add-log t] - ["Tag" magit-tag t] - "---" - ["Diff working tree" magit-diff-working-tree t] - ["Diff" magit-diff t] - ("Log" - ["Log" magit-log t] - ["Reflog" magit-reflog t] - ["Extended..." magit-log-popup t]) - "---" - ["Cherry pick" magit-cherry-pick t] - ["Revert commit" magit-revert-popup t] - "---" - ["Ignore" magit-gitignore t] - ["Ignore locally" magit-gitignore-locally t] - ["Discard" magit-discard t] - ["Reset head" magit-reset-head t] - ["Stash" magit-stash t] - ["Snapshot" magit-snapshot t] - "---" - ["Branch..." magit-checkout t] - ["Merge" magit-merge t] - ["Ediff resolve" magit-ediff-resolve t] - ["Rebase..." magit-rebase-popup t] - "---" - ["Push" magit-push t] - ["Pull" magit-pull t] - ["Remote update" magit-fetch-all t] - ("Submodule" - ["Submodule update" magit-submodule-update t] - ["Submodule update and init" magit-submodule-setup t] - ["Submodule init" magit-submodule-init t] - ["Submodule sync" magit-submodule-sync t]) - "---" - ("Extensions") - "---" - ["Display Git output" magit-process-buffer t] - ["Quit Magit" magit-mode-bury-buffer t])) - -(defun magit-load-config-extensions () - "Load Magit extensions that are defined at the Git config layer." - (dolist (ext (magit-get-all "magit.extension")) - (let ((sym (intern (format "magit-%s-mode" ext)))) - (when (fboundp sym) - (funcall sym 1))))) - -(define-derived-mode magit-mode special-mode "Magit" - "Parent major mode from which Magit major modes inherit. - -Magit is documented in info node `(magit)'." - :group 'magit-modes - (buffer-disable-undo) - (setq truncate-lines t) - (setq buffer-read-only t) - (setq-local line-move-visual t) ; see #1771 - (setq show-trailing-whitespace nil) - (setq list-buffers-directory default-directory) - (hack-dir-local-variables-non-file-buffer) - (make-local-variable 'text-property-default-nonsticky) - (push (cons 'keymap t) text-property-default-nonsticky) - (add-hook 'post-command-hook #'magit-section-update-highlight t t) - (setq-local redisplay-highlight-region-function 'magit-highlight-region) - (setq-local redisplay-unhighlight-region-function 'magit-unhighlight-region) - (when (fboundp 'linum-mode) - (linum-mode -1))) - -(defvar-local magit-region-overlays nil) - -(defun magit-highlight-region (start end window rol) - (mapc #'delete-overlay magit-region-overlays) - (if (and (run-hook-with-args-until-success 'magit-region-highlight-hook - (magit-current-section)) - (not magit-keep-region-overlay)) - (funcall (default-value 'redisplay-unhighlight-region-function) rol) - (funcall (default-value 'redisplay-highlight-region-function) - start end window rol))) - -(defun magit-unhighlight-region (rol) - (setq magit-section-highlighted-section nil) - (mapc #'delete-overlay magit-region-overlays) - (funcall (default-value 'redisplay-unhighlight-region-function) rol)) - -(defvar-local magit-refresh-args nil - "The arguments used to refresh the current buffer.") -(put 'magit-refresh-args 'permanent-local t) - -(defvar-local magit-previous-section nil) -(put 'magit-previous-section 'permanent-local t) - -(defun magit-mode-setup (mode &rest args) - "Setup up a MODE buffer using ARGS to generate its content." - (let ((buffer (magit-mode-get-buffer mode t)) - (section (magit-current-section))) - (with-current-buffer buffer - (setq magit-previous-section section) - (setq magit-refresh-args args) - (funcall mode)) - (magit-display-buffer buffer) - (with-current-buffer buffer - (run-hooks 'magit-mode-setup-hook) - (magit-refresh-buffer)))) - -(defvar magit-display-buffer-noselect nil - "If non-nil, then `magit-display-buffer' doesn't call `select-window'.") - -(defun magit-display-buffer (buffer) - "Display BUFFER in some window and maybe select it. - -Display the buffer using `magit-display-buffer-function' and -then, unless `magit-display-buffer-noselect' is non-nil, select -the window which was used to display the buffer. - -Also run the hooks `magit-pre-display-buffer-hook' -and `magit-post-display-buffer-hook'." - (with-current-buffer buffer - (run-hooks 'magit-pre-display-buffer-hook)) - (let ((window (funcall magit-display-buffer-function buffer))) - (unless magit-display-buffer-noselect - (select-window window))) - (with-current-buffer buffer - (run-hooks 'magit-post-display-buffer-hook))) - -(defun magit-display-buffer-traditional (buffer) - "Display BUFFER the way this has traditionally been done." - (display-buffer - buffer (if (and (derived-mode-p 'magit-mode) - (not (memq (with-current-buffer buffer major-mode) - '(magit-process-mode - magit-revision-mode - magit-diff-mode - magit-stash-mode - magit-status-mode)))) - '(display-buffer-same-window) - nil))) ; display in another window - -(defun magit-maybe-set-dedicated () - "Mark the selected window as dedicated if appropriate. - -If a new window was created to display the buffer, then remember -that fact. That information is used by `magit-mode-quit-window', -to determine whether the window should be deleted when its last -Magit buffer is buried." - (let ((window (get-buffer-window (current-buffer)))) - (when (and (window-live-p window) - (not (window-prev-buffers window))) - (set-window-parameter window 'magit-dedicated t)))) - -(defvar-local magit--default-directory nil - "Value of `default-directory' when buffer is generated. -This exists to prevent a let-bound `default-directory' from -tricking `magit-mode-get-buffer' or `magit-mode-get-buffers' into -thinking a buffer belongs to a repo that it doesn't.") -(put 'magit--default-directory 'permanent-local t) - -(defun magit-mode-get-buffers () - (let ((topdir (magit-toplevel))) - (--filter (with-current-buffer it - (and (derived-mode-p 'magit-mode) - (equal magit--default-directory topdir))) - (buffer-list)))) - -(defvar-local magit-buffer-locked-p nil) -(put 'magit-buffer-locked-p 'permanent-local t) - -(defun magit-mode-get-buffer (mode &optional create frame) - (-if-let (topdir (magit-toplevel)) - (or (--first (with-current-buffer it - (and (eq major-mode mode) - (equal magit--default-directory topdir) - (not magit-buffer-locked-p))) - (if frame - (-map #'window-buffer - (window-list (unless (eq frame t) frame))) - (buffer-list))) - (and create - (let ((default-directory topdir)) - (magit-generate-new-buffer mode)))) - (user-error "Not inside a Git repository"))) - -(defun magit-generate-new-buffer (mode) - (let* ((name (funcall magit-generate-buffer-name-function mode)) - (buffer (generate-new-buffer name))) - (with-current-buffer buffer - (setq magit--default-directory default-directory)) - (when magit-uniquify-buffer-names - (add-to-list 'uniquify-list-buffers-directory-modes mode) - (with-current-buffer buffer - (setq list-buffers-directory default-directory)) - (let ((uniquify-buffer-name-style - (if (eq uniquify-buffer-name-style 'forward) - 'post-forward-angle-brackets - uniquify-buffer-name-style))) - (uniquify-rationalize-file-buffer-names - name (file-name-directory (directory-file-name default-directory)) - buffer))) - buffer)) - -(defun magit-generate-buffer-name-default-function (mode &optional value) - (let ((m (substring (symbol-name mode) 0 -5)) - (v (and value (format "%s" (if (listp value) value (list value)))))) - (format-spec - magit-buffer-name-format - `((?m . ,m) - (?M . ,(if (eq mode 'magit-status-mode) "magit" m)) - (?v . ,(or v "")) - (?V . ,(if v (concat " " v) "")) - (?t . ,(if magit-uniquify-buffer-names - (file-name-nondirectory - (directory-file-name default-directory)) - default-directory)))))) - -(defun magit-toggle-buffer-lock () - "Lock the current buffer to its value or unlock it. - -Locking a buffer to its value, prevents it from being reused to -display another value. The name of a locked buffer contains its -value, which allows telling it apart from other locked buffers -and the unlocked buffer. - -Not all Magit buffers can be locked to their values, for example -it wouldn't make sense to lock a status buffer. - -There can only be a single unlocked buffer using a certain -major-mode per repository. So when a buffer is being unlocked -and another unlocked buffer already exists for that mode and -repository, then the former buffer is instead deleted and the -latter is displayed in its place." - (interactive) - (if magit-buffer-locked-p - (-if-let (unlocked (magit-mode-get-buffer major-mode)) - (let ((locked (current-buffer))) - (set-buffer unlocked) - (kill-buffer locked)) - (setq magit-buffer-locked-p nil) - (rename-buffer (funcall magit-generate-buffer-name-function - major-mode))) - (setq magit-buffer-locked-p - (cond ((memq major-mode '(magit-cherry-mode - magit-log-mode - magit-reflog-mode - magit-refs-mode - magit-revision-mode - magit-stash-mode - magit-stashes-mode)) - (car magit-refresh-args)) - ((eq major-mode 'magit-diff-mode) - (let ((rev (nth 0 magit-refresh-args)) - (args (nth 1 magit-refresh-args))) - (cond - ((member "--no-index" args) - (nth 3 magit-refresh-args)) - (rev (if args (cons rev args) rev)) - (t (if (member "--cached" args) "staged" "unstaged"))))))) - (if magit-buffer-locked-p - (rename-buffer (funcall magit-generate-buffer-name-function - major-mode magit-buffer-locked-p)) - (user-error "Buffer has no value it could be locked to")))) - -(defun magit-mode-bury-buffer (&optional kill-buffer) - "Bury the current buffer. -With a prefix argument, kill the buffer instead. -This is done using `magit-bury-buffer-function'." - (interactive "P") - (funcall magit-bury-buffer-function kill-buffer)) - -(defun magit-mode-quit-window (kill-buffer) - "Quit the selected window and bury its buffer. - -This behaves similar to `quit-window', but when the window -was originally created to display a Magit buffer and the -current buffer is the last remaining Magit buffer that was -ever displayed in the selected window, then delete that -window." - (if (or (one-window-p) - (--first (let ((buffer (car it))) - (and (not (eq buffer (current-buffer))) - (buffer-live-p buffer) - (or (not (window-parameter nil 'magit-dedicated)) - (with-current-buffer buffer - (derived-mode-p 'magit-mode - 'magit-process-mode))))) - (window-prev-buffers))) - (quit-window kill-buffer) - (let ((window (selected-window))) - (quit-window kill-buffer) - (when (window-live-p window) - (delete-window window))))) - -;;; Refresh Machinery - -(defvar inhibit-magit-refresh nil) - -(defvar magit-pre-refresh-hook nil) - -(defun magit-refresh () - "Refresh some buffers belonging to the current repository. - -Refresh the current buffer if its major mode derives from -`magit-mode', and refresh the corresponding status buffer. - -If option `magit-revert-buffers' call for it, then also revert -all unmodified buffers that visit files being tracked in the -current repository." - (interactive) - (unless inhibit-magit-refresh - (run-hooks 'magit-pre-refresh-hook) - (unless (when (derived-mode-p 'magit-mode) - (magit-refresh-buffer) - (derived-mode-p 'magit-status-mode)) - (--when-let (magit-mode-get-buffer 'magit-status-mode) - (with-current-buffer it - (magit-refresh-buffer)))) - (magit-revert-buffers))) - -(defun magit-refresh-all () - "Refresh all buffers belonging to the current repository. - -Refresh all Magit buffers belonging to the current repository. - -Also always revert all unmodified buffers that visit files being -tracked in the current repository." - (interactive) - (dolist (buffer (magit-mode-get-buffers)) - (with-current-buffer buffer (magit-refresh-buffer))) - (magit-revert-buffers t)) - -(defvar-local magit-refresh-start-time nil) - -(defun magit-refresh-buffer () - "Refresh the current Magit buffer." - (setq magit-refresh-start-time (current-time)) - (let ((refresh (intern (format "%s-refresh-buffer" - (substring (symbol-name major-mode) 0 -5))))) - (when (functionp refresh) - (when magit-refresh-verbose - (message "Refreshing buffer `%s'..." (buffer-name))) - (let* ((buffer (current-buffer)) - (windows - (--mapcat (with-selected-window it - (with-current-buffer buffer - (-when-let (section (magit-current-section)) - (list - (nconc (list it section) - (magit-refresh-get-relative-position)))))) - (or (get-buffer-window-list buffer nil t) - (list (selected-window)))))) - (deactivate-mark) - (setq magit-section-highlight-overlays nil - magit-section-highlighted-section nil - magit-section-highlighted-sections nil - magit-section-unhighlight-sections nil) - (let ((inhibit-read-only t)) - (erase-buffer) - (save-excursion - (apply refresh magit-refresh-args))) - (dolist (window windows) - (with-selected-window (car window) - (with-current-buffer buffer - (apply #'magit-section-goto-successor (cdr window))))) - (run-hooks 'magit-refresh-buffer-hook) - (magit-section-update-highlight) - (set-buffer-modified-p nil)) - (when magit-refresh-verbose - (message "Refreshing buffer `%s'...done (%.3fs)" (buffer-name) - (float-time (time-subtract (current-time) - magit-refresh-start-time))))))) - -(defun magit-refresh-get-relative-position () - (-when-let (section (magit-current-section)) - (let ((start (magit-section-start section))) - (list (count-lines start (point)) - (- (point) (line-beginning-position)) - (and (eq (magit-section-type section) 'hunk) - (region-active-p) - (progn (goto-char (line-beginning-position)) - (when (looking-at "^[-+]") (forward-line)) - (while (looking-at "^[ @]") (forward-line)) - (let ((beg (point))) - (cond ((looking-at "^[-+]") - (forward-line) - (while (looking-at "^[-+]") (forward-line)) - (while (looking-at "^ ") (forward-line)) - (forward-line -1) - (regexp-quote (buffer-substring-no-properties - beg (line-end-position)))) - (t t))))))))) - - -(defvar inhibit-magit-revert nil) -(defvar magit-revert-buffers-backlog nil) - -(defun magit-revert-buffers (&optional force) - "Revert unmodified file-visiting buffers of the current repository. - -If either `magit-revert-buffers' is non-nil and `inhibit-magit-revert' -is nil, or if optional FORCE is non-nil; then revert all unmodified -buffers that visit files being tracked in the current repository. - -When called interactively then the revert is forced." - (interactive (list t)) - (when (or force (and magit-revert-buffers (not inhibit-magit-revert))) - (-when-let (topdir (magit-toplevel)) - (let* ((tracked (magit-revision-files "HEAD")) - (buffers - (if (> (length tracked) - (length (buffer-list))) - (--filter - (let ((file (buffer-file-name it))) - (and file - (equal (file-remote-p file) - (file-remote-p topdir)) - (file-in-directory-p file topdir) - (member (file-relative-name file topdir) tracked))) - (buffer-list)) - (--mapcat - (--when-let (find-buffer-visiting (expand-file-name it topdir)) - (list it)) - tracked)))) - (when (and buffers - (or force - (not (eq magit-revert-buffers 'ask)) - (magit-confirm 'revert-buffer - "Revert %s from visited file" - "Revert %i buffers from visited files" - (mapcar #'buffer-name buffers)))) - (cond - ((numberp magit-revert-buffers) - (magit-revert-buffers-async buffers)) - ((eq magit-revert-buffers 'silent) - (mapc #'magit-revert-buffer buffers)) - (t - (let ((cnt (length buffers))) - (when (> cnt 0) - (message "Reverting (up to) %s file-visiting buffer(s)..." cnt) - (setq cnt (length (-non-nil (mapcar #'magit-revert-buffer - buffers)))) - (if (> cnt 0) - (pcase magit-revert-buffers - (`t - (message "Reverting %s file-visiting buffer(s)...done" cnt)) - (`usage - (message - "Reverting %s file-visiting buffer(s)...done%s%s%s" cnt - (substitute-command-keys - "\n This can be undone using `\\[undo]' in the ") - "affected buffers\n Customize behavior using `M-x " - "customize-option RET magit-revert-buffers RET'")) - ((or `nil `ask) - (message "Reverting %s file-visiting buffer(s)...done%s" - cnt (if force " (forced)" "")))) - (message "(No buffers need to be reverted)"))))))))))) - -(defun magit-revert-buffers-async (&optional buffers) - (setq buffers (nconc buffers (--filter (not (memq it buffers)) - magit-revert-buffers-backlog))) - (while (and buffers (not (input-pending-p))) - (let ((buf (pop buffers))) - (when (buffer-live-p buf) - (with-current-buffer buf - (magit-revert-buffer buf))))) - (setq magit-revert-buffers-backlog buffers)) - -(defun magit-revert-buffer (&optional buffer) - "Revert the current file-visiting buffer." - (let (ret) - (with-current-buffer (or buffer (current-buffer)) - (if (and (file-readable-p buffer-file-name) - (not (verify-visited-file-modtime (current-buffer)))) - (if magit-blame-mode - (progn (message "Reverting %s inhibited due to magit-blame-mode" - buffer-file-name) - (run-hooks 'magit-not-reverted-hook)) - (if (eq magit-revert-buffers 'silent) - (revert-buffer 'ignore-auto t t) - (message "Reverting buffer `%s'..." (buffer-name)) - (revert-buffer 'ignore-auto t t) - (message "Reverting buffer `%s'...done" (buffer-name))) - (run-hooks 'magit-after-revert-hook) - (setq ret t)) - (run-hooks 'magit-not-reverted-hook))) - ret)) - -(add-hook 'git-commit-setup-hook #'magit-revert-buffers) - -(defun magit-refresh-vc-mode-line () - "Update `vc-mode' which is displayed in the mode-line. -Like `vc-mode-line' but simpler, more efficient, and less buggy." - (setq vc-mode - (if vc-display-status - (magit-with-toplevel - (let* ((rev (or (magit-get-current-branch) - (magit-rev-parse "--short" "HEAD"))) - (msg (cl-letf (((symbol-function #'vc-working-revision) - (lambda (&rest _) rev))) - (vc-default-mode-line-string - 'Git buffer-file-name)))) - (propertize - (concat " " msg) - 'mouse-face 'mode-line-highlight - 'help-echo (concat (get-text-property 0 'help-echo msg) - "\nCurrent revision: " rev - "\nmouse-1: Version Control menu") - 'local-map vc-mode-line-map))) - " Git")) - (force-mode-line-update)) - -(defvar disable-magit-save-buffers nil) - -(defun magit-pre-command-hook () - (setq disable-magit-save-buffers nil)) -(add-hook 'pre-command-hook #'magit-pre-command-hook) - -(defvar magit-after-save-refresh-buffers nil) - -(defun magit-after-save-refresh-buffers () - (dolist (buffer magit-after-save-refresh-buffers) - (with-current-buffer buffer - (magit-refresh-buffer))) - (setq magit-after-save-refresh-buffers nil) - (remove-hook 'post-command-hook 'magit-after-save-refresh-buffers)) - -(defun magit-after-save-refresh-status () - "Refresh the status buffer of the current repository. - -This function is intended to be added to `after-save-hook'. - -If the status buffer does not exist or the file being visited in -the current buffer isn't inside a repository, then do nothing. - -Note that refreshing a Magit buffer is done by re-creating its -contents from scratch, which can be slow in large repositories. -If you are not satisfied with Magit's performance, then you -should obviously not add this function to that hook." - (unless disable-magit-save-buffers - (--when-let (ignore-errors (magit-mode-get-buffer 'magit-status-mode)) - (add-to-list 'magit-after-save-refresh-buffers it) - (add-hook 'post-command-hook 'magit-after-save-refresh-buffers)))) - -(defun magit-maybe-save-repository-buffers () - "Maybe save file-visiting buffers belonging to the current repository. -Do so if `magit-save-repository-buffers' is non-nil." - (when (and magit-save-repository-buffers - (not disable-magit-save-buffers)) - (setq disable-magit-save-buffers t) - (let ((msg (current-message))) - (magit-save-repository-buffers - (eq magit-save-repository-buffers 'dontask)) - (when (and msg (not (equal msg (current-message)))) - (message "%s" msg))))) - -(add-hook 'magit-pre-refresh-hook #'magit-maybe-save-repository-buffers) -(add-hook 'magit-pre-call-git-hook #'magit-maybe-save-repository-buffers) -(add-hook 'magit-pre-start-git-hook #'magit-maybe-save-repository-buffers) - -(defun magit-save-repository-buffers (&optional arg) - "Save file-visiting buffers belonging to the current repository. -After any buffer where `buffer-save-without-query' is non-nil -is saved without asking, the user is asked about each modified -buffer which visits a file in the current repository. Optional -argument (the prefix) non-nil means save all with no questions." - (interactive "P") - (-when-let (topdir (magit-rev-parse-safe "--show-toplevel")) - (save-some-buffers - arg (-partial (lambda (topdir) - (and buffer-file-name - ;; Avoid needlessly connecting to unrelated remotes. - (string-prefix-p topdir buffer-file-name) - (equal (magit-rev-parse-safe "--show-toplevel") - topdir))) - topdir)))) - -;;; Restore Window Configuration - -(defvar magit-inhibit-save-previous-winconf nil) - -(defvar-local magit-previous-window-configuration nil) -(put 'magit-previous-window-configuration 'permanent-local t) - -(defun magit-save-window-configuration () - "Save the current window configuration. - -Later, when the buffer is buried, it may be restored by -`magit-restore-window-configuration'." - (if magit-inhibit-save-previous-winconf - (when (eq magit-inhibit-save-previous-winconf 'unset) - (setq magit-previous-window-configuration nil)) - (unless (get-buffer-window (current-buffer) (selected-frame)) - (setq magit-previous-window-configuration - (current-window-configuration))))) - -(defun magit-restore-window-configuration (&optional kill-buffer) - "Bury or kill the current buffer and restore previous window configuration." - (let ((winconf magit-previous-window-configuration) - (buffer (current-buffer)) - (frame (selected-frame))) - (quit-window kill-buffer (selected-window)) - (when (and winconf (equal frame (window-configuration-frame winconf))) - (set-window-configuration winconf) - (when (buffer-live-p buffer) - (with-current-buffer buffer - (setq magit-previous-window-configuration nil)))))) - -;;; Buffer History - -(defun magit-go-backward () - "Move backward in current buffer's history." - (interactive) - (if help-xref-stack - (help-xref-go-back (current-buffer)) - (user-error "No previous entry in buffer's history"))) - -(defun magit-go-forward () - "Move forward in current buffer's history." - (interactive) - (if help-xref-forward-stack - (help-xref-go-forward (current-buffer)) - (user-error "No next entry in buffer's history"))) - -(defun magit-insert-xref-buttons (&optional _) - "Insert xref buttons." - (when (or help-xref-stack help-xref-forward-stack) - (when help-xref-stack - (magit-xref-insert-button help-back-label 'magit-xref-backward)) - (when help-xref-forward-stack - (when help-xref-stack - (insert " ")) - (magit-xref-insert-button help-forward-label 'magit-xref-forward)))) - -(defun magit-xref-insert-button (label type) - (magit-insert-section (button label) - (insert-text-button label 'type type - 'help-args (list (current-buffer))))) - -(define-button-type 'magit-xref-backward - :supertype 'help-back - 'mouse-face 'magit-section-highlight - 'help-echo (purecopy "mouse-2, RET: go back to previous history entry")) - -(define-button-type 'magit-xref-forward - :supertype 'help-forward - 'mouse-face 'magit-section-highlight - 'help-echo (purecopy "mouse-2, RET: go back to next history entry")) - -(defun magit-xref-setup () - "Insert backward/forward buttons if the major-mode supports it. -Currently `magit-log-mode', `magit-reflog-mode', -`magit-diff-mode', and `magit-revision-mode' support it" - (when (memq major-mode '(magit-log-mode - magit-reflog-mode - magit-diff-mode - magit-revision-mode)) - (when help-xref-stack-item - (push (cons (point) help-xref-stack-item) help-xref-stack) - (setq help-xref-forward-stack nil)) - (when (called-interactively-p 'interactive) - (--when-let (nthcdr 10 help-xref-stack) - (setcdr it nil))) - (setq help-xref-stack-item - `(magit-xref-restore ,default-directory ,@magit-refresh-args)))) - -(defun magit-xref-restore (&rest args) - (magit-xref-setup) - (setq default-directory (car args)) - (setq magit-refresh-args (cdr args)) - (magit-refresh-buffer)) - -;;; magit-mode.el ends soon -(provide 'magit-mode) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-mode.el ends here diff --git a/elpa/magit-20151119.202/magit-pkg.el b/elpa/magit-20151119.202/magit-pkg.el deleted file mode 100644 index 8d00af1d..00000000 --- a/elpa/magit-20151119.202/magit-pkg.el +++ /dev/null @@ -1,12 +0,0 @@ -(define-package "magit" "20151119.202" "A Git porcelain inside Emacs" - '((emacs "24.4") - (async "20150909.2257") - (dash "20151021.113") - (with-editor "20151111") - (git-commit "20151111") - (magit-popup "20151111")) - :url "https://github.com/magit/magit" :keywords - '("git" "tools" "vc")) -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/magit-20151119.202/magit-process.el b/elpa/magit-20151119.202/magit-process.el deleted file mode 100644 index 1d6495df..00000000 --- a/elpa/magit-20151119.202/magit-process.el +++ /dev/null @@ -1,877 +0,0 @@ -;;; magit-process.el --- process functionality - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library implements the tools used to run Git for side-effects. - -;; Note that the functions used to run Git and then consume its -;; output, are defined in `magit-git.el'. There's a bit of overlap -;; though. - -;;; Code: - -(require 'cl-lib) -(require 'dash) - -(require 'with-editor) -(require 'magit-utils) -(require 'magit-section) -(require 'magit-git) -(require 'magit-mode) - -(eval-when-compile (require 'dired)) -(declare-function dired-uncache 'dired) - -;;; Options - -(defcustom magit-process-connection-type (not (eq system-type 'cygwin)) - "Connection type used for the Git process. - -If nil, use pipes: this is usually more efficient, and works on Cygwin. -If t, use ptys: this enables Magit to prompt for passphrases when needed." - :group 'magit-process - :type '(choice (const :tag "pipe" nil) - (const :tag "pty" t))) - -(defcustom magit-need-cygwin-noglob - (equal "x0\n" (with-temp-buffer - (process-file magit-git-executable - nil (current-buffer) nil - "-c" "alias.echo=!echo" "echo" "x{0}") - (buffer-string))) - "Whether to use a workaround for Cygwin's globbing behavior. - -If non-nil, add environment variables to `process-environment' to -prevent the git.exe distributed by Cygwin and MSYS2 from -attempting to perform glob expansion when called from a native -Windows build of Emacs. See #2246." - :package-version '(magit . "2.3.0") - :group 'magit-process - :type '(choice (const :tag "Yes" t) - (const :tag "No" nil))) - -(defcustom magit-process-popup-time -1 - "Popup the process buffer if a command takes longer than this many seconds." - :group 'magit-process - :type '(choice (const :tag "Never" -1) - (const :tag "Immediately" 0) - (integer :tag "After this many seconds"))) - -(defcustom magit-process-log-max 32 - "Maximum number of sections to keep in a process log buffer. -When adding a new section would go beyond the limit set here, -then the older half of the sections are remove. Sections that -belong to processes that are still running are never removed. -When this is nil, no sections are ever removed." - :package-version '(magit . "2.1.0") - :group 'magit-process - :type '(choice (const :tag "Never remove old sections" nil) integer)) - -(defcustom magit-credential-cache-daemon-socket - (--some (-let [(prog . args) (split-string it)] - (if (string-match-p - "\\`\\(?:\\(?:/.*/\\)?git-credential-\\)?cache\\'" prog) - (or (cl-loop for (opt val) on args - if (string= opt "--socket") - return val) - (expand-file-name "~/.git-credential-cache/socket")))) - ;; Note: `magit-process-file' is not yet defined when - ;; evaluating this form, so we use `process-lines'. - (ignore-errors - (process-lines magit-git-executable - "config" "--get-all" "credential.helper"))) - "If non-nil, start a credential cache daemon using this socket. - -When using Git's cache credential helper in the normal way, Emacs -sends a SIGHUP to the credential daemon after the git subprocess -has exited, causing the daemon to also quit. This can be avoided -by starting the `git-credential-cache--daemon' process directly -from Emacs. - -The function `magit-maybe-start-credential-cache-daemon' takes -care of starting the daemon if necessary, using the value of this -option as the socket. If this option is nil, then it does not -start any daemon. Likewise if another daemon is already running, -then it starts no new daemon. This function has to be a member -of the hook variable `magit-credential-hook' for this to work. -If an error occurs while starting the daemon, most likely because -the necessary executable is missing, then the function removes -itself from the hook, to avoid further futile attempts." - :package-version '(magit . "2.3.0") - :group 'magit-process - :type '(choice (file :tag "Socket") - (const :tag "Don't start a cache daemon" nil))) - -(defcustom magit-process-yes-or-no-prompt-regexp - " [\[(]\\([Yy]\\(?:es\\)?\\)[/|]\\([Nn]o?\\)[\])] ?[?:] ?$" - "Regexp matching Yes-or-No prompts of Git and its subprocesses." - :package-version '(magit . "2.1.0") - :group 'magit-process - :type 'regexp) - -(defcustom magit-process-password-prompt-regexps - '("^\\(Enter \\)?[Pp]assphrase\\( for \\(RSA \\)?key '.*'\\)?: ?$" - ;; match-group 99 is used to identify a host - "^\\(Enter \\)?[Pp]assword\\( for '\\(?99:.*\\)'\\)?: ?$" - "^.*'s password: ?$" - "^Yubikey for .*: ?$") - "List of regexps matching password prompts of Git and its subprocesses. -Also see `magit-process-find-password-functions'." - :package-version '(magit . "2.1.0") - :group 'magit-process - :type '(repeat (regexp))) - -(defcustom magit-process-find-password-functions nil - "List of functions to try in sequence to get a password. - -These functions may be called when git asks for a password, which -is detected using `magit-process-password-prompt-regexps'. They -are called if and only if matching the prompt resulted in the -value of the 99th submatch to be non-nil. Therefore users can -control for which prompts these functions should be called by -putting the host name in the 99th submatch, or not. - -If the functions are called, then they are called in the order -given, with the host name as only argument, until one of them -returns non-nil. If they are not called or none of them returns -non-nil, then the password is read from the user instead." - :package-version '(magit . "2.3.0") - :group 'magit-process - :type 'hook - :options '(magit-process-password-auth-source)) - -(defcustom magit-process-username-prompt-regexps - '("^Username for '.*': ?$") - "List of regexps matching username prompts of Git and its subprocesses." - :package-version '(magit . "2.1.0") - :group 'magit-process - :type '(repeat (regexp))) - -(defface magit-process-ok - '((t :inherit magit-section-heading :foreground "green")) - "Face for zero exit-status." - :group 'magit-faces) - -(defface magit-process-ng - '((t :inherit magit-section-heading :foreground "red")) - "Face for non-zero exit-status." - :group 'magit-faces) - -;;; Process Mode - -(defvar magit-process-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map magit-mode-map) - map) - "Keymap for `magit-process-mode'.") - -(define-derived-mode magit-process-mode magit-mode "Magit Process" - "Mode for looking at Git process output." - :group 'magit-process - (hack-dir-local-variables-non-file-buffer)) - -(defun magit-process-buffer (&optional nodisplay) - "Display the current repository's process buffer. - -If that buffer doesn't exist yet, then create it. -Non-interactively return the buffer and unless -optional NODISPLAY is non-nil also display it." - (interactive) - (let ((topdir (magit-toplevel))) - (unless topdir - (magit--with-safe-default-directory nil - (setq topdir default-directory) - (let (prev) - (while (not (equal topdir prev)) - (setq prev topdir) - (setq topdir (file-name-directory (directory-file-name topdir))))))) - (let ((buffer (or (--first (with-current-buffer it - (and (eq major-mode 'magit-process-mode) - (equal default-directory topdir))) - (buffer-list)) - (let ((default-directory topdir)) - (magit-generate-new-buffer 'magit-process-mode))))) - (with-current-buffer buffer - (if magit-root-section - (when magit-process-log-max - (magit-process-truncate-log)) - (magit-process-mode) - (let ((inhibit-read-only t)) - (make-local-variable 'text-property-default-nonsticky) - (magit-insert-section (processbuf) - (insert "\n"))))) - (unless nodisplay - (magit-display-buffer buffer)) - buffer))) - -(defun magit-process-kill () - "Kill the process at point." - (interactive) - (magit-section-when process - (let ((process (magit-section-value it))) - (if (eq (process-status process) 'run) - (when (magit-confirm 'kill-process) - (kill-process process)) - (user-error "Process isn't running"))))) - -;;; Synchronous Processes - -(defvar magit-process-raise-error nil) - -(defun magit-git (&rest args) - "Call Git synchronously in a separate process, for side-effects. - -Option `magit-git-executable' specifies the Git executable. -The arguments ARGS specify arguments to Git, they are flattened -before use. - -Process output goes into a new section in the buffer returned by -`magit-process-buffer'. If Git exits with a non-zero status, -then raise an error." - (let ((magit-process-raise-error t)) - (magit-call-git args))) - -(defun magit-run-git (&rest args) - "Call Git synchronously in a separate process, and refresh. - -Option `magit-git-executable' specifies the Git executable and -option `magit-git-global-arguments' specifies constant arguments. -The arguments ARGS specify arguments to Git, they are flattened -before use. - -After Git returns, the current buffer (if it is a Magit buffer) -as well as the current repository's status buffer are refreshed. -Unmodified buffers visiting files that are tracked in the current -repository are reverted if `magit-revert-buffers' is non-nil. - -Process output goes into a new section in the buffer returned by -`magit-process-buffer'." - (magit-call-git args) - (magit-refresh)) - -(defun magit-run-git-no-revert (&rest args) - "Call Git synchronously in a separate process, and refresh. - -Option `magit-git-executable' specifies the Git executable and -option `magit-git-global-arguments' specifies constant arguments. -The arguments ARGS specify arguments to Git, they are flattened -before use. - -After Git returns, the current buffer (if it is a Magit buffer) -as well as the current repository's status buffer are refreshed. - -Process output goes into a new section in the buffer returned by -`magit-process-buffer'." - (let ((inhibit-magit-revert t)) - (magit-run-git args))) - -(defvar magit-pre-call-git-hook nil) - -(defun magit-call-git (&rest args) - "Call Git synchronously in a separate process. - -Option `magit-git-executable' specifies the Git executable and -option `magit-git-global-arguments' specifies constant arguments. -The arguments ARGS specify arguments to Git, they are flattened -before use. - -Process output goes into a new section in the buffer returned by -`magit-process-buffer'." - (run-hooks 'magit-pre-call-git-hook) - (apply #'magit-call-process magit-git-executable - (magit-process-git-arguments args))) - -(defun magit-call-process (program &rest args) - "Call PROGRAM synchronously in a separate process. -Process output goes into a new section in the buffer returned by -`magit-process-buffer'." - (-let [(process-buf . section) (magit-process-setup program args)] - (magit-process-finish - (let ((inhibit-read-only t)) - (apply #'magit-process-file program nil process-buf nil args)) - process-buf (current-buffer) default-directory section))) - -(defun magit-process-file (&rest args) - "Process files synchronously in a separate process. -Identical to `process-file' but temporarily enable Cygwin's -\"noglob\" option during the call." - (let ((process-environment (append (magit-cygwin-env-vars) - process-environment))) - (apply #'process-file args))) - -(defun magit-cygwin-env-vars () - (append magit-git-environment - (when magit-need-cygwin-noglob - (mapcar (lambda (var) - (concat var "=" (--if-let (getenv var) - (concat it " noglob") - "noglob"))) - '("CYGWIN" "MSYS"))))) - -(defun magit-run-git-with-input (input &rest args) - "Call Git in a separate process. -ARGS is flattened and then used as arguments to Git. - -The first argument, INPUT, should be a buffer or the name of -an existing buffer. The content of that buffer is used as the -process' standard input. It may also be nil in which case the -current buffer is used. - -Option `magit-git-executable' specifies the Git executable and -option `magit-git-global-arguments' specifies constant arguments. -The remaining arguments ARGS specify arguments to Git, they are -flattened before use. - -After Git returns, the current buffer (if it is a Magit buffer) -as well as the current repository's status buffer are refreshed. -Unmodified buffers visiting files that are tracked in the current -repository are reverted if `magit-revert-buffers' is non-nil. -When INPUT is nil then do not refresh any buffers. - -This function actually starts a asynchronous process, but it then -waits for that process to return." - (declare (indent 1)) - (magit-start-git (or input (current-buffer)) args) - (magit-process-wait) - (when input (magit-refresh))) - -(defvar magit-this-process nil) - -(defun magit-run-git-with-logfile (file &rest args) - "Call Git in a separate process and log its output to FILE. -See `magit-run-git' for more information. -This function might have a short halflive." - (magit-start-git nil args) - (process-put magit-this-process 'logfile file) - (set-process-filter magit-this-process 'magit-process-logfile-filter) - (magit-process-wait) - (magit-refresh)) - -;;; Asynchronous Processes - -(defun magit-run-git-async (&rest args) - "Start Git, prepare for refresh, and return the process object. -ARGS is flattened and then used as arguments to Git. - -Display the command line arguments in the echo area. - -After Git returns some buffers are refreshed: the buffer that was -current when this function was called (if it is a Magit buffer -and still alive), as well as the respective Magit status buffer. -Unmodified buffers visiting files that are tracked in the current -repository are reverted if `magit-revert-buffers' is non-nil. - -See `magit-start-process' for more information." - (message "Running %s %s" magit-git-executable - (mapconcat 'identity (-flatten args) " ")) - (magit-start-git nil args)) - -(defun magit-run-git-async-no-revert (&rest args) - "Start Git, prepare for refresh, and return the process object. -ARGS is flattened and then used as arguments to Git. - -Display the command line arguments in the echo area. - -After Git returns some buffers are refreshed: the buffer that was -current when this function was called (if it is a Magit buffer -and still alive), as well as the respective Magit status buffer. - -See `magit-start-process' for more information." - (let ((inhibit-magit-revert t)) - (magit-run-git-async args))) - -(defun magit-run-git-with-editor (&rest args) - "Export GIT_EDITOR and start Git. -Also prepare for refresh and return the process object. -ARGS is flattened and then used as arguments to Git. - -Display the command line arguments in the echo area. - -After Git returns some buffers are refreshed: the buffer that was -current when this function was called (if it is a Magit buffer -and still alive), as well as the respective Magit status buffer. - -See `magit-start-process' and `with-editor' for more information." - (with-editor "GIT_EDITOR" - (let ((magit-process-popup-time -1) - (inhibit-magit-revert nil)) - (magit-run-git-async args)))) - -(defun magit-run-git-sequencer (&rest args) - "Export GIT_EDITOR and start Git. -Also prepare for refresh and return the process object. -ARGS is flattened and then used as arguments to Git. - -Display the command line arguments in the echo area. - -After Git returns some buffers are refreshed: the buffer that was -current when this function was called (if it is a Magit buffer -and still alive), as well as the respective Magit status buffer. -If the sequence stops at a commit, make the section representing -that commit the current section by moving `point' there. - -Unmodified buffers visiting files that are tracked in the current -repository are reverted if `magit-revert-buffers' is non-nil. - -See `magit-start-process' and `with-editor' for more information." - (with-editor "GIT_EDITOR" - (let ((magit-process-popup-time -1)) - (magit-run-git-async args))) - (set-process-sentinel magit-this-process #'magit-sequencer-process-sentinel) - magit-this-process) - -(defvar magit-pre-start-git-hook nil) - -(defun magit-start-git (input &rest args) - "Start Git, prepare for refresh, and return the process object. - -If INPUT is non-nil, it has to be a buffer or the name of an -existing buffer. The buffer content becomes the processes -standard input. - -Option `magit-git-executable' specifies the Git executable and -option `magit-git-global-arguments' specifies constant arguments. -The remaining arguments ARGS specify arguments to Git, they are -flattened before use. - -After Git returns some buffers are refreshed: the buffer that was -current when this function was called (if it is a Magit buffer -and still alive), as well as the respective Magit status buffer. -Unmodified buffers visiting files that are tracked in the current -repository are reverted if `magit-revert-buffers' is non-nil. - -See `magit-start-process' for more information." - (run-hooks 'magit-pre-start-git-hook) - (apply #'magit-start-process magit-git-executable input - (magit-process-git-arguments args))) - -(defun magit-start-process (program &optional input &rest args) - "Start PROGRAM, prepare for refresh, and return the process object. - -If optional argument INPUT is non-nil, it has to be a buffer or -the name of an existing buffer. The buffer content becomes the -processes standard input. - -The process is started using `start-file-process' and then setup -to use the sentinel `magit-process-sentinel' and the filter -`magit-process-filter'. Information required by these functions -is stored in the process object. When this function returns the -process has not started to run yet so it is possible to override -the sentinel and filter. - -After the process returns, `magit-process-sentinel' refreshes the -buffer that was current when `magit-start-process' was called (if -it is a Magit buffer and still alive), as well as the respective -Magit status buffer. Unmodified buffers visiting files that are -tracked in the current repository are reverted if -`magit-revert-buffers' is non-nil." - (-let* (((process-buf . section) - (magit-process-setup program args)) - (process - (let ((process-connection-type - ;; Don't use a pty, because it would set icrnl - ;; which would modify the input (issue #20). - (and (not input) magit-process-connection-type)) - (process-environment (append (magit-cygwin-env-vars) - process-environment))) - (apply #'start-file-process - (file-name-nondirectory program) - process-buf program args)))) - (with-editor-set-process-filter process #'magit-process-filter) - (set-process-sentinel process #'magit-process-sentinel) - (set-process-buffer process process-buf) - (process-put process 'section section) - (process-put process 'command-buf (current-buffer)) - (process-put process 'default-dir default-directory) - (when inhibit-magit-refresh - (process-put process 'inhibit-refresh t)) - (when inhibit-magit-revert - (process-put process 'inhibit-revert t)) - (setf (magit-section-process section) process) - (with-current-buffer process-buf - (set-marker (process-mark process) (point))) - (when input - (with-current-buffer input - (process-send-region process (point-min) (point-max)) - (process-send-eof process))) - (setq magit-this-process process) - (setf (magit-section-value section) process) - (magit-process-display-buffer process) - process)) - -;;; Process Internals - -(defun magit-process-setup (program args) - (magit-process-set-mode-line program args) - (let ((pwd default-directory) - (buf (magit-process-buffer t))) - (cons buf (with-current-buffer buf - (prog1 (magit-process-insert-section pwd program args nil nil) - (backward-char 1)))))) - -(defun magit-process-insert-section (pwd program args &optional errcode errlog) - (let ((inhibit-read-only t) - (magit-insert-section--parent magit-root-section)) - (goto-char (1- (point-max))) - (magit-insert-section (process) - (insert (if errcode - (format "%3s " (propertize (number-to-string errcode) - 'face 'magit-process-ng)) - "run ")) - (unless (equal (expand-file-name pwd) - (expand-file-name default-directory)) - (insert (file-relative-name pwd default-directory) ?\s)) - (insert (propertize program 'face 'magit-section-heading)) - (insert " ") - (when (and args (equal program magit-git-executable)) - (setq args (-split-at (length magit-git-global-arguments) args)) - (insert (propertize (char-to-string magit-ellipsis) - 'face 'magit-section-heading - 'help-echo (mapconcat #'identity (car args) " "))) - (insert " ") - (setq args (cadr args))) - (insert (propertize (mapconcat #'identity args " ") - 'face 'magit-section-heading)) - (magit-insert-heading) - (when errlog - (insert-file-contents errlog) - (goto-char (1- (point-max)))) - (insert "\n")))) - -(defun magit-process-truncate-log () - (let* ((head nil) - (tail (magit-section-children magit-root-section)) - (count (length tail))) - (when (> (1+ count) magit-process-log-max) - (while (and (cdr tail) - (> count (/ magit-process-log-max 2))) - (let* ((inhibit-read-only t) - (section (car tail)) - (process (magit-section-process section))) - (cond ((not process)) - ((memq (process-status process) '(exit signal)) - (delete-region (magit-section-start section) - (1+ (magit-section-end section))) - (cl-decf count)) - (t - (push section head)))) - (pop tail)) - (setf (magit-section-children magit-root-section) - (nconc (reverse head) tail))))) - -(defun magit-process-sentinel (process event) - "Default sentinel used by `magit-start-process'." - (when (memq (process-status process) '(exit signal)) - (setq event (substring event 0 -1)) - (when (string-match "^finished" event) - (message (concat (capitalize (process-name process)) " finished"))) - (magit-process-finish process) - (when (eq process magit-this-process) - (setq magit-this-process nil)) - (unless (process-get process 'inhibit-refresh) - (let ((inhibit-magit-revert (process-get process 'inhibit-revert)) - (command-buf (process-get process 'command-buf))) - (if (buffer-live-p command-buf) - (with-current-buffer command-buf - (magit-refresh)) - (with-temp-buffer - (setq default-directory (process-get process 'default-dir)) - (magit-refresh))))))) - -(defun magit-sequencer-process-sentinel (process event) - "Special sentinel used by `magit-run-git-sequencer'." - (when (memq (process-status process) '(exit signal)) - (magit-process-sentinel process event) - (--when-let (magit-mode-get-buffer 'magit-status-mode) - (with-current-buffer it - (--when-let - (magit-get-section - `((commit . ,(magit-rev-parse "HEAD")) - (,(pcase (car (cadr (-split-at - (1+ (length magit-git-global-arguments)) - (process-command process)))) - ((or "rebase" "am") 'rebase-sequence) - ((or "cherry-pick" "revert") 'sequence))) - (status))) - (goto-char (magit-section-start it)) - (magit-section-update-highlight)))))) - -(defun magit-process-filter (proc string) - "Default filter used by `magit-start-process'." - (with-current-buffer (process-buffer proc) - (let ((inhibit-read-only t)) - (magit-process-yes-or-no-prompt proc string) - (magit-process-username-prompt proc string) - (magit-process-password-prompt proc string) - (goto-char (process-mark proc)) - (setq string (propertize string 'magit-section - (process-get proc 'section))) - ;; Find last ^M in string. If one was found, ignore - ;; everything before it and delete the current line. - (let ((ret-pos (length string))) - (while (and (>= (cl-decf ret-pos) 0) - (/= ?\r (aref string ret-pos)))) - (if (< ret-pos 0) - (insert string) - (delete-region (line-beginning-position) (point)) - (insert (substring string (1+ ret-pos))))) - (set-marker (process-mark proc) (point))))) - -(defun magit-process-logfile-filter (process string) - "Special filter used by `magit-run-git-with-logfile'." - (magit-process-filter process string) - (let ((file (process-get process 'logfile))) - (with-temp-file file - (when (file-exists-p file) - (insert-file-contents file) - (goto-char (point-max))) - (insert string) - (write-region (point-min) (point-max) file)))) - -(defmacro magit-process-kill-on-abort (proc &rest body) - (declare (indent 1) (debug (form body))) - (let ((map (cl-gensym))) - `(let ((,map (make-sparse-keymap))) - (set-keymap-parent ,map minibuffer-local-map) - (define-key ,map "\C-g" - (lambda () - (interactive) - (ignore-errors (kill-process ,proc)) - (abort-recursive-edit))) - (let ((minibuffer-local-map ,map)) - ,@body)))) - -(defun magit-process-yes-or-no-prompt (process string) - "Forward Yes-or-No prompts to the user." - (-when-let (beg (string-match magit-process-yes-or-no-prompt-regexp string)) - (let ((max-mini-window-height 30)) - (process-send-string - process - (downcase - (concat - (match-string - (if (save-match-data - (magit-process-kill-on-abort process - (yes-or-no-p (substring string 0 beg)))) 1 2) - string) - "\n")))))) - -(defun magit-process-password-auth-source (key) - "Use `auth-source-search' to get a password. -If found, return the password. Otherwise, return nil." - (require 'auth-source) - (let ((secret (plist-get (car (auth-source-search :max 1 :host key)) - :secret))) - (if (functionp secret) - (funcall secret) - secret))) - -(defun magit-process-password-prompt (process string) - "Find a password based on prompt STRING and send it to git. -First try the functions in `magit-process-find-password-functions'. -If none of them returns a password, then read it from the user -instead." - (--when-let (magit-process-match-prompt - magit-process-password-prompt-regexps string) - (process-send-string - process (magit-process-kill-on-abort process - (concat (or (--when-let (match-string 99 string) - (run-hook-with-args-until-success - 'magit-process-find-password-functions it)) - (read-passwd it)) - "\n"))))) - -(defun magit-process-username-prompt (process string) - "Forward username prompts to the user." - (--when-let (magit-process-match-prompt - magit-process-username-prompt-regexps string) - (process-send-string - process (magit-process-kill-on-abort process - (concat (read-string it nil nil (user-login-name)) "\n"))))) - -(defun magit-process-match-prompt (prompts string) - "Match STRING against PROMPTS and set match data. -Return the matched string suffixed with \": \", if needed." - (when (--any? (string-match it string) prompts) - (let ((prompt (match-string 0 string))) - (cond ((string-suffix-p ": " prompt) prompt) - ((string-suffix-p ":" prompt) (concat prompt " ")) - (t (concat prompt ": ")))))) - -(defvar magit-credential-hook nil - "Hook run before Git needs credentials.") - -(defvar magit-credential-cache-daemon-process nil) - -(defun magit-maybe-start-credential-cache-daemon () - "Maybe start a `git-credential-cache--daemon' process. - -If such a process is already running or if the value of option -`magit-credential-cache-daemon-socket' is nil, then do nothing. -Otherwise start the process passing the value of that options -as argument." - (unless (or (not magit-credential-cache-daemon-socket) - (process-live-p magit-credential-cache-daemon-process) - (memq magit-credential-cache-daemon-process - (list-system-processes))) - (setq magit-credential-cache-daemon-process - (or (--first (-let (((&alist 'comm comm 'user user) - (process-attributes it))) - (and (string= comm "git-credential-cache--daemon") - (string= user user-login-name))) - (list-system-processes)) - (condition-case err - (start-process "git-credential-cache--daemon" - " *git-credential-cache--daemon*" - magit-git-executable - "credential-cache--daemon" - magit-credential-cache-daemon-socket) - ;; Some Git implementations (e.g. Windows) won't have - ;; this program; if we fail the first time, stop trying. - ((debug error) - (remove-hook 'magit-credential-hook - #'magit-maybe-start-credential-cache-daemon))))))) - -(add-hook 'magit-credential-hook #'magit-maybe-start-credential-cache-daemon) - -(defun magit-process-wait () - (while (and magit-this-process - (eq (process-status magit-this-process) 'run)) - (sit-for 0.1 t))) - -(defadvice tramp-sh-handle-start-file-process - (before magit-tramp-process-environment activate) - (when magit-tramp-process-environment - (ad-set-args 3 (append (cdr magit-tramp-process-environment) - (cons (ad-get-arg 2) - (ad-get-args 3)))) - (ad-set-arg 2 (car magit-tramp-process-environment)))) - -(defadvice tramp-sh-handle-process-file - (before magit-tramp-process-environment activate) - (when magit-tramp-process-environment - (ad-set-args 4 (append magit-tramp-process-environment - (cons (ad-get-arg 0) - (ad-get-args 4)))) - (ad-set-arg 0 "env"))) - -(defun magit-process-set-mode-line (program args) - (when (equal program magit-git-executable) - (setq args (nthcdr (length magit-git-global-arguments) args))) - (let ((str (concat " " program (and args (concat " " (car args)))))) - (dolist (buf (magit-mode-get-buffers)) - (with-current-buffer buf (setq mode-line-process str))))) - -(defun magit-process-unset-mode-line () - (dolist (buf (magit-mode-get-buffers)) - (with-current-buffer buf (setq mode-line-process nil)))) - -(defvar magit-process-error-message-re - (concat "^\\(?:error\\|fatal\\|git\\): \\(.*\\)" paragraph-separate)) - -(define-error 'magit-git-error "Git error") - -(defun magit-process-finish (arg &optional process-buf command-buf - default-dir section) - (unless (integerp arg) - (setq process-buf (process-buffer arg) - command-buf (process-get arg 'command-buf) - default-dir (process-get arg 'default-dir) - section (process-get arg 'section) - arg (process-exit-status arg))) - (magit-process-unset-mode-line) - (when (featurep 'dired) - (dired-uncache default-dir)) - (when (buffer-live-p process-buf) - (with-current-buffer process-buf - (let ((inhibit-read-only t) - (marker (magit-section-start section))) - (goto-char marker) - (save-excursion - (delete-char 3) - (set-marker-insertion-type marker nil) - (insert (propertize (format "%3s" arg) - 'magit-section section - 'face (if (= arg 0) - 'magit-process-ok - 'magit-process-ng))) - (set-marker-insertion-type marker t)) - (if (= (magit-section-end section) - (+ (line-end-position) 2)) - (save-excursion - (goto-char (1+ (line-end-position))) - (delete-char -1) - (setf (magit-section-content section) nil)) - (let ((buf (magit-process-buffer t))) - (when (and (= arg 0) - (not (--any-p (eq (window-buffer it) buf) - (window-list)))) - (magit-section-hide section))))))) - (unless (= arg 0) - (let ((msg (or (and (buffer-live-p process-buf) - (with-current-buffer process-buf - (save-excursion - (goto-char (magit-section-end section)) - (--when-let (magit-section-content section) - (when (re-search-backward - magit-process-error-message-re it t) - (match-string 1)))))) - "Git failed"))) - (if magit-process-raise-error - (signal 'magit-git-error msg) - (message "%s ... [%s buffer %s for details]" msg - (-if-let (key (and (buffer-live-p command-buf) - (with-current-buffer command-buf - (car (where-is-internal - 'magit-process-display-buffer))))) - (format "Hit %s to see" (key-description key)) - "See") - (buffer-name process-buf))))) - arg) - -(defun magit-process-display-buffer (process) - (when (process-live-p process) - (let ((buf (process-buffer process))) - (cond ((not (buffer-live-p buf))) - ((= magit-process-popup-time 0) - (if (minibufferp) - (switch-to-buffer-other-window buf) - (pop-to-buffer buf))) - ((> magit-process-popup-time 0) - (run-with-timer magit-process-popup-time nil - (lambda (p) - (when (eq (process-status p) 'run) - (let ((buf (process-buffer p))) - (when (buffer-live-p buf) - (if (minibufferp) - (switch-to-buffer-other-window buf) - (pop-to-buffer buf)))))) - process)))))) - -;;; magit-process.el ends soon -(provide 'magit-process) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-process.el ends here diff --git a/elpa/magit-20151119.202/magit-remote.el b/elpa/magit-20151119.202/magit-remote.el deleted file mode 100644 index 26667140..00000000 --- a/elpa/magit-20151119.202/magit-remote.el +++ /dev/null @@ -1,432 +0,0 @@ -;;; magit-remote.el --- transfer Git commits - -;; Copyright (C) 2008-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library implements support for interacting with remote -;; repositories. Commands for cloning, fetching, pulling, and -;; pushing are defined here. - -;;; Code: - -(require 'magit) - -;;; Clone - -;;;###autoload -(defun magit-clone (repository directory) - "Clone the REPOSITORY to DIRECTORY. -Then show the status buffer for the new repository." - (interactive - (let ((url (magit-read-string-ns "Clone repository"))) - (list url (read-directory-name - "Clone to: " nil nil nil - (and (string-match "\\([^./]+\\)\\(\\.git\\)?$" url) - (match-string 1 url)))))) - (setq directory (file-name-as-directory (expand-file-name directory))) - (message "Cloning %s..." repository) - (when (= (magit-call-git "clone" repository - ;; Stop cygwin git making a "c:" directory. - (magit-convert-git-filename directory)) - 0) - (message "Cloning %s...done" repository) - (magit-status-internal directory))) - -;;; Setup - -;;;###autoload (autoload 'magit-remote-popup "magit-remote" nil t) -(magit-define-popup magit-remote-popup - "Popup console for remote commands." - 'magit-commands nil nil - :man-page "git-remote" - :actions '((?a "Add" magit-remote-add) - (?r "Rename" magit-remote-rename) - (?k "Remove" magit-remote-remove) - (?u "Set url" magit-remote-set-url))) - -(defun magit-read-url (prompt &optional initial-input) - (let ((url (magit-read-string-ns prompt initial-input))) - (if (string-prefix-p "~" url) - (expand-file-name url) - url))) - -;;;###autoload -(defun magit-remote-add (remote url) - "Add a remote named REMOTE and fetch it." - (interactive (list (magit-read-string-ns "Remote name") - (magit-read-url "Remote url"))) - (magit-run-git-async "remote" "add" "-f" remote url)) - -;;;###autoload -(defun magit-remote-rename (old new) - "Rename the remote named OLD to NEW." - (interactive - (let ((remote (magit-read-remote "Rename remote"))) - (list remote (magit-read-string-ns (format "Rename %s to" remote))))) - (unless (string= old new) - (magit-run-git "remote" "rename" old new))) - -;;;###autoload -(defun magit-remote-set-url (remote url) - "Change the url of the remote named REMOTE to URL." - (interactive - (let ((remote (magit-read-remote "Set url of remote"))) - (list remote (magit-read-url - "Url" (magit-get "remote" remote "url"))))) - (magit-run-git "remote" "set-url" remote url)) - -;;;###autoload -(defun magit-remote-remove (remote) - "Delete the remote named REMOTE." - (interactive (list (magit-read-remote "Delete remote"))) - (magit-run-git "remote" "rm" remote)) - -;;; Fetch - -;;;###autoload (autoload 'magit-fetch-popup "magit-remote" nil t) -(magit-define-popup magit-fetch-popup - "Popup console for fetch commands." - 'magit-commands - :man-page "git-fetch" - :switches '((?p "Prune" "--prune")) - :actions '((?f "Current" magit-fetch-current) - (?o "Other" magit-fetch) - (?a "All" magit-fetch-all) - (?m "Submodules" magit-submodule-fetch)) - :default-action 'magit-fetch-current) - -;;;###autoload -(defun magit-fetch-current (remote &optional args) - "Fetch from the upstream repository of the current branch. -If `HEAD' is detached or if the upstream is not configured, -then read the remote." - (interactive (list (or (magit-get-remote) - (magit-read-remote "Fetch remote")) - (magit-fetch-arguments))) - (run-hooks 'magit-credential-hook) - (magit-run-git-async-no-revert "fetch" remote args)) - -;;;###autoload -(defun magit-fetch (remote &optional args) - "Fetch from another repository." - (interactive (list (magit-read-remote "Fetch remote") - (magit-fetch-arguments))) - (run-hooks 'magit-credential-hook) - (magit-run-git-async-no-revert "fetch" remote args)) - -;;;###autoload -(defun magit-fetch-all (&optional args) - "Fetch from all configured remotes." - (interactive (list (magit-fetch-arguments))) - (run-hooks 'magit-credential-hook) - (magit-run-git-async-no-revert "remote" "update" args)) - -;;; Pull - -;;;###autoload (autoload 'magit-pull-popup "magit-remote" nil t) -(magit-define-popup magit-pull-popup - "Popup console for pull commands." - 'magit-commands - :man-page "git-pull" - :switches '((?r "Rebase" "--rebase")) - :actions '((?F "Current" magit-pull-current) - (?o "Other" magit-pull)) - :default-action 'magit-pull-current) - -;;;###autoload -(defun magit-pull-current (remote branch &optional args) - "Fetch and merge into current branch." - (interactive (magit-pull-read-args t)) - (run-hooks 'magit-credential-hook) - (magit-run-git-with-editor "pull" args - (and (not (equal remote (magit-get-remote))) - (not (equal branch (magit-get-remote-branch))) - (list remote branch)))) - -;;;###autoload -(defun magit-pull (remote branch &optional args) - "Fetch from another repository and merge a fetched branch." - (interactive (magit-pull-read-args)) - (run-hooks 'magit-credential-hook) - (magit-run-git-with-editor "pull" args remote branch)) - -(defun magit-pull-read-args (&optional use-upstream) - (let ((remote (magit-get-remote-branch))) - (unless (and use-upstream remote) - (setq remote (magit-read-remote-branch "Pull" nil remote nil t))) - (list (car remote) (cdr remote) (magit-pull-arguments)))) - -;;; Push - -;;;###autoload (autoload 'magit-push-popup "magit-remote" nil t) -(magit-define-popup magit-push-popup - "Popup console for push commands." - 'magit-commands - :man-page "git-push" - :switches '((?f "Force" "--force-with-lease") - (?h "Disable hooks" "--no-verify") - (?d "Dry run" "--dry-run") - (?u "Set upstream" "--set-upstream")) - :actions '((?P "Current" magit-push-current) - (?Q "Quickly" magit-push-quickly) - (?t "Tags" magit-push-tags) - (?o "Other" magit-push) - (?i "Implicitly" magit-push-implicitly) - (?T "Tag" magit-push-tag) - (?e "Elsewhere" magit-push-elsewhere) - (?m "Matching" magit-push-matching)) - :default-action 'magit-push-current - :max-action-columns 3) - -;;;###autoload -(defun magit-push-current (branch remote &optional remote-branch args) - "Push the current branch to its upstream branch. -If the upstream isn't set, then read the remote branch. - -If `magit-push-always-verify' is not nil, however, always read -the remote branch." - (interactive (magit-push-read-args t t)) - (magit-push branch remote remote-branch args)) - -;;;###autoload -(defun magit-push (branch remote &optional remote-branch args) - "Push a branch to its upstream branch. -If the upstream isn't set, then read the remote branch. - -If `magit-push-always-verify' is not nil, however, always read -the remote branch." - (interactive (magit-push-read-args t)) - (run-hooks 'magit-credential-hook) - (magit-run-git-async-no-revert - "push" "-v" args remote - (if remote-branch - (format "%s:refs/heads/%s" branch remote-branch) - branch))) - -;;;###autoload -(defun magit-push-elsewhere (branch remote remote-branch &optional args) - "Push a branch or commit to some remote branch. -Read the local and remote branch." - (interactive (magit-push-read-args nil nil t)) - (magit-push branch remote remote-branch args)) - -(defcustom magit-push-always-verify 'nag - "Whether certain commands require verification before pushing. - -Starting with v2.1.0 some of the push commands are supposed to -push to the configured upstream branch without requiring user -confirmation or offering to push somewhere else. - -This has taken a few users by surprise, and they suggested that -we force users to opt-in to this behavior. Unfortunately adding -this option means that now other users will complain about us -needlessly forcing them to set an option. But what can you do? -\(I am not making this up. This has happened in the past and it -is very frustrating.) - -You should set the value of this option to nil, causing all push -commands to behave as intended: - -`PP' Push the current branch to its upstream branch, no questions - asked. If no upstream branch is configured or if that is - another local branch, then prompt for the remote and branch - to push to. - -`Po' Push another local branch (not the current branch) to its - upstream branch. If no upstream branch is configured or if - that is another local branch, then prompt for the remote and - branch to push to. - -`Pe' Push any local branch to any remote branch. This command - isn't affected by this option. It always asks which branch - should be pushed (defaulting to the current branch) and then - where that should be pushed (defaulting to the upstream - branch of the previously selected branch). - -There are other push commands besides these. You should read -their doc-strings instead of blindly trying them out and then -being surprised if it turns out that they do something different -from what you expected. For example inside the push popup type -`?i' to learn what \"implicitly\" means here. Or to learn about -all push commands at once, consult the manual. - -While I have your attention, I would also like to warn you that -pushing will be further improved in the v2.4.0 release, and that -you might be surprised by some of these changes, unless you read -the documentation. - -Setting this option to t makes little sense. If you consider -doing that, then you should probably just use `Pe' instead of -`PP' or `Po'." - :package-version '(magit . "2.2.0") - :group 'magit-commands - :type '(choice (const :tag "require verification and mention this option" nag) - (const :tag "require verification" t) - (const :tag "don't require verification" nil))) - -(defun magit-push-read-args (&optional use-upstream use-current default-current) - (let* ((current (magit-get-current-branch)) - (local (or (and use-current current) - (magit-completing-read - "Push" (--if-let (magit-commit-at-point) - (cons it (magit-list-local-branch-names)) - (magit-list-local-branch-names)) - nil nil nil 'magit-revision-history - (or (and default-current current) - (magit-local-branch-at-point) - (magit-commit-at-point))) - (user-error "Nothing selected"))) - (remote (and (magit-branch-p local) - (magit-get-remote-branch local)))) - (unless (and use-upstream remote (not magit-push-always-verify)) - (setq remote (magit-read-remote-branch - (concat - (format "Push %s to" local) - (and use-upstream remote - (eq magit-push-always-verify 'nag) - " [also see option magit-push-always-verify]")) - nil remote local 'confirm))) - (list local (car remote) (cdr remote) (magit-push-arguments)))) - -;;;###autoload -(defun magit-push-quickly (&optional args) - "Push the current branch to some remote. -When the Git variable `magit.pushRemote' is set, then push to -that remote. If that variable is undefined or the remote does -not exist, then push to \"origin\". If that also doesn't exist -then raise an error. The local branch is pushed to the remote -branch with the same name." - (interactive (list (magit-push-arguments))) - (run-hooks 'magit-credential-hook) - (-if-let (branch (magit-get-current-branch)) - (-if-let (remote (or (magit-remote-p (magit-get "magit.pushRemote")) - (magit-remote-p "origin"))) - (magit-run-git-async-no-revert "push" "-v" args remote branch) - (user-error "Cannot determine remote to push to")) - (user-error "No branch is checked out"))) - -;;;###autoload -(defun magit-push-implicitly (&optional args) - "Push without explicitly specifing what to push. -This runs `git push -v'. What is being pushed depends on various -Git variables as described in the `git-push(1)' and `git-config(1)' -manpages." - (interactive (list (magit-push-arguments))) - (run-hooks 'magit-credential-hook) - (magit-run-git-async-no-revert "push" "-v" args)) - -;;;###autoload -(defun magit-push-matching (remote &optional args) - "Push all matching branches to another repository. -If multiple remotes exit, then read one from the user. -If just one exists, use that without requiring confirmation." - (interactive (list (magit-read-remote "Push matching branches to" nil t))) - (run-hooks 'magit-credential-hook) - (magit-run-git-async-no-revert "push" "-v" args remote ":")) - -(defun magit-push-tags (remote &optional args) - "Push all tags to another repository. -If only one remote exists, then push to that. Otherwise prompt -for a remote, offering the remote configured for the current -branch as default." - (interactive (list (magit-read-remote "Push tags to remote" nil t) - (magit-push-arguments))) - (run-hooks 'magit-credential-hook) - (magit-run-git-async-no-revert "push" remote "--tags" args)) - -;;;###autoload -(defun magit-push-tag (tag remote &optional args) - "Push a tag to another repository." - (interactive - (let ((tag (magit-read-tag "Push tag"))) - (list tag (magit-read-remote (format "Push %s to remote" tag) nil t)))) - (run-hooks 'magit-credential-hook) - (magit-run-git-async-no-revert "push" remote tag)) - -;;; Email - -;;;###autoload (autoload 'magit-patch-popup "magit-remote" nil t) -(magit-define-popup magit-patch-popup - "Popup console for patch commands." - 'magit-commands - :man-page "git-format-patch" - :options '((?f "From" "--from=") - (?t "To" "--to=") - (?c "CC" "--cc=") - (?r "In reply to" "--in-reply-to=") - (?v "Reroll count" "--reroll-count=") - (?s "Thread style" "--thread=") - (?U "Context lines" "-U") - (?M "Detect renames" "-M") - (?C "Detect copies" "-C") - (?A "Diff algorithm" "--diff-algorithm=" - magit-diff-select-algorithm) - (?o "Output directory" "--output-directory=")) - :actions '((?p "Format patches" magit-format-patch) - (?r "Request pull" magit-request-pull)) - :default-action 'magit-format-patch) - -;;;###autoload -(defun magit-format-patch (range args) - "Create patches for the commits in RANGE. -When a single commit is given for RANGE, create a patch for the -changes introduced by that commit (unlike 'git format-patch' -which creates patches for all commits that are reachable from -HEAD but not from the specified commit)." - (interactive - (list (-if-let (revs (magit-region-values 'commit)) - (concat (car (last revs)) "^.." (car revs)) - (let ((range (magit-read-range-or-commit "Format range or commit"))) - (if (string-match-p "\\.\\." range) - range - (format "%s~..%s" range range)))) - (magit-patch-arguments))) - (magit-run-git-no-revert "format-patch" range args)) - -;;;###autoload -(defun magit-request-pull (url start end) - "Request upstream to pull from you public repository. - -URL is the url of your publically accessible repository. -START is a commit that already is in the upstream repository. -END is the last commit, usually a branch name, which upstream -is asked to pull. START has to be reachable from that commit." - (interactive - (list (magit-get "remote" (magit-read-remote "Remote") "url") - (magit-read-branch-or-commit "Start" (magit-get-tracked-branch)) - (magit-read-branch-or-commit "End"))) - (let ((dir default-directory)) - ;; mu4e changes default-directory - (compose-mail) - (setq default-directory dir)) - (message-goto-body) - (let ((inhibit-magit-revert t)) - (magit-git-insert "request-pull" start url)) - (set-buffer-modified-p nil)) - -;;; magit-remote.el ends soon -(provide 'magit-remote) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-remote.el ends here diff --git a/elpa/magit-20151119.202/magit-section.el b/elpa/magit-20151119.202/magit-section.el deleted file mode 100644 index 5c7a33b5..00000000 --- a/elpa/magit-20151119.202/magit-section.el +++ /dev/null @@ -1,1093 +0,0 @@ -;;; magit-section.el --- section functionality - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library implements "sections" as used in all Magit buffers. -;; If you have used Magit before then you probably know what that -;; means, otherwise think "read-only Org-Mode for Git", kinda. - -;;; Code: - -(require 'cl-lib) -(require 'dash) - -(require 'magit-utils) - -(defvar magit-keep-region-overlay) - -;;; Options - -(defgroup magit-section nil - "Expandable sections." - :group 'magit) - -(defcustom magit-section-show-child-count t - "Whether to append the number of childen to section headings." - :package-version '(magit . "2.1.0") - :group 'magit-section - :type 'boolean) - -(defcustom magit-section-movement-hook - '(magit-hunk-set-window-start - magit-log-maybe-update-revision-buffer - magit-log-maybe-show-more-commits) - "Hook run by `magit-section-goto'. -That function in turn is used by all section movement commands." - :package-version '(magit . "2.3.0") - :group 'magit-section - :type 'hook - :options '(magit-hunk-set-window-start - magit-status-maybe-update-revision-buffer - magit-status-maybe-update-blob-buffer - magit-log-maybe-update-revision-buffer - magit-log-maybe-update-blob-buffer - magit-log-maybe-show-more-commits)) - -(defcustom magit-section-highlight-hook - '(magit-diff-highlight - magit-section-highlight - magit-section-highlight-selection) - "Functions used to highlight the current section. -Each function is run with the current section as only argument -until one of them returns non-nil." - :package-version '(magit . "2.1.0") - :group 'magit-section - :type 'hook - :options '(magit-diff-highlight - magit-section-highlight - magit-section-highlight-selection)) - -(defcustom magit-section-unhighlight-hook - '(magit-diff-unhighlight) - "Functions used to unhighlight the previously current section. -Each function is run with the current section as only argument -until one of them returns non-nil. Most sections are properly -unhighlighted without requiring a specialized unhighligher, -diff-related sections being the only exception." - :package-version '(magit . "2.1.0") - :group 'magit-section - :type 'hook - :options '(magit-diff-unhighlight)) - -(defcustom magit-section-set-visibility-hook - '(magit-diff-expansion-threshold magit-revision-set-visibility) - "Hook used to set the initial visibility of a section. -Stop at the first function that returns non-nil. The value -should be `show' or `hide'. If no function returns non-nil -determine the visibility as usual, i.e. use the hardcoded -section specific default (see `magit-insert-section')." - :package-version '(magit . "2.1.0") - :group 'magit-section - :type 'hook - :options '(magit-diff-expansion-threshold magit-revision-set-visibility)) - -(defface magit-section-highlight - '((((class color) (background light)) :background "grey95") - (((class color) (background dark)) :background "grey20")) - "Face for highlighting the current section." - :group 'magit-faces) - -(defface magit-section-heading - '((((class color) (background light)) :foreground "DarkGoldenrod4" :weight bold) - (((class color) (background dark)) :foreground "LightGoldenrod2" :weight bold)) - "Face for section headings." - :group 'magit-faces) - -(defface magit-section-secondary-heading '((t :weight bold)) - "Face for section headings of some secondary headings." - :group 'magit-faces) - -(defface magit-section-heading-selection - '((((class color) (background light)) :foreground "salmon4") - (((class color) (background dark)) :foreground "LightSalmon3")) - "Face for selected section headings." - :group 'magit-faces) - -;;; Core - -(cl-defstruct magit-section - type value start content end hidden washer refined - source diff-header process parent children) - -(defvar-local magit-root-section nil - "The root section in the current buffer. -All other sections are descendants of this section. The value -of this variable is set by `magit-insert-section' and you should -never modify it.") -(put 'magit-root-section 'permanent-local t) - -(defun magit-current-section () - "Return the section at point." - (or (get-text-property (point) 'magit-section) magit-root-section)) - -(defun magit-section-ident (section) - "Return an unique identifier for SECTION. -The return value has the form ((TYPE . VALUE)...)." - (cons (cons (magit-section-type section) - (magit-section-value section)) - (--when-let (magit-section-parent section) - (magit-section-ident it)))) - -(defun magit-get-section (ident &optional root) - "Return the section identified by IDENT. -IDENT has to be a list as returned by `magit-section-ident'." - (setq ident (reverse ident)) - (let ((section (or root magit-root-section))) - (when (eq (car (pop ident)) (magit-section-type section)) - (while (and ident - (setq section - (--first - (and (eq (caar ident) (magit-section-type it)) - (equal (cdar ident) (magit-section-value it))) - (magit-section-children section)))) - (pop ident)) - section))) - -;;; Commands -;;;; Movement - -(defun magit-section-forward () - "Move to the beginning of the next visible section." - (interactive) - (if (eobp) - (user-error "No next section") - (let ((section (magit-current-section))) - (if (magit-section-parent section) - (let ((next (and (not (magit-section-hidden section)) - (not (= (magit-section-end section) (1+ (point)))) - (car (magit-section-children section))))) - (while (and section (not next)) - (unless (setq next (car (magit-section-siblings section 'next))) - (setq section (magit-section-parent section)))) - (if next - (magit-section-goto next) - (user-error "No next section"))) - (magit-section-goto 1))))) - -(defun magit-section-backward () - "Move to the beginning of the current or the previous visible section. -When point is at the beginning of a section then move to the -beginning of the previous visible section. Otherwise move to -the beginning of the current section." - (interactive) - (if (bobp) - (user-error "No previous section") - (let ((section (magit-current-section)) children) - (cond - ((and (= (point) (1- (magit-section-end section))) - (setq children (magit-section-children section))) - (magit-section-goto (car (last children)))) - ((and (magit-section-parent section) - (not (= (point) (magit-section-start section)))) - (magit-section-goto section)) - (t - (let ((prev (car (magit-section-siblings section 'prev)))) - (if prev - (while (and (not (magit-section-hidden prev)) - (setq children (magit-section-children prev))) - (setq prev (car (last children)))) - (setq prev (magit-section-parent section))) - (cond (prev - (magit-section-goto prev)) - ((magit-section-parent section) - (user-error "No previous section")) - ;; Eob special cases. - ((not (get-text-property (1- (point)) 'invisible)) - (magit-section-goto -1)) - (t - (goto-char (previous-single-property-change - (1- (point)) 'invisible)) - (forward-line -1) - (magit-section-goto (magit-current-section)))))))))) - -(defun magit-section-up () - "Move to the beginning of the parent section." - (interactive) - (--if-let (magit-section-parent (magit-current-section)) - (magit-section-goto it) - (user-error "No parent section"))) - -(defun magit-section-forward-sibling () - "Move to the beginning of the next sibling section. -If there is no next sibling section, then move to the parent." - (interactive) - (let ((current (magit-current-section))) - (if (magit-section-parent current) - (--if-let (car (magit-section-siblings current 'next)) - (magit-section-goto it) - (magit-section-forward)) - (magit-section-goto 1)))) - -(defun magit-section-backward-sibling () - "Move to the beginning of the previous sibling section. -If there is no previous sibling section, then move to the parent." - (interactive) - (let ((current (magit-current-section))) - (if (magit-section-parent current) - (--if-let (car (magit-section-siblings current 'prev)) - (magit-section-goto it) - (magit-section-backward)) - (magit-section-goto -1)))) - -(defun magit-section-goto (arg) - (if (integerp arg) - (progn (forward-line arg) - (setq arg (magit-current-section))) - (goto-char (magit-section-start arg))) - (run-hook-with-args 'magit-section-movement-hook arg)) - -(defun magit-section-set-window-start (section) - "Ensure the beginning of SECTION is visible." - (unless (pos-visible-in-window-p (magit-section-end section)) - (set-window-start (selected-window) (magit-section-start section)))) - -(defun magit-hunk-set-window-start (section) - "Ensure the beginning of the `hunk' SECTION is visible. -It the SECTION has a different type, then do nothing." - (when (eq (magit-section-type section) 'hunk) - (magit-section-set-window-start section))) - -(defmacro magit-define-section-jumper (sym title &optional value) - "Define an interactive function to go to section SYM. -TITLE is the displayed title of the section." - (let ((fun (intern (format "magit-jump-to-%s" sym)))) - `(progn - (defun ,fun (&optional expand) ,(format "\ -Jump to section '%s'. -With a prefix argument also expand it." title) - (interactive "P") - (--if-let (magit-get-section - (cons '(,sym . ,value) (magit-section-ident magit-root-section))) - (progn (goto-char (magit-section-start it)) - (when expand - (with-local-quit (magit-section-show it)) - (recenter 0))) - (message ,(format "Section '%s' wasn't found" title)))) - (put ',fun 'definition-name ',sym)))) - -;;;; Visibility - -(defun magit-section-show (section) - "Show the body of the current section." - (interactive (list (magit-current-section))) - (setf (magit-section-hidden section) nil) - (-when-let (washer (magit-section-washer section)) - (setf (magit-section-washer section) nil) - (let ((inhibit-read-only t) - (magit-insert-section--parent section) - (content (magit-section-content section))) - (save-excursion - (if (and content (< content (magit-section-end section))) - (funcall washer section) ; already partially washed (hunk) - (goto-char (magit-section-end section)) - (setf (magit-section-content section) (point-marker)) - (funcall washer) - (setf (magit-section-end section) (point-marker))))) - (magit-section-update-highlight)) - (-when-let (beg (magit-section-content section)) - (remove-overlays beg (magit-section-end section) 'invisible t)) - (dolist (child (magit-section-children section)) - (if (magit-section-hidden child) - (magit-section-hide child) - (magit-section-show child)))) - -(defun magit-section-hide (section) - "Hide the body of the current section." - (interactive (list (magit-current-section))) - (if (eq section magit-root-section) - (user-error "Cannot hide root section") - (setf (magit-section-hidden section) t) - (-when-let (beg (magit-section-content section)) - (let ((end (magit-section-end section))) - (remove-overlays beg end 'invisible t) - (let ((o (make-overlay beg end))) - (overlay-put o 'evaporate t) - (overlay-put o 'invisible t)))))) - -(defun magit-section-toggle (section) - "Toggle visibility of the body of the current section." - (interactive (list (magit-current-section))) - (if (eq section magit-root-section) - (user-error "Cannot hide root section") - (goto-char (magit-section-start section)) - (if (magit-section-hidden section) - (magit-section-show section) - (magit-section-hide section)))) - -(defun magit-section-toggle-children (section) - "Toggle visibility of bodies of children of the current section." - (interactive (list (magit-current-section))) - (goto-char (magit-section-start section)) - (let* ((children (magit-section-children section)) - (show (-any? 'magit-section-hidden children))) - (dolist (c children) - (setf (magit-section-hidden c) show))) - (magit-section-show section)) - -(defun magit-section-show-children (section &optional depth) - "Recursively show the bodies of children of the current section. -With a prefix argument show children that deep and hide deeper -children." - (interactive (list (magit-current-section))) - (magit-section-show-children-1 section depth) - (magit-section-show section)) - -(defun magit-section-show-children-1 (section &optional depth) - (dolist (s (magit-section-children section)) - (setf (magit-section-hidden s) nil) - (if depth - (if (> depth 0) - (magit-section-show-children-1 s (1- depth)) - (magit-section-hide s)) - (magit-section-show-children-1 s)))) - -(defun magit-section-hide-children (section) - "Recursively hide the bodies of children of the current section." - (interactive (list (magit-current-section))) - (mapc 'magit-section-hide (magit-section-children section))) - -(defun magit-section-show-headings (section) - "Recursively show headings of children of the current section. -Only show the headings, previously shown text-only bodies are -hidden." - (interactive (list (magit-current-section))) - (magit-section-show-headings-1 section) - (magit-section-show section)) - -(defun magit-section-show-headings-1 (section) - (dolist (s (magit-section-children section)) - (setf (magit-section-hidden s) nil) - (when (or (magit-section-children s) - (not (magit-section-content s))) - (magit-section-show-headings-1 s)))) - -(defun magit-section-cycle (section) - "Cycle visibility of current section and its children." - (interactive (list (magit-current-section))) - (goto-char (magit-section-start section)) - (if (magit-section-hidden section) - (progn (magit-section-show section) - (magit-section-hide-children section)) - (let ((children (magit-section-children section))) - (cond ((and (-any? 'magit-section-hidden children) - (-any? 'magit-section-children children)) - (magit-section-show-headings section)) - ((-any? 'magit-section-hidden-body children) - (magit-section-show-children section)) - (t - (magit-section-hide section)))))) - -(defun magit-section-cycle-global () - "Cycle visibility of all sections in the current buffer." - (interactive) - (let ((children (magit-section-children magit-root-section))) - (cond ((and (-any? 'magit-section-hidden children) - (-any? 'magit-section-children children)) - (magit-section-show-headings magit-root-section)) - ((-any? 'magit-section-hidden-body children) - (magit-section-show-children magit-root-section)) - (t - (mapc 'magit-section-hide children))))) - -(defun magit-section-cycle-diffs () - "Cycle visibility of diff-related sections in the current buffer." - (interactive) - (-when-let (sections - (cond ((derived-mode-p 'magit-status-mode) - (--mapcat - (when it - (when (magit-section-hidden it) - (magit-section-show it)) - (magit-section-children it)) - (list (magit-get-section '((staged) (status))) - (magit-get-section '((unstaged) (status)))))) - ((derived-mode-p 'magit-diff-mode) - (--filter (eq (magit-section-type it) 'file) - (magit-section-children magit-root-section))))) - (if (-any? 'magit-section-hidden sections) - (dolist (s sections) - (magit-section-show s) - (magit-section-hide-children s)) - (let ((children (cl-mapcan 'magit-section-children sections))) - (cond ((and (-any? 'magit-section-hidden children) - (-any? 'magit-section-children children)) - (mapc 'magit-section-show-headings sections)) - ((-any? 'magit-section-hidden-body children) - (mapc 'magit-section-show-children sections)) - (t - (mapc 'magit-section-hide sections))))))) - -(defun magit-section-hidden-body (section &optional pred) - (--if-let (magit-section-children section) - (funcall (or pred '-any?) 'magit-section-hidden-body it) - (and (magit-section-content section) - (magit-section-hidden section)))) - -(defun magit-section-invisible-p (section) - "Return t if the SECTION's body is invisible. -When the body of an ancestor of SECTION is collapsed then -SECTION's body (and heading) obviously cannot be visible." - (or (magit-section-hidden section) - (--when-let (magit-section-parent section) - (magit-section-invisible-p it)))) - -(defun magit-section-show-level (level) - "Show surrounding sections up to LEVEL. -If LEVEL is negative show up to the absolute value. -Sections at higher levels are hidden." - (if (< level 0) - (let ((s (magit-current-section))) - (setq level (- level)) - (while (> (1- (length (magit-section-ident s))) level) - (setq s (magit-section-parent s)) - (goto-char (magit-section-start s))) - (magit-section-show-children magit-root-section (1- level))) - (cl-do* ((s (magit-current-section) (magit-section-parent s)) - (i (1- (length (magit-section-ident s))) (cl-decf i))) - ((cond ((< i level) (magit-section-show-children s (- level i 1)) t) - ((= i level) (magit-section-hide s) t)) - (magit-section-goto s))))) - -(defun magit-section-show-level-1 () - "Show surrounding sections on first level." - (interactive) - (magit-section-show-level 1)) - -(defun magit-section-show-level-1-all () - "Show all sections on first level." - (interactive) - (magit-section-show-level -1)) - -(defun magit-section-show-level-2 () - "Show surrounding sections up to second level." - (interactive) - (magit-section-show-level 2)) - -(defun magit-section-show-level-2-all () - "Show all sections up to second level." - (interactive) - (magit-section-show-level -2)) - -(defun magit-section-show-level-3 () - "Show surrounding sections up to third level." - (interactive) - (magit-section-show-level 3)) - -(defun magit-section-show-level-3-all () - "Show all sections up to third level." - (interactive) - (magit-section-show-level -3)) - -(defun magit-section-show-level-4 () - "Show surrounding sections up to fourth level." - (interactive) - (magit-section-show-level 4)) - -(defun magit-section-show-level-4-all () - "Show all sections up to fourth level." - (interactive) - (magit-section-show-level -4)) - -;;;; Auxiliary - -(defun magit-describe-section () - "Show information about the section at point. -This command is intended for debugging purposes." - (interactive) - (let ((section (magit-current-section))) - (message "%S %S %s-%s" - (magit-section-value section) - (apply 'vector (mapcar 'car (magit-section-ident section))) - (marker-position (magit-section-start section)) - (marker-position (magit-section-end section))))) - -;;; Match - -(defun magit-section-match (condition &optional section) - "Return t if SECTION matches CONDITION. -SECTION defaults to the section at point. - -Conditions can take the following forms: - (CONDITION...) matches if any of the CONDITIONs matches. - [TYPE...] matches if the first TYPE matches the type - of the section at point, the second matches - that of its parent, and so on. - [* TYPE...] matches sections that match [TYPE...] and - also recursively all their child sections. - TYPE matches TYPE regardless of its parents. - -Each TYPE is a symbol. Note that is not necessary to specify all -TYPEs up to the root section as printed by `magit-describe-type', -unless of course your want to be that precise." - ;; When recursing SECTION actually is a type list. Matching - ;; macros also pass such a list instead of a section struct. - (let ((types (if (magit-section-p section) - (mapcar 'car (magit-section-ident section)) - section))) - (when (or types section (magit-current-section)) - (if (listp condition) - (--first (magit-section-match it types) condition) - (magit-section-match-1 (if (symbolp condition) - (list condition) - (append condition nil)) - types))))) - -(defun magit-section-match-1 (l1 l2) - (or (null l1) - (if (eq (car l1) '*) - (or (magit-section-match-1 (cdr l1) l2) - (and l2 - (magit-section-match-1 l1 (cdr l2)))) - (and l2 - (equal (car l1) (car l2)) - (magit-section-match-1 (cdr l1) (cdr l2)))))) - -(defmacro magit-section-when (condition &rest body) - "If the section at point matches CONDITION evaluate BODY. - -If the section matches evaluate BODY forms sequentially and -return the value of the last one, or if there are no BODY forms -return the value of the section. If the section does not match -return nil. - -See `magit-section-match' for the forms CONDITION can take." - (declare (indent 1) - (debug (sexp body))) - `(--when-let (magit-current-section) - (when (magit-section-match ',condition - (mapcar 'car (magit-section-ident it))) - ,@(or body '((magit-section-value it)))))) - -(defmacro magit-section-case (&rest clauses) - "Choose among clauses on the type of the section at point. - -Each clause looks like (CONDITION BODY...). The type of the -section is compared against each CONDITION; the BODY forms of the -first match are evaluated sequentially and the value of the last -form is returned. Inside BODY the symbol `it' is bound to the -section at point. If no clause succeeds or if there is no -section at point return nil. - -See `magit-section-match' for the forms CONDITION can take. -Additionall a CONDITION of t is allowed in the final clause, and -matches if no other CONDITION match, even if there is no section -at point." - (declare (indent 0) - (debug (&rest (sexp body)))) - (let ((ident (cl-gensym "id"))) - `(let* ((it (magit-current-section)) - (,ident (and it (mapcar 'car (magit-section-ident it))))) - (cond ,@(mapcar (lambda (clause) - `(,(or (eq (car clause) t) - `(and it (magit-section-match - ',(car clause) ,ident))) - ,@(cdr clause))) - clauses))))) -;;; Create - -(defvar magit-insert-section--current nil "For internal use only.") -(defvar magit-insert-section--parent nil "For internal use only.") -(defvar magit-insert-section--oldroot nil "For internal use only.") - -(defvar magit-insert-section-hook nil - "Hook run after `magit-insert-section's BODY. -Avoid using this hook and only ever do so if you know -what you are doing and are sure there is no other way.") - -(defmacro magit-insert-section (&rest args) - "Insert a section at point. - -TYPE is the section type, a symbol. Many commands that act on -the current section behave differently depending on that type. -Also if a variable `magit-TYPE-section-map' exists, then use -that as the text-property `keymap' of all text belonging to the -section (but this may be overwritten in subsections). - -Optional VALUE is the value of the section, usually a string -that is required when acting on the section. - -When optional HIDE is non-nil collapse the section body by -default, i.e. when first creating the section, but not when -refreshing the buffer. Else expand it by default. This can be -overwritten using `magit-section-set-visibility-hook'. When a -section is recreated during a refresh, then the visibility of -predecessor is inherited and HIDE is ignored (but the hook is -still honored). - -BODY is any number of forms that actually insert the section's -heading and body. Optional NAME, if specified, has to be a -symbol, which is then bound to the struct of the section being -inserted. - -Before BODY is evaluated the `start' of the section object is set -to the value of `point' and after BODY was evaluated its `end' is -set to the new value of `point'; BODY is responsible for moving -`point' forward. - -If it turns out inside BODY that the section is empty, then -`magit-cancel-section' can be used to abort and remove all traces -of the partially inserted section. This can happen when creating -a section by washing Git's output and Git didn't actually output -anything this time around. - -\(fn [NAME] (TYPE &optional VALUE HIDE) &rest BODY)" - (declare (indent defun) - (debug ([&optional symbolp] (symbolp &optional form form) body))) - (let ((s (if (symbolp (car args)) - (pop args) - (cl-gensym "section")))) - `(let* ((,s (make-magit-section - :type ',(nth 0 (car args)) - :value ,(nth 1 (car args)) - :start (point-marker) - :parent magit-insert-section--parent))) - (setf (magit-section-hidden ,s) - (-if-let (value (run-hook-with-args-until-success - 'magit-section-set-visibility-hook ,s)) - (eq value 'hide) - (--if-let (and magit-insert-section--oldroot - (magit-get-section - (magit-section-ident ,s) - magit-insert-section--oldroot)) - (magit-section-hidden it) - ,(nth 2 (car args))))) - (let ((magit-insert-section--current ,s) - (magit-insert-section--parent ,s) - (magit-insert-section--oldroot - (or magit-insert-section--oldroot - (unless magit-insert-section--parent - (prog1 magit-root-section - (setq magit-root-section ,s)))))) - (catch 'cancel-section - ,@(cdr args) - (run-hooks 'magit-insert-section-hook) - (magit-insert-child-count ,s) - (set-marker-insertion-type (magit-section-start ,s) t) - (let* ((end (setf (magit-section-end ,s) (point-marker))) - (map (intern (format "magit-%s-section-map" - (magit-section-type ,s)))) - (map (and (boundp map) (symbol-value map)))) - (save-excursion - (goto-char (magit-section-start ,s)) - (while (< (point) end) - (let ((next (or (next-single-property-change - (point) 'magit-section) - end))) - (unless (get-text-property (point) 'magit-section) - (put-text-property (point) next 'magit-section ,s) - (when map - (put-text-property (point) next 'keymap map))) - (goto-char next))))) - (if (eq ,s magit-root-section) - (magit-section-show ,s) - (setf (magit-section-children (magit-section-parent ,s)) - (nconc (magit-section-children (magit-section-parent ,s)) - (list ,s))))) - ,s)))) - -(defun magit-cancel-section () - (when magit-insert-section--current - (if (not (magit-section-parent magit-insert-section--current)) - (insert "(empty)\n") - (delete-region (magit-section-start magit-insert-section--current) - (point)) - (setq magit-insert-section--current nil) - (throw 'cancel-section nil)))) - -(defun magit-insert-heading (&rest args) - "Insert the heading for the section currently being inserted. - -This function should only be used inside `magit-insert-section'. - -When called without any arguments, then just set the `content' -slot of the object representing the section being inserted to -a marker at `point'. The section should only contain a single -line when this function is used like this. - -When called with arguments ARGS, which have to be strings, then -insert those strings at point. The section should not contain -any text before this happens and afterwards it should again only -contain a single line. If the `face' property is set anywhere -inside any of these strings, then insert all of them unchanged. -Otherwise use the `magit-section-heading' face for all inserted -text. - -The `content' property of the secton struct is the end of the -heading (which lasts from `start' to `content') and the beginning -of the the body (which lasts from `content' to `end'). If the -value of `content' is nil, then the section has no heading and -its body cannot be collapsed. If a section does have a heading -then its height must be exactly one line, including a trailing -newline character. This isn't enforced, you are responsible for -getting it right. The only exception is that this function does -insert a newline character if necessary." - (declare (indent defun)) - (when args - (let ((heading (apply #'concat args))) - (insert (if (next-single-property-change 0 'face (concat "0" heading)) - heading - (propertize heading 'face 'magit-section-heading))))) - (unless (bolp) - (insert ?\n)) - (setf (magit-section-content magit-insert-section--current) (point-marker))) - -(defvar magit-insert-headers-hook nil "For internal use only.") - -(defun magit-insert-headers (hooks) - (let ((magit-insert-section-hook - (cons 'magit-insert-remaining-headers - (if (listp magit-insert-section-hook) - magit-insert-section-hook - (list magit-insert-section-hook)))) - (magit-insert-headers-hook hooks) - wrapper) - (while (and (setq wrapper (pop magit-insert-headers-hook)) - (= (point) (point-min))) - (funcall wrapper)))) - -(defun magit-insert-remaining-headers () - (if (= (point) (point-min)) - (magit-cancel-section) - (magit-insert-heading) - (remove-hook 'magit-insert-section-hook 'magit-insert-remaining-headers) - (mapc #'funcall magit-insert-headers-hook) - (insert "\n"))) - -(defun magit-insert-child-count (section) - "Modify SECTION's heading to contain number of child sections. - -If `magit-section-show-child-count' is non-nil and the SECTION -has children and its heading ends with \":\", then replace that -with \" (N)\", where N is the number of child sections. - -This function is called by `magit-insert-section' after that has -evaluated its BODY. Admittedly that's a bit of a hack." - ;; This has to be fast, not pretty! - (let (content count) - (when (and magit-section-show-child-count - (setq count (length (magit-section-children section))) - (> count 0) - (setq content (magit-section-content section)) - (eq (char-before (1- content)) ?:)) - (save-excursion - (goto-char (- content 2)) - (insert (format " (%s)" count)) - (delete-char 1))))) - -;;; Update - -(defvar-local magit-section-highlight-overlays nil) -(defvar-local magit-section-highlighted-section nil) -(defvar-local magit-section-highlighted-sections nil) -(defvar-local magit-section-unhighlight-sections nil) - -(defun magit-section-update-region (_) - ;; Don't show complete region. Highlighting emphasizes headings. - (magit-region-sections)) - -(defun magit-section-update-highlight () - (let ((section (magit-current-section))) - (unless (eq section magit-section-highlighted-section) - (let ((inhibit-read-only t) - (deactivate-mark nil) - (selection (magit-region-sections))) - (mapc #'delete-overlay magit-section-highlight-overlays) - (setq magit-section-unhighlight-sections - magit-section-highlighted-sections - magit-section-highlighted-sections nil) - (unless (eq section magit-root-section) - (run-hook-with-args-until-success - 'magit-section-highlight-hook section selection)) - (--each magit-section-unhighlight-sections - (run-hook-with-args-until-success - 'magit-section-unhighlight-hook it selection)) - (restore-buffer-modified-p nil) - (unless (eq magit-section-highlighted-section section) - (setq magit-section-highlighted-section - (unless (magit-section-hidden section) section)))) - (setq deactivate-mark nil)))) - -(defun magit-section-highlight (section selection) - "Highlight SECTION and if non-nil all SELECTION. -This function works for any section but produces undesirable -effects for diff related sections, which by default are -highlighted using `magit-diff-highlight'. Return t." - (cond (selection - (magit-section-make-overlay (magit-section-start (car selection)) - (magit-section-end (car (last selection))) - 'magit-section-highlight) - (magit-section-highlight-selection nil selection)) - (t - (magit-section-make-overlay (magit-section-start section) - (magit-section-end section) - 'magit-section-highlight))) - t) - -(defun magit-section-highlight-selection (_ selection) - "Highlight the section selection region. -If SELECTION is non-nil then it is a list of sections selected by -the region. The headings of these sections are then highlighted. - -This is a fallback for people who don't want to highlight the -current section and therefore removed `magit-section-highlight' -from `magit-section-highlight-hook'. - -This function is necessary to ensure that a representation of -such a region is visible. If neither of these functions were -part of the hook variable, then such a region would be -invisible." - (when selection - (--each selection - (magit-section-make-overlay (magit-section-start it) - (or (magit-section-content it) - (magit-section-end it)) - 'magit-section-heading-selection)) - t)) - -(defun magit-section-make-overlay (start end face) - ;; Yes, this doesn't belong here. But the alternative of - ;; spreading this hack across the code base is even worse. - (when (and magit-keep-region-overlay - (memq face '(magit-section-heading-selection - magit-diff-file-heading-selection - magit-diff-hunk-heading-selection))) - (setq face (list :foreground (face-foreground face)))) - (let ((ov (make-overlay start end nil t))) - (overlay-put ov 'face face) - (overlay-put ov 'evaporate t) - (push ov magit-section-highlight-overlays) - ov)) - -(defun magit-section-goto-successor (section line char arg) - (let ((ident (magit-section-ident section))) - (--if-let (magit-get-section ident) - (let ((start (magit-section-start it))) - (goto-char start) - (unless (eq it magit-root-section) - (ignore-errors - (forward-line line) - (forward-char char)) - (unless (eq (magit-current-section) it) - (goto-char start)))) - (or (and (eq (magit-section-type section) 'hunk) - (-when-let (parent (magit-get-section - (magit-section-ident - (magit-section-parent section)))) - (let* ((children (magit-section-children parent)) - (siblings (magit-section-siblings section 'prev)) - (previous (nth (length siblings) children))) - (if (not arg) - (--when-let (or previous (car (last children))) - (goto-char (magit-section-start it))) - (when previous - (goto-char (magit-section-start previous))) - (if (and (stringp arg) - (re-search-forward - arg (magit-section-end parent) t)) - (goto-char (match-beginning 0)) - (goto-char (magit-section-end (car (last children)))) - (forward-line -1) - (while (looking-at "^ ") (forward-line -1)) - (while (looking-at "^[-+]") (forward-line -1)) - (forward-line)))))) - (goto-char (--if-let (magit-section-goto-successor-1 section) - (if (eq (magit-section-type it) 'button) - (point-min) - (magit-section-start it)) - (point-min))))))) - -(defun magit-section-goto-successor-1 (section) - (or (--when-let (pcase (magit-section-type section) - (`staged 'unstaged) - (`unstaged 'staged) - (`unpushed 'unpulled) - (`unpulled 'unpushed)) - (magit-get-section `((,it) (status)))) - (--when-let (car (magit-section-siblings section 'next)) - (magit-get-section (magit-section-ident it))) - (--when-let (car (magit-section-siblings section 'prev)) - (magit-get-section (magit-section-ident it))) - (--when-let (magit-section-parent section) - (or (magit-get-section (magit-section-ident it)) - (magit-section-goto-successor-1 it))))) - -;;; Utilities - -(cl-defun magit-section-selected-p (section &optional (selection nil sselection)) - (and (not (eq section magit-root-section)) - (or (eq section (magit-current-section)) - (memq section (if sselection - selection - (setq selection (magit-region-sections)))) - (--when-let (magit-section-parent section) - (magit-section-selected-p it selection))))) - -(defun magit-section-parent-value (section) - (setq section (magit-section-parent section)) - (when section (magit-section-value section))) - -(defun magit-section-siblings (section &optional direction) - "Return a list of the sibling sections of SECTION. - -If optional DIRECTION is `prev' then return siblings that come -before SECTION, if it is `next' then return siblings that come -after SECTION. For all other values return all siblings -excluding SECTION itself." - (-when-let (parent (magit-section-parent section)) - (let ((siblings (magit-section-children parent))) - (pcase direction - (`prev (cdr (member section (reverse siblings)))) - (`next (cdr (member section siblings))) - (_ (remq section siblings)))))) - -(defun magit-region-values (&rest types) - "Return a list of the values of the selected sections. - -Also see `magit-region-sections' whose doc-string explains when a -region is a valid section selection. If the region is not active -or is not a valid section selection, then return nil. If optional -TYPES is non-nil then the selection not only has to be valid; the -types of all selected sections additionally have to match one of -TYPES, or nil is returned." - (mapcar 'magit-section-value (apply 'magit-region-sections types))) - -(defun magit-region-sections (&rest types) - "Return a list of the selected sections. - -When the region is active and constitutes a valid section -selection, then return a list of all selected sections. This is -the case when the region begins in the heading of a section and -ends in the heading of a sibling of that first section. When -the selection is not valid then return nil. Most commands that -can act on the selected sections, then instead just act on the -current section, the one point is in. - -When the region looks like it would in any other buffer then -the selection is invalid. When the selection is valid then the -region uses the `magit-section-highlight'. This does not apply -to diffs were things get a bit more complicated, but even here -if the region looks like it usually does, then that's not a -valid selection as far as this function is concerned. - -If optional TYPES is non-nil then the selection not only has to -be valid; the types of all selected sections additionally have to -match one of TYPES, or nil is returned." - (when (use-region-p) - (let* ((rbeg (region-beginning)) - (rend (region-end)) - (sbeg (get-text-property rbeg 'magit-section)) - (send (get-text-property rend 'magit-section))) - (unless (memq send (list sbeg magit-root-section nil)) - (let ((siblings (magit-section-siblings sbeg 'next)) sections) - (when (and (memq send siblings) - (magit-section-position-in-heading-p sbeg rbeg) - (magit-section-position-in-heading-p send rend)) - (while siblings - (push (car siblings) sections) - (when (eq (pop siblings) send) - (setq siblings nil))) - (setq sections (cons sbeg (nreverse sections))) - (when (or (not types) - (--all-p (memq (magit-section-type it) types) sections)) - sections))))))) - -(defun magit-section-position-in-heading-p (section pos) - "Return t if POSITION is inside the heading of SECTION." - (and (>= pos (magit-section-start section)) - (< pos (or (magit-section-content section) - (magit-section-end section))) - t)) - -(defun magit-section-internal-region-p (&optional section) - "Return t if the region is active and inside SECTION's body. -If optional SECTION is nil, use the current section." - (and (region-active-p) - (or section (setq section (magit-current-section))) - (let ((beg (get-text-property (region-beginning) 'magit-section))) - (and (eq beg (get-text-property (region-end) 'magit-section)) - (eq beg section))) - (not (or (magit-section-position-in-heading-p section (region-beginning)) - (magit-section-position-in-heading-p section (region-end)))) - t)) - -(defun magit-wash-sequence (function) - "Repeatedly call FUNCTION until it returns nil or eob is reached. -FUNCTION has to move point forward or return nil." - (while (and (not (eobp)) (funcall function)))) - -(defun magit-add-section-hook (hook function &optional at append local) - "Add to the value of section hook HOOK the function FUNCTION. - -Add FUNCTION at the beginning of the hook list unless optional -APPEND is non-nil, in which case FUNCTION is added at the end. -If FUNCTION already is a member then move it to the new location. - -If optional AT is non-nil and a member of the hook list, then add -FUNCTION next to that instead. Add before or after AT depending -on APPEND. If only FUNCTION is a member of the list, then leave -it where ever it already is. - -If optional LOCAL is non-nil, then modify the hook's buffer-local -value rather than its global value. This makes the hook local by -copying the default value. That copy is then modified. - -HOOK should be a symbol. If HOOK is void, it is first set to nil. -HOOK's value must not be a single hook function. FUNCTION should -be a function that takes no arguments and inserts one or multiple -sections at point, moving point forward. FUNCTION may choose not -to insert its section(s), when doing so would not make sense. It -should not be abused for other side-effects. To remove FUNCTION -again use `remove-hook'." - (unless (boundp hook) - (error "Cannot add function to undefined hook variable %s" hook)) - (or (default-boundp hook) (set-default hook nil)) - (let ((value (if local - (if (local-variable-p hook) - (symbol-value hook) - (unless (local-variable-if-set-p hook) - (make-local-variable hook)) - (copy-sequence (default-value hook))) - (default-value hook)))) - (if at - (when (setq at (member at value)) - (setq value (delq function value)) - (if append - (push function (cdr at)) - (push (car at) (cdr at)) - (setcar at function))) - (setq value (delq function value))) - (unless (member function value) - (setq value (if append - (append value (list function)) - (cons function value)))) - (if local - (set hook value) - (set-default hook value)))) - -;;; magit-section.el ends soon -(provide 'magit-section) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-section.el ends here diff --git a/elpa/magit-20151119.202/magit-sequence.el b/elpa/magit-20151119.202/magit-sequence.el deleted file mode 100644 index 47446c13..00000000 --- a/elpa/magit-20151119.202/magit-sequence.el +++ /dev/null @@ -1,625 +0,0 @@ -;;; magit-sequence.el --- history manipulation in Magit - -;; Copyright (C) 2011-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; Support for Git commands that replay commits and help the user make -;; changes along the way. Supports `cherry-pick', `revert', `rebase', -;; `rebase--interactive' and `am'. - -;;; Code: - -(require 'magit) - -;;; Options -;;;; Faces - -(defface magit-sequence-pick - '((t :inherit default)) - "Face used in sequence sections." - :group 'magit-faces) - -(defface magit-sequence-stop - '((((class color) (background light)) :foreground "DarkOliveGreen4") - (((class color) (background dark)) :foreground "DarkSeaGreen2")) - "Face used in sequence sections." - :group 'magit-faces) - -(defface magit-sequence-part - '((((class color) (background light)) :foreground "Goldenrod4") - (((class color) (background dark)) :foreground "LightGoldenrod2")) - "Face used in sequence sections." - :group 'magit-faces) - -(defface magit-sequence-head - '((((class color) (background light)) :foreground "SkyBlue4") - (((class color) (background dark)) :foreground "LightSkyBlue1")) - "Face used in sequence sections." - :group 'magit-faces) - -(defface magit-sequence-drop - '((((class color) (background light)) :foreground "IndianRed") - (((class color) (background dark)) :foreground "IndianRed")) - "Face used in sequence sections." - :group 'magit-faces) - -(defface magit-sequence-done - '((t :inherit magit-hash)) - "Face used in sequence sections." - :group 'magit-faces) - -(defface magit-sequence-onto - '((t :inherit magit-sequence-done)) - "Face used in sequence sections." - :group 'magit-faces) - -;;; Common - -;;;###autoload -(defun magit-sequencer-continue () - "Resume the current cherry-pick or revert sequence." - (interactive) - (if (magit-sequencer-in-progress-p) - (if (magit-anything-unstaged-p t) - (user-error "Cannot continue due to unstaged changes") - (magit-run-git-sequencer - (if (magit-revert-in-progress-p) "revert" "cherry-pick") "--continue")) - (user-error "No cherry-pick or revert in progress"))) - -;;;###autoload -(defun magit-sequencer-skip () - "Skip the stopped at commit during a cherry-pick or revert sequence." - (interactive) - (if (magit-sequencer-in-progress-p) - (progn (magit-call-git "reset" "--hard") - (magit-sequencer-continue)) - (user-error "No cherry-pick or revert in progress"))) - -;;;###autoload -(defun magit-sequencer-abort () - "Abort the current cherry-pick or revert sequence. -This discards all changes made since the sequence started." - (interactive) - (if (magit-sequencer-in-progress-p) - (magit-run-git-sequencer - (if (magit-revert-in-progress-p) "revert" "cherry-pick") "--abort") - (user-error "No cherry-pick or revert in progress"))) - -(defun magit-sequencer-in-progress-p () - (or (magit-cherry-pick-in-progress-p) - (magit-revert-in-progress-p))) - -;;; Cherry-Pick - -;;;###autoload (autoload 'magit-cherry-pick-popup "magit-sequence" nil t) -(magit-define-popup magit-cherry-pick-popup - "Popup console for cherry-pick commands." - 'magit-commands - :man-page "git-cherry-pick" - :switches '((?s "Add Signed-off-by lines" "--signoff") - (?e "Edit commit messages" "--edit") - (?x "Reference cherry in commit message" "-x") - (?F "Attempt fast-forward" "--ff") - (?m "Reply merge relative to parent" "--mainline=")) - :options '((?s "Strategy" "--strategy=" read-from-minibuffer)) - :actions '((?A "Cherry Pick" magit-cherry-pick) - (?a "Cherry Apply" magit-cherry-apply)) - :sequence-actions '((?A "Continue" magit-sequencer-continue) - (?s "Skip" magit-sequencer-skip) - (?a "Abort" magit-sequencer-abort)) - :sequence-predicate 'magit-sequencer-in-progress-p - :default-arguments '("--ff")) - -(defun magit-cherry-pick-read-args (prompt) - (list (or (nreverse (magit-region-values 'commit)) - (magit-read-other-branch-or-commit prompt)) - (magit-cherry-pick-arguments))) - -;;;###autoload -(defun magit-cherry-pick (commit &optional args) - "Cherry-pick COMMIT. -Prompt for a commit, defaulting to the commit at point. If -the region selects multiple commits, then pick all of them, -without prompting." - (interactive (magit-cherry-pick-read-args "Cherry-pick")) - (magit-assert-one-parent (car (if (listp commit) - commit - (split-string commit "\\.\\."))) - "cherry-pick") - (magit-run-git-sequencer "cherry-pick" args commit)) - -;;;###autoload -(defun magit-cherry-apply (commit &optional args) - "Apply the changes in COMMIT but do not commit them. -Prompt for a commit, defaulting to the commit at point. If -the region selects multiple commits, then apply all of them, -without prompting." - (interactive (magit-cherry-pick-read-args "Apply changes from commit")) - (magit-assert-one-parent commit "cherry-pick") - (magit-run-git-sequencer "cherry-pick" "--no-commit" - (remove "--ff" args) commit)) - -(defun magit-cherry-pick-in-progress-p () - ;; .git/sequencer/todo does not exist when there is only one commit left. - (file-exists-p (magit-git-dir "CHERRY_PICK_HEAD"))) - -;;; Revert - -;;;###autoload (autoload 'magit-revert-popup "magit-sequence" nil t) -(magit-define-popup magit-revert-popup - "Popup console for revert commands." - 'magit-commands - :man-page "git-revert" - :switches '((?s "Add Signed-off-by lines" "--signoff")) - :options '((?s "Strategy" "--strategy=" read-from-minibuffer)) - :actions '((?V "Revert commit(s)" magit-revert) - (?v "Revert changes" magit-revert-no-commit)) - :sequence-actions '((?V "Continue" magit-sequencer-continue) - (?s "Skip" magit-sequencer-skip) - (?a "Abort" magit-sequencer-abort)) - :sequence-predicate 'magit-sequencer-in-progress-p) - -(defun magit-revert-read-args (prompt) - (list (or (magit-region-values 'commit) - (magit-read-branch-or-commit prompt)) - (magit-revert-arguments))) - -;;;###autoload -(defun magit-revert (commit &optional args) - "Revert COMMIT by creating a new commit. -Prompt for a commit, defaulting to the commit at point. If -the region selects multiple commits, then revert all of them, -without prompting." - (interactive (magit-revert-read-args "Revert commit")) - (magit-assert-one-parent commit "revert") - (magit-run-git-sequencer "revert" args commit)) - -;;;###autoload -(defun magit-revert-no-commit (commit &optional args) - "Revert COMMIT by applying it in reverse to the worktree. -Prompt for a commit, defaulting to the commit at point. If -the region selects multiple commits, then revert all of them, -without prompting." - (interactive (magit-revert-read-args "Revert changes")) - (magit-assert-one-parent commit "revert") - (magit-run-git-sequencer "revert" "--no-commit" args commit)) - -(defun magit-revert-in-progress-p () - ;; .git/sequencer/todo does not exist when there is only one commit left. - (file-exists-p (magit-git-dir "REVERT_HEAD"))) - -;;; Patch - -;;;###autoload (autoload 'magit-am-popup "magit-sequence" nil t) -(magit-define-popup magit-am-popup - "Popup console for mailbox commands." - 'magit-commands - :man-page "git-am" - :switches '((?3 "Fall back on 3way merge" "--3way") - (?s "Add Signed-off-by lines" "--signoff") - (?c "Remove text before scissors line" "--scissors") - (?k "Inhibit removal of email cruft" "--keep") - (?b "Limit removal of email cruft" "--keep-non-patch") - (?d "Use author date as committer date" - "--committer-date-is-author-date") - (?D "Use committer date as author date" "--ignore-date")) - :options '((?p "Remove leading slashes from paths" "-p" - magit-popup-read-number)) - :actions '((?w "Apply patches" magit-am-apply-patches) - (?m "Apply maildir" magit-am-apply-maildir)) - :default-arguments '("--3way") - :default-actions 'magit-am-apply-patches - :sequence-actions '((?w "Continue" magit-am-continue) - (?s "Skip" magit-am-skip) - (?a "Abort" magit-am-abort)) - :sequence-predicate 'magit-am-in-progress-p) - -;;;###autoload -(defun magit-am-apply-patches (&optional files args) - "Apply the patches FILES." - (interactive (list (or (magit-region-values 'file) - (list (let ((default (magit-file-at-point))) - (read-file-name - (if default - (format "Apply patch (%s): " default) - "Apply patch: ") - nil default)))) - (magit-am-arguments))) - (magit-run-git-sequencer "am" args "--" (mapcar 'expand-file-name files))) - -;;;###autoload -(defun magit-am-apply-maildir (&optional maildir args) - "Apply the patches from MAILDIR." - (interactive (list (read-file-name "Apply mbox or Maildir: ") - (magit-am-arguments))) - (magit-run-git-sequencer "am" args (expand-file-name maildir))) - -;;;###autoload -(defun magit-am-continue () - "Resume the current patch applying sequence." - (interactive) - (if (magit-am-in-progress-p) - (if (magit-anything-unstaged-p t) - (error "Cannot continue due to unstaged changes") - (magit-run-git-sequencer "am" "--continue")) - (user-error "Not applying any patches"))) - -;;;###autoload -(defun magit-am-skip () - "Skip the stopped at patch during a patch applying sequence." - (interactive) - (if (magit-am-in-progress-p) - (magit-run-git-sequencer "am" "--skip") - (user-error "Not applying any patches"))) - -;;;###autoload -(defun magit-am-abort () - "Abort the current patch applying sequence. -This discards all changes made since the sequence started." - (interactive) - (if (magit-am-in-progress-p) - (magit-run-git "am" "--abort") - (user-error "Not applying any patches"))) - -(defun magit-am-in-progress-p () - (file-exists-p (magit-git-dir "rebase-apply/applying"))) - -;;; Rebase - -;;;###autoload (autoload 'magit-rebase-popup "magit-sequence" nil t) -(magit-define-popup magit-rebase-popup - "Key menu for rebasing." - 'magit-commands - :man-page "git-rebase" - :switches '((?k "Keep empty commits" "--keep-empty") - (?p "Preserve merges" "--preserve-merges") - (?c "Lie about author date" "--committer-date-is-author-date") - (?a "Autosquash" "--autosquash") - (?A "Autostash" "--autostash") - (?i "Interactive" "--interactive")) - :actions '((?r "Rebase" magit-rebase) - (?f "Autosquash" magit-rebase-autosquash) - (?o "Rebase subset" magit-rebase-subset) - nil - (?i "Rebase interactive" magit-rebase-interactive) - (?e "Edit commit" magit-rebase-edit-commit) - (?l "Rebase unpushed" magit-rebase-unpushed) - (?w "Reword commit" magit-rebase-reword-commit)) - :sequence-actions '((?r "Continue" magit-rebase-continue) - (?s "Skip" magit-rebase-skip) - (?e "Edit" magit-rebase-edit) - (?a "Abort" magit-rebase-abort)) - :sequence-predicate 'magit-rebase-in-progress-p - :max-action-columns 2) - -;;;###autoload -(defun magit-rebase (upstream &optional args) - "Start a non-interactive rebase sequence. -All commits not in UPSTREAM are rebased." - (interactive (list (magit-read-other-branch-or-commit - "Rebase onto" - (magit-get-current-branch) - (magit-get-tracked-branch)) - (magit-rebase-arguments))) - (message "Rebasing...") - (magit-run-git-sequencer "rebase" upstream args) - (message "Rebasing...done")) - -;;;###autoload -(defun magit-rebase-subset (newbase start &optional args) - "Start a non-interactive rebase sequence. -Rebase commits from START to `HEAD' onto NEWBASE. -START has to be selected from a list of recent commits." - (interactive (list (magit-read-other-branch-or-commit - "Rebase subset onto" - (magit-get-current-branch) - (magit-get-tracked-branch)) - nil - (magit-rebase-arguments))) - (if start - (progn (message "Rebasing...") - (magit-run-git-sequencer "rebase" "--onto" newbase start args) - (message "Rebasing...done")) - (magit-log-select - `(lambda (commit) - (magit-rebase-subset ,newbase (concat commit "^") (list ,@args))) - (concat "Type %p on a commit to rebase it " - "and commits above it onto " newbase ",")))) - -(defun magit-rebase-interactive-1 (commit args message &optional editor) - (declare (indent 2)) - (when commit - (if (eq commit :merge-base) - (setq commit (--if-let (magit-get-tracked-branch) - (magit-git-string "merge-base" it "HEAD") - nil)) - (when (magit-git-failure "merge-base" "--is-ancestor" commit "HEAD") - (user-error "%s isn't an ancestor of HEAD" commit)) - (if (magit-commit-parents commit) - (setq commit (concat commit "^")) - (setq args (cons "--root" args))))) - (when (and commit - (magit-git-lines "rev-list" "--merges" (concat commit "..HEAD"))) - (magit-read-char-case "Proceed despite merge in rebase range? " nil - (?c "[c]ontinue") - (?s "[s]elect other" (setq commit nil)) - (?a "[a]bort" (user-error "Quit")))) - (if commit - (let ((process-environment process-environment)) - (when editor - (setenv "GIT_SEQUENCE_EDITOR" editor)) - (magit-run-git-sequencer "rebase" "-i" args - (unless (member "--root" args) commit))) - (magit-log-select - `(lambda (commit) - (magit-rebase-interactive-1 commit (list ,@args) ,message ,editor)) - message))) - -;;;###autoload -(defun magit-rebase-interactive (commit &optional args) - "Start an interactive rebase sequence." - (interactive (list (magit-commit-at-point) - (magit-rebase-arguments))) - (magit-rebase-interactive-1 commit args - "Type %p on a commit to rebase it and all commits above it,")) - -;;;###autoload -(defun magit-rebase-unpushed (&optional args) - "Start an interactive rebase sequence of all unpushed commits." - (interactive (list (magit-rebase-arguments))) - (magit-rebase-interactive-1 :merge-base args - "Type %p on a commit to rebase it and all commits above it,")) - -;;;###autoload -(defun magit-rebase-autosquash (&optional args) - "Combine squash and fixup commits with their intended targets." - (interactive (list (magit-rebase-arguments))) - (magit-rebase-interactive-1 :merge-base (cons "--autosquash" args) - "Type %p on a commit to squash into it and the commits above it," - "true")) - -;;;###autoload -(defun magit-rebase-edit-commit (commit &optional args) - "Edit a single older commit using rebase." - (interactive (list (magit-commit-at-point) - (magit-rebase-arguments))) - (magit-rebase-interactive-1 commit args - "Type %p on a commit to edit it," - "perl -i -p -e '++$x if not $x and s/^pick/edit/'")) - -;;;###autoload -(defun magit-rebase-reword-commit (commit &optional args) - "Reword a single older commit using rebase." - (interactive (list (magit-commit-at-point) - (magit-rebase-arguments))) - (magit-rebase-interactive-1 commit args - "Type %p on a commit to reword its message," - "perl -i -p -e '++$x if not $x and s/^pick/reword/'")) - -;;;###autoload -(defun magit-rebase-continue () - "Restart the current rebasing operation." - (interactive) - (if (magit-rebase-in-progress-p) - (if (magit-anything-unstaged-p t) - (user-error "Cannot continue rebase with unstaged changes") - (magit-run-git-sequencer "rebase" "--continue")) - (user-error "No rebase in progress"))) - -;;;###autoload -(defun magit-rebase-skip () - "Skip the current commit and restart the current rebase operation." - (interactive) - (if (magit-rebase-in-progress-p) - (magit-run-git-sequencer "rebase" "--skip") - (user-error "No rebase in progress"))) - -;;;###autoload -(defun magit-rebase-edit () - "Edit the todo list of the current rebase operation." - (interactive) - (if (magit-rebase-in-progress-p) - (magit-run-git-sequencer "rebase" "--edit-todo") - (user-error "No rebase in progress"))) - -;;;###autoload -(defun magit-rebase-abort () - "Abort the current rebase operation, restoring the original branch." - (interactive) - (if (magit-rebase-in-progress-p) - (magit-run-git "rebase" "--abort") - (user-error "No rebase in progress"))) - -(defun magit-rebase-in-progress-p () - "Return t if a rebase is in progress." - (or (file-exists-p (magit-git-dir "rebase-merge")) - (file-exists-p (magit-git-dir "rebase-apply/onto")))) - -;;; Sections - -(defun magit-insert-sequencer-sequence () - "Insert section for the on-going cherry-pick or revert sequence. -If no such sequence is in progress, do nothing." - (let ((picking (magit-cherry-pick-in-progress-p))) - (when (or picking (magit-revert-in-progress-p)) - (magit-insert-section (sequence) - (magit-insert-heading (if picking "Cherry Picking" "Reverting")) - (-when-let (lines (cdr (magit-file-lines (magit-git-dir "sequencer/todo")))) - (dolist (line (nreverse lines)) - (when (string-match "^\\(pick\\|revert\\) \\([^ ]+\\) \\(.*\\)$" line) - (magit-bind-match-strings (cmd hash msg) line - (magit-insert-section (commit hash) - (insert (propertize cmd 'face 'magit-sequence-pick) - " " (propertize hash 'face 'magit-hash) - " " msg "\n")))))) - (magit-sequence-insert-sequence - (magit-file-line (magit-git-dir (if picking - "CHERRY_PICK_HEAD" - "REVERT_HEAD"))) - (magit-file-line (magit-git-dir "sequencer/head"))) - (insert "\n"))))) - -(defun magit-insert-am-sequence () - "Insert section for the on-going patch applying sequence. -If no such sequence is in progress, do nothing." - (when (magit-am-in-progress-p) - (magit-insert-section (rebase-sequence) - (magit-insert-heading "Applying patches") - (let ((patches (nreverse (magit-rebase-patches))) - patch commit) - (while patches - (setq patch (pop patches) - commit (magit-rev-verify-commit - (cadr (split-string (magit-file-line patch))))) - (cond ((and commit patches) - (magit-sequence-insert-commit - "pick" commit 'magit-sequence-pick)) - (patches - (magit-sequence-insert-am-patch - "pick" patch 'magit-sequence-pick)) - (commit - (magit-sequence-insert-sequence commit "ORIG_HEAD")) - (t - (magit-sequence-insert-am-patch - "stop" patch 'magit-sequence-stop) - (magit-sequence-insert-sequence nil "ORIG_HEAD"))))) - (insert ?\n)))) - -(defun magit-sequence-insert-am-patch (type patch face) - (magit-insert-section (file patch) - (insert (propertize type 'face face) - ?\s (propertize (file-name-nondirectory patch) 'face 'magit-hash) - ?\n))) - -(defun magit-insert-rebase-sequence () - "Insert section for the on-going rebase sequence. -If no such sequence is in progress, do nothing." - (when (magit-rebase-in-progress-p) - (let* ((interactive (file-directory-p (magit-git-dir "rebase-merge"))) - (dir (if interactive "rebase-merge/" "rebase-apply/")) - (name (-> (concat dir "head-name") magit-git-dir magit-file-line)) - (onto (-> (concat dir "onto") magit-git-dir magit-file-line)) - (onto (or (magit-rev-name onto name) - (magit-rev-name onto "refs/heads/*") onto)) - (name (or (magit-rev-name name "refs/heads/*") name))) - (magit-insert-section (rebase-sequence) - (magit-insert-heading (format "Rebasing %s onto %s" name onto)) - (if interactive - (magit-rebase-insert-merge-sequence) - (magit-rebase-insert-apply-sequence)) - (magit-sequence-insert-sequence - (magit-file-line - (magit-git-dir - (concat dir (if interactive "stopped-sha" "original-commit")))) - onto (--map (cadr (split-string it)) - (magit-file-lines (magit-git-dir "rebase-merge/done")))) - (insert ?\n))))) - -(defun magit-rebase-insert-merge-sequence () - (dolist (line (nreverse - (magit-file-lines - (magit-git-dir "rebase-merge/git-rebase-todo")))) - (when (string-match "^\\([^# ]+\\) \\([^ ]+\\) .*$" line) - (magit-bind-match-strings (action hash) line - (magit-sequence-insert-commit action hash 'magit-sequence-pick))))) - -(defun magit-rebase-insert-apply-sequence () - (dolist (patch (nreverse (cdr (magit-rebase-patches)))) - (magit-sequence-insert-commit - "pick" (cadr (split-string (magit-file-line patch))) 'magit-sequence-pick))) - -(defun magit-rebase-patches () - (directory-files (magit-git-dir "rebase-apply") t "^[0-9]\\{4\\}$")) - -(defun magit-sequence-insert-sequence (stop onto &optional orig) - (let ((head (magit-rev-parse "HEAD")) done) - (setq onto (if onto (magit-rev-parse onto) head)) - (setq done (magit-git-lines "log" "--format=%H" (concat onto "..HEAD"))) - (when (and stop (not (member stop done))) - (let ((id (magit-patch-id stop))) - (--if-let (--first (equal (magit-patch-id it) id) done) - (setq stop it) - (cond - ((--first (magit-rev-equal it stop) done) - ;; The commit's testament has been executed. - (magit-sequence-insert-commit "void" stop 'magit-sequence-drop)) - ;; The faith of the commit is still undecided... - ((magit-anything-unmerged-p) - ;; ...and time travel isn't for the faint of heart. - (magit-sequence-insert-commit "join" stop 'magit-sequence-part)) - ((magit-anything-modified-p t) - ;; ...and the dust hasn't settled yet... - (magit-sequence-insert-commit - (let ((staged (magit-commit-tree "oO" nil "HEAD")) - (unstaged (magit-commit-worktree "oO" "--reset"))) - (cond - ;; ...but we could end up at the same tree just by committing. - ((or (magit-rev-equal staged stop) - (magit-rev-equal unstaged stop)) "goal") - ;; ...but the changes are still there, untainted. - ((or (equal (magit-patch-id staged) id) - (equal (magit-patch-id unstaged) id)) "same") - ;; ...and some changes are gone and/or others were added. - (t "work"))) - stop 'magit-sequence-part)) - ;; The commit is definitely gone... - ((--first (magit-rev-equal it stop) done) - ;; ...but all of its changes are still in effect. - (magit-sequence-insert-commit "poof" stop 'magit-sequence-drop)) - (t - ;; ...and some changes are gone and/or other changes were added. - (magit-sequence-insert-commit "gone" stop 'magit-sequence-drop))) - (setq stop nil)))) - (dolist (rev done) - (apply 'magit-sequence-insert-commit - (cond ((equal rev stop) - ;; ...but its reincarnation lives on. - ;; Or it didn't die in the first place. - (list (if (and (equal rev head) - (equal (magit-patch-id (concat stop "^")) - (magit-patch-id (car (last orig 2))))) - "stop" ; We haven't done anything yet. - "same") ; There are new commits. - rev (if (equal rev head) - 'magit-sequence-head - 'magit-sequence-stop))) - ((equal rev head) - (list "done" rev 'magit-sequence-head)) - (t - (list "done" rev 'magit-sequence-done))))) - (magit-sequence-insert-commit "onto" onto - (if (equal onto head) - 'magit-sequence-head - 'magit-sequence-onto)))) - -(defun magit-sequence-insert-commit (type hash face) - (magit-insert-section (commit hash) - (insert (propertize type 'face face) ?\s - (magit-format-rev-summary hash) ?\n))) - -;;; magit-sequence.el ends soon -(provide 'magit-sequence) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-sequence.el ends here diff --git a/elpa/magit-20151119.202/magit-stash.el b/elpa/magit-20151119.202/magit-stash.el deleted file mode 100644 index 1b639f14..00000000 --- a/elpa/magit-20151119.202/magit-stash.el +++ /dev/null @@ -1,400 +0,0 @@ -;;; magit-stash.el --- stash support for Magit - -;; Copyright (C) 2008-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; Support for Git stashes. - -;;; Code: - -(require 'magit) - -;;; Commands - -;;;###autoload (autoload 'magit-stash-popup "magit-stash" nil t) -(magit-define-popup magit-stash-popup - "Popup console for stash commands." - 'magit-commands - :man-page "git-stash" - :switches '((?u "Also save untracked files" "--include-untracked") - (?a "Also save untracked and ignored files" "--all")) - :actions '((?z "Save" magit-stash) - (?Z "Snapshot" magit-snapshot) - (?p "Pop" magit-stash-pop) - (?i "Save index" magit-stash-index) - (?I "Snapshot index" magit-snapshot-index) - (?a "Apply" magit-stash-apply) - (?w "Save worktree" magit-stash-worktree) - (?W "Snapshot worktree" magit-snapshot-worktree) - (?l "List" magit-stash-list) - (?x "Save keeping index" magit-stash-keep-index) - (?r "Snapshot to wipref" magit-wip-commit) - (?v "Show" magit-stash-show) - (?b "Branch" magit-stash-branch) - (?k "Drop" magit-stash-drop) nil - (?f "Format patch" magit-stash-format-patch)) - :default-action 'magit-stash - :max-action-columns 3) - -;;;###autoload -(defun magit-stash (message &optional include-untracked) - "Create a stash of the index and working tree. -Untracked files are included according to popup arguments. -One prefix argument is equivalent to `--include-untracked' -while two prefix arguments are equivalent to `--all'." - (interactive (magit-stash-read-args)) - (magit-stash-save message t t include-untracked t)) - -;;;###autoload -(defun magit-stash-index (message) - "Create a stash of the index only. -Unstaged and untracked changes are not stashed. The stashed -changes are applied in reverse to both the index and the -worktree. This command can fail when the worktree is not clean. -Applying the resulting stash has the inverse effect." - (interactive (list (magit-stash-read-message))) - (magit-stash-save message t nil nil t 'worktree)) - -;;;###autoload -(defun magit-stash-worktree (message &optional include-untracked) - "Create a stash of the working tree only. -Untracked files are included according to popup arguments. -One prefix argument is equivalent to `--include-untracked' -while two prefix arguments are equivalent to `--all'." - (interactive (magit-stash-read-args)) - (magit-stash-save message nil t include-untracked t 'index)) - -;;;###autoload -(defun magit-stash-keep-index (message &optional include-untracked) - "Create a stash of the index and working tree, keeping index intact. -Untracked files are included according to popup arguments. -One prefix argument is equivalent to `--include-untracked' -while two prefix arguments are equivalent to `--all'." - (interactive (magit-stash-read-args)) - (magit-stash-save message t t include-untracked t 'index)) - -(defun magit-stash-read-args () - (list (magit-stash-read-message) - (magit-stash-read-untracked))) - -(defun magit-stash-read-untracked () - (let ((prefix (prefix-numeric-value current-prefix-arg)) - (args (magit-stash-arguments))) - (cond ((or (= prefix 16) (member "--all" args)) 'all) - ((or (= prefix 4) (member "--include-untracked" args)) t)))) - -(defun magit-stash-read-message () - (let* ((default (format "On %s: " - (or (magit-get-current-branch) "(no branch)"))) - (input (magit-read-string "Stash message" default))) - (if (equal input default) - (concat default (magit-rev-format "%h %s")) - input))) - -;;;###autoload -(defun magit-snapshot (&optional include-untracked) - "Create a snapshot of the index and working tree. -Untracked files are included according to popup arguments. -One prefix argument is equivalent to `--include-untracked' -while two prefix arguments are equivalent to `--all'." - (interactive (magit-snapshot-read-args)) - (magit-snapshot-save t t include-untracked t)) - -;;;###autoload -(defun magit-snapshot-index () - "Create a snapshot of the index only. -Unstaged and untracked changes are not stashed." - (interactive) - (magit-snapshot-save t nil nil t)) - -;;;###autoload -(defun magit-snapshot-worktree (&optional include-untracked) - "Create a snapshot of the working tree only. -Untracked files are included according to popup arguments. -One prefix argument is equivalent to `--include-untracked' -while two prefix arguments are equivalent to `--all'." - (interactive (magit-snapshot-read-args)) - (magit-snapshot-save nil t include-untracked t)) - -(defun magit-snapshot-read-args () - (list (magit-stash-read-untracked))) - -(defun magit-snapshot-save (index worktree untracked &optional refresh) - (magit-stash-save (concat "WIP on " (magit-stash-summary)) - index worktree untracked refresh t)) - -;;;###autoload -(defun magit-stash-apply (stash) - "Apply a stash to the working tree. -Try to preserve the stash index. If that fails because there -are staged changes, apply without preserving the stash index." - (interactive (list (magit-read-stash "Apply stash" t))) - (if (= (magit-call-git "stash" "apply" "--index" stash) 0) - (magit-refresh) - (magit-run-git "stash" "apply" stash))) - -(defun magit-stash-pop (stash) - "Apply a stash to the working tree and remove it from stash list. -Try to preserve the stash index. If that fails because there -are staged changes, apply without preserving the stash index -and forgo removing the stash." - (interactive (list (magit-read-stash "Apply pop" t))) - (if (= (magit-call-git "stash" "apply" "--index" stash) 0) - (magit-stash-drop stash) - (magit-run-git "stash" "apply" stash))) - -;;;###autoload -(defun magit-stash-drop (stash) - "Remove a stash from the stash list. -When the region is active offer to drop all contained stashes." - (interactive (list (--if-let (magit-region-values 'stash) - (magit-confirm t nil "Drop %i stashes" it) - (magit-read-stash "Drop stash")))) - (dolist (stash (if (listp stash) - (nreverse (prog1 stash (setq stash (car stash)))) - (list stash))) - (message "Deleted refs/%s (was %s)" stash - (magit-rev-parse "--short" stash)) - (magit-call-git "reflog" "delete" "--updateref" "--rewrite" stash)) - (-when-let (ref (and (string-match "\\(.+\\)@{[0-9]+}$" stash) - (match-string 1 stash))) - (unless (string-match "^refs/" ref) - (setq ref (concat "refs/" ref))) - (unless (magit-rev-verify (concat ref "@{0}")) - (magit-run-git "update-ref" "-d" ref))) - (magit-refresh)) - -;;;###autoload -(defun magit-stash-clear (ref) - "Remove all stashes saved in REF's reflog by deleting REF." - (interactive - (let ((ref (or (magit-section-when 'stashes) "refs/stash"))) - (if (magit-confirm t (format "Drop all stashes in %s" ref)) - (list ref) - (user-error "Abort")))) - (magit-run-git "update-ref" "-d" ref)) - -;;;###autoload -(defun magit-stash-branch (stash branch) - "Create and checkout a new BRANCH from STASH." - (interactive (list (magit-read-stash "Branch stash" t) - (magit-read-string-ns "Branch name"))) - (magit-run-git "stash" "branch" branch stash)) - -;;;###autoload -(defun magit-stash-format-patch (stash) - "Create a patch from STASH" - (interactive (list (magit-read-stash "Create patch from stash" t))) - (with-temp-file (magit-rev-format "0001-%f.patch" stash) - (magit-git-insert "stash" "show" "-p" stash)) - (magit-refresh)) - -;;; Plumbing - -(defun magit-stash-save (message index worktree untracked - &optional refresh keep noerror ref) - (if (or (and index (magit-staged-files t)) - (and worktree (magit-modified-files t)) - (and untracked (magit-untracked-files (eq untracked 'all)))) - (magit-with-toplevel - (magit-stash-store message (or ref "refs/stash") - (magit-stash-create message index worktree untracked)) - (if (eq keep 'worktree) - (with-temp-buffer - (magit-git-insert "diff" "--cached") - (magit-run-git-with-input nil - "apply" "--reverse" "--cached" "--ignore-space-change" "-") - (magit-run-git-with-input nil - "apply" "--reverse" "--ignore-space-change" "-")) - (unless (eq keep t) - (if (eq keep 'index) - (magit-call-git "checkout" "--" ".") - (magit-call-git "reset" "--hard" "HEAD")) - (when untracked - (magit-call-git "clean" "-f" (and (eq untracked 'all) "-x"))))) - (when refresh - (magit-refresh))) - (unless noerror - (user-error "No %s changes to save" (cond ((not index) "unstaged") - ((not worktree) "staged") - (t "local")))))) - -(defun magit-stash-store (message ref commit) - (magit-reflog-enable ref t) - (unless (magit-git-success "update-ref" "-m" message ref commit - (or (magit-rev-verify ref) "")) - (error "Cannot update %s with %s" ref commit))) - -(defun magit-stash-create (message index worktree untracked) - (unless (magit-rev-parse "--verify" "HEAD") - (error "You do not have the initial commit yet")) - (let ((magit-git-global-arguments (nconc (list "-c" "commit.gpgsign=false") - magit-git-global-arguments)) - (default-directory (magit-toplevel)) - (summary (magit-stash-summary)) - (head "HEAD")) - (when (and worktree (not index)) - (setq head (magit-commit-tree "pre-stash index" nil "HEAD"))) - (or (setq index (magit-commit-tree (concat "index on " summary) nil head)) - (error "Cannot save the current index state")) - (and untracked - (setq untracked (magit-untracked-files (eq untracked 'all))) - (setq untracked (magit-with-temp-index nil nil - (or (and (magit-update-files untracked) - (magit-commit-tree - (concat "untracked files on " summary))) - (error "Cannot save the untracked files"))))) - (magit-with-temp-index index "-m" - (when worktree - (or (magit-update-files (magit-git-items "diff" "-z" "--name-only" head)) - (error "Cannot save the current worktree state"))) - (or (magit-commit-tree message nil head index untracked) - (error "Cannot save the current worktree state"))))) - -(defun magit-stash-summary () - (concat (or (magit-get-current-branch) "(no branch)") - ": " (magit-rev-format "%h %s"))) - -;;; Sections - -(defvar magit-stashes-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-delete-thing] 'magit-stash-clear) - map) - "Keymap for `stashes' section.") - -(defvar magit-stash-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-visit-thing] 'magit-stash-show) - (define-key map [remap magit-delete-thing] 'magit-stash-drop) - (define-key map "a" 'magit-stash-apply) - (define-key map "A" 'magit-stash-pop) - map) - "Keymap for `stash' sections.") - -(magit-define-section-jumper stashes "Stashes" "refs/stash") - -(cl-defun magit-insert-stashes (&optional (ref "refs/stash") - (heading "Stashes:")) - "Insert `stashes' section showing reflog for \"refs/stash\". -If optional REF is non-nil show reflog for that instead. -If optional HEADING is non-nil use that as section heading -instead of \"Stashes:\"." - (when (magit-rev-verify ref) - (magit-insert-section (stashes ref (not magit-status-expand-stashes)) - (magit-insert-heading heading) - (magit-git-wash (apply-partially 'magit-log-wash-log 'stash) - "reflog" "--format=%gd %at %gs" ref)))) - -;;; List Stashes - -;;;###autoload -(defun magit-stash-list () - "List all stashes in a buffer." - (interactive) - (magit-mode-setup #'magit-stashes-mode "refs/stash")) - -(define-derived-mode magit-stashes-mode magit-reflog-mode "Magit Stashes" - "Mode for looking at lists of stashes." - :group 'magit-log - (hack-dir-local-variables-non-file-buffer)) - -(cl-defun magit-stashes-refresh-buffer (ref) - (magit-insert-section (stashesbuf) - (magit-insert-heading (if (equal ref "refs/stash") - "Stashes:" - (format "Stashes [%s]:" ref))) - (magit-git-wash (apply-partially 'magit-log-wash-log 'stash) - "reflog" "--format=%gd %at %gs" ref))) - -;;; Show Stash - -(defcustom magit-stash-sections-hook - '(magit-insert-stash-worktree - magit-insert-stash-index - magit-insert-stash-untracked) - "Hook run to insert sections into stash buffers." - :package-version '(magit . "2.1.0") - :group 'magit-log - :type 'hook) - -;;;###autoload -(defun magit-stash-show (stash &optional args files) - "Show all diffs of a stash in a buffer." - (interactive (cons (or (and (not current-prefix-arg) - (magit-stash-at-point)) - (magit-read-stash "Show stash")) - (-let [(args files) (magit-diff-arguments)] - (list (delete "--stat" args) files)))) - (magit-mode-setup #'magit-stash-mode stash nil args files)) - -(define-derived-mode magit-stash-mode magit-diff-mode "Magit Stash" - "Mode for looking at individual stashes." - :group 'magit-diff - (hack-dir-local-variables-non-file-buffer)) - -(defun magit-stash-refresh-buffer (stash _const args files) - (setq header-line-format - (concat - "\s" (propertize (capitalize stash) 'face 'magit-section-heading) - "\s" (magit-rev-format "%s" stash))) - (magit-insert-section (stash) - (run-hooks 'magit-stash-sections-hook))) - -(defun magit-stash-insert-section (commit range message &optional files) - (magit-insert-section (commit commit) - (magit-insert-heading message) - (magit-git-wash #'magit-diff-wash-diffs - "diff" (cdr magit-refresh-args) "--no-prefix" "-u" range "--" files))) - -(defun magit-insert-stash-index () - "Insert section showing the index commit of the stash." - (let ((stash (car magit-refresh-args))) - (magit-stash-insert-section (format "%s^2" stash) - (format "%s^..%s^2" stash stash) - "Index"))) - -(defun magit-insert-stash-worktree () - "Insert section showing the worktree commit of the stash." - (let ((stash (car magit-refresh-args))) - (magit-stash-insert-section stash - (format "%s^2..%s" stash stash) - "Working tree"))) - -(defun magit-insert-stash-untracked () - "Insert section showing the untracked files commit of the stash." - (let ((stash (car magit-refresh-args)) - (rev (concat (car magit-refresh-args) "^3"))) - (when (magit-rev-verify rev) - (magit-stash-insert-section (format "%s^3" stash) - (format "%s^..%s^3" stash stash) - "Untracked files" - (magit-git-items "ls-tree" "-z" "--name-only" - "--full-tree" rev))))) - -;;; magit-stash.el ends soon -(provide 'magit-stash) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-stash.el ends here diff --git a/elpa/magit-20151119.202/magit-utils.el b/elpa/magit-20151119.202/magit-utils.el deleted file mode 100644 index aed42851..00000000 --- a/elpa/magit-20151119.202/magit-utils.el +++ /dev/null @@ -1,408 +0,0 @@ -;;; magit-utils.el --- various utilities - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; Contains code from GNU Emacs https://www.gnu.org/software/emacs, -;; released under the GNU General Public License version 3 or later. - -;; 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: - -;; This library defines several utility functions used by several -;; other libraries which cannot depend on one another (because -;; circular dependencies are not good). Luckily most (all) of these -;; functions have very little (nothing) to do with Git, so we not only -;; have to do this, it even makes sense. - -;; Unfortunately there are also some options which are used by several -;; libraries which cannot depend on one another, they are defined here -;; too. - -;;; Code: - -(require 'cl-lib) -(require 'dash) - -(eval-when-compile (require 'ido)) -(declare-function ido-completing-read+ 'ido-completing-read+) - -(defvar magit-wip-before-change-mode) - -;;; Options - -(defcustom magit-completing-read-function 'magit-builtin-completing-read - "Function to be called when requesting input from the user." - :group 'magit - :type '(radio (function-item magit-builtin-completing-read) - (function-item magit-ido-completing-read) - (function-item helm-completing-read-with-cands-in-buffer) - (function :tag "Other"))) - -(defcustom magit-no-confirm nil - "A list of symbols for actions Magit should not confirm, or t. - -Many potentially dangerous commands by default ask the user for -confirmation. Each of the below symbols stands for an action -which, when invoked unintentionally or without being fully aware -of the consequences, could lead to tears. In many cases there -are several commands that perform variations of a certain action, -so we don't use the command names but more generic symbols. - -Applying changes: - - `discard' Discarding one or more changes (i.e. hunks or the - complete diff for a file) loses that change, obviously. - - `reverse' Reverting one or more changes can usually be undone - by reverting the reversion. - - `stage-all-changes', `unstage-all-changes' When there are both - staged and unstaged changes, then un-/staging everything would - destroy that distinction. Of course that also applies when - un-/staging a single change, but then less is lost and one does - that so often that having to confirm every time would be - unacceptable. - -Files: - - `delete' When a file that isn't yet tracked by Git is deleted - then it is completely lost, not just the last changes. Very - dangerous. - - `trash' Instead of deleting a file it can also be move to the - system trash. Obviously much less dangerous than deleting it. - - Also see option `magit-delete-by-moving-to-trash'. - - `resurrect' A deleted file can easily be resurrected by - \"deleting\" the deletion, which is done using the same command - that was used to delete the same file in the first place. - - `rename' Renaming a file can easily be undone. - -Sequences: - - `reset-bisect' Aborting (known to Git as \"resetting\") a - bisect operation loses all information collected so far. - - `abort-merge' Aborting a merge throws away all conflict - resolutions which has already been carried out by the user. - - `merge-dirty' Merging with a dirty worktree can make it hard to - go back to the state before the merge was initiated. - -References: - - `delete-unmerged-branch' Once a branch has been deleted it can - only be restored using low-level recovery tools provided by - Git. And even then the reflog is gone. The user always has - to confirm the deletion of a branch by accepting the default - choice (or selecting another branch), but when a branch has - not been merged yet, also make sure the user is aware of that. - - `drop-stashes' Dropping a stash is dangerous because Git stores - stashes in the reflog. Once a stash is removed, there is no - going back without using low-level recovery tools provided by - Git. When a single stash is dropped, then the user always has - to confirm by accepting the default (or selecting another). - This action only concerns the deletion of multiple stashes at - once. - -Various: - - `kill-process' There seldom is a reason to kill a process. - -Global settings: - - Instead of adding all of the above symbols to the value of this - option you can also set it to the atom `t', which has the same - effect as adding all of the above symbols. Doing that most - certainly is a bad idea, especially because other symbols might - be added in the future. So even if you don't want to be asked - for confirmation for any of these actions, you are still better - of adding all of the respective symbols individually. - - When `magit-wip-before-change-mode' is enabled then these actions - can fairly easily be undone: `discard', `reverse', - `stage-all-changes', and `unstage-all-changes'. If and only if - this mode is enabled then `safe-with-wip' has the same effect - as adding all of these symbols individually." - :package-version '(magit . "2.1.0") - :group 'magit - :type '(choice (const :tag "No confirmation needed" t) - (set (const reverse) (const discard) - (const rename) (const resurrect) - (const trash) (const delete) - (const abort-merge) (const merge-dirty) - (const drop-stashes) (const resect-bisect) - (const kill-process) (const delete-unmerged-branch) - (const stage-all-changes) (const unstage-all-changes) - (const safe-with-wip)))) - -(defcustom magit-ellipsis ?… - "Character used to abreviate text." - :package-version '(magit . "2.1.0") - :group 'magit-modes - :type 'character) - -(defcustom magit-update-other-window-delay 0.2 - "Delay before automatically updating the other window. - -When moving around in certain buffers certain other buffers, -which are being displayed in another window, may optionally be -updated to display information about the section at point. - -When holding down a key to move by more than just one section, -then that would update that buffer for each section on the way. -To prevent that, updating the revision buffer is delayed, and -this option controls for how long. For optimal experience you -might have to adjust this delay and/or the keyboard repeat rate -and delay of your graphical environment or operating system." - :package-version '(magit . "2.3.0") - :group 'magit-modes - :type 'number) - -;;; User Input - -(defun magit-completing-read - (prompt collection &optional predicate require-match initial-input hist def) - "Magit wrapper around `completing-read' or an alternative function. - -Option `magit-completing-read-function' can be used to wrap -around another `completing-read'-like function. Unless it -doesn't have the exact same signature, an additional wrapper is -required. Even if it has the same signature it might be a good -idea to wrap it, so that `magit-prompt-with-default' can be used. - -See `completing-read' for the meanings of the arguments, but note -that this wrapper makes the following changes: - -- If REQUIRE-MATCH is nil and the user exits without a choice, - then return nil instead of an empty string. - -- If REQUIRE-MATCH is non-nil and the users exits without a - choice, then raise an user-error. - -- \": \" is appended to PROMPT. - -- If a `magit-completing-read-function' is used which in turn - uses `magit-prompt-with-completion' and DEF is non-nil, then - PROMPT is modified to end with \" (default DEF): \". - -The use of another completing function and/or wrapper obviously -results in additional differences." - (let ((reply (funcall magit-completing-read-function - (concat prompt ": ") collection predicate - require-match initial-input hist def))) - (if (string= reply "") - (if require-match - (user-error "Nothing selected") - nil) - reply))) - -(defun magit-builtin-completing-read - (prompt choices &optional predicate require-match initial-input hist def) - "Magit wrapper for standard `completing-read' function." - (completing-read (magit-prompt-with-default prompt def) - choices predicate require-match - initial-input hist def)) - -(defun magit-ido-completing-read - (prompt choices &optional predicate require-match initial-input hist def) - "Ido-based `completing-read' almost-replacement. - -Unfortunately `ido-completing-read' is not suitable as a -drop-in replacement for `completing-read', instead we use -`ido-completing-read+' from the third-party package by the -same name." - (if (require 'ido-completing-read+ nil t) - (ido-completing-read+ prompt choices predicate require-match - initial-input hist def) - (display-warning 'magit "ido-completing-read+ is not installed - -To use Ido completion with Magit you need to install the -third-party `ido-completing-read+' packages. Falling -back to built-in `completing-read' for now." :error) - (magit-builtin-completing-read prompt choices predicate require-match - initial-input hist def))) - -(defun magit-prompt-with-default (prompt def) - (if (and def (> (length prompt) 2) - (string-equal ": " (substring prompt -2))) - (format "%s (default %s): " (substring prompt 0 -2) def) - prompt)) - -(defvar magit-minibuffer-local-ns-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map minibuffer-local-map) - (define-key map "\s" 'magit-whitespace-disallowed) - (define-key map "\t" 'magit-whitespace-disallowed) - map)) - -(defun magit-whitespace-disallowed () - "Beep to tell the user that whitespace is not allowed." - (interactive) - (ding) - (message "Whitespace isn't allowed here") - (setq defining-kbd-macro nil) - (force-mode-line-update)) - -(defun magit-read-string (prompt &optional initial-input history default-value - inherit-input-method no-whitespace) - "Read a string from the minibuffer, prompting with string PROMPT. - -This is similar to `read-string', but -* empty input is only allowed if DEFAULT-VALUE is non-nil in - which case that is returned, -* whitespace is not allowed if NO-WHITESPACE is non-nil, -* \": \" is appended to PROMPT, and -* an invalid DEFAULT-VALUE is silently ignored." - (when default-value - (when (consp default-value) - (setq default-value (car default-value))) - (unless (stringp default-value) - (setq default-value nil))) - (let* ((minibuffer-completion-table nil) - (val (read-from-minibuffer - (magit-prompt-with-default (concat prompt ": ") default-value) - initial-input (and no-whitespace magit-minibuffer-local-ns-map) - nil history default-value inherit-input-method))) - (when (and (string= val "") default-value) - (setq val default-value)) - (cond ((string= val "") - (user-error "Need non-empty input")) - ((and no-whitespace (string-match-p "[\s\t\n]" val)) - (user-error "Input contains whitespace")) - (t val)))) - -(defun magit-read-string-ns (prompt &optional initial-input history - default-value inherit-input-method) - "Call `magit-read-string' with non-nil NO-WHITESPACE." - (magit-read-string prompt initial-input history default-value - inherit-input-method t)) - -(defmacro magit-read-char-case (prompt verbose &rest clauses) - (declare (indent 2) - (debug (form form &rest (characterp form body)))) - `(pcase (read-char-choice - (concat ,prompt - ,(concat (mapconcat 'cadr clauses ", ") - (and verbose ", or [C-g] to abort") " ")) - ',(mapcar 'car clauses)) - ,@(--map `(,(car it) ,@(cddr it)) clauses))) - -(cl-defun magit-confirm (action &optional prompt prompt-n (items nil sitems)) - (declare (indent defun)) - (setq prompt-n (format (concat (or prompt-n prompt) "? ") (length items)) - prompt (format (concat (or prompt (magit-confirm-make-prompt action)) - "? ") - (car items))) - (cond ((and (not (eq action t)) - (or (eq magit-no-confirm t) - (memq action - `(,@magit-no-confirm - ,@(and magit-wip-before-change-mode - (memq 'safe-with-wip magit-no-confirm) - `(discard reverse - stage-all-changes - unstage-all-changes)))))) - (or (not sitems) items)) - ((not sitems) - (y-or-n-p prompt)) - ((= (length items) 1) - (and (y-or-n-p prompt) items)) - ((> (length items) 1) - (let ((buffer (get-buffer-create " *Magit Confirm*"))) - (with-current-buffer buffer - (with-current-buffer-window - buffer (cons 'display-buffer-below-selected - '((window-height . fit-window-to-buffer))) - (lambda (window _value) - (with-selected-window window - (unwind-protect (and (y-or-n-p prompt-n) items) - (when (window-live-p window) - (quit-restore-window window 'kill))))) - (dolist (item items) - (insert item "\n")))))))) - -(defun magit-confirm-files (action files &optional prompt) - (when files - (unless prompt - (setq prompt (magit-confirm-make-prompt action))) - (magit-confirm action - (concat prompt " %s") - (concat prompt " %i files") - files))) - -(defun magit-confirm-make-prompt (action) - (let ((prompt (symbol-name action))) - (replace-regexp-in-string - "-" " " (concat (upcase (substring prompt 0 1)) (substring prompt 1))))) - -;;; Text Utilities - -(defmacro magit-bind-match-strings (varlist string &rest body) - "Bind varibles to submatches accoring to VARLIST then evaluate BODY. -Bind the symbols in VARLIST to submatches of the current match -data, starting with 1 and incrementing by 1 for each symbol. If -the last match was against a string then that has to be provided -as STRING." - (declare (indent 2) (debug (listp form body))) - (let ((s (cl-gensym "string")) - (i 0)) - `(let ((,s ,string)) - (let ,(save-match-data - (--map (list it (list 'match-string (cl-incf i) s)) varlist)) - ,@body)))) - -(defun magit-delete-line () - "Delete the rest of the current line." - (delete-region (point) (1+ (line-end-position)))) - -(defun magit-delete-match (&optional num) - "Delete text matched by last search. -If optional NUM is specified only delete that subexpression." - (delete-region (match-beginning (or num 0)) - (match-end (or num 0)))) - -(defun magit-file-line (file) - "Return the first line of FILE as a string." - (when (file-regular-p file) - (with-temp-buffer - (insert-file-contents file) - (buffer-substring-no-properties (point-min) - (line-end-position))))) - -(defun magit-file-lines (file &optional keep-empty-lines) - "Return a list of strings containing one element per line in FILE. -Unless optional argument KEEP-EMPTY-LINES is t, trim all empty lines." - (when (file-regular-p file) - (with-temp-buffer - (insert-file-contents file) - (split-string (buffer-string) "\n" (not keep-empty-lines))))) - -;;; magit-utils.el ends soon -(provide 'magit-utils) -;; Local Variables: -;; coding: utf-8 -;; indent-tabs-mode: nil -;; End: -;;; magit-utils.el ends here diff --git a/elpa/magit-20151119.202/magit-wip.el b/elpa/magit-20151119.202/magit-wip.el deleted file mode 100644 index 26caa3c9..00000000 --- a/elpa/magit-20151119.202/magit-wip.el +++ /dev/null @@ -1,289 +0,0 @@ -;;; magit-wip.el --- commit snapshots to work-in-progress refs - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; 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: - -;; This library defines tree global modes which automatically commit -;; snapshots to branch specific work-in-progress refs before and after -;; making changes, and two commands which can be used to do so on -;; demand. - -;;; Code: - -(require 'magit-core) -(require 'magit-log) - -;;; Options - -(defgroup magit-wip nil - "Automatically commit to work-in-progress refs." - :group 'magit-extensions) - -(defcustom magit-wip-after-save-local-mode-lighter " sWip" - "Lighter for Magit-Wip-After-Save-Local mode." - :package-version '(magit . "2.1.0") - :group 'magit-wip - :type 'string) - -(defcustom magit-wip-after-apply-mode-lighter " aWip" - "Lighter for Magit-Wip-After-Apply mode." - :package-version '(magit . "2.1.0") - :group 'magit-wip - :type 'string) - -(defcustom magit-wip-before-change-mode-lighter " cWip" - "Lighter for Magit-Wip-Before-Change mode." - :package-version '(magit . "2.1.0") - :group 'magit-wip - :type 'string) - -(defcustom magit-wip-namespace "refs/wip/" - "Namespace used for work-in-progress refs. -The wip refs are named \"index/\" -and \"wtree/\". When snapshots -are created while the `HEAD' is detached then \"HEAD\" -is used as `branch-ref'." - :package-version '(magit . "2.1.0") - :group 'magit-wip - :type 'string) - -;;; Modes - -(define-minor-mode magit-wip-after-save-local-mode - "After saving, also commit to a worktree work-in-progress ref. - -After saving the current file-visiting buffer this mode also -commits the changes to the worktree work-in-progress ref for -the current branch. - -This mode should be enabled globally by turning on the globalized -variant `magit-wip-after-save-mode'." - :package-version '(magit . "2.1.0") - :lighter magit-wip-after-save-local-mode-lighter - (if magit-wip-after-save-local-mode - (if (and buffer-file-name (magit-inside-worktree-p)) - (add-hook 'after-save-hook 'magit-wip-commit-buffer-file t t) - (setq magit-wip-after-save-local-mode nil) - (user-error "Need a worktree and a file")) - (remove-hook 'after-save-hook 'magit-wip-commit-buffer-file t))) - -(defun magit-wip-after-save-local-mode-turn-on () - (and buffer-file-name - (ignore-errors (magit-inside-worktree-p)) - (magit-file-tracked-p buffer-file-name) - (magit-wip-after-save-local-mode))) - -;;;###autoload -(define-globalized-minor-mode magit-wip-after-save-mode - magit-wip-after-save-local-mode magit-wip-after-save-local-mode-turn-on - :package-version '(magit . "2.1.0") - :group 'magit-wip) - -(defun magit-wip-commit-buffer-file () - "Commit visited file to a worktree work-in-progress ref. - -Also see `magit-wip-after-save-mode' which calls this function -automatically whenever a buffer visiting a tracked file is saved." - (interactive) - (--when-let (magit-wip-get-ref) - (magit-with-toplevel - (let ((file (file-relative-name buffer-file-name))) - (magit-wip-commit-worktree - it (list file) (if (called-interactively-p 'any) - (format "wip-save %s after save" file) - (format "autosave %s after save" file))))))) - -;;;###autoload -(define-minor-mode magit-wip-after-apply-mode - "Commit to work-in-progress refs. - -After applying a change using any \"apply variant\" -command (apply, stage, unstage, discard, and reverse) commit the -affected files to the current wip refs. For each branch there -may be two wip refs; one contains snapshots of the files as found -in the worktree and the other contains snapshots of the entries -in the index." - :package-version '(magit . "2.1.0") - :group 'magit-wip - :lighter magit-wip-after-change-mode-lighter - :global t) - -(defun magit-wip-commit-after-apply (&optional files msg) - (when magit-wip-after-apply-mode - (magit-wip-commit files msg))) - -;;;###autoload -(define-minor-mode magit-wip-before-change-mode - "Commit to work-in-progress refs before certain destructive changes. - -Before invoking a revert command or an \"apply variant\" -command (apply, stage, unstage, discard, and reverse) commit the -affected tracked files to the current wip refs. For each branch -there may be two wip refs; one contains snapshots of the files -as found in the worktree and the other contains snapshots of the -entries in the index. - -Only changes to files which could potentially be affected by the -command which is about to be called are committed." - :package-version '(magit . "2.1.0") - :group 'magit-wip - :lighter magit-wip-before-change-mode-lighter - :global t) - -(defun magit-wip-commit-before-change (&optional files msg) - (when magit-wip-before-change-mode - (magit-with-toplevel - (magit-wip-commit files msg)))) - -;;; Core - -(defun magit-wip-commit (&optional files msg) - "Commit all tracked files to the work-in-progress refs. - -Interactively, commit all changes to all tracked files using -a generic commit message. With a prefix-argument the commit -message is read in the minibuffer. - -Non-interactively, only commit changes to FILES using MSG as -commit message." - (interactive (list nil (if current-prefix-arg - (magit-read-string "Wip commit message") - "wip-save tracked files"))) - (--when-let (magit-wip-get-ref) - (magit-wip-commit-index it files msg) - (magit-wip-commit-worktree it files msg))) - -(defun magit-wip-commit-index (ref files msg &optional cached-only) - (let* ((wipref (concat magit-wip-namespace "index/" ref)) - (parent (magit-wip-get-parent ref wipref))) - (when (magit-git-failure "diff-index" "--quiet" - (and cached-only "--cached") - parent "--" files) - (magit-wip-update-wipref wipref (magit-git-string "write-tree") - parent files msg "index")))) - -(defun magit-wip-commit-worktree (ref files msg) - (let* ((wipref (concat magit-wip-namespace "wtree/" ref)) - (parent (magit-wip-get-parent ref wipref)) - (tree (magit-with-temp-index parent "--reset" - (if files - (magit-call-git "add" "--" files) - (magit-with-toplevel - (magit-call-git "add" "-u" "."))) - (magit-git-string "write-tree")))) - (when (magit-git-failure "diff-tree" "--quiet" parent tree "--" files) - (magit-wip-update-wipref wipref tree parent files msg "worktree")))) - -(defun magit-wip-update-wipref (wipref tree parent files msg start-msg) - (let ((len (length files))) - (unless (and msg (not (= (aref msg 0) ?\s))) - (setq msg (concat - (cond ((= len 0) "autosave tracked files") - ((> len 1) (format "autosave %s files" len)) - (t (concat "autosave " - (file-relative-name (car files) - (magit-toplevel))))) - msg))) - (magit-reflog-enable wipref) - (unless (equal parent wipref) - (setq start-msg (concat "restart autosaving " start-msg)) - (magit-call-git "update-ref" wipref "-m" start-msg - (magit-git-string "commit-tree" "-p" parent - "-m" start-msg - (concat parent "^{tree}"))) - (setq parent wipref)) - (magit-call-git "update-ref" wipref "-m" msg - (magit-git-string "commit-tree" tree - "-p" parent "-m" msg)))) - -(defun magit-wip-get-ref () - (let ((ref (or (magit-git-string "symbolic-ref" "HEAD") "HEAD"))) - (when (magit-rev-verify ref) - ref))) - -(defun magit-wip-get-parent (ref wipref) - (if (and (magit-rev-verify wipref) - (equal (magit-git-string "merge-base" wipref ref) - (magit-rev-verify ref))) - wipref - ref)) - -;;; Log - -(defun magit-wip-log-current (branch args files count) - "Show log for the current branch and its wip refs. -With a negative prefix argument only show the worktree wip ref. -The absolute numeric value of the prefix argument controls how -many \"branches\" of each wip ref are shown." - (interactive - (nconc (list (or (magit-get-current-branch) "HEAD")) - (magit-log-arguments) - (list (prefix-numeric-value current-prefix-arg)))) - (magit-wip-log branch args files count)) - -(defun magit-wip-log (branch args files count) - "Show log for a branch and its wip refs. -With a negative prefix argument only show the worktree wip ref. -The absolute numeric value of the prefix argument controls how -many \"branches\" of each wip ref are shown." - (interactive - (nconc (list (magit-completing-read - "Log branch and its wip refs" - (-snoc (magit-list-local-branch-names) "HEAD") - nil t nil 'magit-revision-history - (or (magit-branch-at-point) - (magit-get-current-branch) - "HEAD"))) - (magit-log-arguments) - (list (prefix-numeric-value current-prefix-arg)))) - (unless (equal branch "HEAD") - (setq branch (concat "refs/heads/" branch))) - (magit-log (nconc (list branch) - (magit-wip-log-get-tips - (concat magit-wip-namespace "wtree/" branch) - (abs count)) - (and (>= count 0) - (magit-wip-log-get-tips - (concat magit-wip-namespace "index/" branch) - (abs count)))) - args files)) - -(defun magit-wip-log-get-tips (wipref count) - (-when-let (reflog (magit-git-lines "reflog" wipref)) - (let (tips) - (while (and reflog (> count 1)) - (setq reflog (cl-member "^[^ ]+ [^:]+: restart autosaving" - reflog :test #'string-match-p)) - (when (and (cadr reflog) - (string-match "^[^ ]+ \\([^:]+\\)" (cadr reflog))) - (push (match-string 1 (cadr reflog)) tips)) - (setq reflog (cddr reflog)) - (cl-decf count)) - (cons wipref (nreverse tips))))) - -;;; magit-wip.el ends soon -(provide 'magit-wip) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-wip.el ends here diff --git a/elpa/magit-20151119.202/magit.el b/elpa/magit-20151119.202/magit.el deleted file mode 100644 index 48ac5d8b..00000000 --- a/elpa/magit-20151119.202/magit.el +++ /dev/null @@ -1,2715 +0,0 @@ -;;; magit.el --- A Git porcelain inside Emacs - -;; Copyright (C) 2008-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Marius Vollmer -;; Maintainer: Jonas Bernoulli -;; Kyle Meyer -;; Noam Postavsky -;; Former-Maintainers: -;; Nicolas Dudebout -;; Peter J. Weisberg -;; Phil Jackson -;; Rémi Vanicat -;; Yann Hodique - -;; Package-Requires: ((emacs "24.4") (async "20150909.2257") (dash "20151021.113") (with-editor "20151111") (git-commit "20151111") (magit-popup "20151111")) -;; Keywords: git tools vc -;; Homepage: https://github.com/magit/magit - -;; Magit requires at least GNU Emacs 24.4 and Git 1.9.4. - -;; 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: - -;; Magit is an interface to the version control system Git, -;; implemented as an Emacs package. Magit aspires to be a complete -;; Git porcelain. While we cannot (yet) claim, that Magit wraps and -;; improves upon each and every Git command, it is complete enough to -;; allow even experienced Git users to perform almost all of their -;; daily version control tasks directly from within Emacs. While many -;; fine Git clients exist, only Magit and Git itself deserve to be -;; called porcelains. - -;;; Code: - -(require 'cl-lib) -(require 'dash) - -(require 'with-editor) -(require 'git-commit) -(require 'magit-core) -(require 'magit-diff) -(require 'magit-apply) -(require 'magit-log) - -(require 'format-spec) -(require 'package nil t) ; used in `magit-version' - -(eval-when-compile (require 'dired-x)) -(declare-function dired-jump 'dired-x) -(eval-when-compile (require 'eshell)) -(declare-function eshell-parse-arguments 'eshell) -(eval-when-compile (require 'message)) -(declare-function message-goto-body 'message) - -(defconst magit--minimal-git "1.9.4") -(defconst magit--minimal-emacs "24.4") - -;;; Options -;;;; Status Mode - -(defgroup magit-status nil - "Inspect and manipulate Git repositories." - :group 'magit-modes) - -(defcustom magit-status-mode-hook nil - "Hook run after entering Magit-Status mode." - :group 'magit-status - :type 'hook) - -(defcustom magit-status-headers-hook - '(magit-insert-diff-filter-header - magit-insert-head-branch-header - magit-insert-pull-branch-header - magit-insert-push-branch-header - magit-insert-tags-header) - "Hook run to insert headers into the status buffer. - -This hook is run by `magit-insert-status-headers', which in turn -has to be a member of `magit-insert-status-sections' to be used -at all." - :package-version '(magit . "2.1.0") - :group 'magit-status - :type 'hook - :options '(magit-insert-diff-filter-header - magit-insert-repo-header - magit-insert-remote-header - magit-insert-head-branch-header - magit-insert-pull-branch-header - magit-insert-push-branch-header - magit-insert-tags-header)) - -(defcustom magit-status-sections-hook - '(magit-insert-status-headers - magit-insert-merge-log - magit-insert-rebase-sequence - magit-insert-am-sequence - magit-insert-sequencer-sequence - magit-insert-bisect-output - magit-insert-bisect-rest - magit-insert-bisect-log - magit-insert-untracked-files - magit-insert-unstaged-changes - magit-insert-staged-changes - magit-insert-stashes - magit-insert-unpulled-commits - magit-insert-unpushed-commits) - "Hook run to insert sections into a status buffer." - :package-version '(magit . "2.1.0") - :group 'magit-status - :type 'hook) - -(defcustom magit-status-refresh-hook nil - "Hook run after a status buffer has been refreshed." - :package-version '(magit . "2.1.0") - :group 'magit-status - :type 'hook) - -(defcustom magit-status-expand-stashes t - "Whether the list of stashes is expanded initially." - :package-version '(magit . "2.3.0") - :group 'magit-status - :type 'boolean) - -;;;; Refs Mode - -(defgroup magit-refs nil - "Inspect and manipulate Git branches and tags." - :group 'magit-modes) - -(defcustom magit-refs-mode-hook nil - "Hook run after entering Magit-Refs mode." - :package-version '(magit . "2.1.0") - :group 'magit-refs - :type 'hook) - -(defcustom magit-refs-sections-hook - '(magit-insert-branch-description - magit-insert-local-branches - magit-insert-remote-branches - magit-insert-tags) - "Hook run to insert sections into a references buffer." - :package-version '(magit . "2.1.0") - :group 'magit-refs - :type 'hook) - -(defcustom magit-refs-show-commit-count nil - "Whether to show commit counts in Magit-Refs mode buffers. - -all Show counts for branches and tags. -branch Show counts for branches only. -nil Never show counts." - :package-version '(magit . "2.1.0") - :group 'magit-refs - :safe (lambda (val) (memq val '(all branch nil))) - :type '(choice (const all :tag "For branches and tags") - (const branch :tag "For branches only") - (const nil :tag "Never"))) -(put 'magit-refs-show-commit-count 'safe-local-variable 'symbolp) -(put 'magit-refs-show-commit-count 'permanent-local t) - -(defcustom magit-refs-show-margin 'branch - "Whether to initially show the margin in refs buffers. - -When non-nil the committer name and date are initially displayed -in the margin of refs buffers. The margin can be shown or hidden -in the current buffer using the command `magit-toggle-margin'." - :package-version '(magit . "2.1.0") - :group 'magit-refs - :safe (lambda (val) (memq val '(all branch nil))) - :type '(choice (const all :tag "For branches and tags") - (const branch :tag "For branches only") - (const nil :tag "Never"))) - -(defcustom magit-visit-ref-create nil - "Whether `magit-visit-ref' may create new branches. - -When this is non-nil, then \"visiting\" a remote branch in a -refs buffer works by creating a new local branch which tracks -the remote branch and then checking out the new local branch." - :package-version '(magit . "2.1.0") - :group 'magit-refs - :group 'magit-commands - :type 'boolean) - -;;;; Miscellaneous - -(defcustom magit-branch-read-upstream-first t - "When creating a branch, read upstream before name of new branch." - :package-version '(magit . "2.2.0") - :group 'magit-commands - :type 'boolean) - -(defcustom magit-repository-directories nil - "Directories containing Git repositories. -Magit checks these directories for Git repositories and offers -them as choices when `magit-status' is used with a prefix -argument." - :group 'magit - :type '(repeat string)) - -(defcustom magit-repository-directories-depth 3 - "The maximum depth to look for Git repositories. -When looking for a Git repository below the directories in -`magit-repository-directories', only descend this many levels -deep." - :group 'magit - :type 'integer) - -;;;; Faces - -(defface magit-header-line - '((t :inherit magit-section-heading)) - "Face for the `header-line'." - :group 'magit-faces) - -(defface magit-dimmed - '((((class color) (background light)) :foreground "grey50") - (((class color) (background dark)) :foreground "grey50")) - "Face for text that shouldn't stand out." - :group 'magit-faces) - -(defface magit-hash - '((((class color) (background light)) :foreground "grey60") - (((class color) (background dark)) :foreground "grey40")) - "Face for the sha1 part of the log output." - :group 'magit-faces) - -(defface magit-tag - '((((class color) (background light)) :foreground "Goldenrod4") - (((class color) (background dark)) :foreground "LightGoldenrod2")) - "Face for tag labels shown in log buffer." - :group 'magit-faces) - -(defface magit-branch-remote - '((((class color) (background light)) :foreground "DarkOliveGreen4") - (((class color) (background dark)) :foreground "DarkSeaGreen2")) - "Face for remote branch head labels shown in log buffer." - :group 'magit-faces) - -(defface magit-branch-local - '((((class color) (background light)) :foreground "SkyBlue4") - (((class color) (background dark)) :foreground "LightSkyBlue1")) - "Face for local branches." - :group 'magit-faces) - -(defface magit-branch-current - '((((class color) (background light)) :inherit magit-branch-local :box t) - (((class color) (background dark)) :inherit magit-branch-local :box t)) - "Face for current branch." - :group 'magit-faces) - -(defface magit-head - '((((class color) (background light)) :inherit magit-branch-local) - (((class color) (background dark)) :inherit magit-branch-local)) - "Face for the symbolic ref \"HEAD\"." - :group 'magit-faces) - -(defface magit-refname - '((((class color) (background light)) :foreground "grey30") - (((class color) (background dark)) :foreground "grey80")) - "Face for refnames without a dedicated face." - :group 'magit-faces) - -(defface magit-refname-stash - '((t :inherit magit-refname)) - "Face for wip refnames." - :group 'magit-faces) - -(defface magit-refname-wip - '((t :inherit magit-refname)) - "Face for wip refnames." - :group 'magit-faces) - -(defface magit-signature-good - '((t :foreground "green")) - "Face for good signatures." - :group 'magit-faces) - -(defface magit-signature-bad - '((t :foreground "red")) - "Face for bad signatures." - :group 'magit-faces) - -(defface magit-signature-untrusted - '((t :foreground "cyan")) - "Face for good untrusted signatures." - :group 'magit-faces) - -(defface magit-cherry-unmatched - '((t :foreground "cyan")) - "Face for unmatched cherry commits." - :group 'magit-faces) - -(defface magit-cherry-equivalent - '((t :foreground "magenta")) - "Face for equivalent cherry commits." - :group 'magit-faces) - -(defface magit-filename - '((t :weight normal)) - "Face for filenames." - :group 'magit-faces) - -;;; Inspect -;;;; Status Mode -;;;;; Status Core - -(defvar magit-status-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map magit-mode-map) - (define-key map "jz" 'magit-jump-to-stashes) - (define-key map "jt" 'magit-jump-to-tracked) - (define-key map "jn" 'magit-jump-to-untracked) - (define-key map "ju" 'magit-jump-to-unstaged) - (define-key map "js" 'magit-jump-to-staged) - (define-key map "jf" 'magit-jump-to-unpulled) - (define-key map "jp" 'magit-jump-to-unpushed) - map) - "Keymap for `magit-status-mode'.") - -(eval-after-load 'dired-x - '(define-key magit-status-mode-map [remap dired-jump] 'magit-dired-jump)) - -(define-derived-mode magit-status-mode magit-mode "Magit" - "Mode for looking at Git status. - -This mode is documented in info node `(magit)Status buffer'. - -\\\ -Type \\[magit-refresh] to refresh the current buffer. -Type \\[magit-section-toggle] to expand or hide the section at point. -Type \\[magit-visit-thing] to visit the change or commit at point. - -Type \\[magit-dispatch-popup] to see available prefix popups. - -Staging and applying changes is documented in info node -`(magit)Staging and unstaging' and info node `(magit)Applying'. - -\\Type \ -\\[magit-apply] to apply the change at point, \ -\\[magit-stage] to stage, -\\[magit-unstage] to unstage, \ -\\[magit-discard] to discard, or \ -\\[magit-reverse] to reverse it. - -\\\ -Type \\[magit-commit-popup] to create a commit. - -\\{magit-status-mode-map}" - :group 'magit-status - (hack-dir-local-variables-non-file-buffer)) - -;;;###autoload -(defun magit-status (&optional directory) - "Show the status of the current Git repository in a buffer. -With a prefix argument prompt for a repository to be shown. -With two prefix arguments prompt for an arbitrary directory. -If that directory isn't the root of an existing repository -then offer to initialize it as a new repository." - (interactive - (list (and (or current-prefix-arg (not (magit-toplevel))) - (magit-read-repository - (>= (prefix-numeric-value current-prefix-arg) 16))))) - (if directory - (let ((toplevel (magit-toplevel directory))) - (setq directory (file-name-as-directory (expand-file-name directory))) - (if (and toplevel (string-equal directory toplevel)) - (magit-status-internal directory) - (when (y-or-n-p - (if toplevel - (format "%s is a repository. Create another in %s? " - toplevel directory) - (format "Create repository in %s? " directory))) - (magit-init directory)))) - (magit-status-internal default-directory))) - -(put 'magit-status 'interactive-only 'magit-status-internal) - -;;;###autoload -(defun magit-status-internal (directory) - (magit-tramp-asserts directory) - (let ((default-directory directory)) - (magit-mode-setup #'magit-status-mode))) - -;;;;; Standard Status Sections - -(defun magit-status-refresh-buffer () - (magit-git-exit-code "update-index" "--refresh") - (magit-insert-section (status) - (run-hooks 'magit-status-sections-hook)) - (run-hooks 'magit-status-refresh-hook)) - -(defun magit-insert-status-headers () - "Insert header sections appropriate for `magit-status-mode' buffers. -The sections are inserted by running the functions on the hook -`magit-status-headers-hook'." - (if (magit-rev-verify "HEAD") - (magit-insert-headers magit-status-headers-hook) - (insert "In the beginning there was darkness\n\n"))) - -(cl-defun magit-insert-head-branch-header - (&optional (branch (magit-get-current-branch))) - "Insert a header line about the current branch or detached `HEAD'." - (let ((output (magit-rev-format "%h %s" "HEAD"))) - (string-match "^\\([^ ]+\\) \\(.*\\)" output) - (magit-bind-match-strings (commit summary) output - (if branch - (magit-insert-section (branch branch) - (insert (format "%-10s" "Head: ")) - (insert (propertize branch 'face 'magit-branch-local)) - (insert ?\s summary ?\n)) - (magit-insert-section (commit commit) - (insert (format "%-10s" "Head: ")) - (insert (propertize commit 'face 'magit-hash)) - (insert ?\s summary ?\n)))))) - -(cl-defun magit-insert-pull-branch-header - (&optional (branch (magit-get-current-branch)) - (pull (magit-get-tracked-branch branch)) - keyword) - "Insert a header line about branch normally pulled into the current branch." - (when pull - (magit-insert-section (branch pull) - (insert (format "%-10s" - (or keyword - (if (magit-get-boolean "branch" branch "rebase") - "Rebase: " - "Merge: ")))) - (insert (propertize pull 'face - (if (string= (magit-get "branch" branch "remote") ".") - 'magit-branch-local - 'magit-branch-remote))) - (insert ?\s) - (if (magit-rev-verify pull) - (insert (or (magit-rev-format "%s" pull) "")) - (insert (propertize "is missing" 'face 'font-lock-warning-face))) - (insert ?\n)))) - -(cl-defun magit-insert-push-branch-header - (&optional (branch (magit-get-current-branch)) - (push (magit-get-push-branch branch))) - "Insert a header line about the branch the current branch is pushed to" - (when push - (magit-insert-section (branch push) - (insert (format "%-10s" "Push: ")) - (insert (propertize push 'face 'magit-branch-remote) ?\s) - (if (magit-rev-verify push) - (insert (or (magit-rev-format "%s" push) "")) - (insert (propertize "is missing" 'face 'font-lock-warning-face))) - (insert ?\n)))) - -(defun magit-insert-tags-header () - "Insert a header line about the current and/or next tag." - (let* ((this-tag (magit-get-current-tag nil t)) - (next-tag (magit-get-next-tag nil t)) - (this-cnt (cadr this-tag)) - (next-cnt (cadr next-tag)) - (this-tag (car this-tag)) - (next-tag (car next-tag)) - (both-tags (and this-tag next-tag t))) - (when (or this-tag next-tag) - (magit-insert-section (tag (or this-tag next-tag)) - (insert (format "%-10s" (if both-tags "Tags: " "Tag: "))) - (when this-tag - (insert (magit-format-status-tag-sentence this-tag this-cnt nil))) - (when both-tags - (insert ", ")) - (when next-tag - (insert (magit-format-status-tag-sentence next-tag next-cnt t))) - (insert ?\n))))) - -(defun magit-format-status-tag-sentence (tag count next) - (concat (propertize tag 'face 'magit-tag) - (and (> count 0) - (format " (%s)" - (propertize (format "%s" count) 'face - (if next 'magit-tag 'magit-branch-local)))))) - -(defun magit-insert-diff-filter-header () - "Insert a header line showing the effective diff filters." - (when magit-diff-section-file-args - (magit-insert-section (filter 'diff) - (insert (propertize (format "%-10s" "Filter! ") - 'face 'magit-section-heading)) - (insert (mapconcat #'identity magit-diff-section-file-args " ")) - (insert ?\n)))) - -(magit-define-section-jumper untracked "Untracked files") - -(defvar magit-untracked-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-delete-thing] 'magit-discard) - (define-key map "s" 'magit-stage) - map) - "Keymap for the `untracked' section.") - -(defun magit-insert-untracked-files () - "Maybe insert a list or tree of untracked files. -Do so depending on the value of `status.showUntrackedFiles'." - (let ((show (or (magit-get "status.showUntrackedFiles") "normal"))) - (unless (equal show "no") - (if (equal show "all") - (-when-let (files (magit-untracked-files)) - (magit-insert-section (untracked) - (magit-insert-heading "Untracked files:") - (magit-insert-un/tracked-files-1 files nil) - (insert ?\n))) - (-when-let - (files (--mapcat (and (eq (aref it 0) ??) - (list (substring it 3))) - (magit-git-items "status" "-z" "--porcelain"))) - (magit-insert-section (untracked) - (magit-insert-heading "Untracked files:") - (dolist (file files) - (magit-insert-section (file file) - (insert (propertize file 'face 'magit-filename) ?\n)))) - (insert ?\n)))))) - -(defun magit-insert-un/tracked-files-1 (files directory) - (while (and files (string-prefix-p (or directory "") (car files))) - (let ((dir (file-name-directory (car files)))) - (if (equal dir directory) - (let ((file (pop files))) - (magit-insert-section (file file) - (insert (propertize file 'face 'magit-filename) ?\n))) - (magit-insert-section (file dir t) - (insert (propertize dir 'file 'magit-filename) ?\n) - (magit-insert-heading) - (setq files (magit-insert-un/tracked-files-1 files dir)))))) - files) - -;;;;; Auxiliary Status Sections - -(magit-define-section-jumper tracked "Tracked files") - -(defun magit-insert-tracked-files () - "Insert a tree of tracked files." - (-when-let (files (magit-list-files)) - (magit-insert-section (tracked nil t) - (magit-insert-heading "Tracked files:") - (magit-insert-un/tracked-files-1 files nil) - (insert ?\n)))) - -(defun magit-insert-user-header () - "Insert a header line about the current user." - (let ((name (magit-get "user.name")) - (email (magit-get "user.email"))) - (when (and name email) - (magit-insert-section (user name) - (insert (format "%-10s" "User: ")) - (insert (propertize name 'face 'magit-log-author)) - (insert " <" email ">\n"))))) - -(defun magit-insert-repo-header () - "Insert a header line showing the path to the repository top-level." - (let ((topdir (magit-toplevel))) - (magit-insert-section (repo topdir) - (insert (format "%-10s%s\n" "Repo: " (abbreviate-file-name topdir)))))) - -(defun magit-insert-remote-header () - "Insert a header line about the remote of the current branch. - -If no remote is configured for the current branch, then fall back -showing the \"origin\" remote, or if that does not exist the first -remote in alphabetic order." - (--when-let (or (magit-get-remote) - (let ((remotes (magit-list-remotes))) - (or (car (member "origin" remotes)) - (car remotes)))) - (magit-insert-section (remote it) - (insert (format "%-10s" "Remote: ")) - (insert (propertize it 'face 'magit-branch-remote) ?\s) - (insert (magit-get "remote" it "url") ?\n)))) - -;;;;; Status Miscellaneous - -(defun ido-enter-magit-status () - "Drop into `magit-status' from file switching. - -To make this command available use something like: - - (add-hook 'ido-setup-hook - (lambda () - (define-key ido-completion-map - (kbd \"C-x g\") 'ido-enter-magit-status))) - -Starting with Emacs 25.1 the Ido keymaps are defined just once -instead of every time Ido is invoked, so now you can modify it -like pretty much every other keymap: - - (define-key ido-common-completion-map - (kbd \"C-x g\") 'ido-enter-magit-status)" - (interactive) - (with-no-warnings ; FIXME these are internal variables - (setq ido-exit 'fallback fallback 'magit-status)) - (exit-minibuffer)) - -(defun magit-status-maybe-update-revision-buffer (&optional _) - "When moving in the status buffer, update the revision buffer. -If there is no revision buffer in the same frame, then do nothing." - (when (derived-mode-p 'magit-status-mode) - (magit-log-maybe-update-revision-buffer-1))) - -(defun magit-status-maybe-update-blob-buffer (&optional _) - "When moving in the status buffer, update the blob buffer. -If there is no blob buffer in the same frame, then do nothing." - (when (derived-mode-p 'magit-status-mode) - (magit-log-maybe-update-blob-buffer-1))) - -;;;; Refs Mode - -(defvar magit-refs-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map magit-mode-map) - (define-key map "\C-y" 'magit-refs-set-show-commit-count) - map) - "Keymap for `magit-refs-mode'.") - -(define-derived-mode magit-refs-mode magit-mode "Magit Refs" - "Mode which lists and compares references. - -This mode is documented in info node `(magit)References buffer'. - -\\\ -Type \\[magit-refresh] to refresh the current buffer. -Type \\[magit-section-toggle] to expand or hide the section at point. -Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ -to visit the commit or branch at point. - -Type \\[magit-branch-popup] to see available branch commands. -Type \\[magit-merge-popup] to merge the branch or commit at point. -Type \\[magit-cherry-pick-popup] to apply the commit at point. -Type \\[magit-reset] to reset HEAD to the commit at point. - -\\{magit-refs-mode-map}" - :group 'magit-refs - (hack-dir-local-variables-non-file-buffer)) - -;;;###autoload (autoload 'magit-show-refs-popup "magit" nil t) -(magit-define-popup magit-show-refs-popup - "Popup console for `magit-show-refs'." - 'magit-refs - :man-page "git-branch" - :switches '((?m "Merged to HEAD" "--merged") - (?M "Merged to master" "--merged=master") - (?n "Not merged to HEAD" "--no-merged") - (?N "Not merged to master" "--no-merged=master")) - :options '((?c "Contains" "--contains=" magit-read-branch-or-commit) - (?m "Merged" "--merged=" magit-read-branch-or-commit) - (?n "Not merged" "--no-merged=" magit-read-branch-or-commit)) - :actions '((?y "Show refs, comparing them with HEAD" - magit-show-refs-head) - (?c "Show refs, comparing them with current branch" - magit-show-refs-current) - (?o "Show refs, comparing them with other branch" - magit-show-refs)) - :default-action 'magit-show-refs-head - :use-prefix 'popup) - -;;;###autoload -(defun magit-show-refs-head (&optional args) - "List and compare references in a dedicated buffer. -Refs are compared with `HEAD'." - (interactive (list (magit-show-refs-arguments))) - (magit-show-refs nil args)) - -;;;###autoload -(defun magit-show-refs-current (&optional args) - "List and compare references in a dedicated buffer. -Refs are compared with the current branch or `HEAD' if -it is detached." - (interactive (list (magit-show-refs-arguments))) - (magit-show-refs (magit-get-current-branch) args)) - -;;;###autoload -(defun magit-show-refs (&optional ref args) - "List and compare references in a dedicated buffer. -Refs are compared with a branch read form the user." - (interactive (list (magit-read-other-branch "Compare with") - (magit-show-refs-arguments))) - (magit-mode-setup #'magit-refs-mode ref args)) - -(defun magit-branch-manager () - "The Branch Manager is dead, long live the Branch Manager. - -\\\ -Please use the new top-level binding `\\[magit-show-refs-popup]'. -The old binding `b v' will be removed soon." - (interactive) - (magit-show-refs-head) - (message (documentation 'magit-branch-manager)) - (sit-for 3)) - -(defun magit-refs-refresh-buffer (&rest ignore) - (setq magit-set-buffer-margin-refresh (not magit-show-margin)) - (unless (magit-rev-verify (or (car magit-refresh-args) "HEAD")) - (setq magit-refs-show-commit-count nil)) - (magit-insert-section (branchbuf) - (run-hooks 'magit-refs-sections-hook))) - -(defconst magit-refs-branch-line-re - (concat "^" - "\\(?:[ \\*]\\) " - "\\(?1:([^)]+)\\|[^ ]+?\\)" ; branch - "\\(?: +\\)" - "\\(?2:[0-9a-fA-F]+\\) " ; sha1 - "\\(?:\\[" - "\\(?4:[^:]+\\)" ; upstream - "\\(?:: \\(?:" - "\\(?7:gone\\)\\|" ; gone - "\\(?:ahead \\(?5:[0-9]+\\)\\)?" ; ahead - "\\(?:, \\)?" - "\\(?:behind \\(?6:[0-9]+\\)\\)?" ; behind - "\\)\\)?" - "\\] \\)?" - "\\(?3:.*\\)")) ; message - -(defvar magit-refs-local-branch-format "%4c %-25n %U%m\n" - "Format used for local branches in refs buffers.") -(defvar magit-refs-remote-branch-format "%4c %-25n %m\n" - "Format used for remote branches in refs buffers.") -(defvar magit-refs-tags-format "%4c %-25n %m\n" - "Format used for tags in refs buffers.") -(defvar magit-refs-indent-cherry-lines 3 - "Indentation of cherries in refs buffers.") - -(defvar magit-branch-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-visit-thing] 'magit-visit-ref) - (define-key map [remap magit-delete-thing] 'magit-branch-delete) - (define-key map "R" 'magit-branch-rename) - map) - "Keymap for `branch' sections.") - -(defvar magit-remote-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-delete-thing] 'magit-remote-remove) - (define-key map "R" 'magit-remote-rename) - map) - "Keymap for `remote' sections.") - -(defun magit-refs-set-show-commit-count () - "Change for which refs the commit count is shown." - (interactive) - (setq-local magit-refs-show-commit-count - (magit-read-char-case "Show commit counts for " nil - (?a "[a]ll refs" 'all) - (?b "[b]ranches only" t) - (?n "[n]othing" nil))) - (magit-refresh)) - -(defun magit-visit-ref () - "Visit the reference or revision at point. - -In most places use `magit-show-commit' to visit the reference or -revision at point. - -In `magit-refs-mode', when there is a reference at point, instead -checkout that reference. When option `magit-visit-ref-create' is -non-nil and point is on remote branch, then create a local branch -with the same name and check it out. - -With a prefix argument only focus on the reference at point, i.e. -the commit counts and cherries are updated to be relative to that -reference, but it is not checked out." - (interactive) - (if (derived-mode-p 'magit-refs-mode) - (magit-section-case - (([branch * branchbuf] - [tag * branchbuf]) - (let ((ref (magit-section-value (magit-current-section)))) - (if current-prefix-arg - (magit-show-refs ref) - (if (magit-section-when [branch remote]) - (let ((start ref) - (arg "-b")) - (string-match "^[^/]+/\\(.+\\)" ref) - (setq ref (match-string 1 ref)) - (when (magit-branch-p ref) - (if (yes-or-no-p - (format "Branch %s already exists. Recreate it?" ref)) - (setq arg "-B") - (user-error "Abort"))) - (magit-run-git "checkout" arg ref start)) - (magit-run-git "checkout" ref)) - (setcar magit-refresh-args ref) - (magit-refresh)))) - ([commit * branchbuf] - (call-interactively #'magit-show-commit))) - (call-interactively #'magit-show-commit))) - -(defun magit-insert-local-branches () - "Insert sections showing all local branches." - (magit-insert-section (local nil) - (magit-insert-heading "Branches:") - (let ((current (magit-get-current-branch)) - (branches (magit-list-local-branch-names))) - (dolist (line (magit-git-lines "branch" "-vv" - (cadr magit-refresh-args))) - (string-match magit-refs-branch-line-re line) - (magit-bind-match-strings - (branch hash message upstream ahead behind gone) line - (when (string-match-p "(" branch) - (setq branch nil)) - (magit-insert-branch - branch magit-refs-local-branch-format current branches - 'magit-branch-local hash message upstream ahead behind gone)))) - (insert ?\n))) - -(defun magit-insert-remote-branches () - "Insert sections showing all remote-tracking branches." - (dolist (remote (magit-list-remotes)) - (magit-insert-section (remote remote) - (magit-insert-heading - (let ((pull (magit-get "remote" remote "url")) - (push (magit-get "remote" remote "pushurl"))) - (format "%s (%s):" (capitalize remote) - (concat pull (and pull push ", ") push)))) - (let ((current (magit-get-current-branch)) - (branches (magit-list-local-branch-names))) - (dolist (line (magit-git-lines "branch" "-vvr" - (cadr magit-refresh-args))) - (when (string-match magit-refs-branch-line-re line) - (magit-bind-match-strings (branch hash message) line - (when (string-match-p (format "^%s/" remote) branch) - (magit-insert-branch - branch magit-refs-remote-branch-format current branches - 'magit-branch-remote hash message)))))) - (insert ?\n)))) - -(defun magit-insert-branch (branch format &rest args) - "For internal use, don't add to a hook." - (unless magit-refs-show-commit-count - (setq format (replace-regexp-in-string "%[0-9]\\([cC]\\)" "%1\\1" format t))) - (if (equal branch "HEAD") - (magit-insert-section it (commit (magit-rev-parse "HEAD") t) - (apply #'magit-insert-branch-1 it nil format args)) - (magit-insert-section it (branch branch t) - (apply #'magit-insert-branch-1 it branch format args)))) - -(defun magit-insert-branch-1 - (section branch format current branches face - &optional hash message upstream ahead behind gone) - "For internal use, don't add to a hook." - (let* ((head (or (car magit-refresh-args) current "HEAD")) - (count (and branch - (magit-refs-format-commit-count branch head format))) - (mark (cond ((or (equal branch head) - (and (not branch) (equal head "HEAD"))) - (if (equal branch current) - (propertize "@" 'face 'magit-head) - (propertize "#" 'face 'magit-tag))) - ((equal branch current) - (propertize "." 'face 'magit-head))))) - (when upstream - (setq upstream (propertize upstream 'face - (if (member upstream branches) - 'magit-branch-local - 'magit-branch-remote)))) - (magit-insert-heading - (format-spec - format - `((?a . ,(or ahead "")) - (?b . ,(or behind "")) - (?c . ,(or mark count "")) - (?C . ,(or mark " ")) - (?h . ,(or (propertize hash 'face 'magit-hash) "")) - (?m . ,(or message "")) - (?n . ,(propertize (or branch "(detached)") 'face face)) - (?u . ,(or upstream "")) - (?U . ,(if upstream - (format (propertize "[%s%s] " 'face 'magit-dimmed) - upstream - (cond - (gone - (concat ": " (propertize gone 'face 'error))) - ((or ahead behind) - (concat ": " - (and ahead (format "ahead %s" ahead)) - (and ahead behind ", ") - (and behind (format "behind %s" behind)))) - (t ""))) - ""))))) - (when magit-show-margin - (magit-refs-format-margin branch)) - (magit-refs-insert-cherry-commits head branch section))) - -(defvar magit-tag-section-map - (let ((map (make-sparse-keymap))) - (define-key map [remap magit-visit-thing] 'magit-visit-ref) - (define-key map [remap magit-delete-thing] 'magit-tag-delete) - map) - "Keymap for `tag' sections.") - -(defun magit-insert-tags () - "Insert sections showing all tags." - (-when-let (tags (magit-git-lines "tag" "-l" "-n")) - (magit-insert-section (tags) - (magit-insert-heading "Tags:") - (let ((head (or (car magit-refresh-args) - (magit-get-current-branch) - "HEAD")) - (format (if magit-refs-show-commit-count - magit-refs-tags-format - (replace-regexp-in-string - "%[0-9]\\([cC]\\)" "%1\\1" magit-refs-tags-format t)))) - (dolist (tag (nreverse tags)) - (string-match "^\\([^ \t]+\\)[ \t]+\\([^ \t\n].*\\)?" tag) - (let* ((message (match-string 2 tag)) - (tag (match-string 1 tag)) - (count (magit-refs-format-commit-count tag head format t)) - (mark (and (equal tag head) - (propertize "#" 'face 'magit-tag)))) - (magit-insert-section section (tag tag t) - (magit-insert-heading - (format-spec format - `((?n . ,(propertize tag 'face 'magit-tag)) - (?c . ,(or mark count "")) - (?m . ,(or message ""))))) - (when (and magit-show-margin - (eq magit-refs-show-margin 'all)) - (magit-refs-format-margin (concat tag "^{commit}"))) - (magit-refs-insert-cherry-commits head tag section))))) - (insert ?\n)))) - -(defun magit-refs-insert-cherry-commits (head ref section) - (if (magit-section-hidden section) - (setf (magit-section-washer section) - (apply-partially #'magit-refs-insert-cherry-commits-1 - head ref section)) - (magit-refs-insert-cherry-commits-1 head ref section))) - -(defun magit-refs-insert-cherry-commits-1 (head ref section) - (let ((start (point))) - (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) - "cherry" "-v" "--abbrev" head ref magit-refresh-args) - (unless (= (point) start) - (insert (propertize "\n" 'magit-section section))))) - -(defun magit-refs-format-commit-count (ref head format &optional tag-p) - (and (string-match-p "%-?[0-9]+c" format) - (if tag-p - (eq magit-refs-show-commit-count 'all) - magit-refs-show-commit-count) - (let ((count (cadr (magit-rev-diff-count head ref)))) - (and (> count 0) - (propertize (number-to-string count) 'face 'magit-dimmed))))) - -(defun magit-refs-format-margin (commit) - (save-excursion - (goto-char (line-beginning-position 0)) - (let ((line (magit-rev-format "%ct%cN" commit))) - (magit-format-log-margin (substring line 10) - (substring line 0 10))))) - -;;;; Files - -;;;###autoload -(defun magit-find-file (rev file) - "View FILE from REV. -Switch to a buffer visiting blob REV:FILE, -creating one if none already exists." - (interactive (magit-find-file-read-args "Find file")) - (switch-to-buffer (magit-find-file-noselect rev file))) - -;;;###autoload -(defun magit-find-file-other-window (rev file) - "View FILE from REV, in another window. -Like `magit-find-file', but create a new window or reuse an -existing one." - (interactive (magit-find-file-read-args "Find file in other window")) - (switch-to-buffer-other-window (magit-find-file-noselect rev file))) - -(defun magit-find-file-read-args (prompt) - (let ((rev (magit-read-branch-or-commit "Find file from revision"))) - (list rev (magit-read-file-from-rev rev prompt)))) - -(defvar magit-read-file-hist nil) - -(defun magit-read-file-from-rev (rev prompt &optional default) - (let ((files (magit-revision-files rev))) - (magit-completing-read - prompt files nil t nil 'magit-read-file-hist - (car (member (or default (magit-current-file)) files))))) - -(defun magit-read-changed-file (rev-or-range prompt &optional default) - (magit-read-file-choice - prompt - (magit-changed-files rev-or-range) - default - (concat "No file changed in " rev-or-range))) - -(defun magit-get-revision-buffer (rev file &optional create) - (funcall (if create 'get-buffer-create 'get-buffer) - (format "%s.~%s~" file (subst-char-in-string ?/ ?_ rev)))) - -(defun magit-get-revision-buffer-create (rev file) - (magit-get-revision-buffer rev file t)) - -(defvar magit-find-file-hook nil) - -(defun magit-find-file-noselect (rev file) - "Read FILE from REV into a buffer and return the buffer. -FILE must be relative to the top directory of the repository." - (let ((topdir (magit-toplevel))) - (when (file-name-absolute-p file) - (setq file (file-relative-name file topdir))) - (or (magit-get-revision-buffer rev file) - (with-current-buffer (magit-get-revision-buffer-create rev file) - (let ((inhibit-read-only t)) - (erase-buffer) - (magit-git-insert "cat-file" "-p" (concat rev ":" file))) - (setq magit-buffer-revision (magit-rev-format "%H" rev) - magit-buffer-refname rev - magit-buffer-file-name (expand-file-name file topdir)) - (let ((buffer-file-name magit-buffer-file-name)) - (normal-mode t)) - (setq buffer-read-only t) - (set-buffer-modified-p nil) - (goto-char (point-min)) - (magit-blob-mode 1) - (run-hooks 'magit-find-file-hook) - (current-buffer))))) - -(defvar magit-find-index-hook nil) - -(defun magit-find-file-index-noselect (file &optional revert) - "Read FILE from the index into a buffer and return the buffer. -FILE must to be relative to the top directory of the repository." - (let* ((bufname (concat file ".~{index}~")) - (origbuf (get-buffer bufname)) - (default-directory (magit-toplevel))) - (with-current-buffer (get-buffer-create bufname) - (when (or (not origbuf) revert - (y-or-n-p (format "%s already exists; revert it? " bufname))) - (let ((inhibit-read-only t) - (temp (car (split-string - (or (magit-git-string "checkout-index" "--temp" file) - (error "Error making temp file")) - "\t")))) - (erase-buffer) - (insert-file-contents temp nil nil nil t) - (delete-file temp))) - (setq magit-buffer-revision "{index}" - magit-buffer-refname "{index}" - magit-buffer-file-name (expand-file-name file)) - (let ((buffer-file-name magit-buffer-file-name)) - (normal-mode t)) - (setq buffer-read-only t) - (set-buffer-modified-p nil) - (goto-char (point-min)) - (run-hooks 'magit-find-index-hook) - (current-buffer)))) - -(defun magit-update-index () - "Update the index with the contents of the current buffer. -The current buffer has to be visiting a file in the index, which -is done using `magit-find-index-noselect'." - (interactive) - (let ((file (magit-file-relative-name))) - (unless (equal magit-buffer-refname "{index}") - (user-error "%s isn't visiting the index" file)) - (if (y-or-n-p (format "Update index with contents of %s" (buffer-name))) - (let ((index (make-temp-file "index")) - (buffer (current-buffer))) - (when magit-wip-before-change-mode - (magit-wip-commit-before-change (list file) " before un-/stage")) - (with-temp-file index - (insert-buffer-substring buffer)) - (magit-call-git "update-index" "--cacheinfo" - (substring (magit-git-string "ls-files" "-s" file) 0 6) - (magit-git-string "hash-object" "-t" "blob" "-w" - (concat "--path=" file) - "--" index) - file) - (set-buffer-modified-p nil) - (when magit-wip-after-apply-mode - (magit-wip-commit-after-apply (list file) " after un-/stage"))) - (message "Abort"))) - (--when-let (magit-mode-get-buffer 'magit-status-mode) - (with-current-buffer it (magit-refresh))) - t) - -;;;###autoload -(defun magit-dired-jump (&optional other-window) - "Visit file at point using Dired. -With a prefix argument, visit in other window. If there -is no file at point then instead visit `default-directory'." - (interactive "P") - (dired-jump other-window (--if-let (magit-file-at-point) - (expand-file-name it) - default-directory))) - -;;;###autoload -(defun magit-checkout-file (rev file) - "Checkout FILE from REV." - (interactive - (let ((rev (magit-read-branch-or-commit - "Checkout from revision" magit-buffer-revision))) - (list rev (magit-read-file-from-rev rev "Checkout file")))) - (magit-with-toplevel - (magit-run-git "checkout" rev "--" file))) - -;;; Manipulate -;;;; Init - -;;;###autoload -(defun magit-init (directory) - "Initialize a Git repository, then show its status. - -If the directory is below an existing repository, then the user -has to confirm that a new one should be created inside. If the -directory is the root of the existing repository, then the user -has to confirm that it should be reinitialized. - -Non-interactively DIRECTORY is (re-)initialized unconditionally." - (interactive - (let ((directory (file-name-as-directory - (expand-file-name - (read-directory-name "Create repository in: "))))) - (-when-let (toplevel (magit-toplevel directory)) - (setq toplevel (expand-file-name toplevel)) - (unless (y-or-n-p (if (string-equal toplevel directory) - (format "Reinitialize existing repository %s? " - directory) - (format "%s is a repository. Create another in %s? " - toplevel directory))) - (user-error "Abort"))) - (list directory))) - ;; `git init' does not understand the meaning of "~"! - (magit-call-git "init" (magit-convert-git-filename - (expand-file-name directory))) - (magit-status-internal directory)) - -;;;; Branch - -;;;###autoload (autoload 'magit-branch-popup "magit" nil t) -(magit-define-popup magit-branch-popup - "Popup console for branch commands." - 'magit-commands - :man-page "git-branch" - :switches '((?t "Set upstream configuration" "--track")) - :actions '((?c "Create" magit-branch) - (?u "Set upstream" magit-branch-set-upstream) - (?k "Delete" magit-branch-delete) - (?b "Checkout" magit-checkout) - (?U "Unset upstream" magit-branch-unset-upstream) - (?r "Rename" magit-branch-rename) - (?B "Create & checkout" magit-branch-and-checkout) - (?e "Set description" magit-branch-edit-description) - (?v "(Branch Manager)" magit-branch-manager) - (?s "Spin off" magit-branch-spinoff) nil nil - (?x "Reset" magit-branch-reset)) - :default-arguments '("--track") - :default-action 'magit-checkout - :max-action-columns 3) - -;;;###autoload -(defun magit-checkout (revision) - "Checkout REVISION, updating the index and the working tree. -If REVISION is a local branch then that becomes the current -branch. If it is something else then `HEAD' becomes detached. -Checkout fails if the working tree or the staging area contain -changes. -\n(git checkout REVISION)." - (interactive (list (magit-read-other-branch-or-commit "Checkout"))) - (magit-run-git "checkout" revision)) - -;;;###autoload -(defun magit-branch (branch start-point &optional args) - "Create BRANCH at branch or revision START-POINT. -\n(git branch [ARGS] BRANCH START-POINT)." - (interactive (magit-branch-read-args "Create branch")) - (magit-run-git-no-revert "branch" args branch start-point)) - -;;;###autoload -(defun magit-branch-and-checkout (branch start-point &optional args) - "Create and checkout BRANCH at branch or revision START-POINT. -\n(git checkout [ARGS] -b BRANCH START-POINT)." - (interactive (magit-branch-read-args "Create and checkout branch" - (magit-stash-at-point))) - (if (string-match-p "^stash@{[0-9]+}$" start-point) - (magit-run-git "stash" "branch" branch start-point) - (magit-run-git "checkout" args "-b" branch start-point))) - -(defun magit-branch-read-args (prompt &optional secondary-default) - (let ((args (magit-branch-arguments)) start branch) - (cond - (magit-branch-read-upstream-first - (setq start (magit-read-branch-or-commit (concat prompt " starting at") - secondary-default)) - (setq branch (magit-read-string-ns - "Branch name" - (and (member start (magit-list-remote-branch-names)) - (mapconcat #'identity - (cdr (split-string start "/")) "/"))))) - (t - (setq branch (magit-read-string-ns "Branch name")) - (setq start (magit-read-branch-or-commit (concat prompt " starting at") - secondary-default)))) - (unless (magit-branch-p start) - (setq args (delete "--track" args))) - (list branch start args))) - -;;;###autoload -(defun magit-branch-spinoff (branch &rest args) - "Create new branch from the unpushed commits. - -Create and checkout a new branch starting at and tracking the -current branch. That branch in turn is reset to the last commit -it shares with its upstream. If the current branch has no -upstream or no unpushed commits, then the new branch is created -anyway and the previously current branch is not touched. - -This is useful to create a feature branch after work has already -began on the old branch (likely but not necessarily \"master\")." - (interactive (list (magit-read-string "Spin off branch") - (magit-branch-arguments))) - (when (magit-branch-p branch) - (user-error "Branch %s already exists" branch)) - (-if-let (current (magit-get-current-branch)) - (let (tracked base) - (magit-call-git "checkout" args "-b" branch current) - (if (and (setq tracked (magit-get-tracked-branch current)) - (setq base (magit-git-string "merge-base" current tracked)) - (not (magit-rev-equal base current))) - (magit-run-git "update-ref" "-m" - (format "reset: moving to %s" base) - (concat "refs/heads/" current) base) - (magit-refresh))) - (magit-run-git "checkout" "-b" branch))) - -;;;###autoload -(defun magit-branch-reset (branch to &optional args) - "Reset a branch to the tip of another branch or any other commit. - -When resetting to another branch, then also set that branch as -the upstream of the branch being reset. - -When the branch being reset is the current branch, then do a -hard reset. If there are any uncommitted changes, then the user -has to confirming the reset because those changes would be lost. - -This is useful when you have started work on a feature branch but -realize it's all crap and want to start over." - (interactive - (let* ((atpoint (magit-branch-at-point)) - (branch (magit-read-local-branch "Reset branch" atpoint))) - (list branch - (magit-completing-read (format "Reset %s to" branch) - (delete branch (magit-list-branch-names)) - nil nil nil 'magit-revision-history - (or (and (not (equal branch atpoint)) atpoint) - (magit-get-tracked-branch branch))) - (magit-branch-arguments)))) - (unless (member "--force" args) - (setq args (cons "--force" args))) - (if (magit-branch-p to) - (unless (member "--track" args) - (setq args (cons "--track" args))) - (setq args (delete "--track" args))) - (if (equal branch (magit-get-current-branch)) - (if (and (magit-anything-modified-p) - (not (yes-or-no-p "Uncommitted changes will be lost. Proceed?"))) - (user-error "Abort") - (magit-reset-hard to) - (magit-branch-set-upstream branch to)) - (magit-branch branch to args))) - -;;;###autoload -(defun magit-branch-delete (branches &optional force) - "Delete one or multiple branches. -If the region marks multiple branches, then offer to delete -those, otherwise prompt for a single branch to be deleted, -defaulting to the branch at point." - (interactive - (let ((branches (magit-region-values 'branch)) - (force current-prefix-arg)) - (if (if (> (length branches) 1) - (magit-confirm t nil "Delete %i branches" branches) - (setq branches - (list (magit-read-branch (if current-prefix-arg - "Force delete branch" - "Delete branch") - (magit-get-previous-branch))))) - (unless force - (--when-let (-intersection - (-union (magit-list-unmerged-branches) - (magit-list-unmerged-to-upstream-branches)) - branches) - (if (magit-confirm 'delete-unmerged-branch - "Delete unmerged branch %s" - "Delete %i unmerged branches" it) - (setq force t) - (or (setq branches (-difference branches it)) - (user-error "Abort"))))) - (user-error "Abort")) - (list branches force))) - (let* ((refs (-map #'magit-ref-fullname branches)) - (ambiguous (--filter (not it) refs))) - (when ambiguous - (user-error - "%s ambiguous. Please cleanup using git directly." - (let ((len (length ambiguous))) - (cond - ((= len 1) - (format "%s is" (--first (not (magit-ref-fullname it)) branches))) - ((= len (length refs)) - (format "These %s names are" len)) - (t - (format "%s of these names are" len)))))) - (cond - ((string-match "^refs/remotes/\\([^/]+\\)" (car refs)) - (let* ((remote (match-string 1 (car refs))) - (offset (1+ (length remote)))) - (magit-run-git-async - "push" remote (--map (concat ":" (substring it offset)) branches)))) - ((> (length branches) 1) - (magit-run-git "branch" (if force "-D" "-d") - (delete (magit-get-current-branch) branches))) - (t ; And now for something completely different. - (let* ((branch (car branches)) - (prompt (format "Branch %s is checked out. " branch))) - (when (equal branch (magit-get-current-branch)) - (pcase (if (or (equal branch "master") - (not (magit-rev-verify "master"))) - (magit-read-char-case prompt nil - (?d "[d]etach HEAD & delete" 'detach) - (?a "[a]bort" 'abort)) - (magit-read-char-case prompt nil - (?d "[d]etach HEAD & delete" 'detach) - (?c "[c]heckout master & delete" 'master) - (?a "[a]bort" 'abort))) - (`detach (magit-call-git "checkout" "--detach")) - (`master (magit-call-git "checkout" "master")) - (`abort (user-error "Abort"))) - (setq force t)) - (magit-run-git "branch" (if force "-D" "-d") branch)))))) - -(put 'magit-branch-delete 'interactive-only t) - -;;;###autoload -(defun magit-branch-set-upstream (branch upstream) - "Change the UPSTREAM branch of BRANCH." - (interactive - (let ((branch (magit-read-local-branch "Change upstream of branch"))) - (list branch (magit-completing-read - "Change upstream to branch" - (delete branch (magit-list-branch-names)) - nil nil nil 'magit-revision-history)))) - (magit-run-git-no-revert "branch" (concat "--set-upstream-to=" upstream) - branch)) - -;;;###autoload -(defun magit-branch-unset-upstream (branch) - "Unset the upstream branch of BRANCH." - (interactive (list (magit-read-local-branch "Unset upstream of branch"))) - (magit-run-git-no-revert "branch" "--unset-upstream" branch)) - -;;;###autoload -(defun magit-branch-rename (old new &optional force) - "Rename branch OLD to NEW. -With prefix, forces the rename even if NEW already exists. -\n(git branch -m|-M OLD NEW)." - (interactive - (let ((branch (magit-read-local-branch "Rename branch"))) - (list branch - (magit-read-string-ns (format "Rename branch '%s' to" branch)) - current-prefix-arg))) - (unless (string= old new) - (magit-run-git-no-revert "branch" (if force "-M" "-m") old new))) - -;;;###autoload -(defun magit-branch-edit-description (branch) - "Edit the description of BRANCH." - (interactive (list (magit-read-local-branch "Edit branch description"))) - (magit-run-git-with-editor "branch" "--edit-description")) - -(defun magit-insert-branch-description () - "Insert header containing the description of the current branch. -Insert a header line with the name and description of the -current branch. The description is taken from the Git variable -`branch..description'; if that is undefined then no header -line is inserted at all." - (let ((branch (magit-get-current-branch))) - (--when-let (magit-git-lines - "config" (format "branch.%s.description" branch)) - (magit-insert-section (branchdesc branch t) - (magit-insert-heading branch ": " (car it)) - (insert (mapconcat 'identity (cdr it) "\n")) - (insert "\n\n"))))) - -;;;; Merge - -;;;###autoload (autoload 'magit-merge-popup "magit" nil t) -(magit-define-popup magit-merge-popup - "Popup console for merge commands." - 'magit-commands - :man-page "git-merge" - :switches '((?f "Fast-forward only" "--ff-only") - (?n "No fast-forward" "--no-ff") - (?s "Squash" "--squash")) - :options '((?s "Strategy" "--strategy=" read-from-minibuffer)) - :actions '((?m "Merge" magit-merge) - (?e "Merge and edit message" magit-merge-editmsg) - (?p "Preview merge" magit-merge-preview) - (?n "Merge but don't commit" magit-merge-nocommit)) - :sequence-actions '((?m "Commit merge" magit-commit) - (?a "Abort merge" magit-merge-abort)) - :sequence-predicate 'magit-merge-state - :default-action 'magit-merge - :max-action-columns 2) - -;;;###autoload -(defun magit-merge (rev &optional args nocommit) - "Merge commit REV into the current branch; using default message. - -Unless there are conflicts or a prefix argument is used create a -merge commit using a generic commit message and without letting -the user inspect the result. With a prefix argument pretend the -merge failed to give the user the opportunity to inspect the -merge. - -\(git merge --no-edit|--no-commit [ARGS] REV)" - (interactive (list (magit-read-other-branch-or-commit "Merge") - (magit-merge-arguments) - current-prefix-arg)) - (magit-merge-assert) - (magit-run-git "merge" (if nocommit "--no-commit" "--no-edit") args rev)) - -;;;###autoload -(defun magit-merge-editmsg (rev &optional args) - "Merge commit REV into the current branch; and edit message. -Perform the merge and prepare a commit message but let the user -edit it. -\n(git merge --edit [ARGS] rev)" - (interactive (list (magit-read-other-branch-or-commit "Merge") - (magit-merge-arguments))) - (magit-merge-assert) - (with-editor "GIT_EDITOR" - (let ((magit-process-popup-time -1)) - (magit-run-git-async "merge" "--edit" args rev)))) - -;;;###autoload -(defun magit-merge-nocommit (rev &optional args) - "Merge commit REV into the current branch; pretending it failed. -Pretend the merge failed to give the user the opportunity to -inspect the merge and change the commit message. -\n(git merge --no-commit [ARGS] rev)" - (interactive (list (magit-read-other-branch-or-commit "Merge") - (magit-merge-arguments))) - (magit-merge-assert) - (magit-run-git "merge" "--no-commit" args rev)) - -;;;###autoload -(defun magit-merge-preview (rev) - "Preview result of merging REV into the current branch." - (interactive (list (magit-read-other-branch-or-commit "Preview merge"))) - (magit-mode-setup #'magit-merge-preview-mode rev)) - -(define-derived-mode magit-merge-preview-mode magit-diff-mode "Magit Merge" - "Mode for previewing a merge." - :group 'magit-diff - (hack-dir-local-variables-non-file-buffer)) - -(defun magit-merge-preview-refresh-buffer (rev) - (let* ((branch (magit-get-current-branch)) - (head (or branch (magit-rev-verify "HEAD")))) - (setq header-line-format - (propertize (format "Preview merge of %s into %s" - rev (or branch "HEAD")) - 'face 'magit-header-line)) - (magit-insert-section (diffbuf) - (magit-git-wash #'magit-diff-wash-diffs - "merge-tree" (magit-git-string "merge-base" head rev) head rev)))) - -;;;###autoload -(defun magit-merge-abort () - "Abort the current merge operation. -\n(git merge --abort)" - (interactive) - (if (file-exists-p (magit-git-dir "MERGE_HEAD")) - (when (magit-confirm 'abort-merge) - (magit-run-git-async "merge" "--abort")) - (user-error "No merge in progress"))) - -(defun magit-checkout-stage (file arg) - "During a conflict checkout and stage side, or restore conflict." - (interactive - (let ((file (magit-completing-read "Checkout file" - (magit-tracked-files) nil nil nil - 'magit-read-file-hist - (magit-current-file)))) - (cond ((member file (magit-unmerged-files)) - (list file (magit-checkout-read-stage file))) - ((yes-or-no-p (format "Restore conflicts in %s? " file)) - (list file "--merge")) - (t - (user-error "Quit"))))) - (pcase (cons arg (cddr (car (magit-file-status file)))) - ((or `("--ours" ?D ,_) - `("--theirs" ,_ ?D)) - (magit-run-git "rm" "--" file)) - (_ (if (equal arg "--merge") - ;; This fails if the file was deleted on one - ;; side. And we cannot do anything about it. - (magit-run-git "checkout" "--merge" "--" file) - (magit-call-git "checkout" arg "--" file) - (magit-run-git "add" "-u" "--" file))))) - -(defun magit-merge-state () - (file-exists-p (magit-git-dir "MERGE_HEAD"))) - -(defun magit-merge-assert () - (or (not (magit-anything-modified-p)) - (magit-confirm 'merge-dirty - "Merging with dirty worktree is risky. Continue") - (user-error "Abort"))) - -(defun magit-checkout-read-stage (file) - (magit-read-char-case (format "For %s checkout: " file) t - (?o "[o]ur stage" "--ours") - (?t "[t]heir stage" "--theirs") - (?c "[c]onflict" "--merge"))) - -(defun magit-insert-merge-log () - "Insert section for the on-going merge. -Display the heads that are being merged. -If no merge is in progress, do nothing." - (-when-let (heads (mapcar 'magit-get-shortname - (magit-file-lines (magit-git-dir "MERGE_HEAD")))) - (magit-insert-section (commit (car heads)) - (magit-insert-heading - (format "Merging %s:" (mapconcat 'identity heads ", "))) - (magit-insert-log - (concat (magit-git-string "merge-base" "--octopus" "HEAD" (car heads)) - ".." (car heads)) - (let ((args magit-log-section-arguments)) - (unless (member "--decorate=full" magit-log-section-arguments) - (push "--decorate=full" args)) - args))))) - -;;;; Reset - -;;;###autoload -(defun magit-reset-index (commit) - "Reset the index to COMMIT. -Keep the head and working tree as-is, so if COMMIT refers to the -head this effectivley unstages all changes. -\n(git reset COMMIT)" - (interactive (list (magit-read-branch-or-commit "Reset index to"))) - (magit-reset-internal nil commit ".")) - -;;;###autoload -(defun magit-reset (commit &optional hard) - "Reset the head and index to COMMIT, but not the working tree. -With a prefix argument also reset the working tree. -\n(git reset --mixed|--hard COMMIT)" - (interactive (list (magit-read-branch-or-commit - (if current-prefix-arg - "Hard reset to" - "Reset head to")) - current-prefix-arg)) - (magit-reset-internal (if hard "--hard" "--mixed") commit)) - -;;;###autoload -(defun magit-reset-head (commit) - "Reset the head and index to COMMIT, but not the working tree. -\n(git reset --mixed COMMIT)" - (interactive (list (magit-read-branch-or-commit "Reset head to"))) - (magit-reset-internal "--mixed" commit)) - -;;;###autoload -(defun magit-reset-soft (commit) - "Reset the head to COMMIT, but not the index and working tree. -\n(git reset --soft REVISION)" - (interactive (list (magit-read-branch-or-commit "Soft reset to"))) - (magit-reset-internal "--soft" commit)) - -;;;###autoload -(defun magit-reset-hard (commit) - "Reset the head, index, and working tree to COMMIT. -\n(git reset --hard REVISION)" - (interactive (list (magit-read-branch-or-commit "Hard reset to"))) - (magit-reset-internal "--hard" commit)) - -(defun magit-reset-internal (arg commit &optional path) - (when (and (not (member arg '("--hard" nil))) - (equal (magit-rev-parse commit) - (magit-rev-parse "HEAD~"))) - (with-temp-buffer - (magit-git-insert "show" "-s" "--format=%B" "HEAD") - (when git-commit-major-mode - (funcall git-commit-major-mode)) - (git-commit-setup-font-lock) - (git-commit-save-message))) - (let ((cmd (if (and (equal commit "HEAD") (not arg)) "unstage" "reset"))) - (magit-wip-commit-before-change nil (concat " before " cmd)) - (magit-run-git "reset" arg commit "--" path) - (when (equal cmd "unstage") - (magit-wip-commit-after-apply nil " after unstage")))) - -;;;; Files - -(defun magit-file-rename (file newname) - "Rename the FILE to NEWNAME. -If FILE isn't tracked in Git fallback to using `rename-file'." - (interactive - (let* ((file (magit-read-file "Rename file")) - (newname (read-file-name (format "Rename %s to file: " file)))) - (list (expand-file-name file (magit-toplevel)) - (expand-file-name newname)))) - (if (magit-file-tracked-p file) - (let ((oldbuf (get-file-buffer file))) - (when (and oldbuf (buffer-modified-p oldbuf)) - (user-error "Save %s before moving it" file)) - (when (file-exists-p newname) - (user-error "%s already exists" newname)) - (magit-run-git "mv" file newname) - (when oldbuf - (with-current-buffer oldbuf - (let ((buffer-read-only buffer-read-only)) - (set-visited-file-name newname)) - (if (fboundp 'vc-refresh-state) - (vc-refresh-state) - (with-no-warnings - (vc-find-file-hook)))))) - (rename-file file newname current-prefix-arg) - (magit-refresh))) - -(defun magit-file-untrack (file) - "Untrack FILE. -Stop tracking FILE in Git but do not remove it from the working -tree." - (interactive (list (magit-read-tracked-file "Untrack file"))) - (magit-run-git "rm" "--cached" "--" file)) - -(defun magit-file-delete (file &optional force) - "Delete FILE. -With a prefix argument FORCE do so even when FILE has uncommitted -changes. - -If FILE isn't tracked in Git fallback to using `delete-file'." - (interactive (list (magit-read-file "Delete file"))) - (if (magit-file-tracked-p file) - (magit-run-git "rm" (and force "--force") "--" file) - (delete-file (expand-file-name file (magit-toplevel)) t) - (magit-refresh))) - -(defun magit-read-tracked-file (prompt) - (magit-read-file prompt t)) - -(defun magit-read-file (prompt &optional tracked-only) - (let ((choices (nconc (magit-list-files) - (unless tracked-only (magit-untracked-files))))) - (magit-completing-read prompt choices nil t nil nil - (car (member (or (magit-section-when (file)) - (magit-file-relative-name - nil tracked-only)) - choices))))) - -(defun magit-read-files (prompt initial-contents) - (mapconcat 'identity - (completing-read-multiple (or prompt "File,s: ") - (magit-list-files) - nil nil initial-contents) ",")) - -(defun magit-read-file-choice (prompt files &optional error default) - "Read file from FILES. - -If FILES has only one member, return that instead of prompting. -If FILES has no members, give a user error. ERROR can be given -to provide a more informative error. - -If DEFAULT is non-nil, use this as the default value instead of -`magit-current-file'." - (pcase (length files) - (0 (user-error (or error "No file choices"))) - (1 (car files)) - (_ (magit-completing-read - prompt files nil t nil 'magit-read-file-hist - (car (member (or default (magit-current-file)) files)))))) - -;;; Miscellaneous -;;;; Tag - -;;;###autoload (autoload 'magit-tag-popup "magit" nil t) -(magit-define-popup magit-tag-popup - "Popup console for tag commands." - 'magit-commands - :man-page "git-tag" - :switches '((?a "Annotate" "--annotate") - (?s "Sign" "--sign") - (?f "Force" "--force")) - :actions '((?t "Create" magit-tag) - (?k "Delete" magit-tag-delete) - (?p "Prune" magit-tag-prune)) - :default-action 'magit-tag) - -;;;###autoload -(defun magit-tag (name rev &optional args) - "Create a new tag with the given NAME at REV. -With a prefix argument annotate the tag. -\n(git tag [--annotate] NAME REV)" - (interactive (list (magit-read-tag "Tag name") - (magit-read-branch-or-commit "Place tag on") - (let ((args (magit-tag-arguments))) - (when current-prefix-arg - (add-to-list 'args "--annotate")) - args))) - (magit-run-git-with-editor "tag" args name rev)) - -;;;###autoload -(defun magit-tag-delete (tags) - "Delete one or more tags. -If the region marks multiple tags (and nothing else), then offer -to delete those, otherwise prompt for a single tag to be deleted, -defaulting to the tag at point. -\n(git tag -d TAGS)" - (interactive (list (--if-let (magit-region-values 'tag) - (magit-confirm t nil "Delete %i tags" it) - (magit-read-tag "Delete tag" t)))) - (magit-run-git-no-revert "tag" "-d" tags)) - -(defun magit-tag-prune (tags remote-tags remote) - "Offer to delete tags missing locally from REMOTE, and vice versa." - (interactive - (let* ((remote (magit-read-remote "Prune tags using remote")) - (tags (magit-list-tags)) - (rtags (prog2 (message "Determining remote tags...") - (magit-list-remote-tags remote) - (message "Determining remote tags...done"))) - (ltags (-difference tags rtags)) - (rtags (-difference rtags tags))) - (unless (or ltags rtags) - (message "Same tags exist locally and remotely")) - (unless (magit-confirm t "Delete %s locally" - "Delete %i tags locally" ltags) - (setq ltags nil)) - (unless (magit-confirm t "Delete %s from remote" - "Delete %i tags from remote" rtags) - (setq rtags nil)) - (list ltags rtags remote))) - (when tags - (magit-call-git "tag" "-d" tags)) - (when remote-tags - (magit-run-git-async-no-revert - "push" remote (--map (concat ":" it) remote-tags)))) - -;;;; Notes - -;;;###autoload (autoload 'magit-notes-popup "magit" nil t) -(magit-define-popup magit-notes-popup - "Popup console for notes commands." - 'magit-commands - :man-page "git-tag" - :switches '((?n "Dry run" "--dry-run")) - :options '((?r "Manipulate ref" "--ref=" magit-notes-popup-read-ref) - (?s "Merge strategy" "--strategy=" read-from-minibuffer)) - :actions '((?T "Edit" magit-notes-edit) - (?r "Remove" magit-notes-remove) - (?m "Merge" magit-notes-merge) - (?p "Prune" magit-notes-prune) - (?s "Set ref" magit-notes-set-ref) - (?S "Set display refs" magit-notes-set-display-refs)) - :sequence-actions '((?c "Commit merge" magit-notes-merge-commit) - (?a "Abort merge" magit-notes-merge-abort)) - :sequence-predicate 'magit-notes-merging-p - :default-action 'magit-notes-edit) - -(defun magit-notes-edit (commit &optional ref) - "Edit the note attached to COMMIT. -REF is the notes ref used to store the notes. - -Interactively or when optional REF is nil use the value of Git -variable `core.notesRef' or \"refs/notes/commits\" if that is -undefined." - (interactive (magit-notes-read-args "Edit notes")) - (magit-run-git-with-editor "notes" (and ref (concat "--ref=" ref)) - "edit" commit)) - -(defun magit-notes-remove (commit &optional ref) - "Remove the note attached to COMMIT. -REF is the notes ref from which the note is removed. - -Interactively or when optional REF is nil use the value of Git -variable `core.notesRef' or \"refs/notes/commits\" if that is -undefined." - (interactive (magit-notes-read-args "Remove notes")) - (magit-run-git-with-editor "notes" "remove" commit)) - -(defun magit-notes-merge (ref) - "Merge the notes ref REF into the current notes ref. - -The current notes ref is the value of Git variable -`core.notesRef' or \"refs/notes/commits\" if that is undefined. - -When there are conflict, then they have to resolved in the -temporary worktree \".git/NOTES_MERGE_WORKTREE\". When -done use `magit-notes-merge-commit' to finish. To abort -use `magit-notes-merge-abort'." - (interactive (list (magit-read-string-ns "Merge reference"))) - (magit-run-git-with-editor "notes" "merge" ref)) - -(defun magit-notes-merge-commit () - "Commit the current notes ref merge. -Also see `magit-notes-merge'." - (interactive) - (magit-run-git-with-editor "notes" "merge" "--commit")) - -(defun magit-notes-merge-abort () - "Abort the current notes ref merge. -Also see `magit-notes-merge'." - (interactive) - (magit-run-git-with-editor "notes" "merge" "--abort")) - -(defun magit-notes-prune (&optional dry-run) - "Remove notes about unreachable commits." - (interactive (list (and (member "--dry-run" (magit-notes-arguments)) t))) - (when dry-run - (magit-process-buffer)) - (magit-run-git-with-editor "notes" "prune" (and dry-run "--dry-run"))) - -(defun magit-notes-set-ref (ref &optional global) - "Set the current notes ref to REF. -The ref is made current by setting the value of the Git variable -`core.notesRef'. With a prefix argument GLOBAL change the global -value, else the value in the current repository. When this is -undefined, then \"refs/notes/commit\" is used. - -Other `magit-notes-*' commands, as well as the sub-commands -of Git's `note' command, default to operate on that ref." - (interactive - (list (magit-completing-read "Set notes ref" - (nconc (list "refs/" "refs/notes/") - (magit-list-notes-refnames)) - nil nil - (--when-let (magit-get "core.notesRef") - (if (string-match "^refs/notes/\\(.+\\)" it) - (match-string 1 it) - it))) - current-prefix-arg)) - (if ref - (magit-run-git-no-revert "config" (and global "--global") "core.notesRef" - (if (string-prefix-p "refs/" ref) - ref - (concat "refs/notes/" ref))) - (magit-run-git-no-revert "config" (and global "--global") - "--unset" "core.notesRef"))) - -(defun magit-notes-set-display-refs (refs &optional global) - "Set notes refs to be display in addition to \"core.notesRef\". -REFS is a colon separated list of notes refs. The values are -stored in the Git variable `notes.displayRef'. With a prefix -argument GLOBAL change the global values, else the values in -the current repository." - (interactive - (list (magit-completing-read "Set additional notes ref(s)" - (nconc (list "refs/" "refs/notes/") - (magit-list-notes-refnames)) - nil nil - (mapconcat #'identity - (magit-get-all "notes.displayRef") - ":")) - current-prefix-arg)) - (when (and refs (atom refs)) - (setq refs (split-string refs ":"))) - (when global - (setq global "--global")) - (magit-git-success "config" "--unset-all" global "notes.displayRef") - (dolist (ref refs) - (magit-call-git "config" "--add" global "notes.displayRef" ref)) - (let ((inhibit-magit-revert t)) - (magit-refresh))) - -(defun magit-notes-read-args (prompt) - (list (magit-read-branch-or-commit prompt) - (--when-let (--first (string-match "^--ref=\\(.+\\)" it) - (magit-notes-arguments)) - (match-string 1 it)))) - -(defun magit-notes-popup-read-ref (prompt &optional initial-input) - (magit-completing-read prompt (nconc (list "refs/" "refs/notes/") - (magit-list-notes-refnames)) - nil nil initial-input)) - -(defun magit-notes-merging-p () - (let ((dir (magit-git-dir "NOTES_MERGE_WORKTREE"))) - (and (file-directory-p dir) - (directory-files dir nil "^[^.]")))) - -;;;; Submodules - -;;;###autoload (autoload 'magit-submodule-popup "magit" nil t) -(magit-define-popup magit-submodule-popup - "Popup console for submodule commands." - 'magit-commands nil nil - :man-page "git-submodule" - :actions '((?a "Add" magit-submodule-add) - (?b "Setup" magit-submodule-setup) - (?i "Init" magit-submodule-init) - (?u "Update" magit-submodule-update) - (?s "Sync" magit-submodule-sync) - (?f "Fetch" magit-submodule-fetch) - (?d "Deinit" magit-submodule-deinit))) - -;;;###autoload -(defun magit-submodule-add (url &optional path) - "Add the repository at URL as a submodule. -Optional PATH is the path to the submodule relative to the root -of the superproject. If it is nil then the path is determined -based on URL." - (interactive - (magit-with-toplevel - (let ((path (read-file-name - "Add submodule: " nil nil nil - (magit-section-when [file untracked] - (directory-file-name (magit-section-value it)))))) - (when path - (setq path (file-name-as-directory (expand-file-name path))) - (when (member path (list "" default-directory)) - (setq path nil))) - (list (magit-read-string-ns - "Remote url" - (and path (magit-git-repo-p path t) - (let ((default-directory path)) - (magit-get "remote" (or (magit-get-remote) "origin") - "url")))) - (and path (directory-file-name (file-relative-name path))))))) - (magit-run-git "submodule" "add" url path)) - -;;;###autoload -(defun magit-submodule-setup () - "Clone and register missing submodules and checkout appropriate commits." - (interactive) - (magit-submodule-update t)) - -;;;###autoload -(defun magit-submodule-init () - "Register submodules listed in \".gitmodules\" into \".git/config\"." - (interactive) - (magit-with-toplevel - (magit-run-git-async "submodule" "init"))) - -;;;###autoload -(defun magit-submodule-update (&optional init) - "Clone missing submodules and checkout appropriate commits. -With a prefix argument also register submodules in \".git/config\"." - (interactive "P") - (magit-with-toplevel - (magit-run-git-async "submodule" "update" (and init "--init")))) - -;;;###autoload -(defun magit-submodule-sync () - "Update each submodule's remote URL according to \".gitmodules\"." - (interactive) - (magit-with-toplevel - (magit-run-git-async "submodule" "sync"))) - -;;;###autoload -(defun magit-submodule-fetch (&optional all) - "Fetch all submodules. -With a prefix argument fetch all remotes." - (interactive "P") - (magit-with-toplevel - (magit-run-git-async "submodule" "foreach" - (format "git fetch %s || true" (if all "--all" ""))))) - -;;;###autoload -(defun magit-submodule-deinit (path) - "Unregister the submodule at PATH." - (interactive - (list (magit-completing-read "Deinit module" (magit-get-submodules) - nil t nil nil (magit-section-when module)))) - (magit-with-toplevel - (magit-run-git-async "submodule" "deinit" path))) - -;;;; File Mode - -(defvar magit-file-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\C-xg" 'magit-status) - (define-key map "\C-x\M-g" 'magit-dispatch-popup) - (define-key map "\C-c\M-g" 'magit-file-popup) - map) - "Keymap for `magit-file-mode'.") - -(magit-define-popup magit-file-popup - "Popup consule for Magit commands in file-visiting buffers." - :actions '((?s "Stage" magit-stage-file) - (?l "Log" magit-log-buffer-file) - (?c "Commit" magit-commit-popup) - (?u "Unstage" magit-unstage-file) - (?b "Blame" magit-blame-popup) nil nil - (?p "Find blob" magit-blob-previous)) - :max-action-columns 3) - -(defvar magit-file-mode-lighter "") - -(define-minor-mode magit-file-mode - "Enable some Magit features in file-visiting buffers. - -Currently this only adds the following key bindings. -\n\\{magit-file-mode-map}" - :package-version '(magit . "2.2.0") - :lighter magit-file-mode-lighter - :keymap magit-file-mode-map) - -(defun magit-file-mode-turn-on () - (and buffer-file-name - (ignore-errors (magit-inside-worktree-p)) - (magit-file-mode))) - -;;;###autoload -(define-globalized-minor-mode global-magit-file-mode - magit-file-mode magit-file-mode-turn-on - :package-version '(magit . "2.2.0") - :group 'magit-modes) - -(define-obsolete-function-alias 'global-magit-file-buffer-mode - 'global-magit-file-mode "2.3.0") - -;;;; Blob Mode - -(defvar magit-blob-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "n" 'magit-blob-next) - (define-key map "p" 'magit-blob-previous) - (define-key map "q" 'magit-kill-this-buffer) - map) - "Keymap for `magit-blob-mode'.") - -(define-minor-mode magit-blob-mode - "Enable some Magit features in blob-visiting buffers. - -Currently this only adds the following key bindings. -\n\\{magit-blob-mode-map}" - :package-version '(magit . "2.3.0")) - -(defun magit-blob-next () - "Visit the next blob which modified the current file." - (interactive) - (if magit-buffer-file-name - (magit-blob-visit (or (magit-blob-successor magit-buffer-revision - magit-buffer-file-name) - magit-buffer-file-name) - (line-number-at-pos)) - (if (buffer-file-name (buffer-base-buffer)) - (user-error "You have reached the end of time") - (user-error "Buffer isn't visiting a file or blob")))) - -(defun magit-blob-previous () - "Visit the previous blob which modified the current file." - (interactive) - (-if-let (file (or magit-buffer-file-name - (buffer-file-name (buffer-base-buffer)))) - (--if-let (magit-blob-ancestor magit-buffer-revision file) - (magit-blob-visit it (line-number-at-pos)) - (user-error "You have reached the beginning of time")) - (user-error "Buffer isn't visiting a file or blob"))) - -(defun magit-blob-visit (blob-or-file line) - (if (stringp blob-or-file) - (find-file blob-or-file) - (-let [(rev file) blob-or-file] - (magit-find-file rev file) - (let ((str (magit-rev-format "%ct%s" rev))) - (message "%s (%s ago)" (substring str 10) - (magit-format-duration - (abs (truncate (- (float-time) - (string-to-number - (substring str 0 10))))) - magit-duration-spec))))) - (goto-char (point-min)) - (forward-line (1- line))) - -(defun magit-blob-ancestor (rev file) - (let ((lines (magit-with-toplevel - (magit-git-lines "log" "-2" "--format=%H" "--name-only" - "--follow" (or rev "HEAD") "--" file)))) - (if rev (cddr lines) (butlast lines 2)))) - -(defun magit-blob-successor (rev file) - (let ((lines (magit-with-toplevel - (magit-git-lines "log" "--format=%H" "--name-only" "--follow" - "HEAD" "--" "lisp/magit-blame.el")))) - (catch 'found - (while lines - (if (equal (nth 2 lines) rev) - (throw 'found (list (nth 0 lines) (nth 1 lines))) - (setq lines (nthcdr 2 lines))))))) - -(defun magit-kill-this-buffer () - "Kill the current buffer." - (interactive) - (kill-buffer (current-buffer))) - -;;;; Dispatch Popup - -;;;###autoload (autoload 'magit-dispatch-popup "magit" nil t) -(magit-define-popup magit-dispatch-popup - "Popup console for dispatching other popups." - 'magit-commands nil nil - :actions '("Popup and dwim commands" - (?A "Cherry-picking" magit-cherry-pick-popup) - (?b "Branching" magit-branch-popup) - (?B "Bisecting" magit-bisect-popup) - (?c "Committing" magit-commit-popup) - (?d "Diffing" magit-diff-popup) - (?D "Change diffs" magit-diff-refresh-popup) - (?e "Ediff dwimming" magit-ediff-dwim) - (?E "Ediffing" magit-ediff-popup) - (?f "Fetching" magit-fetch-popup) - (?F "Pulling" magit-pull-popup) - (?l "Logging" magit-log-popup) - (?m "Merging" magit-merge-popup) - (?M "Remoting" magit-remote-popup) - (?o "Submodules" magit-submodule-popup) - (?P "Pushing" magit-push-popup) - (?r "Rebasing" magit-rebase-popup) - (?t "Tagging" magit-tag-popup) - (?T "Notes" magit-notes-popup) - (?V "Reverting" magit-revert-popup) - (?w "Apply patches" magit-am-popup) - (?W "Format patches" magit-patch-popup) - (?y "Show Refs" magit-show-refs-popup) - (?z "Stashing" magit-stash-popup) - (?! "Running" magit-run-popup) - "Applying changes" - (?a "Apply" magit-apply) - (?s "Stage" magit-stage) - (?u "Unstage" magit-unstage) - nil - (?v "Reverse" magit-reverse) - (?S "Stage all" magit-stage-modified) - (?U "Unstage all" magit-unstage-all) - nil - (?k "Discard" magit-discard) - "\ - g refresh current buffer - TAB toggle section at point - RET visit thing at point - - C-h m show all key bindings" nil) - :max-action-columns 4) - -;;;; Git Popup - -(defvar magit-git-command-history nil) - -;;;###autoload (autoload 'magit-run-popup "magit" nil t) -(magit-define-popup magit-run-popup - "Popup console for running raw Git commands." - 'magit-commands nil nil - :actions '((?! "Git Subcommand (in topdir)" magit-git-command-topdir) - (?k "Gitk" magit-run-gitk) - (?p "Git Subcommand (in pwd)" magit-git-command) - (?a "Gitk --all" magit-run-gitk-all) - (?s "Shell command (in topdir)" magit-shell-command-topdir) - (?b "Gitk --branches" magit-run-gitk-branches) - (?S "Shell command (in pwd)" magit-shell-command) - (?g "Git Gui" magit-run-git-gui)) - :default-action 'magit-git-command - :max-action-columns 2) - -;;;###autoload -(defun magit-git-command (args directory) - "Execute a Git subcommand asynchronously, displaying the output. -With a prefix argument run Git in the root of the current -repository, otherwise in `default-directory'." - (interactive (magit-read-shell-command "Git subcommand (pwd: %s)")) - (require 'eshell) - (with-temp-buffer - (insert args) - (setq args (mapcar 'eval (eshell-parse-arguments (point-min) - (point-max)))) - (setq default-directory directory) - (let ((magit-git-global-arguments - ;; A human will want globbing by default. - (remove "--literal-pathspecs" - magit-git-global-arguments))) - (magit-run-git-async args))) - (magit-process-buffer)) - -;;;###autoload -(defun magit-git-command-topdir (args directory) - "Execute a Git subcommand asynchronously, displaying the output. -Run Git in the top-level directory of the current repository. -\n(fn)" ; arguments are for internal use - (interactive (magit-read-shell-command "Git subcommand (pwd: %s)" t)) - (magit-git-command args directory)) - -;;;###autoload -(defun magit-shell-command (args directory) - "Execute a shell command asynchronously, displaying the output. -With a prefix argument run the command in the root of the current -repository, otherwise in `default-directory'." - (interactive (magit-read-shell-command "Shell command (pwd: %s)")) - (require 'eshell) - (with-temp-buffer - (insert args) - (setq args (mapcar 'eval (eshell-parse-arguments (point-min) - (point-max)))) - (setq default-directory directory) - (apply #'magit-start-process (car args) nil (cdr args))) - (magit-process-buffer)) - -;;;###autoload -(defun magit-shell-command-topdir (args directory) - "Execute a shell command asynchronously, displaying the output. -Run the command in the top-level directory of the current repository. -\n(fn)" ; arguments are for internal use - (interactive (magit-read-shell-command "Shell command (pwd: %s)" t)) - (magit-shell-command args directory)) - -(defun magit-read-shell-command (prompt &optional root) - (let ((dir (if (or root current-prefix-arg) - (or (magit-toplevel) - (user-error "Not inside a Git repository")) - default-directory))) - (list (magit-read-string (format prompt (abbreviate-file-name dir)) - nil 'magit-git-command-history) - dir))) - -;;;; Read Repository - -(defun magit-read-repository (&optional read-directory-name) - "Read a Git repository in the minibuffer, with completion. - -The completion choices are the basenames of top-levels of -repositories found in the directories specified by option -`magit-repository-directories'. In case of name conflicts -the basenames are prefixed with the name of the respective -parent directories. The returned value is the actual path -to the selected repository. - -With prefix argument simply read a directory name using -`read-directory-name'." - (if (and (not read-directory-name) magit-repository-directories) - (let* ((repos (magit-list-repos-uniquify - (--map (cons (file-name-nondirectory it) it) - (magit-list-repos)))) - (reply (magit-completing-read "Git repository" repos))) - (file-name-as-directory - (or (cdr (assoc reply repos)) - (if (file-directory-p reply) - (expand-file-name reply) - (user-error "Not a repository or a directory: %s" reply))))) - (file-name-as-directory - (read-directory-name "Git repository: " - (or (magit-toplevel) default-directory))))) - -(defun magit-list-repos () - (--mapcat (magit-list-repos-1 it magit-repository-directories-depth) - magit-repository-directories)) - -(defun magit-list-repos-1 (directory depth) - (cond ((file-readable-p (expand-file-name ".git" directory)) - (list directory)) - ((and (> depth 0) (file-accessible-directory-p directory)) - (--mapcat (when (file-directory-p it) - (magit-list-repos-1 it (1- depth))) - (directory-files directory t "^[^.]" t))))) - -(defun magit-list-repos-uniquify (alist) - (let (result (dict (make-hash-table :test 'equal))) - (dolist (a (delete-dups 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) - (setq result - (append result - (magit-list-repos-uniquify - (--map (cons (concat - key "\\" - (file-name-nondirectory - (directory-file-name - (substring it 0 (- (length key)))))) - it) - value)))))) - dict) - result)) - -;;;; Revision Stack - -(defvar magit-revision-stack nil) - -(defcustom magit-pop-revision-stack-format - '("[%N: %h] " "%N: %H\n %s\n" "\\[\\([0-9]+\\)[]:]") - "Control how `magit-pop-revision-stack' inserts a revision. - -The command `magit-pop-revision-stack' inserts a representation -of the revision last pushed to the `magit-revision-stack' into -the current buffer. It inserts text at point and/or near the end -of the buffer, and removes the consumed revision from the stack. - -The entries on the stack have the format (HASH TOPLEVEL) and this -option has the format (POINT-FORMAT EOB-FORMAT INDEX-REGEXP), all -of which may be nil or a string (though either one of EOB-FORMAT -or POINT-FORMAT should be a string, and if INDEX-REGEXP is -non-nil, then the two formats should be too). - -First INDEX-REGEXP is used to find the previously inserted entry, -by searching backward from point. The first submatch must match -the index number. That number is incremented by one, and becomes -the index number of the entry to be inserted. If you don't want -to number the inserted revisions, then use nil for INDEX-REGEXP. - -If INDEX-REGEXP is non-nil then both POINT-FORMAT and EOB-FORMAT -should contain \"%N\", which is replaced with the number that was -determined in the previous step. - -Both formats, if non-nil and after removing %N, are then expanded -using `git show --format=FORMAT ...' inside TOPLEVEL. - -The expansion of POINT-FORMAT is inserted at point, and the -expansion of EOB-FORMAT is inserted at the end of the buffer (if -the buffer ends with a comment, then it is inserted right before -that)." - :package-version '(magit . "2.3.0") - :group 'magit-status - :type '(list (choice (string :tag "Insert at point format") - (cons (string :tag "Insert at point format") - (repeat (string :tag "Argument to git show"))) - (const :tag "Don't insert at point" nil)) - (choice (string :tag "Insert at eob format") - (cons (string :tag "Insert at eob format") - (repeat (string :tag "Argument to git show"))) - (const :tag "Don't insert at eob" nil)) - (choice (regexp :tag "Find index regexp") - (const :tag "Don't number entries" nil)))) - -(defun magit-pop-revision-stack (rev toplevel) - "Insert a representation of a revision into the current buffer. - -Pop a revision from the `magit-revision-stack' and insert it into -the current buffer according to `magit-pop-revision-stack-format'. -Revisions can be put on the stack using `magit-copy-section-value' -and `magit-copy-buffer-revision'. - -If the stack is empty or with a prefix argument instead read a -revision in the minibuffer. By using the minibuffer history this -allows selecting an item which was popped earlier or to insert an -arbitrary reference or revision without first pushing it onto the -stack. - -When reading the revision from the minibuffer, then it might not -be possible to guess the correct repository. When this command -is called inside a repository (e.g. while composing a commit -message), then that repository is used. Otherwise (e.g. while -composing an email) then the repository recorded for the top -element of the stack is used (even though we insert another -revision). If not called inside a repository and with an empty -stack, or with two prefix arguments, then read the repository in -the minibuffer too." - (interactive - (if (or current-prefix-arg (not magit-revision-stack)) - (let ((default-directory - (or (and (not (= (prefix-numeric-value current-prefix-arg) 16)) - (or (magit-toplevel) - (cadr (car magit-revision-stack)))) - (magit-read-repository)))) - (list (magit-read-branch-or-commit "Insert revision") - default-directory)) - (push (caar magit-revision-stack) magit-revision-history) - (pop magit-revision-stack))) - (if rev - (-let [(pnt-format eob-format idx-format) magit-pop-revision-stack-format] - (let ((default-directory toplevel) - (idx (and idx-format - (save-excursion - (if (re-search-backward idx-format nil t) - (number-to-string - (1+ (string-to-number (match-string 1)))) - "1")))) - pnt-args eob-args) - (when (listp pnt-format) - (setq pnt-args (cdr pnt-format) - pnt-format (car pnt-format))) - (when (listp eob-format) - (setq eob-args (cdr eob-format) - eob-format (car eob-format))) - (when pnt-format - (when idx-format - (setq pnt-format - (replace-regexp-in-string "%N" idx pnt-format t t))) - (magit-rev-insert-format pnt-format rev pnt-args) - (backward-delete-char 1)) - (when eob-format - (when idx-format - (setq eob-format - (replace-regexp-in-string "%N" idx eob-format t t))) - (save-excursion - (goto-char (point-max)) - (skip-syntax-backward ">s-") - (beginning-of-line) - (if (and comment-start (looking-at comment-start)) - (while (looking-at comment-start) - (forward-line -1)) - (forward-line) - (unless (= (current-column) 0) - (insert ?\n))) - (insert ?\n) - (magit-rev-insert-format eob-format rev eob-args) - (backward-delete-char 1))))) - (user-error "Revision stack is empty"))) - -(define-key git-commit-mode-map - (kbd "C-c C-w") 'magit-pop-revision-stack) - -(defun magit-copy-section-value () - "Save the value of the current section for later use. - -Save the section value to the `kill-ring', and, provided that -the current section is a commit, branch, or tag section, push -the (referenced) revision to the `magit-revision-stack' for use -with `magit-pop-revision-stack'. - -When the current section is a branch or a tag, and a prefix -argument is used, then save the revision at its tip to the -`kill-ring' instead of the reference name. - -When the region is active, then save that to the `kill-ring', -like `kill-ring-save' would, instead of behaving as described -above." - (interactive) - (if (region-active-p) - (copy-region-as-kill (mark) (point) 'region) - (-when-let* ((section (magit-current-section)) - (value (magit-section-value section))) - (magit-section-case - ((branch commit module-commit tag) - (let ((default-directory default-directory) ref) - (magit-section-case - ((branch tag) - (setq ref value)) - (module-commit - (setq default-directory - (file-name-as-directory - (expand-file-name (magit-section-parent-value section) - (magit-toplevel)))))) - (setq value (magit-rev-parse value)) - (push (list value default-directory) magit-revision-stack) - (kill-new (message "%s" (or (and current-prefix-arg ref) - value))))) - (t (kill-new (message "%s" value))))))) - -(defun magit-copy-buffer-revision () - "Save the revision of the current buffer for later use. - -Save the revision shown in the current buffer to the `kill-ring' -and push it to the `magit-revision-stack'. - -This command is mainly intended for use in `magit-revision-mode' -buffers, the only buffers where it is always unambiguous exactly -which revision should be saved. - -Most other Magit buffers usually show more than one revision, in -some way or another, so this command has to select one of them, -and that choice might not always be the one you think would have -been the best pick. - -In such buffers it is often more useful to save the value of -the current section instead, using `magit-copy-section-value'. - -When the region is active, then save that to the `kill-ring', -like `kill-ring-save' would, instead of behaving as described -above." - (interactive) - (if (region-active-p) - (copy-region-as-kill (mark) (point) 'region) - (-when-let (rev (cond ((memq major-mode '(magit-cherry-mode - magit-log-select-mode - magit-reflog-mode - magit-refs-mode - magit-revision-mode - magit-stash-mode - magit-stashes-mode)) - (car magit-refresh-args)) - ((memq major-mode '(magit-diff-mode - magit-log-mode)) - (let ((r (caar magit-refresh-args))) - (if (string-match "\\.\\.\\.?\\(.+\\)" r) - (match-string 1 r) - r))) - ((eq major-mode 'magit-status-mode) "HEAD"))) - (when (magit-rev-verify-commit rev) - (setq rev (magit-rev-parse rev)) - (push (list rev default-directory) magit-revision-stack) - (kill-new (message "%s" rev)))))) - -;;; magit.el ends soon - -(defconst magit-font-lock-keywords - (eval-when-compile - `((,(concat "(\\(magit-define-section-jumper\\)\\_>" - "[ \t'\(]*" - "\\(\\(?:\\sw\\|\\s_\\)+\\)?") - (1 'font-lock-keyword-face) - (2 'font-lock-function-name-face nil t)) - (,(concat "(" (regexp-opt '("magit-insert-section" - "magit-section-case" - "magit-section-when" - "magit-bind-match-strings" - "magit-with-temp-index" - "magit-with-blob" - "magit-with-toplevel") t) - "\\_>") - . 1)))) - -(font-lock-add-keywords 'emacs-lisp-mode magit-font-lock-keywords) - -(defvar magit-version 'undefined - "The version of Magit that you're using. -Use the function by the same name instead of this variable.") - -;;;###autoload -(defun magit-version () - "Return the version of Magit currently in use. -When called interactive also show the used versions of Magit, -Git, and Emacs in the echo area." - (interactive) - (let ((magit-git-global-arguments nil) - (toplib (or load-file-name buffer-file-name)) - debug) - (unless (and toplib - (equal (file-name-nondirectory toplib) "magit.el")) - (setq toplib (locate-library "magit.el"))) - (push toplib debug) - (when toplib - (let* ((topdir (file-name-directory toplib)) - (gitdir (expand-file-name - ".git" (file-name-directory - (directory-file-name topdir)))) - (static (expand-file-name "magit-version.el" topdir))) - (or (progn - (push 'repo debug) - (when (and (file-exists-p gitdir) - ;; It is a repo, but is it the Magit repo? - (file-exists-p - (expand-file-name "../lisp/magit.el" gitdir))) - (push t debug) - ;; Inside the repo the version file should only exist - ;; while running make. - (unless noninteractive - (ignore-errors (delete-file static))) - (setq magit-version - (let ((default-directory topdir)) - (magit-git-string "describe" "--tags" "--dirty"))))) - (progn - (push 'static debug) - (when (file-exists-p static) - (push t debug) - (load-file static) - magit-version)) - (when (featurep 'package) - (push 'elpa debug) - (ignore-errors - (--when-let (assq 'magit package-alist) - (push t debug) - (setq magit-version - (and (fboundp 'package-desc-version) - (package-version-join - (package-desc-version (cadr it))))))))))) - (if (stringp magit-version) - (when (called-interactively-p 'any) - (message "Magit %s, Git %s, Emacs %s" - (or magit-version "(unknown)") - (or (magit-git-version) "(unknown)") - emacs-version)) - (setq debug (reverse debug)) - (setq magit-version 'error) - (when magit-version - (push magit-version debug)) - (message "Cannot determine Magit's version %S" debug)) - magit-version)) - -(defun magit-git-version (&optional numeric) - (--when-let (let (magit-git-global-arguments) - (ignore-errors (substring (magit-git-string "version") 12))) - (if numeric - (and (string-match "^\\([0-9]+\\.[0-9]+\\.[0-9]+\\)" it) - (match-string 1 it)) - it))) - -(defun magit-startup-asserts () - (let ((version (magit-git-version t))) - (when (and version - (version< version magit--minimal-git) - (not (equal (getenv "TRAVIS") "true"))) - (display-warning 'magit (format "\ -Magit requires Git >= %s, you are using %s. - -If this comes as a surprise to you, because you do actually have -a newer version installed, then that probably means that the -older version happens to appear earlier on the `$PATH'. If you -always start Emacs from a shell, then that can be fixed in the -shell's init file. If you start Emacs by clicking on an icon, -or using some sort of application launcher, then you probably -have to adjust the environment as seen by graphical interface. -For X11 something like ~/.xinitrc should work. - -If you use Tramp to work inside remote Git repositories, then you -have to make sure a suitable Git is used on the remote machines -too.\n" magit--minimal-git version) :error))) - (when (version< emacs-version magit--minimal-emacs) - (display-warning 'magit (format "\ -Magit requires Emacs >= %s, you are using %s. - -If this comes as a surprise to you, because you do actually have -a newer version installed, then that probably means that the -older version happens to appear earlier on the `$PATH'. If you -always start Emacs from a shell, then that can be fixed in the -shell's init file. If you start Emacs by clicking on an icon, -or using some sort of application launcher, then you probably -have to adjust the environment as seen by graphical interface. -For X11 something like ~/.xinitrc should work.\n" - magit--minimal-emacs emacs-version) - :error)) - (--each '((magit-log-edit . git-commit) - (git-commit-mode . git-commit) - (git-rebase-mode . git-rebase)) - (when (or (featurep (car it)) (locate-library (symbol-name (car it)))) - (display-warning 'magit (format "%s has to be removed - -Magit is no longer compatible with the library `%s', -which was used in earlier releases. Please remove it, so that -Magit can use the successor `%s' without the obsolete -library getting in the way. Then restart Emacs.\n" - (car it) (car it) (cdr it)) :error)))) - -(defvar magit--remotes-using-recent-git nil) - -(defun magit-tramp-asserts (directory) - (-when-let (remote (file-remote-p directory)) - (unless (member remote magit--remotes-using-recent-git) - (-if-let (version (let ((default-directory directory)) - (magit-git-version t))) - (if (version<= magit--minimal-git version) - (push version magit--remotes-using-recent-git) - (display-warning 'magit (format "\ -Magit requires Git >= %s, but on %s the version is %s. - -If multiple Git versions are installed on the host then the -problem might be that TRAMP uses the wrong executable. - -First check the value of `magit-git-executable'. Its value is -used when running git locally as well as when running it on a -remote host. The default value is \"git\", except on Windows -where an absolute path is used for performance reasons. - -If the value already is just \"git\" but TRAMP never-the-less -doesn't use the correct executable, then consult the info node -`(tramp)Remote programs'.\n" magit--minimal-git remote version) :error)) - (display-warning 'magit (format "\ -Magit cannot find Git on %s. - -First check the value of `magit-git-executable'. Its value is -used when running git locally as well as when running it on a -remote host. The default value is \"git\", except on Windows -where an absolute path is used for performance reasons. - -If the value already is just \"git\" but TRAMP never-the-less -doesn't find the executable, then consult the info node -`(tramp)Remote programs'.\n" remote) :error))))) - -(define-obsolete-function-alias 'magit-insert-head-header - 'magit-insert-head-branch-header "Magit 2.4.0") - -(define-obsolete-function-alias 'magit-insert-upstream-header - 'magit-insert-pull-branch-header "Magit 2.4.0") - -(provide 'magit) - -(cl-eval-when (load eval) - (require 'magit-sequence) - (require 'magit-commit) - (require 'magit-remote) - (require 'magit-bisect) - (require 'magit-stash) - (require 'magit-blame) - (unless (load "magit-autoloads" t t) - (require 'magit-ediff) - (require 'magit-extras) - (require 'git-rebase))) - -(if after-init-time - (progn (magit-startup-asserts) - (magit-version)) - (add-hook 'after-init-hook #'magit-startup-asserts t) - (add-hook 'after-init-hook #'magit-version t)) - -;; Local Variables: -;; coding: utf-8 -;; indent-tabs-mode: nil -;; End: -;;; magit.el ends here diff --git a/elpa/magit-20151119.202/magit.info b/elpa/magit-20151119.202/magit.info deleted file mode 100644 index 54473215..00000000 --- a/elpa/magit-20151119.202/magit.info +++ /dev/null @@ -1,158 +0,0 @@ -This is magit.info, produced by makeinfo version 5.2 from magit.texi. - -Magit is an interface to the version control system Git, implemented as -an Emacs package. Magit aspires to be a complete Git porcelain. While -we cannot (yet) claim that Magit wraps and improves upon each and every -Git command, it is complete enough to allow even experienced Git users -to perform almost all of their daily version control tasks directly from -within Emacs. While many fine Git clients exist, only Magit and Git -itself deserve to be called porcelains. - - Copyright (C) 2015 Jonas Bernoulli - - You can redistribute this document 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 document 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. -INFO-DIR-SECTION Emacs -START-INFO-DIR-ENTRY -* Magit: (magit). Using Git from Emacs with Magit. -END-INFO-DIR-ENTRY - - -Indirect: -magit.info-1: 1217 -magit.info-2: 304678 - -Tag Table: -(Indirect) -Node: Top1217 -Node: Introduction5669 -Node: Installation10362 -Node: Updating from an older release10737 -Node: Installing from an Elpa archive12332 -Node: Installing from the Git repository13911 -Node: Post-installation tasks16155 -Node: Getting started17681 -Node: Interface concepts23416 -Node: Modes and Buffers23742 -Node: Switching Buffers25357 -Node: Naming Buffers28421 -Node: Quitting Windows31256 -Node: Automatic save32842 -Node: Automatic refresh and revert33907 -Node: Sections38567 -Node: Section movement39519 -Node: Section visibility43446 -Node: Section hooks47037 -Node: Section types and values49075 -Node: Section options50345 -Node: Popup buffers and prefix commands50817 -Node: Completion and confirmation52131 -Node: Running Git55037 -Node: Viewing Git output55273 -Node: Running Git manually56273 -Node: Git executable58399 -Node: Global Git arguments60406 -Node: Inspecting61213 -Node: Status buffer62340 -Node: Status sections64884 -Node: Status header sections69227 -Node: Status options71057 -Node: Logging71781 -Node: Refreshing logs74148 -Node: Log Buffer75533 -Node: Select from log78622 -Node: Reflog79562 -Node: Diffing80040 -Node: Refreshing diffs83036 -Node: Diff buffer86017 -Node: Diff options87919 -Node: Revision buffer89551 -Node: Ediffing90506 -Node: References buffer93555 -Node: References sections98265 -Node: Bisecting99140 -Node: Visiting blobs100636 -Node: Blaming101145 -Node: Manipulating104465 -Node: Repository setup104757 -Node: Staging and unstaging105520 -Node: Staging from file-visiting buffers107869 -Node: Applying109037 -Node: Committing110680 -Node: Initiating a commit111263 -Node: Editing commit messages114575 -Node: Branching124971 -Node: Merging128663 -Node: Rebasing130747 -Node: Editing rebase sequences133734 -Node: Rebase sequence log136768 -Node: Cherry picking143512 -Node: Reverting145118 -Node: Resetting146481 -Node: Stashing147991 -Node: Transferring151136 -Node: Remotes151374 -Node: Fetching152177 -Node: Pulling152993 -Node: Pushing153493 -Node: Creating and sending patches156472 -Node: Applying patches157167 -Node: Miscellaneous158165 -Node: Tagging158456 -Node: Notes159241 -Node: Submodules161766 -Node: Common commands163086 -Node: Wip modes164834 -Node: Minor mode for buffers visiting files171570 -Node: Minor mode for buffers visiting blobs173713 -Node: Customizing174518 -Node: Per-repository configuration176190 -Node: Essential settings177838 -Node: Safety178162 -Node: Performance181343 -Node: Plumbing187297 -Node: Calling Git187925 -Node: Getting a value from Git189448 -Node: Calling Git for effect192552 -Node: Section plumbing199056 -Node: Creating sections199284 -Node: Section selection203087 -Node: Matching sections204767 -Node: Refreshing buffers209969 -Node: Conventions213104 -Node: Confirmation and completion213281 -Node: Theming Faces214179 -Node: FAQ222330 -Node: Magit is slow223499 -Node: I changed several thousand files at once and now Magit is unusable223700 -Node: I am having problems committing224416 -Node: I don't like how branching and pushing works224869 -Node: I cannot install the pre-requisits for Magit v2225348 -Node: I am using an Emacs release older than v244225819 -Node: I am using a Git release older than v194227431 -Node: I am using MS Windows and cannot push with Magit228418 -Node: How to install the gitman info manual?228997 -Node: How can I show Git's output?231579 -Node: Expanding a file to show the diff causes it to disappear232391 -Node: Point is wrong in the COMMIT_EDITMSG buffer232917 -Node: Can Magit be used as ediff-version-control-package?233935 -Node: How to show diffs for gpg-encrypted files?235959 -Node: Emacs 245 hangs when loading Magit236550 -Node: Keystroke Index237069 -Node: Command Index264479 -Node: Function Index292553 -Node: Variable Index304678 - -End Tag Table - - -Local Variables: -coding: utf-8 -End: diff --git a/elpa/magit-20151119.202/magit.info-1 b/elpa/magit-20151119.202/magit.info-1 deleted file mode 100644 index d24bb1b0..00000000 --- a/elpa/magit-20151119.202/magit.info-1 +++ /dev/null @@ -1,7171 +0,0 @@ -This is magit.info, produced by makeinfo version 5.2 from magit.texi. - -Magit is an interface to the version control system Git, implemented as -an Emacs package. Magit aspires to be a complete Git porcelain. While -we cannot (yet) claim that Magit wraps and improves upon each and every -Git command, it is complete enough to allow even experienced Git users -to perform almost all of their daily version control tasks directly from -within Emacs. While many fine Git clients exist, only Magit and Git -itself deserve to be called porcelains. - - Copyright (C) 2015 Jonas Bernoulli - - You can redistribute this document 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 document 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. -INFO-DIR-SECTION Emacs -START-INFO-DIR-ENTRY -* Magit: (magit). Using Git from Emacs with Magit. -END-INFO-DIR-ENTRY - - -File: magit.info, Node: Top, Next: Introduction, Up: (dir) - -Magit User Manual -***************** - -Magit is an interface to the version control system Git, implemented as -an Emacs package. Magit aspires to be a complete Git porcelain. While -we cannot (yet) claim that Magit wraps and improves upon each and every -Git command, it is complete enough to allow even experienced Git users -to perform almost all of their daily version control tasks directly from -within Emacs. While many fine Git clients exist, only Magit and Git -itself deserve to be called porcelains. - - Copyright (C) 2015 Jonas Bernoulli - - You can redistribute this document 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 document 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. - -* Menu: - -* Introduction:: -* Installation:: -* Getting started:: -* Interface concepts:: -* Inspecting:: -* Manipulating:: -* Transferring:: -* Miscellaneous:: -* Customizing:: -* Plumbing:: -* FAQ:: -* Keystroke Index:: -* Command Index:: -* Function Index:: -* Variable Index:: - -— The Detailed Node Listing — - -Installation - -* Updating from an older release:: -* Installing from an Elpa archive:: -* Installing from the Git repository:: -* Post-installation tasks:: - -Interface concepts - -* Modes and Buffers:: -* Automatic save:: -* Automatic refresh and revert:: -* Sections:: -* Popup buffers and prefix commands:: -* Completion and confirmation:: -* Running Git:: - -Modes and Buffers - -* Switching Buffers:: -* Naming Buffers:: -* Quitting Windows:: - -Sections - -* Section movement:: -* Section visibility:: -* Section hooks:: -* Section types and values:: -* Section options:: - -Running Git - -* Viewing Git output:: -* Running Git manually:: -* Git executable:: -* Global Git arguments:: - -Inspecting - -* Status buffer:: -* Logging:: -* Diffing:: -* Ediffing:: -* References buffer:: -* Bisecting:: -* Visiting blobs:: -* Blaming:: - -Status buffer - -* Status sections:: -* Status header sections:: -* Status options:: - -Logging - -* Refreshing logs:: -* Log Buffer:: -* Select from log:: -* Reflog:: - -Diffing - -* Refreshing diffs:: -* Diff buffer:: -* Diff options:: -* Revision buffer:: - -References buffer - -* References sections:: - -Manipulating - -* Repository setup:: -* Staging and unstaging:: -* Applying:: -* Committing:: -* Branching:: -* Merging:: -* Rebasing:: -* Cherry picking:: -* Resetting:: -* Stashing:: - -Staging and unstaging - -* Staging from file-visiting buffers:: - -Committing - -* Initiating a commit:: -* Editing commit messages:: - -Rebasing - -* Editing rebase sequences:: -* Rebase sequence log:: - -Cherry picking - -* Reverting:: - -Transferring - -* Remotes:: -* Fetching:: -* Pulling:: -* Pushing:: -* Creating and sending patches:: -* Applying patches:: - -Miscellaneous - -* Tagging:: -* Notes:: -* Submodules:: -* Common commands:: -* Wip modes:: -* Minor mode for buffers visiting files:: -* Minor mode for buffers visiting blobs:: - -Customizing - -* Per-repository configuration:: -* Essential settings:: - -Essential settings - -* Safety:: -* Performance:: - -Plumbing - -* Calling Git:: -* Section plumbing:: -* Refreshing buffers:: -* Conventions:: - -Calling Git - -* Getting a value from Git:: -* Calling Git for effect:: - -Section plumbing - -* Creating sections:: -* Section selection:: -* Matching sections:: - -Conventions - -* Confirmation and completion:: -* Theming Faces:: - -FAQ - -* Magit is slow:: -* I changed several thousand files at once and now Magit is unusable:: -* I am having problems committing:: -* I don't like how branching and pushing works:: -* I cannot install the pre-requisits for Magit v2:: -* I am using an Emacs release older than v24.4: I am using an Emacs release older than v244. -* I am using a Git release older than v1.9.4: I am using a Git release older than v194. -* I am using MS Windows and cannot push with Magit:: -* How to install the gitman info manual?:: -* How can I show Git's output?:: -* Expanding a file to show the diff causes it to disappear:: -* Point is wrong in the COMMIT_EDITMSG buffer:: -* Can Magit be used as ediff-version-control-package?:: -* How to show diffs for gpg-encrypted files?:: -* Emacs 24.5 hangs when loading Magit: Emacs 245 hangs when loading Magit. - - - -File: magit.info, Node: Introduction, Next: Installation, Prev: Top, Up: Top - -1 Introduction -************** - -Magit is an interface to the version control system Git, implemented as -an Emacs package. Magit aspires to be a complete Git porcelain. While -we cannot (yet) claim that Magit wraps and improves upon each and every -Git command, it is complete enough to allow even experienced Git users -to perform almost all of their daily version control tasks directly from -within Emacs. While many fine Git clients exist, only Magit and Git -itself deserve to be called porcelains. - - Staging and otherwise applying changes is one of the most important -features in a Git porcelain and here Magit outshines anything else, -including Git itself. Git’s own staging interface (‘git add --patch’) -is so cumbersome that many users only use it in exceptional cases. In -Magit staging a hunk or even just part of a hunk is as trivial as -staging all changes made to a file. - - The most visible part of Magit’s interface is the status buffer, -which displays information about the current repository. Its content is -created by running several Git commands and making their output -actionable. Among other things, it displays information about the -current branch, lists unpulled and unpushed changes and contains -sections displaying the staged and unstaged changes. That might sound -noisy, but, since sections are collapsible, it’s not. - - To stage or unstage a change one places the cursor on the change and -then types ‘s’ or ‘u’. The change can be a file or a hunk, or when the -region is active (i.e. when there is a selection) several files or -hunks, or even just part of a hunk. The change or changes that these -commands - and many others - would act on are highlighted. - - Magit also implements several other "apply variants" in addition to -staging and unstaging. One can discard or reverse a change, or apply it -to the working tree. Git’s own porcelain only supports this for staging -and unstaging and you would have to do something like ‘git diff ... | -??? | git apply ...’ to discard, revert, or apply a single hunk on the -command line. In fact that’s exactly what Magit does internally (which -is what lead to the term "apply variants"). - - Magit isn’t just for Git experts, but it does assume some prior -experience with Git as well as Emacs. That being said, many users have -reported that using Magit was what finally taught them what Git is -capable of and how to use it to its fullest. Other users wished they -had switched to Emacs sooner so that they would have gotten their hands -on Magit earlier. - - While one has to know the basic features of Emacs to be able to make -full use of Magit, acquiring just enough Emacs skills doesn’t take long -and is worth it, even for users who prefer other editors. Vim users are -advised to give Evil (https://bitbucket.org/lyro/evil/wiki/Home), the -"Extensible VI Layer for Emacs", and Spacemacs -(https://github.com/syl20bnr/spacemacs), an "Emacs starter-kit focused -on Evil" a try. - - Magit provides a consistent and efficient Git porcelain. After a -short learning period, you will be able to perform most of your daily -version control tasks faster than you would on the command line. You -will likely also start using features that seemed too daunting in the -past. - - Magit fully embraces Git. It exposes many advanced features using a -simple but flexible interface instead of only wrapping the trivial ones -like many GUI clients do. Of course Magit supports logging, cloning, -pushing, and other commands that usually don’t fail in spectacular ways; -but it also supports tasks that often cannot be completed in a single -step. Magit fully supports tasks such as merging, rebasing, -cherry-picking, reverting, and blaming by not only providing a command -to initiate these tasks but also by displaying context sensitive -information along the way and providing commands that are useful for -resolving conflicts and resuming the sequence after doing so. - - Magit wraps and in many cases improves upon at least the following -Git porcelain commands: ‘add’, ‘am’, ‘bisect’, ‘blame’, ‘branch’, -‘checkout’, ‘cherry’, ‘cherry-pick’, ‘clean’, ‘clone’, ‘commit’, -‘config’, ‘describe’, ‘diff’, ‘fetch’, ‘format-patch’, ‘init’, ‘log’, -‘merge’, ‘merge-tree’, ‘mv’, ‘notes’, ‘pull’, ‘rebase’, ‘reflog’, -‘remote’, ‘request-pull’, ‘reset’, ‘revert’, ‘rm’, ‘show’, ‘stash’, -‘submodule’, and ‘tag’. Many more Magit porcelain commands are -implemented on top of Git plumbing commands. - - -File: magit.info, Node: Installation, Next: Getting started, Prev: Introduction, Up: Top - -2 Installation -************** - -Magit can be installed using Emacs’ package manager or manually from its -development repository. - -* Menu: - -* Updating from an older release:: -* Installing from an Elpa archive:: -* Installing from the Git repository:: -* Post-installation tasks:: - - -File: magit.info, Node: Updating from an older release, Next: Installing from an Elpa archive, Up: Installation - -2.1 Updating from an older release -================================== - -When updating from ‘1.2.*’ or ‘1.4.*’, you should first uninstall Magit -and some of its dependencies and restart Emacs before installing the -latest release. - - • The old Magit installation has to be removed because some macros - have changed and using the old definitions when building the new - release would lead to very strange results, including compile - errors. This is due to a limitation in Emacs’ package manager or - rather Emacs itself: it’s not possible to reliably unload a feature - or even all features belonging to a package. - - • Furthermore the old dependencies ‘git-commit-mode’ and - ‘git-rebase-mode’ have to be removed because they are no longer - used by the ‘2.1.0’ release and later, and get in the way of their - successors ‘git-commit’ and ‘git-rebase’. - - So please uninstall the packages ‘magit’, ‘git-commit-mode’, and -‘git-rebase-mode’. Then quit Emacs and start a new instance. Only then -follow the instructions in either one of the next two sections. - - Also note that starting with the ‘2.1.0’ release, Magit requires at -least Emacs ‘24.4’ and Git ‘1.9.4’. You should make sure you have at -least these releases installed before updating Magit. And if you -connect to remote hosts using Tramp, then you should also make sure to -install a recent enough Git version on these hosts. - - -File: magit.info, Node: Installing from an Elpa archive, Next: Installing from the Git repository, Prev: Updating from an older release, Up: Installation - -2.2 Installing from an Elpa archive -=================================== - -If you are updating from a release older than ‘2.1.0’, then you have to -first uninstall the old version. See *note Updating from an older -release: Updating from an older release. - - Magit is available from all three of the popular unofficial Elpa -archives: Melpa, Melpa-Stable, and Marmalade. If you haven’t used -Emacs’ package manager before, then it is high time you familiarize -yourself with it by reading the documentation in the Emacs manual, see -*note (emacs)Packages::. Then add one of the archives to -‘package-archives’: - - • To use Melpa: - - (require 'package) - (add-to-list 'package-archives - '("melpa" . "http://melpa.org/packages/") t) - - • To use Melpa-Stable: - - (require 'package) - (add-to-list 'package-archives - '("melpa-stable" . "http://stable.melpa.org/packages/") t) - - • To use Marmalade: - - (require 'package) - (add-to-list 'package-archives - '("marmalade" . "http://marmalade-repo.org/packages/") t) - - Once you have added your preferred archive, you need to update the -local package list using: - - M-x package-refresh-contents RET - - Once you have done that, you can install Magit and its dependencies -using: - - M-x package-install RET magit RET - - Now see *note Post-installation tasks: Post-installation tasks. - - -File: magit.info, Node: Installing from the Git repository, Next: Post-installation tasks, Prev: Installing from an Elpa archive, Up: Installation - -2.3 Installing from the Git repository -====================================== - -If you are updating from a release older than ‘2.1.0’, then you have to -first uninstall the old version. See *note Updating from an older -release: Updating from an older release. - - Magit depends on the ‘dash’ library, available from all three of the -popular third-party Elpa archives. Install it using ‘M-x -package-install RET dash RET’. Of course you may also install it -manually from its development repository, but I won’t cover that here. - - Then clone the Magit repository: - - $ git clone git://github.com/magit/magit.git ~/.emacs.d/site-lisp/magit - $ cd ~/.emacs.d/site-lisp/magit - - Then compile the libraries and generate the info manuals: - - $ make - - If you haven’t installed ‘dash’ using Elpa or at -‘/path/to/magit/../dash’, then you have to tell ‘make’ where to find it. -To do so create ‘/path/to/magit/config.mk’ with the following content -before running ‘make’: - - LOAD_PATH = -L /path/to/magit/lisp -L /path/to/dash - - Finally add this to your init file: - - (add-to-list 'load-path "~/.emacs.d/site-lisp/magit/lisp") - (require 'magit) - - (with-eval-after-load 'info - (info-initialize) - (add-to-list 'Info-directory-list - "~/.emacs.d/site-lisp/magit/Documentation/")) - - Note that you have to add the ‘lisp/’ subdirectory to the -‘load-path’, not the top-level of the repository. - - Instead of requiring the feature ‘magit’, you could only load the -autoloads, by loading the file ‘magit-autoloads.el’. - - Instead of running Magit directly from the repository by adding that -to the ‘load-path’, you might want to instead install it in some other -directory using ‘sudo make install’ and setting ‘load-path’ accordingly. - - To update Magit use: - - $ git pull - $ make - - At times it might be necessary to run ‘make clean all’ instead. - - To view all available targets use ‘make help’. - - Now see *note Post-installation tasks: Post-installation tasks. - - -File: magit.info, Node: Post-installation tasks, Prev: Installing from the Git repository, Up: Installation - -2.4 Post-installation tasks -=========================== - -After installing Magit you should verify that you are indeed using the -Magit, Git, and Emacs releases you think you are using. It’s best to -restart Emacs before doing so, to make sure you are not using an -outdated value for ‘load-path’. - - M-x magit-version RET - - should display something like - - Magit 2.2.0, Git 2.4.2, Emacs 24.5.1 - - Then you might also want to read about options that many users likely -want to customize. See *note Essential settings: Essential settings. - - To be able to follow cross references to Git manpages found in this -manual, you might also have to manually install the ‘gitman’ info -manual, or advice ‘Info-follow-nearest-node’ to instead open the actual -manpage. See *note How to install the gitman info manual?: How to -install the gitman info manual?. - - If you are completely new to Magit then see *note Getting started: -Getting started. - - If you have used an older Magit release before, then you should have -a look at the release notes - -and - - - And last but not least please consider making a donation, to ensure -that I can keep working on Magit. See -for various donation options. - - -File: magit.info, Node: Getting started, Next: Interface concepts, Prev: Installation, Up: Top - -3 Getting started -***************** - -This section describes the most essential features that many Magitians -use on a daily basis. It only scratches the surface but should be -enough to get you started. - - (You might want to create a repository just for this walk-through, -e.g. by cloning an existing repository. If you don’t use a separate -repository then make sure you create a snapshot as described below). - - To display information about the current Git repository, type ‘M-x -magit-status’. You will be doing that so often that it is best to bind -this command globally: - - (global-set-key (kbd "C-x g") 'magit-status) - - Most Magit commands are commonly invoked from this buffer. It should -be considered the primary interface to interact with Git using Magit. -There are many other Magit buffers, but they are usually created from -this buffer. - - Depending on what state your repository is in, this buffer will -contain sections titled "Staged changes", "Unstaged changes", "Unpulled -commits", "Unpushed commits", and/or some others. - - If some staged and/or unstaged changes exist, you should back them up -now. Type ‘z’ to show the stashing popup buffer featuring various stash -variants and arguments that can be passed to these commands. Do not -worry about those for now, just type ‘Z’ (uppercase) to create a stash -while also keeping the index and work tree intact. The status buffer -should now also contain a section titled "Stashes". - - Otherwise, if there are no uncommitted changes, you should create -some now by editing and saving some of the tracked files. Then go back -to the status buffer, while at the same time refreshing it, by typing -‘C-x g’. (When the status buffer, or any Magit buffer for that matter, -is the current buffer, then you can also use just ‘g’ to refresh it). - - Move between sections using ‘p’ and ‘n’. Note that the bodies of -some sections are hidden. Type ‘TAB’ to expand or collapse the section -at point. You can also use ‘C-tab’ to cycle the visibility of the -current section and its children. Move to a file section inside the -section named "Unstaged changes" and type ‘s’ to stage the changes you -have made to that file. That file now appears under "Staged changes". - - Magit can stage and unstage individual hunks, not just complete -files. Move to the file you have just staged, expand it using ‘TAB’, -move to one of the hunks using ‘n’, and unstage just that by typing ‘u’. -Note how the staging (‘s’) and unstaging (‘u’) commands operate on the -change at point. Many other commands behave the same way. - - You can also un-/stage just part of a hunk. Inside the body of a -hunk section (move there using ‘C-n’), set the mark using ‘C-SPC’ and -move down until some added and removed lines fall inside the region but -not all of them. Again type ‘s’ to stage. - - It’s also possible to un-/stage multiple files at once. Move to a -file section, type ‘C-SPC’, move to the next file using ‘n’, and then -‘s’ to stage both files. Note that both the mark and point have to be -on the headings of sibling sections for this to work. If the region -looks like it does in other buffers, then it doesn’t select Magit -sections that can be acted on as a unit. - - And then of course you want to commit your changes. Type ‘c’. This -shows the committing popup buffer featuring various commit variants and -arguments that can be passed to ‘git commit’. Do not worry about those -for now. We want to create a "normal" commit, which is done by typing -‘c’ again. - - Now two new buffers appear. One is for writing the commit message, -the other shows a diff with the changes that are about to committed. -Write a message and then type ‘C-c C-c’ to actually create the commit. - - You probably don’t want to push the commit you just created because -you just committed some random changes, but if that is not the case you -could push it by typing ‘P’ to bring up the push popup and then ‘P’ -again to push to the configured upstream. (If the upstream is not -configured, then you would be prompted for the push target instead.) - - Instead we are going to undo the changes made so far. Bring up the -log for the current branch by typing ‘l l’, move to the last commit -created before starting with this walk through using ‘n’, and do a hard -reset using ‘C-u x’. *WARNING*: this discards all uncommitted changes. -If you did not follow the advice about using a separate repository for -these experiments and did not create a snapshot of uncommitted changes -before starting to try out Magit, then don’t do this. - - So far we have mentioned the commit, push, and log popups. These are -probably among the popups you will be using the most, but many others -exist. To show a popup with all other popups (as well as the various -apply commands), type ‘h’. Try a few. - - The key bindings in that popup correspond to the bindings in Magit -buffers, including but not limited to the status buffer. So you could -type ‘h d’ to bring up the diff popup, but once you remember that "d" -stands for "diff", you would usually do so by just typing ‘d’. But the -"popup of popups" is useful even once you have memorized all the -bindings, as it can provide easy access to Magit commands from non-Magit -buffers. So you should bind this globally too: - - (global-set-key (kbd "C-x M-g") 'magit-dispatch-popup) - - You might also want to enable ‘global-magit-file-mode’ (see *note -Minor mode for buffers visiting files: Minor mode for buffers visiting -files.). - - -File: magit.info, Node: Interface concepts, Next: Inspecting, Prev: Getting started, Up: Top - -4 Interface concepts -******************** - -* Menu: - -* Modes and Buffers:: -* Automatic save:: -* Automatic refresh and revert:: -* Sections:: -* Popup buffers and prefix commands:: -* Completion and confirmation:: -* Running Git:: - - -File: magit.info, Node: Modes and Buffers, Next: Automatic save, Up: Interface concepts - -4.1 Modes and Buffers -===================== - -Magit provides several major-modes. For each of these modes there -usually exists only one buffer per repository. Separate modes and thus -buffers exist for commits, diffs, logs, and some other things. - - Besides these special purpose buffers, there also exists an overview -buffer, called the *status buffer*. Its usually from this buffer that -the user invokes Git commands, or creates or visits other buffers. - - In this manual we often speak about "Magit buffers". By that we mean -buffers whose major-modes derive from ‘magit-mode’. - -‘M-x magit-toggle-buffer-lock’ (‘magit-toggle-buffer-lock’) - - This command locks the current buffer to its value or if the buffer - is already locked, then it unlocks it. - - Locking a buffer to its value, prevents it from being reused to - display another value. The name of a locked buffer contains its - value, which allows telling it apart from other locked buffers and - the unlocked buffer. - - Not all Magit buffers can be locked to their values, for example it - wouldn’t make sense to lock a status buffer. - - There can only be a single unlocked buffer using a certain - major-mode per repository. So when a buffer is being unlocked and - another unlocked buffer already exists for that mode and - repository, then the former buffer is instead deleted and the - latter is displayed in its place. - -* Menu: - -* Switching Buffers:: -* Naming Buffers:: -* Quitting Windows:: - - -File: magit.info, Node: Switching Buffers, Next: Naming Buffers, Up: Modes and Buffers - -4.1.1 Switching Buffers ------------------------ - - -- Function: magit-display-buffer buffer - - This function is a wrapper around ‘display-buffer’ and is used to - display any Magit buffer. It displays BUFFER in some window and, - unlike ‘display-buffer’, also selects that window, provided - ‘magit-display-buffer-noselect’ is ‘nil’. It also runs the hooks - mentioned below. - - -- Variable: magit-display-buffer-noselect - - When this is non-nil, then ‘magit-display-buffer’ only displays the - buffer but forgoes also selecting the window. This variable should - not be set globally, it is only intended to be let-bound, by code - that automatically updates "the other window". This is used for - example when the revision buffer is updated when you move inside - the log buffer. - - -- User Option: magit-display-buffer-function - - The function specified here is called by ‘magit-display-buffer’ - with one argument, a buffer, to actually display that buffer. This - function should call ‘display-buffer’ with that buffer as first and - a list of display actions as second argument. - - Instead of using a wrapper around ‘display-buffer’, that function - itself can be used here, in which case the display actions have to - be specified by adding them to ‘display-buffer-alist’ instead. - - To learn about display actions, see *note (elisp)Choosing a Window - for Display::. - - -- Function: magit-display-buffer-traditional buffer - - This function is the current default value of the option - ‘magit-display-buffer-function’. Before that option and this - function were added, the behavior was hard-coded in many places all - over the code base but now all the rules are contained in this one - function (except for the "noselect" special case mentioned above). - - If you want to use different rules, then a good way of doing that - is to start with a copy of this function and then adjust it to your - needs. More functions to choose from will be added in the future, - and eventually the default will change. - - -- User Option: magit-pre-display-buffer-hook - - This hook is run by ‘magit-display-buffer’ before displaying the - buffer. - - -- Function: magit-save-window-configuration - - This function saves the current window configuration. Later when - the buffer is buried, it may be restored by - ‘magit-restore-window-configuration’. - - -- User Option: magit-post-display-buffer-hook - - This hook is run by ‘magit-display-buffer’ after displaying the - buffer. - - -- Function: magit-maybe-set-dedicated - - This function remembers if a new window had to be created to - display the buffer, or whether an existing window was reused. This - information is later used by ‘magit-mode-quit-window’, to determine - whether the window should be deleted when its last Magit buffer is - buried. - - -File: magit.info, Node: Naming Buffers, Next: Quitting Windows, Prev: Switching Buffers, Up: Modes and Buffers - -4.1.2 Naming Buffers --------------------- - - -- User Option: magit-generate-buffer-name-function - - The function used to generate the names of Magit buffers. - - Such a function should take the options - ‘magit-uniquify-buffer-names’ as well as ‘magit-buffer-name-format’ - into account. If it doesn’t, then should be clearly stated in the - doc-string. And if it supports %-sequences beyond those mentioned - in the doc-string of the option ‘magit-buffer-name-format’, then - its own doc-string should describe the additions. - - -- Function: magit-generate-buffer-name-default-function mode - - This function returns a buffer name suitable for a buffer whose - major-mode is MODE and which shows information about the repository - in which ‘default-directory’ is located. - - This function uses ‘magit-buffer-name-format’ and supporting all of - the %-sequences mentioned the documentation of that option. It - also respects the option ‘magit-uniquify-buffer-names’. - - -- User Option: magit-buffer-name-format - - The format string used to name Magit buffers. - - At least the following %-sequences are supported: - - • ‘%m’ - - The name of the major-mode, but with the ‘-mode’ suffix - removed. - - • ‘%M’ - - Like ‘%m’ but abbreviate ‘magit-status-mode’ as ‘magit’. - - • ‘%v’ - - The value the buffer is locked to, in parentheses, or an empty - string if the buffer is not locked to a value. - - • ‘%V’ - - Like ‘%v’, but the string is prefixed with a space, unless it - is an empty string. - - • ‘%t’ - - The top-level directory of the working tree of the repository, - or if ‘magit-uniquify-buffer-names’ is non-nil an abbreviation - of that. - The value should always contain either ‘%m’ or ‘%M’, ‘%v’ or ‘%V’, - and ‘%t’. If ‘magit-uniquify-buffer-names’ is non-nil, then the - value must end with ‘%t’. - - -- User Option: magit-uniquify-buffer-names - - This option controls whether the names of Magit buffers are - uniquified. If the names are not being uniquified, then they - contain the full path of the top-level of the working tree of the - corresponding repository. If they are being uniquified, then they - end with the basename of the top-level, or if that would conflict - with the name used for other buffers, then the names of all these - buffers are adjusted until they no longer conflict. - - This is done using the ‘uniquify’ package; customize its options to - control how buffer names are uniquified. - - -File: magit.info, Node: Quitting Windows, Prev: Naming Buffers, Up: Modes and Buffers - -4.1.3 Quitting Windows ----------------------- - -‘q’ (‘magit-mode-bury-buffer’) - - This command buries the current Magit buffer. With a prefix - argument, it instead kills the buffer. - - -- User Option: magit-bury-buffer-function - - The function used to actually bury or kill the current buffer. - - ‘magit-mode-bury-buffer’ calls this function with one argument. If - the argument is non-nil, then the function has to kill the current - buffer. Otherwise it has to bury it alive. The default value - currently is ‘magit-restore-window-configuration’. - - -- Function: magit-restore-window-configuration kill-buffer - - Bury or kill the current buffer using ‘quit-window’, which is - called with KILL-BUFFER as first and the selected window as second - argument. - - Then restore the window configuration that existed right before the - current buffer was displayed in the selected frame. Unfortunately - that also means that point gets adjusted in all the buffers, which - are being displayed in the selected frame. - - -- Function: magit-mode-quit-window kill-buffer - - Bury or kill the current buffer using ‘quit-window’, which is - called with KILL-BUFFER as first and the selected window as second - argument. - - Then, if the window was originally created to display a Magit - buffer and the buried buffer was the last remaining Magit buffer - that was ever displayed in the window, then that is deleted. - - -File: magit.info, Node: Automatic save, Next: Automatic refresh and revert, Prev: Modes and Buffers, Up: Interface concepts - -4.2 Automatic save -================== - -File-visiting buffers are by default saved at certain points in time. -This doesn’t guarantee that Magit buffers are always up-to-date, but, -provided one only edits files by editing them in Emacs and uses only -Magit to interact with Git, one can be fairly confident. When in doubt -or after outside changes, type ‘g’ (‘magit-refresh’) to save and refresh -explicitly. - - -- User Option: magit-save-repository-buffers - - This option controls whether file-visiting buffers are saved before - certain events. - - If this is non-nil then all modified file-visiting buffers - belonging to the current repository may be saved before running - commands, before creating new Magit buffers, and before explicitly - refreshing such buffers. If this is ‘dontask’ then this is done - without user intervention. If it is ‘t’ then the user has to - confirm each save. - - -File: magit.info, Node: Automatic refresh and revert, Next: Sections, Prev: Automatic save, Up: Interface concepts - -4.3 Automatic refresh and revert -================================ - -After running a command which may change the state of the current -repository, the current Magit buffer and the corresponding status buffer -are refreshed. Status buffer may optionally be automatically refreshed -whenever a buffer is saved to a file inside the respective repository. - - Automatically refreshing Magit buffers ensures that the displayed -information is up-to-date most of the time but can lead to a noticeable -delay in big repositories. Other Magit buffers are not refreshed to -keep the delay to a minimum and also because doing so can sometimes be -undesirable. - - -- User Option: magit-revert-buffers - - This option controls if and how file-visiting buffers in the - current repository are reverted. - - Unmodified buffers visiting files belonging to the current - repository may be reverted after refreshing the current Magit - buffer and after running certain other commands. - - • ‘nil’ - - Don’t revert any buffers. - - • ‘ask’ - - List the buffers which might potentially have to be reverted - and ask the user whether she wants to revert them. If so, - then do it synchronously. - - • ‘t’ - - Revert the buffers synchronously, mentioning each one as it is - being reverted and then also show a summary in the echo area. - - • ‘usage’ - - Like ‘t’ but include usage information in the summary. This - is the default so that users come here and pick what is right - for them. - - • ‘silent’ - - Revert the buffers synchronously and be quiet about it. - - This is the recommended setting, because for the other values - the revert messages might prevent you from seeing other, more - important, messages in the echo area. - - • NUMBER - - An integer or float. Revert the buffers asynchronously, - mentioning each one as it is being reverted. If user input - arrives, then stop reverting. After NUMBER seconds resume - reverting. - - Buffers can also be refreshed explicitly, which is useful in buffers -that weren’t current during the last refresh and after changes were made -to the repository outside of Magit. - -‘g’ (‘magit-refresh’) - - This command refreshes the current buffer if its major mode derives - from ‘magit-mode’ as well as the corresponding status buffer. - - If the option ‘magit-revert-buffers’ calls for it, then it also - reverts all unmodified buffers that visit files being tracked in - the current repository. - -‘G’ (‘magit-refresh-all’) - - This command refreshes all Magit buffers belonging to the current - repository and also reverts all unmodified buffers that visit files - being tracked in the current repository. - - The file-visiting buffers are always reverted, even if - ‘magit-revert-buffers’ is nil. - - -- Function: magit-after-save-refresh-status - - This function is intended to be added to ‘after-save-hook’. After - doing that the corresponding status buffer is refreshed whenever a - buffer is saved to a file inside a repository. - - Note that refreshing a Magit buffer is done by re-creating its - contents from scratch, which can be slow in large repositories. If - you are not satisfied with Magit’s performance, then you should - obviously not add this function to that hook. - - -- User Option: magit-refresh-buffer-hook - - This hook is run in each Magit buffer that was refreshed during the - current refresh - normally the current buffer and the status - buffer. - - -- User Option: magit-after-revert-hook - - This hook is run in each file-visiting buffer belonging to the - current repository that was actually reverted during a refresh. - - Note that adding something here is very expensive. If you - experience performance issues, you might want to check this hook, - as well as ‘magit-not-reverted-hook’ and, if possible, remove some - of the functions added by third-party packages. - - -- User Option: magit-not-reverted-hook - - This hook is run in each file-visiting buffer belonging to the - current repository that was reverted during a refresh. The file - was not reverted because it did not change, and so Magit does not - have to do anything. This hook is intended for third-party - extensions that need to run some functions even on such files. - - -File: magit.info, Node: Sections, Next: Popup buffers and prefix commands, Prev: Automatic refresh and revert, Up: Interface concepts - -4.4 Sections -============ - -Magit buffers are organized into nested sections, which can be collapsed -and expanded, similar to how sections are handled in Org mode. Each -section also has a type, and some sections also have a value. For each -section type there can also be a local keymap, shared by all sections of -that type. - - Taking advantage of the section value and type, many commands operate -on the current section, or when the region is active and selects -sections of the same type, all of the selected sections. Commands that -only make sense for a particular section type (as opposed to just -behaving differently depending on the type) are usually bound in section -type keymaps. - -* Menu: - -* Section movement:: -* Section visibility:: -* Section hooks:: -* Section types and values:: -* Section options:: - - -File: magit.info, Node: Section movement, Next: Section visibility, Up: Sections - -4.4.1 Section movement ----------------------- - -To move within a section use the usual keys (‘C-p’, ‘C-n’, ‘C-b’, ‘C-f’ -etc), whose global bindings are not shadowed. To move to another -section use the following commands. - -‘p’ (‘magit-section-backward’) - - When not at the beginning of a section, then move to the beginning - of the current section. At the beginning of a section, instead - move to the beginning of the previous visible section. - -‘n’ (‘magit-section-forward’) - - Move to the beginning of the next visible section. - -‘M-p’ (‘magit-section-backward-siblings’) - - Move to the beginning of the previous sibling section. If there is - no previous sibling section, then move to the parent section - instead. - -‘M-n’ (‘magit-section-forward-siblings’) - - Move to the beginning of the next sibling section. If there is no - next sibling section, then move to the parent section instead. - -‘^’ (‘magit-section-up’) - - Move to the beginning of the parent of the current section. - - The above commands all call the hook ‘magit-section-movement-hook’. -And, except for the second, the below functions are all members of that -hook’s default value. - - -- Variable: magit-section-movement-hook - - This hook is run by all of the above movement commands, after - arriving at the destination. - - -- Function: magit-hunk-set-window-start - - This hook function ensures that the beginning of the current - section is visible, provided it is a ‘hunk’ section. Otherwise, it - does nothing. - - -- Function: magit-section-set-window-start - - This hook function ensures that the beginning of the current - section is visible, regardless of the section’s type. If you add - this to ‘magit-section-movement-hook’, then you must remove the - hunk-only variant in turn. - - -- Function: magit-log-maybe-show-more-commits - - This hook function only has an effect in log buffers, and ‘point’ - is on the "show more" section. If that is the case, then it - doubles the number of commits that are being shown. - - -- Function: magit-log-maybe-update-revision-buffer - - When moving inside a log buffer, then this function updates the - revision buffer, provided it is already being displayed in another - window of the same frame. - - -- Function: magit-log-maybe-update-blob-buffer - - When moving inside a log buffer and another window of the same - frame displays a blob buffer, then this function instead displays - the blob buffer for the commit at point in that window. - - -- Function: magit-status-maybe-update-revision-buffer - - When moving inside a status buffer, then this function updates the - revision buffer, provided it is already being displayed in another - window of the same frame. - - -- Function: magit-status-maybe-update-blob-buffer - - When moving inside a status buffer and another window of the same - frame displays a blob buffer, then this function instead displays - the blob buffer for the commit at point in that window. - - -- User Option: magit-update-other-window-delay - - Delay before automatically updating the other window. - - When moving around in certain buffers certain other buffers, which - are being displayed in another window, may optionally be updated to - display information about the section at point. - - When holding down a key to move by more than just one section, then - that would update that buffer for each section on the way. To - prevent that, updating the revision buffer is delayed, and this - option controls for how long. For optimal experience you might - have to adjust this delay and/or the keyboard repeat rate and delay - of your graphical environment or operating system. - - -File: magit.info, Node: Section visibility, Next: Section hooks, Prev: Section movement, Up: Sections - -4.4.2 Section visibility ------------------------- - -Magit provides many commands for changing the visibility of sections, -but all you need to get started are the next two. - -‘TAB’ (‘magit-section-toggle’) - - Toggle the visibility of the body of the current section. - -‘C-’ (‘magit-section-cycle’) - - Cycle the visibility of current section and its children. - -‘M-’ (‘magit-section-cycle-diffs’) - - Cycle the visibility of diff-related sections in the current - buffer. - -‘s-’ (‘magit-section-cycle-global’) - - Cycle the visibility of all sections in the current buffer. - - -- Command: magit-section-show-level-1 - -- Command: magit-section-show-level-2 - -- Command: magit-section-show-level-3 - -- Command: magit-section-show-level-4 - - To show sections surrounding the current section, up to level N, - press the respective number key (‘1’, ‘2’, ‘3’, or ‘4’). - - -- Command: magit-section-show-level-1-all - -- Command: magit-section-show-level-2-all - -- Command: magit-section-show-level-3-all - -- Command: magit-section-show-level-4-all - - To show all sections up to level N, press the respective number key - and meta (‘M-1’, ‘M-2’, ‘M-3’, or ‘M-4’). - - Some functions, which are used to implement the above commands, are -also exposed as commands themselves. By default no keys are bound to -these commands, as they are generally perceived to be much less useful. -But your mileage may vary. - - -- Command: magit-section-show - - Show the body of the current section. - - -- Command: magit-section-hide - - Hide the body of the current section. - - -- Command: magit-section-show-headings - - Recursively show headings of children of the current section. Only - show the headings. Previously shown text-only bodies are hidden. - - -- Command: magit-section-show-children - - Recursively show the bodies of children of the current section. - With a prefix argument show children down to the level of the - current section, and hide deeper children. - - -- Command: magit-section-hide-children - - Recursively hide the bodies of children of the current section. - - -- Command: magit-section-toggle-children - - Toggle visibility of bodies of children of the current section. - - When a buffer is first created then some sections are shown expanded -while others are not. This is hard coded. When a buffer is refreshed -then the previous visibility is preserved. The initial visibility of -certain sections can also be overwritten using the hook -‘magit-section-set-visibility-hook’. - - -- Variable: magit-section-set-visibility-hook - - This hook is run when first creating a buffer and also when - refreshing an existing buffer, and is used to determine the - visibility of the section currently being inserted. - - Each function is called with one argument, the section being - inserted. It should return ‘hide’ or ‘show’, or to leave the - visibility undefined ‘nil’. If no function decides on the - visibility and the buffer is being refreshed, then the visibility - is preserved; or if the buffer is being created, then the hard - coded default is used. - - Usually this should only be used to set the initial visibility but - not during refreshes. If ‘magit-insert-section--oldroot’ is - non-nil, then the buffer is being refreshed and these functions - should immediately return ‘nil’. - - -File: magit.info, Node: Section hooks, Next: Section types and values, Prev: Section visibility, Up: Sections - -4.4.3 Section hooks -------------------- - -Which sections are inserted into certain buffers is controlled with -hooks. This includes the status and the refs buffers. For other -buffers, e.g. log, diff, and revision buffers, this is not possible. - - For buffers whose sections can be customized by the user, a hook -variable called ‘magit-TYPE-sections-hook’ exists. This hook should be -changed using ‘magit-add-section-hook’. Avoid using ‘add-hooks’ or the -Custom interface. - - The various available section hook variables are described later in -this manual along with the appropriate "section inserter functions". - - -- Function: magit-add-section-hook hook function &optional at append - local - - Add the function FUNCTION to the value of section hook HOOK. - - Add FUNCTION at the beginning of the hook list unless optional - APPEND is non-nil, in which case FUNCTION is added at the end. If - FUNCTION already is a member then move it to the new location. - - If optional AT is non-nil and a member of the hook list, then add - FUNCTION next to that instead. Add before or after AT depending on - APPEND. If only FUNCTION is a member of the list, then leave it - wherever it already is. - - If optional LOCAL is non-nil, then modify the hook’s buffer-local - value rather than its global value. This makes the hook local by - copying the default value. That copy is then modified. - - HOOK should be a symbol. If HOOK is void, it is first set to nil. - HOOK’s value must not be a single hook function. FUNCTION should - be a function that takes no arguments and inserts one or multiple - sections at point, moving point forward. FUNCTION may choose not - to insert its section(s), when doing so would not make sense. It - should not be abused for other side-effects. - - To remove a function from a section hook, use ‘remove-hook’. - - -File: magit.info, Node: Section types and values, Next: Section options, Prev: Section hooks, Up: Sections - -4.4.4 Section types and values ------------------------------- - -Each section has a type, for example ‘hunk’, ‘file’, and ‘commit’. -Instances of certain section types also have a value. The value of a -section of type ‘file’, for example, is a file name. - - Users usually do not have to worry about a section’s type and value, -but knowing them can be handy at times. - -‘M-x magit-describe-section’ (‘magit-describe-section’) - - Show information about the section at point in the echo area, as - "VALUE [TYPE PARENT-TYPE…] BEGINNING-END". - - Many commands behave differently depending on the type of the section -at point and/or somehow consume the value of that section. But that is -only one of the reasons why the same key may do something different, -depending on what section is current. - - Additionally for each section type a keymap *might* be defined, named -‘magit-TYPE-section-map’. That keymap is used as text property keymap -of all text belonging to any section of the respective type. If such a -map does not exist for a certain type, then you can define it yourself, -and it will automatically be used. - - -File: magit.info, Node: Section options, Prev: Section types and values, Up: Sections - -4.4.5 Section options ---------------------- - -This section describes options that have an effect on more than just a -certain type of sections. As you can see there are not many of those. - - -- User Option: magit-section-show-child-count - - Whether to append the number of children to section headings. This - only affects sections that could benefit from this information. - - -File: magit.info, Node: Popup buffers and prefix commands, Next: Completion and confirmation, Prev: Sections, Up: Interface concepts - -4.5 Popup buffers and prefix commands -===================================== - -Many Magit commands are implemented using *popup buffers*. First the -user invokes a *popup* or *prefix* command, which causes a popup buffer -with the available *infix* arguments and *suffix* commands to be -displayed. The user then optionally toggles/sets some arguments and -finally invokes one of the suffix commands. - - This is implemented in the library ‘magit-popup’. Earlier releases -used the library ‘magit-key-mode’. A future release will switch to a -yet-to-be-written successor, which will likely be named ‘transient’. - - Because ‘magit-popup’ can also be used by other packages without -having to depend on all of Magit, it is documented in its own manual. -See *note (magit-popup)Top::. - -‘C-c C-c’ (‘magit-dispatch-popup’) - - This popup command shows a buffer featuring all other Magit popup - commands as well as some other commands that are not popup commands - themselves. - - This command is also, or especially, useful outside Magit buffers, so -you should setup a global binding: - - (global-set-key (kbd "C-x M-g") 'magit-dispatch-popup) - - -File: magit.info, Node: Completion and confirmation, Next: Running Git, Prev: Popup buffers and prefix commands, Up: Interface concepts - -4.6 Completion and confirmation -=============================== - -Many commands read a value from the user. By default this is done using -the built-in function ‘completing-read’, but Magit can instead use -another completion framework. - - -- User Option: magit-completing-read-function - - The value of this variable is the function used to perform - completion. Because functions _intended_ to replace - ‘completing-read’ often are not fully compatible drop-in - replacements, and also because Magit expects them to add the - default choice to the prompt themselves, such functions should not - be used directly. Instead a wrapper function has to be used. - - Currently only the real ‘completing-read’ and Ido -(http://www.emacswiki.org/emacs/InteractivelyDoThings) are fully -supported. More frameworks will be supported in the future. - - -- Function: magit-builtin-completing-read prompt choices &optional - predicate require-match initial-input hist def - - Perform completion using ‘completion-read’. - - -- Function: magit-ido-completing-read prompt choices &optional - predicate require-match initial-input hist def - - Perform completion using ‘ido-completing-read+’ from the package by - the same name (which you have to explicitly install). Ido itself - comes with a supposed drop-in replacement ‘ido-completing-read’, - but that has too many deficits to serve our needs. - - By default many commands that could potentially lead to data loss -have to be confirmed. This includes many very common commands, so this -can become annoying quickly. Many of these actions can be undone, -provided ‘magit-wip-before-change-mode’ is turned on (which it is not by -default, due to performance concerns). - - -- User Option: magit-no-confirm - - The value of this option is a list of symbols, representing - commands which do not have to be confirmed by the user before being - carried out. - - When the global mode ‘magit-wip-before-change-mode’ is enabled then - many commands can be undone. If that mode is enabled then adding - ‘safe-with-wip’ to this list has the same effect as adding - ‘discard’, ‘reverse’, ‘stage-all-changes’, and - ‘unstage-all-changes’. - - (add-to-list 'magit-no-confirm 'safe-with-wip) - - For a list of all symbols that can be added to the value of this - variable, see the doc-string. - - Note that there are commands that ignore this option and always -require confirmation, or which can be told not to do so using another -dedicated option. Also most commands, when acting on multiple sections -at once always, require confirmation, even when they do respect this -option when acting on a single section. - - -File: magit.info, Node: Running Git, Prev: Completion and confirmation, Up: Interface concepts - -4.7 Running Git -=============== - -* Menu: - -* Viewing Git output:: -* Running Git manually:: -* Git executable:: -* Global Git arguments:: - - -File: magit.info, Node: Viewing Git output, Next: Running Git manually, Up: Running Git - -4.7.1 Viewing Git output ------------------------- - -Magit runs Git either for side-effects (e.g. when pushing) or to get -some value (e.g. the name of the current branch). When Git is run for -side-effects then the output goes into a per-repository log buffer, -which can be consulted when things don’t go as expected. - -‘$’ (‘magit-process’) - - This commands displays the process buffer for the current - repository. - - Inside that buffer, the usual key bindings for navigating and showing -sections are available. There is one additional command. - -‘k’ (‘magit-process-kill’) - - This command kills the process represented by the section at point. - - -- User Option: magit-git-debug - - When this is non-nil then the output of all calls to git are logged - in the process buffer. This is useful when debugging, otherwise it - just negatively affects performance. - - -File: magit.info, Node: Running Git manually, Next: Git executable, Prev: Viewing Git output, Up: Running Git - -4.7.2 Running Git manually --------------------------- - -While Magit provides many Emacs commands to interact with Git, it does -not cover everything. In those cases your existing Git knowledge will -come in handy. Magit provides some commands for running arbitrary Git -commands by typing them into the minibuffer, instead of having to switch -to a shell. - -‘!’ (‘magit-run-popup’) - - Shows the popup buffer featuring the below suffix commands. - - These suffix commands run a Git subcommand. The user input has to -begin with the subcommand, "git" is assumed. - -‘! !’ (‘magit-git-command-topdir’) - - This command reads a Git subcommand from the user and executes it - in the top-level directory of the current repository. - -‘! p’ (‘magit-git-command’) - - This command reads a Git subcommand from the user and executes it - in ‘default-directory’. With a prefix argument the command is - executed in the top-level directory of the current repository - instead. - - These suffix commands run arbitrary shell commands. - -‘! s’ (‘magit-shell-command-topdir’) - - This command reads a shell command from the user and executes it in - the top-level directory of the current repository. - -‘! S’ (‘magit-shell-command’) - - This command reads a shell command from the user and executes it in - ‘default-directory’. With a prefix argument the command is - executed in the top-level directory of the current repository - instead. - - These suffix commands start external gui tools. - -‘! k’ (‘magit-run-gitk’) - - This command runs ‘gitk’ in the current repository. - -‘! a’ (‘magit-run-gitk-all’) - - This command runs ‘gitk --all’ in the current repository. - -‘! b’ (‘magit-run-gitk-branches’) - - This command runs ‘gitk --branches’ in the current repository. - -‘! g’ (‘magit-run-git-gui’) - - This command runs ‘git gui’ in the current repository. - - -File: magit.info, Node: Git executable, Next: Global Git arguments, Prev: Running Git manually, Up: Running Git - -4.7.3 Git executable --------------------- - -Except on MS Windows, Magit defaults to running Git without specifying -the path to the git executable. Instead the first executable found by -Emacs on ‘exec-path’ is used (whose value in turn is set based on the -value of the environment variable ‘$PATH’ when Emacs was started). - - This has the advantage that it continues to work even when using -Tramp to connect to a remote machine on which the executable is found in -a different place. The downside is that if you have multiple versions -of Git installed, then you might end up using another version than the -one you think you are using. - -‘M-x magit-version’ (‘magit-version’) - - Shows the currently used versions of Magit, Git, and Emacs in the - echo area. Non-interactively this just returns the Magit version. - - When the ‘system-type’ is ‘windows-nt’, then ‘magit-git-executable’ -is set to an absolute path when Magit is first loaded. This is -necessary because Git on that platform comes with several wrapper -scripts for the actual git binary, which are also placed on ‘$PATH’, and -using one of these wrappers instead of the binary would degrade -performance horribly. - - If Magit doesn’t find the correct executable then you *can* work -around that by setting ‘magit-git-executable’ to an absolute path. But -note that doing so is a kludge. It is better to make sure the order in -the environment variable ‘$PATH’ is correct, and that Emacs is started -with that environment in effect. If you have to connect from Windows to -a non-Windows machine, then you must change the value to "git". - - -- User Option: magit-git-executable - - The git executable used by Magit, either the full path to the - executable or the string "git" to let Emacs find the executable - itself, using the standard mechanism for doing such things. - - -File: magit.info, Node: Global Git arguments, Prev: Git executable, Up: Running Git - -4.7.4 Global Git arguments --------------------------- - - -- User Option: magit-git-global-arguments - - The arguments set here are used every time the git executable is - run as a subprocess. They are placed right after the executable - itself and before the git command - as in ‘git HERE... COMMAND - REST’. For valid arguments see *note (gitman)git:: . - - Be careful what you add here, especially if you are using Tramp to - connect to servers with ancient Git versions. Never remove - anything that is part of the default value, unless you really know - what you are doing. And think very hard before adding something; - it will be used every time Magit runs Git for any purpose. - - -File: magit.info, Node: Inspecting, Next: Manipulating, Prev: Interface concepts, Up: Top - -5 Inspecting -************ - -The functionality provided by Magit can be roughly divided into three -groups: inspecting existing data, manipulating existing data or adding -new data, and transferring data. Of course that is a rather crude -distinction that often falls short, but it’s more useful than no -distinction at all. This section is concerned with inspecting data, the -next two with manipulating and transferring it. Then follows a section -about miscellaneous functionality, which cannot easily be fit into this -distinction. - - Of course other distinctions make sense too, e.g. Git’s distinction -between porcelain and plumbing commands, which for the most part is -equivalent to Emacs’ distinction between interactive commands and -non-interactive functions. All of the sections mentioned before are -mainly concerned with the porcelain – Magit’s plumbing layer is -described later. - -* Menu: - -* Status buffer:: -* Logging:: -* Diffing:: -* Ediffing:: -* References buffer:: -* Bisecting:: -* Visiting blobs:: -* Blaming:: - - -File: magit.info, Node: Status buffer, Next: Logging, Up: Inspecting - -5.1 Status buffer -================= - -While other Magit buffers contain e.g. one particular diff or one -particular log, the status buffer contains the diffs for staged and -unstaged changes, logs for unpushed and unpulled commits, lists of -stashes and untracked files, and information related to the current -branch. - - During certain incomplete operations – for example when a merge -resulted in a conflict – additional information is displayed that helps -proceeding with or aborting the operation. - - The command ‘magit-status’ displays the status buffer belonging to -the current repository in another window. This command is used so often -that it should be bound globally. We recommend using ‘C-x g’: - - (global-set-key (kbd "C-x g") 'magit-status) - -‘C-x g’ (‘magit-status’) - - Show the status of the current Git repository in a buffer. With a - prefix argument prompt for a repository to be shown. With two - prefix arguments prompt for an arbitrary directory. If that - directory isn’t the root of an existing repository, then offer to - initialize it as a new repository. - - -- User Option: magit-repository-directories - - Directories containing Git repositories. Magit checks these - directories for Git repositories and offers them as choices when - ‘magit-status’ is used with a prefix argument. - - -- User Option: magit-repository-directories-depth - - The maximum depth to look for Git repositories. When looking for a - Git repository below the directories in - ‘magit-repository-directories’, only descend this many levels deep. - - -- Command: ido-enter-magit-status - - From an Ido prompt used to open a file, instead drop into - ‘magit-status’. This is similar to ‘ido-magic-delete-char’, which, - despite its name, usually causes a Dired buffer to be created. - - To make this command available, use something like: - - (add-hook 'ido-setup-hook - (lambda () - (define-key ido-completion-map - (kbd \"C-x g\") 'ido-enter-magit-status))) - - Starting with Emacs 25.1 the Ido keymaps are defined just once - instead of every time Ido is invoked, so now you can modify it like - pretty much every other keymap: - - (define-key ido-common-completion-map - (kbd \"C-x g\") 'ido-enter-magit-status) - -* Menu: - -* Status sections:: -* Status header sections:: -* Status options:: - - -File: magit.info, Node: Status sections, Next: Status header sections, Up: Status buffer - -5.1.1 Status sections ---------------------- - -The contents of status buffers is controlled using the hook -‘magit-status-sections-hook’. See *note Section hooks: Section hooks. -to learn about such hooks and how to customize them. - - -- User Option: magit-status-sections-hook - - Hook run to insert sections into a status buffer. - - The first function on that hook by default is -‘magit-insert-status-headers’; it is described in the next section. By -default the following functions are also members of that hook: - - -- Function: magit-insert-merge-log - - Insert section for the on-going merge. Display the heads that are - being merged. If no merge is in progress, do nothing. - - -- Function: magit-insert-rebase-sequence - - Insert section for the on-going rebase sequence. If no such - sequence is in progress, do nothing. - - -- Function: magit-insert-am-sequence - - Insert section for the on-going patch applying sequence. If no - such sequence is in progress, do nothing. - - -- Function: magit-insert-sequencer-sequence - - Insert section for the on-going cherry-pick or revert sequence. If - no such sequence is in progress, do nothing. - - -- Function: magit-insert-bisect-output - - While bisecting, insert section with output from ‘git bisect’. - - -- Function: magit-insert-bisect-rest - - While bisecting, insert section visualizing the bisect state. - - -- Function: magit-insert-bisect-log - - While bisecting, insert section logging bisect progress. - - -- Function: magit-insert-untracked-files - - Maybe insert a list or tree of untracked files. Do so depending on - the value of ‘status.showUntrackedFiles’. - - -- Function: magit-insert-unstaged-changes - - Insert section showing unstaged changes. - - -- Function: magit-insert-staged-changes - - Insert section showing staged changes. - - -- Function: magit-insert-stashes &optional ref heading - - Insert the ‘stashes’ section showing reflog for "refs/stash". If - optional REF is non-nil show reflog for that instead. If optional - HEADING is non-nil use that as section heading instead of - "Stashes:". - - -- Function: magit-insert-unpulled-commits - - Insert section showing unpulled commits. - - -- Function: magit-insert-unpushed-commits - - Insert section showing unpushed commits. - - The following functions can also be added to the above hook: - - -- Function: magit-insert-tracked-files - - Insert a tree of tracked files. - - -- Function: magit-insert-unpulled-or-recent-commits - - Insert section showing unpulled or recent commits. If an upstream - is configured for the current branch and it is ahead of the current - branch, then show the missing commits. Otherwise, show the last - ‘magit-log-section-commit-count’ commits. - - -- Function: magit-insert-recent-commits - - Insert section showing the last ‘magit-log-section-commit-count’ - commits. - - -- User Option: magit-log-section-commit-count - - How many recent commits ‘magit-insert-recent-commits’ and - ‘magit-insert-unpulled-or-recent-commits’ (provided there are no - unpulled commits) show. - - -- Function: magit-insert-unpulled-cherries - - Insert section showing unpulled commits. Like - ‘magit-insert-unpulled-commits’ but prefix each commit that has not - been applied yet (i.e. a commit with a patch-id not shared with - any local commit) with "+", and all others with "-". - - -- Function: magit-insert-unpulled-module-commits - - Insert sections for all submodules with unpulled commits. These - sections can be expanded to show the respective commits. - - -- Function: magit-insert-unpushed-cherries - - Insert section showing unpushed commits. Like - ‘magit-insert-unpushed-commits’ but prefix each commit which has - not been applied to upstream yet (i.e. a commit with a patch-id - not shared with any upstream commit) with "+" and all others with - "-". - - -- Function: magit-insert-unpushed-module-commits - - Insert sections for all submodules with unpushed commits. These - sections can be expanded to show the respective commits. - - See *note References buffer: References buffer. for some more section -inserters, which could be used here. - - -File: magit.info, Node: Status header sections, Next: Status options, Prev: Status sections, Up: Status buffer - -5.1.2 Status header sections ----------------------------- - -The contents of status buffers is controlled using the hook -‘magit-status-sections-hook’, as described in the previous section. By -default ‘magit-insert-status-headers’ is the first member of that hook -variable. - - -- Function: magit-insert-status-headers - - Insert headers sections appropriate for ‘magit-status-mode’ - buffers. The sections are inserted by running the functions on the - hook ‘magit-status-headers-hook’. - - -- User Option: magit-status-headers-hook - - Hook run to insert headers sections into the status buffer. - - This hook is run by ‘magit-insert-status-headers’, which in turn - has to be a member of ‘magit-insert-status-sections’ to be used at - all. - - By default the following functions are members of the above hook: - - -- Function: magit-insert-head-header - - Insert a header line about the ‘HEAD’ commit. - - -- Function: magit-insert-upstream-header - - Insert a header line about the upstream branch and its tip. - - -- Function: magit-insert-tags-header - - Insert a header line about the current and/or next tag. - - The following functions can also be added to the above hook: - - -- Function: magit-insert-repo-header - - Insert a header line showing the path to the repository top-level. - - -- Function: magit-insert-remote-header - - Insert a header line about the remote of the current branch. - - If no remote is configured for the current branch, then fall back - showing the "origin" remote, or if that does not exist the first - remote in alphabetic order. - - -- Function: magit-insert-user-header - - Insert a header line about the current user. - - -File: magit.info, Node: Status options, Prev: Status header sections, Up: Status buffer - -5.1.3 Status options --------------------- - - -- User Option: magit-status-refresh-hook - - Hook run after a status buffer has been refreshed. - - -- User Option: magit-log-section-args - - Additional Git arguments used when creating log sections. Only - ‘--graph’, ‘--decorate’, and ‘--show-signature’ are supported. - This option is only a temporary kludge and will be removed. - - Note that due to an issue in Git the use of ‘--graph’ is very slow - with long histories, so you probably don’t want to add this here. - - Also see the proceeding section for more options concerning status -buffers. - - -File: magit.info, Node: Logging, Next: Diffing, Prev: Status buffer, Up: Inspecting - -5.2 Logging -=========== - -The status buffer contains logs for the unpushed and unpulled commits, -but that obviously isn’t enough. The prefix command ‘magit-log-popup’, -on ‘l’, features several suffix commands, which show a specific log in a -separate log buffer. - - Like other popups, the log popup also features several arguments that -can be changed before invoking one of the suffix commands. However in -case of the log popup these arguments correspond to those currently in -use in the current repository’s log buffer. When the log popup is -invoked while no log buffer exists for the current repository yet, then -the default value of ‘magit-log-arguments’ is used instead. - - For information about the various arguments, see *note -(gitman)git-log:: . - - The log popup also features several reflog commands. See *note -Reflog: Reflog. - -‘l’ (‘magit-log-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘l l’ (‘magit-log-current’) - - Show log for the current branch. When ‘HEAD’ is detached or with a - prefix argument, show log for one or more revs read from the - minibuffer. - -‘l o’ (‘magit-log’) - - Show log for one or more revs read from the minibuffer. The user - can input any revision or revisions separated by a space, or even - ranges, but only branches, tags, and a representation of the commit - at point are available as completion candidates. - -‘l h’ (‘magit-log-head’) - - Show log for ‘HEAD’. - -‘l L’ (‘magit-log-branches’) - - Show log for all local branches and ‘HEAD’. - -‘l b’ (‘magit-log-all-branches’) - - Show log for all local and remote branches and ‘HEAD’. - -‘l a’ (‘magit-log-all’) - - Show log for all references and ‘HEAD’. - - The following related commands are not available from the popup. - -‘Y’ (‘magit-cherry’) - - Show commits in a branch that are not merged in the upstream - branch. - -‘M-x magit-log-buffer-file’ (‘magit-log-buffer-file’) - - Show log for the file visited in the current buffer. - -* Menu: - -* Refreshing logs:: -* Log Buffer:: -* Select from log:: -* Reflog:: - - -File: magit.info, Node: Refreshing logs, Next: Log Buffer, Up: Logging - -5.2.1 Refreshing logs ---------------------- - -The prefix command ‘magit-log-refresh-popup’, on ‘L’, can be used to -change the log arguments used in the current buffer, without changing -which log is shown. This works in dedicated log buffers, but also in -the status buffer. - -‘L’ (‘magit-log-refresh-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘L g’ (‘magit-log-refresh’) - - This suffix command sets the local log arguments for the current - buffer. - -‘L s’ (‘magit-log-set-default-arguments’) - - This suffix command sets the default log arguments for buffers of - the same type as that of the current buffer. Other existing - buffers of the same type are not affected because their local - values have already been initialized. - -‘L w’ (‘magit-log-save-default-arguments’) - - This suffix command sets the default log arguments for buffers of - the same type as that of the current buffer, and saves the value - for future sessions. Other existing buffers of the same type are - not affected because their local values have already been - initialized. - -‘L t’ (‘magit-toggle-margin’) - - Show or hide the margin. - - -File: magit.info, Node: Log Buffer, Next: Select from log, Prev: Refreshing logs, Up: Logging - -5.2.2 Log Buffer ----------------- - -‘L’ (‘magit-log-refresh-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. See *note - Refreshing logs: Refreshing logs. - -‘q’ (‘magit-log-bury-buffer’) - - Bury the current buffer or the revision buffer in the same frame. - Like ‘magit-mode-bury-buffer’ (which see) but with a negative - prefix argument instead bury the revision buffer, provided it is - displayed in the current frame. - -‘C-c C-b’ (‘magit-go-backward’) - - Move backward in current buffer’s history. - -‘C-c C-f’ (‘magit-go-forward’) - - Move forward in current buffer’s history. - -‘SPC’ (‘magit-diff-show-or-scroll-up’) - - Update the commit or diff buffer for the thing at point. - - Either show the commit or stash at point in the appropriate buffer, - or if that buffer is already being displayed in the current frame - and contains information about that commit or stash, then instead - scroll the buffer up. If there is no commit or stash at point, - then prompt for a commit. - -‘DEL’ (‘magit-diff-show-or-scroll-down’) - - Update the commit or diff buffer for the thing at point. - - Either show the commit or stash at point in the appropriate buffer, - or if that buffer is already being displayed in the current frame - and contains information about that commit or stash, then instead - scroll the buffer down. If there is no commit or stash at point, - then prompt for a commit. - -‘=’ (‘magit-log-toggle-commit-limit’) - - Toggle the number of commits the current log buffer is limited to. - If the number of commits is currently limited, then remove that - limit. Otherwise set it to 256. - -‘+’ (‘magit-log-double-commit-limit’) - - Double the number of commits the current log buffer is limited to. - -‘=’ (‘magit-log-half-commit-limit’) - - Half the number of commits the current log buffer is limited to. - - -- User Option: magit-log-auto-more - - Insert more log entries automatically when moving past the last - entry. Only considered when moving past the last entry with - ‘magit-goto-*-section’ commands. - - -- User Option: magit-log-show-margin - - Whether to initially show the margin in log buffers. - - When non-nil the author name and date are initially displayed in - the margin of log buffers. The margin can be shown or hidden in - the current buffer using the command ‘magit-toggle-margin’. - - When a log buffer contains a verbose log, then the margin is never - displayed. In status buffers this option is ignored, but it is - possible to show the margin using the mentioned command. - - -- User Option: magit-log-show-refname-after-summary - - Whether to show the refnames after the commit summaries. This is - useful if you use really long branch names. - - -File: magit.info, Node: Select from log, Next: Reflog, Prev: Log Buffer, Up: Logging - -5.2.3 Select from log ---------------------- - -When the user has to select a recent commit that is reachable from -‘HEAD’, using regular completion would be inconvenient (because most -humans cannot remember hashes or "HEAD~5", at least not without double -checking). Instead a log buffer is used to select the commit, which has -the advantage that commits are presented in order and with the commit -message. The following additional key bindings are available when a log -is used for selection: - -‘C-c C-c’ (‘magit-log-select-pick’) - - Select the commit at point and act on it. Call - ‘magit-log-select-pick-function’ with the selected commit as - argument. - -‘C-c C-k’ (‘magit-log-select-quit’) - - Abort selecting a commit, don’t act on any commit. - - This feature is used by rebase and squash commands. - - -File: magit.info, Node: Reflog, Prev: Select from log, Up: Logging - -5.2.4 Reflog ------------- - -Also see *note (gitman)git-reflog:: . - - These reflog commands are available from the log popup. See *note -Logging: Logging. - -‘l r’ (‘magit-reflog-current’) - - Display the reflog of the current branch. - -‘l O’ (‘magit-reflog-other’) - - Display the reflog of a branch. - -‘l H’ (‘magit-reflog-head’) - - Display the ‘HEAD’ reflog. - - -File: magit.info, Node: Diffing, Next: Ediffing, Prev: Logging, Up: Inspecting - -5.3 Diffing -=========== - -The status buffer contains diffs for the staged and unstaged commits, -but that obviously isn’t enough. The prefix command ‘magit-diff-popup’, -on ‘d’, features several suffix commands, which show a specific diff in -a separate diff buffer. - - Like other popups, the diff popup also features several arguments -that can be changed before invoking one of the suffix commands. However -in case of the diff popup these arguments correspond to those currently -in use in the current repository’s diff buffer. When the diff popup is -invoked while no diff buffer exists for the current repository yet, then -the default value of ‘magit-diff-arguments’ is used instead. - - Also see *note (gitman)git-diff:: . - -‘d’ (‘magit-diff-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘d d’ (‘magit-diff-dwim’) - - Show changes for the thing at point. - -‘d r’ (‘magit-diff’) - - Show differences between two commits. - - RANGE should be a range (A..B or A…B) but can also be a single - commit. If one side of the range is omitted, then it defaults to - HEAD. If just a commit is given, then changes in the working tree - relative to that commit are shown. - - If the region is active, use the revisions on the first and last - line of the region. With a prefix argument, instead of diffing the - revisions, choose a revision to view changes along, starting at the - common ancestor of both revisions (i.e., use a "…" range). - -‘d w’ (‘magit-diff-worktree’) - - Show changes between the current working tree and the ‘HEAD’ - commit. With a prefix argument show changes between the working - tree and a commit read from the minibuffer. - -‘d s’ (‘magit-diff-staged’) - - Show changes between the index and the ‘HEAD’ commit. With a - prefix argument show changes between the index and a commit read - from the minibuffer. - -‘d u’ (‘magit-diff-unstaged’) - - Show changes between the working tree and the index. - -‘d p’ (‘magit-diff-paths’) - - Show changes between any two files on disk. - -‘M-x magit-diff-unpushed’ (‘magit-diff-unpushed’) - - Show unpushed changes. - -‘M-x magit-diff-unpulled’ (‘magit-diff-unpulled’) - - Show unpulled changes. - - All of the above suffix commands update the repository’s diff buffer. -The diff popup also features two commands which show differences in -another buffer: - -‘d c’ (‘magit-show-commit’) - - Show the commit at point. If there is no commit at point or with a - prefix argument, prompt for a commit. - -‘d t’ (‘magit-stash-show’) - - Show all diffs of a stash in a buffer. - -* Menu: - -* Refreshing diffs:: -* Diff buffer:: -* Diff options:: -* Revision buffer:: - - -File: magit.info, Node: Refreshing diffs, Next: Diff buffer, Up: Diffing - -5.3.1 Refreshing diffs ----------------------- - -The prefix command ‘magit-diff-refresh-popup’, on ‘D’, can be used to -change the diff arguments used in the current buffer, without changing -which diff is shown. This works in dedicated diff buffers, but also in -the status buffer. - -‘D’ (‘magit-diff-refresh-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘D g’ (‘magit-diff-refresh’) - - This suffix command sets the local diff arguments for the current - buffer. - -‘D s’ (‘magit-diff-set-default-arguments’) - - This suffix command sets the default diff arguments for buffers of - the same type as that of the current buffer. Other existing - buffers of the same type are not affected because their local - values have already been initialized. - -‘D w’ (‘magit-diff-save-default-arguments’) - - This suffix command sets the default diff arguments for buffers of - the same type as that of the current buffer, and saves the value - for future sessions. Other existing buffers of the same type are - not affected because their local values have already been - initialized. - -‘D t’ (‘magit-diff-toggle-refine-hunk’) - - This command toggles hunk refinement on or off. - -‘D r’ (‘magit-diff-switch-range-type’) - - This command converts the diff range type from "revA..revB" to - "revB…revA", or vice versa. - -‘D f’ (‘magit-diff-flip-revs’) - - This command swaps revisions in the diff range from "revA..revB" to - "revB..revA", or vice versa. - - In addition to the above popup, which allows changing any of the -supported arguments, there also exist some commands which change a -particular argument. - -‘-’ (‘magit-diff-less-context’) - - This command decreases the context for diff hunks by COUNT lines. - -‘+’ (‘magit-diff-more-context’) - - This command increases the context for diff hunks by COUNT lines. - -‘0’ (‘magit-diff-default-context’) - - This command resets the context for diff hunks to the default - height. - - The following commands quickly change what diff is being displayed -without having to using one of the diff popups. - -‘C-c C-d’ (‘magit-diff-while-committing’) - - While committing, this command shows the changes that are about to - be committed. While amending, invoking the command again toggles - between showing just the new changes or all the changes that will - be committed. - - This binding is available in the diff buffer as well as the commit - message buffer. - -‘C-c C-b’ (‘magit-go-backward’) - - This command moves backward in current buffer’s history. - -‘C-c C-f’ (‘magit-go-forward’) - - This command moves forward in current buffer’s history. - - -File: magit.info, Node: Diff buffer, Next: Diff options, Prev: Refreshing diffs, Up: Diffing - -5.3.2 Diff buffer ------------------ - -‘RET’ (‘magit-diff-visit-file’) - - From a diff, visit the corresponding file at the appropriate - position. - - When the file is already being displayed in another window of the - same frame, then just select that window and adjust point. With a - prefix argument also display in another window. - - If the diff shows changes in the worktree, the index, or ‘HEAD’, - then visit the actual file. Otherwise when the diff is about an - older commit, then visit the respective blob using - ‘magit-find-file’. Also see ‘magit-diff-visit-file-worktree’, - which, as the name suggests, always visits the actual file. - -‘C-’ (‘magit-diff-visit-file-worktree’) - - From a diff, visit the corresponding file at the appropriate - position. - - When the file is already being displayed in another window of the - same frame, then just select that window and adjust point. With a - prefix argument also display in another window. - - The actual file in the worktree is visited. The positions in the - hunk headers get less useful the "older" the changes are, and as a - result, jumping to the appropriate position gets less reliable. - - Also see ‘magit-diff-visit-file-worktree’, which visits the - respective blob, unless the diff shows changes in the worktree, the - index, or ‘HEAD’. - -‘j’ (‘magit-jump-to-diffstat-or-diff’) - - Jump to the diffstat or diff. When point is on a file inside the - diffstat section, then jump to the respective diff section. - Otherwise, jump to the diffstat section or a child thereof. - -‘SPC’ (‘scroll-up’) - - Scroll text upward. - -‘DEL’ (‘scroll-down’) - - Scroll text downward. - - -File: magit.info, Node: Diff options, Next: Revision buffer, Prev: Diff buffer, Up: Diffing - -5.3.3 Diff options ------------------- - - -- User Option: magit-diff-refine-hunk - - Whether to show word-granularity differences within diff hunks. - - • ‘nil’ never show fine differences. - - • ‘t’ show fine differences for the current diff hunk only. - - • ‘all’ show fine differences for all displayed diff hunks. - - -- User Option: magit-diff-paint-whitespace - - Specify where to highlight whitespace errors. - - See ‘magit-highlight-trailing-whitespace’, - ‘magit-highlight-indentation’. The symbol ‘t’ means in all diffs, - ‘status’ means only in the status buffer, and nil means nowhere. - - -- User Option: magit-diff-highlight-trailing - - Whether to highlight whitespace at the end of a line in diffs. - Used only when ‘magit-diff-paint-whitespace’ is non-nil. - - -- User Option: magit-diff-highlight-indentation - - Highlight the "wrong" indentation style. Used only when - ‘magit-diff-paint-whitespace’ is non-nil. - - The value is a list of cons cells. The car is a regular - expression, and the cdr is the value that applies to repositories - whose directory matches the regular expression. If more than one - element matches, then the *last* element in the list applies. The - default value should therefore come first in the list. - - If the value is ‘tabs’, highlight indentation with tabs. If the - value is an integer, highlight indentation with at least that many - spaces. Otherwise, highlight neither. - - -File: magit.info, Node: Revision buffer, Prev: Diff options, Up: Diffing - -5.3.4 Revision buffer ---------------------- - - -- User Option: magit-revision-insert-related-refs - - Whether to show related refs in revision buffers. - - -- User Option: magit-revision-show-gravatar - - Whether to show gravatar images in revision buffers. - - If non-nil, then the value has to be a cons-cell which specifies - where the gravatar images for the author and/or the committer are - inserted inside the text that was previously inserted according to - ‘magit-revision-header-format’. - - Both cells are regular expressions. The car specifies where to - insert the author gravatar image. The top halve of the image is - inserted right after the matched text, the bottom halve on the next - line at the same offset. The cdr specifies where to insert the - committer image, accordingly. Either the car or the cdr may be - nil. - - -File: magit.info, Node: Ediffing, Next: References buffer, Prev: Diffing, Up: Inspecting - -5.4 Ediffing -============ - -‘e’ (‘magit-ediff-dwim’) - - Compare, stage, or resolve using Ediff. - - This command tries to guess what file, and what commit or range the - user wants to compare, stage, or resolve using Ediff. It might - only be able to guess either the file, or range/commit, in which - case the user is asked about the other. It might not always guess - right, in which case the appropriate ‘magit-ediff-*’ command has to - be used explicitly. If it cannot read the user’s mind at all, then - it asks the user for a command to run. - -‘E’ (‘magit-ediff-popup’) - - This prefix command shows the following suffix commands in a popup - buffer. - -‘E r’ (‘magit-ediff-compare’) - - Compare two revisions of a file using Ediff. - - If the region is active, use the revisions on the first and last - line of the region. With a prefix argument, instead of diffing the - revisions, choose a revision to view changes along, starting at the - common ancestor of both revisions (i.e., use a "…" range). - -‘E m’ (‘magit-ediff-resolve’) - - Resolve outstanding conflicts in a file using Ediff, defaulting to - the file at point. - - Provided that the value of ‘merge.conflictstyle’ is ‘diff3’, you - can view the file’s merge-base revision using ‘/’ in the Ediff - control buffer. - - In the rare event that you want to manually resolve all conflicts, - including those already resolved by Git, use - ‘ediff-merge-revisions-with-ancestor’. - -‘E s’ (‘magit-ediff-stage’) - - Stage and unstage changes to a file using Ediff, defaulting to the - file at point. - -‘E u’ (‘magit-ediff-show-unstaged’) - - Show unstaged changes to a file using Ediff. - -‘E i’ (‘magit-ediff-show-staged’) - - Show staged changes to a file using Ediff. - -‘E w’ (‘magit-ediff-show-working-tree’) - - Show changes in a file between HEAD and working tree using Ediff. - -‘E c’ (‘magit-ediff-show-commit’) - - Show changes to a file introduced by a commit using Ediff. - - -- User Option: magit-ediff-dwim-show-on-hunks - - This option controls what command ‘magit-ediff-dwim’ calls when - point is on uncommitted hunks. When nil, always run - ‘magit-ediff-stage’. Otherwise, use ‘magit-ediff-show-staged’ and - ‘magit-ediff-show-unstaged’ to show staged and unstaged changes, - respectively. - - -- User Option: magit-ediff-quit-hook - - This hook is run after quitting an Ediff session that was created - using a Magit command. The hook functions are run inside the Ediff - control buffer, and should not change the current buffer. - - This is similar to ‘ediff-quit-hook’ but takes the needs of Magit - into account. The regular ‘ediff-quit-hook’ is ignored by Ediff - sessions that were created using a Magit command. - - -File: magit.info, Node: References buffer, Next: Bisecting, Prev: Ediffing, Up: Inspecting - -5.5 References buffer -===================== - -‘y’ (‘magit-show-refs-popup’) - - List and compare references in a dedicated buffer. By default all - refs are compared with ‘HEAD’, but with a prefix argument this - command instead acts as a prefix command and shows the following - suffix commands along with the appropriate infix arguments in a - popup buffer. - -‘y y’ (‘magit-show-refs-head’) - - List and compare references in a dedicated buffer. Refs are - compared with ‘HEAD’. - -‘y c’ (‘magit-show-refs-current’) - - List and compare references in a dedicated buffer. Refs are - compared with the current branch or ‘HEAD’ if it is detached. - -‘y o’ (‘magit-show-refs’) - - List and compare references in a dedicated buffer. Refs are - compared with a branch read from the user. - - -- User Option: magit-refs-show-commit-count - - Whether to show commit counts in Magit-Refs mode buffers. - - • ‘all’ Show counts for branches and tags. - - • ‘branch’ Show counts for branches only. - - • ‘nil’ Never show counts. - The default is ‘nil’ because anything else can be very expensive. - - -- User Option: magit-refs-show-margin - - Whether to initially show the margin in refs buffers. - - When non-nil the committer name and date are initially displayed in - the margin of refs buffers. The margin can be shown or hidden in - the current buffer using the command ‘magit-toggle-margin’. - - The following variables control how individual refs are displayed. -If you change one of these variables (especially the "%c" part), then -you should also change the others to keep things aligned. The following -%-sequences are supported: - - • ‘%a’ Number of commits this ref has over the one we compare to. - - • ‘%b’ Number of commits the ref we compare to has over this one. - - • ‘%c’ Number of commits this ref has over the one we compare to. - For the ref which all other refs are compared this is instead "@", - if it is the current branch, or "#" otherwise. - - • ‘%C’ For the ref which all other refs are compared this is "@", if - it is the current branch, or "#" otherwise. For all other refs " - ". - - • ‘%h’ Hash of this ref’s tip. - - • ‘%m’ Commit summary of the tip of this ref. - - • ‘%n’ Name of this ref. - - • ‘%u’ Upstream of this local branch and additional local vs. - upstream information. - - • ‘%U’ Upstream of this local branch. - - -- Variable: magit-refs-local-branch-format - - Format used for local branches in refs buffers. - - -- Variable: magit-refs-remote-branch-format - - Format used for remote branches in refs buffers. - - -- Variable: magit-refs-tags-format - - Format used for tags in refs buffers. - - -- Variable: magit-refs-indent-cherry-lines - - Indentation of cherries in refs buffers. This should be N-1 where - N is taken from "%Nc" in the above format strings. - - Everywhere in Magit ‘RET’ visits the thing represented by the section -at point. In almost all cases visiting is done by showing some -information in another buffer and *not* doing anything else. In refs -buffers ‘RET’ behaves differently, and because many users have grown -accustomed to that inconsistency we are keeping it that way. - -‘RET’ (‘magit-visit-ref’) - - Everywhere except in refs buffers this command behaves exactly like - ‘magit-show-commit’; it shows the commit at point in another - buffer. - - In refs buffers, when there is a local branch at point, then this - command instead checks out that branch. When there is a remote - branch or a tag at point then the respective commit is checked out - causing ‘HEAD’ to be detached. - - When a prefix argument it used, then this command only *focuses* on - the reference at point, i.e. the commit counts and cherries are - updated to be relative to that reference, but nothing is checked - out. - - -- User Option: magit-visit-ref-create - - When this is non-nil and ‘magit-visit-ref’ is called inside a refs - buffer, then it "visits" the remote branch at point by creating a - new local branch which tracks that remote branch and then checking - out the newly created branch. - - This is not enabled by default because one has to use an extremely - loose definition of the verb "to visit" to be able to argue that - creating and then checking out a new local branch is a form of - visiting a remote branch. - -* Menu: - -* References sections:: - - -File: magit.info, Node: References sections, Up: References buffer - -5.5.1 References sections -------------------------- - -The contents of references buffers is controlled using the hook -‘magit-refs-sections-hook’. See *note Section hooks: Section hooks. to -learn about such hooks and how to customize them. All of the below -functions are members of the default value. Note that it makes much -less sense to customize this hook than it does for the respective hook -used for the status buffer. - - -- User Option: magit-refs-sections-hook - - Hook run to insert sections into a references buffer. - - -- Function: magit-insert-local-branches - - Insert sections showing all local branches. - - -- Function: magit-insert-remote-branches - - Insert sections showing all remote-tracking branches. - - -- Function: magit-insert-tags - - Insert sections showing all tags. - - -File: magit.info, Node: Bisecting, Next: Visiting blobs, Prev: References buffer, Up: Inspecting - -5.6 Bisecting -============= - -Also see *note (gitman)git-bisect:: . - -‘B’ (‘magit-bisect-popup’) - - This prefix command shows the following suffix commands in a popup - buffer. - - When bisecting is not in progress, then the popup buffer features the -following commands. - -‘B s’ (‘magit-bisect-start’) - - Start a bisect session. - - Bisecting a bug means to find the commit that introduced it. This - command starts such a bisect session by asking for a known good and - a bad commit. - -‘B u’ (‘magit-bisect-run’) - - Bisect automatically by running commands after each step. - - When bisecting is in progress, then the popup buffer features these -commands instead. - -‘B b’ (‘magit-bisect-bad’) - - Mark the current commit as bad. Use this after you have asserted - that the commit does contain the bug in question. - -‘B g’ (‘magit-bisect-good’) - - Mark the current commit as good. Use this after you have asserted - that the commit does not contain the bug in question. - -‘B k’ (‘magit-bisect-skip’) - - Skip the current commit. Use this if for some reason the current - commit is not a good one to test. This command lets Git choose a - different one. - -‘B r’ (‘magit-bisect-reset’) - - After bisecting, cleanup bisection state and return to original - ‘HEAD’. - - -File: magit.info, Node: Visiting blobs, Next: Blaming, Prev: Bisecting, Up: Inspecting - -5.7 Visiting blobs -================== - -‘M-x magit-find-file’ (‘magit-find-file’) - - View FILE from REV. Switch to a buffer visiting blob REV:FILE, - creating one if none already exists. - -‘M-x magit-find-file-other-window’ (‘magit-find-file-other-window’) - - View FILE from REV, in another window. Like ‘magit-find-file’, but - create a new window or reuse an existing one. - - -File: magit.info, Node: Blaming, Prev: Visiting blobs, Up: Inspecting - -5.8 Blaming -=========== - -Also see *note (gitman)git-blame:: . - -‘M-x magit-blame’ (‘magit-blame’) - - Display edit history of FILE up to REVISION. - - Interactively blame the file being visited in the current buffer. - If the buffer visits a revision of that file, then blame up to that - revision. Otherwise, blame the file’s full history, including - uncommitted changes. - - If Magit-Blame mode is already turned on then blame recursively, by - visiting REVISION:FILE (using ‘magit-find-file’), where revision is - the revision before the revision that added the lines at point. - - ARGS is a list of additional arguments to pass to ‘git blame’; only - arguments available from ‘magit-blame-popup’ should be used. - -‘M-x magit-blame-popup’ (‘magit-blame-popup’) - - This prefix command shows the above suffix command along with the - appropriate infix arguments in a popup buffer. - -‘RET’ (‘magit-show-commit’) - - Show the commit at point. If there is no commit at point or with a - prefix argument, prompt for a commit. - -‘SPC’ (‘magit-diff-show-or-scroll-up’) - - Update the commit or diff buffer for the thing at point. - - Either show the commit or stash at point in the appropriate buffer, - or if that buffer is already being displayed in the current frame - and contains information about that commit or stash, then instead - scroll the buffer up. If there is no commit or stash at point, - then prompt for a commit. - -‘DEL’ (‘magit-diff-show-or-scroll-down’) - - Update the commit or diff buffer for the thing at point. - - Either show the commit or stash at point in the appropriate buffer, - or if that buffer is already being displayed in the current frame - and contains information about that commit or stash, then instead - scroll the buffer down. If there is no commit or stash at point, - then prompt for a commit. - -‘n’ (‘magit-blame-next-chunk’) - - Move to the next chunk. - -‘N’ (‘magit-blame-next-chunk-same-commit’) - - Move to the next chunk from the same commit. - -‘p’ (‘magit-blame-previous-chunk’) - - Move to the previous chunk. - -‘P’ (‘magit-blame-previous-chunk-same-commit’) - - Move to the previous chunk from the same commit. - -‘q’ (‘magit-blame-quit’) - - Turn off Magit-Blame mode. If the buffer was created during a - recursive blame, then also kill the buffer. - -‘M-w’ (‘magit-blame-copy-hash’) - - Save the hash of the current chunk’s commit to the kill ring. - -‘t’ (‘magit-blame-toggle-headings’) - - Show or hide blame chunk headings. - - -- User Option: magit-blame-heading-format - - Format string used for blame headings. - - -- User Option: magit-blame-time-format - - Format string used for time strings in blame headings. - - -- User Option: magit-blame-show-headings - - Whether to initially show blame block headings. The headings can - also be toggled locally using command - ‘magit-blame-toggle-headings’. - - -- User Option: magit-blame-goto-chunk-hook - - Hook run by ‘magit-blame-next-chunk’ and - ‘magit-blame-previous-chunk’. - - -File: magit.info, Node: Manipulating, Next: Transferring, Prev: Inspecting, Up: Top - -6 Manipulating -************** - -* Menu: - -* Repository setup:: -* Staging and unstaging:: -* Applying:: -* Committing:: -* Branching:: -* Merging:: -* Rebasing:: -* Cherry picking:: -* Resetting:: -* Stashing:: - - -File: magit.info, Node: Repository setup, Next: Staging and unstaging, Up: Manipulating - -6.1 Repository setup -==================== - -‘M-x magit-init’ (‘magit-init’) - - This command initializes a repository and then shows the status - buffer for the new repository. - - If the directory is below an existing repository, then the user has - to confirm that a new one should be created inside. If the - directory is the root of the existing repository, then the user has - to confirm that it should be reinitialized. - -‘M-x magit-clone’ (‘magit-clone’) - - This command clones a repository and then shows the status buffer - for the new repository. - - The user is queried for a remote url and a local directory. - - -File: magit.info, Node: Staging and unstaging, Next: Applying, Prev: Repository setup, Up: Manipulating - -6.2 Staging and unstaging -========================= - -Like Git, Magit can of course stage and unstage complete files. Unlike -Git, it also allows users to gracefully un-/stage individual hunks and -even just part of a hunk. To stage individual hunks and parts of hunks -using Git directly, one has to use the very modal and rather clumsy -interface of a ‘git add --interactive’ session. - - With Magit, on the other hand, one can un-/stage individual hunks by -just moving point into the respective section inside a diff displayed in -the status buffer or a separate diff buffer and typing ‘s’ or ‘u’. To -operate on just parts of a hunk, mark the changes that should be -un-/staged using the region and then press the same key that would be -used to un-/stage. To stage multiple files or hunks at once use a -region that starts inside the heading of such a section and ends inside -the heading of a sibling section of the same type. - - Besides staging and unstaging, Magit also provides several other -"apply variants" that can also operate on a file, multiple files at -once, a hunk, multiple hunks at once, and on parts of a hunk. These -apply variants are described in the next section. - -‘s’ (‘magit-stage’) - - Add the change at point to the staging area. - -‘S’ (‘magit-stage-modified’) - - Stage all changes to files modified in the worktree. Stage all new - content of tracked files and remove tracked files that no longer - exist in the working tree from the index also. With a prefix - argument also stage previously untracked (but not ignored) files. - -‘u’ (‘magit-unstage’) - - Remove the change at point from the staging area. - -‘U’ (‘magit-unstage-all’) - - Remove all changes from the staging area. - -‘M-x magit-reset-index’ (‘magit-reset-index’) - - Reset the index to some commit. The commit is read from the user - and defaults to the commit at point. If there is no commit at - point, then it defaults to ‘HEAD’. - - To stage a smaller unit than a range of lines, similar to ‘git add ---patch’ followed by ‘e’ would do, then you can use ‘magit-ediff-stage’ -to do so. - -* Menu: - -* Staging from file-visiting buffers:: - - -File: magit.info, Node: Staging from file-visiting buffers, Up: Staging and unstaging - -6.2.1 Staging from file-visiting buffers ----------------------------------------- - -Fine-grained un-/staging has to be done from the status or a diff -buffer, but it’s also possible to un-/stage all changes made to the file -visited in the current buffer right from inside that buffer. - -‘M-x magit-stage-file’ (‘magit-stage-file’) - - When invoked inside a file-visiting buffer, then stage all changes - to that file. In a Magit buffer, stage the file at point if any. - Otherwise prompt for a file to be staged. With a prefix argument - always prompt the user for a file, even in a file-visiting buffer - or when there is a file section at point. - -‘M-x magit-unstage-file’ (‘magit-unstage-file’) - - When invoked inside a file-visiting buffer, then unstage all - changes to that file. In a Magit buffer, unstage the file at point - if any. Otherwise prompt for a file to be unstaged. With a prefix - argument always prompt the user for a file, even in a file-visiting - buffer or when there is a file section at point. - - -File: magit.info, Node: Applying, Next: Committing, Prev: Staging and unstaging, Up: Manipulating - -6.3 Applying -============ - -Magit provides several "apply variants": stage, unstage, discard, -reverse, and "regular apply". At least when operating on a hunk they -are all implemented using ‘git apply’, which is why they are called -"apply variants". - - • Stage. Apply a change from the working tree to the index. The - change also remains in the working tree. - - • Unstage. Remove a change from the index. The change remains in - the working tree. - - • Discard. On a staged change, remove it from the working tree and - the index. On an unstaged change, remove it from the working tree - only. - - • Reverse. Reverse a change in the working tree. Both committed and - staged changes can be reversed. Unstaged changes cannot be - reversed. Discard them instead. - - • Apply. Apply a change to the working tree. Both committed and - staged changes can be applied. Unstaged changes cannot be applied - - as they already have been applied. - - The previous section described the staging and unstaging commands. -What follows are the commands which implement the remaining apply -variants. - -‘a’ (‘magit-apply’) - - Apply the change at point to the working tree. - -‘k’ (‘magit-discard’) - - Remove the change at point from the working tree. - -‘v’ (‘magit-reverse’) - - Reverse the change at point in the working tree. - - With a prefix argument all apply variants attempt a 3-way merge when -appropriate (i.e. when ‘git apply’ is used internally). - - -File: magit.info, Node: Committing, Next: Branching, Prev: Applying, Up: Manipulating - -6.4 Committing -============== - -When the user initiates a commit, Magit calls ‘git commit’ without any -arguments, so Git has to get it from the user. It creates the file -‘.git/COMMIT_EDITMSG’ and then opens that file in an editor. Magit -arranges for that editor to be the Emacsclient. Once the user finishes -the editing session, the Emacsclient exits and Git creates the commit -using the file’s content as message. - -* Menu: - -* Initiating a commit:: -* Editing commit messages:: - - -File: magit.info, Node: Initiating a commit, Next: Editing commit messages, Up: Committing - -6.4.1 Initiating a commit -------------------------- - -Also see *note (gitman)git-commit:: . - -‘c’ (‘magit-commit-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘c c’ (‘magit-commit’) - - Create a new commit on ‘HEAD’. With a prefix argument amend to the - commit at ‘HEAD’ instead. - -‘c a’ (‘magit-commit-amend’) - - Amend the last commit. - -‘c e’ (‘magit-commit-extend’) - - Amend the last commit, without editing the message. With a prefix - argument keep the committer date, otherwise change it. The option - ‘magit-commit-extend-override-date’ can be used to inverse the - meaning of the prefix argument. - - Non-interactively respect the optional OVERRIDE-DATE argument and - ignore the option. - -‘c w’ (‘magit-commit-reword’) - - Reword the last commit, ignoring staged changes. With a prefix - argument keep the committer date, otherwise change it. The option - ‘magit-commit-reword-override-date’ can be used to inverse the - meaning of the prefix argument. - - Non-interactively respect the optional OVERRIDE-DATE argument and - ignore the option. - -‘c f’ (‘magit-commit-fixup’) - - Create a fixup commit. - - With a prefix argument the target commit has to be confirmed. - Otherwise the commit at point may be used without confirmation - depending on the value of option ‘magit-commit-squash-confirm’. - -‘c F’ (‘magit-commit-instant-fixup’) - - Create a fixup commit and instantly rebase. - -‘c s’ (‘magit-commit-squash’) - - Create a squash commit, without editing the squash message. - - With a prefix argument the target commit has to be confirmed. - Otherwise the commit at point may be used without confirmation - depending on the value of option ‘magit-commit-squash-confirm’. - -‘c S’ (‘magit-commit-instant-squash’) - - Create a squash commit and instantly rebase. - -‘c A’ (‘magit-commit-augment’) - - Create a squash commit, editing the squash message. - - With a prefix argument the target commit has to be confirmed. - Otherwise the commit at point may be used without confirmation - depending on the value of option ‘magit-commit-squash-confirm’. - - -- User Option: magit-commit-ask-to-stage - - Whether to ask to stage everything when committing and nothing is - staged. - - -- User Option: magit-commit-extend-override-date - - Whether using ‘magit-commit-extend’ changes the committer date. - - -- User Option: magit-commit-reword-override-date - - Whether using ‘magit-commit-reword’ changes the committer date. - - -- User Option: magit-commit-squash-confirm - - Whether the commit targeted by squash and fixup has to be - confirmed. When non-nil then the commit at point (if any) is used - as default choice. Otherwise it has to be confirmed. This option - only affects ‘magit-commit-squash’ and ‘magit-commit-fixup’. The - "instant" variants always require confirmation because making an - error while using those is harder to recover from. - - -File: magit.info, Node: Editing commit messages, Prev: Initiating a commit, Up: Committing - -6.4.2 Editing commit messages ------------------------------ - -After initiating a commit as described in the previous section, two new -buffers appear. One shows the changes that are about to committed, -while the other is used to write the message. All regular editing -commands are available in the commit message buffer. This section only -describes the additional commands. - - Commit messages are edited in an edit session - in the background Git -is waiting for the editor, in our case the Emacsclient, to save the -commit message in a file (in most cases ‘.git/COMMIT_EDITMSG’) and then -return. If the Emacsclient returns with a non-zero exit status then Git -does not create the commit. So the most important commands are those -for finishing and aborting the commit. - -‘C-c C-c’ (‘with-editor-finish’) - - Finish the current editing session by returning with exit code 0. - Git then creates the commit using the message it finds in the file. - -‘C-c C-k’ (‘with-editor-cancel’) - - Cancel the current editing session by returning with exit code 1. - Git then cancels the commit, but leaves the file untouched. - - In addition to being used by Git, these messages may also be stored -in a ring that persists until Emacs is closed. By default the message -is stored at the beginning and the end of an edit session (regardless of -whether the session is finished successfully or was canceled). It is -sometimes useful to bring back messages from that ring. - -‘C-s M-s’ (‘git-commit-save-message’) - - Save the current buffer content to the commit message ring. - -‘M-p’ (‘git-commit-prev-message’) - - Cycle backward through the commit message ring, after saving the - current message to the ring. With a numeric prefix ARG, go back - ARG comments. - -‘M-n’ (‘git-commit-next-message’) - - Cycle forward through the commit message ring, after saving the - current message to the ring. With a numeric prefix ARG, go back - ARG comments. - - By default the diff for the changes that are about to be committed -are automatically shown when invoking the commit. When amending to an -existing commit it may be useful to show either the changes that are -about to be added to that commit or to show those changes together with -those that are already committed. - -‘C-c C-d’ (‘magit-diff-while-committing’) - - While committing, show the changes that are about to be committed. - While amending, invoking the command again toggles between showing - just the new changes or all the changes that will be committed. - -‘C-c C-w’ (‘magit-pop-revision-stack’) - - This command inserts a representation of a revision into the - current buffer. It can be used inside buffers used to write commit - messages but also in other buffers such as buffers used to edit - emails or ChangeLog files. - - By default this command pops the revision which was last added to - the ‘magit-revision-stack’ and inserts it into the current buffer - according to ‘magit-pop-revision-stack-format’. Revisions can be - put on the stack using ‘magit-copy-section-value’ and - ‘magit-copy-buffer-revision’. - - If the stack is empty or with a prefix argument it instead reads a - revision in the minibuffer. By using the minibuffer history this - allows selecting an item which was popped earlier or to insert an - arbitrary reference or revision without first pushing it onto the - stack. - - When reading the revision from the minibuffer, then it might not be - possible to guess the correct repository. When this command is - called inside a repository (e.g. while composing a commit - message), then that repository is used. Otherwise (e.g. while - composing an email) then the repository recorded for the top - element of the stack is used (even though we insert another - revision). If not called inside a repository and with an empty - stack, or with two prefix arguments, then read the repository in - the minibuffer too. - - -- User Option: magit-pop-revision-stack-format - - This option controls how the command ‘magit-pop-revision-stack’ - inserts a revision into the current buffer. - - The entries on the stack have the format ‘(HASH TOPLEVEL)’ and this - option has the format ‘(POINT-FORMAT EOB-FORMAT INDEX-REGEXP)’, all - of which may be nil or a string (though either one of EOB-FORMAT or - POINT-FORMAT should be a string, and if INDEX-REGEXP is non-nil, - then the two formats should be too). - - First INDEX-REGEXP is used to find the previously inserted entry, - by searching backward from point. The first submatch must match - the index number. That number is incremented by one, and becomes - the index number of the entry to be inserted. If you don’t want to - number the inserted revisions, then use nil for INDEX-REGEXP. - - If INDEX-REGEXP is non-nil then both POINT-FORMAT and EOB-FORMAT - should contain \"%N\", which is replaced with the number that was - determined in the previous step. - - Both formats, if non-nil and after removing %N, are then expanded - using ‘git show –format=FORMAT …’ inside TOPLEVEL. - - The expansion of POINT-FORMAT is inserted at point, and the - expansion of EOB-FORMAT is inserted at the end of the buffer (if - the buffer ends with a comment, then it is inserted right before - that). - - Some projects use pseudo headers in commit messages. Magit colorizes -such headers and provides some commands to insert such headers. - - -- User Option: git-commit-known-pseudo-headers - - A list of Git pseudo headers to be highlighted. - -‘C-c C-a’ (‘git-commit-ack’) - - Insert a header acknowledging that you have looked at the commit. - -‘C-c C-r’ (‘git-commit-review’) - - Insert a header acknowledging that you have reviewed the commit. - -‘C-c C-s’ (‘git-commit-signoff’) - - Insert a header to sign off the commit. - -‘C-c C-t’ (‘git-commit-test’) - - Insert a header acknowledging that you have tested the commit. - -‘C-c C-o’ (‘git-commit-cc’) - - Insert a header mentioning someone who might be interested. - -‘C-c C-p’ (‘git-commit-reported’) - - Insert a header mentioning the person who reported the issue being - fixed by the commit. - -‘C-c C-i’ (‘git-commit-suggested’) - - Insert a header mentioning the person who suggested the change. - - ‘git-commit-mode’ is a minor mode that is only used to establish the -above key bindings. This allows using an arbitrary major mode when -editing the commit message. It’s even possible to use a different major -mode in different repositories, which is useful when different projects -impose different commit message conventions. - - -- User Option: git-commit-major-mode - - The value of this option is the major mode used to edit Git commit - messages. - - Because ‘git-commit-mode’ is a minor mode, we don’t use its mode hook -to setup the buffer, except for the key bindings. All other setup -happens in the function ‘git-commit-setup’, which among other things -runs the hook ‘git-commit-setup-hook’. The following functions are -suitable for that hook. - - -- User Option: git-commit-setup-hook - - Hook run at the end of ‘git-commit-setup’. - - -- Function: magit-revert-buffers &optional force - - Revert unmodified file-visiting buffers of the current repository. - - If either ‘magit-revert-buffers’ is non-nil and - ‘inhibit-magit-revert’ is nil, or if optional FORCE is non-nil, - then revert all unmodified buffers that visit files being tracked - in the current repository. - - -- Function: git-commit-save-message - - Save the current buffer content to the commit message ring. - - -- Function: git-commit-setup-changelog-support - - After this function is called, ChangeLog entries are treated as - paragraphs. - - -- Function: git-commit-turn-on-auto-fill - - Turn on ‘auto-fill-mode’ and set ‘fill-column’ to the value of - ‘git-commit-fill-column’. - - -- Function: git-commit-turn-on-flyspell - - Turn on Flyspell mode. Also prevent comments from being checked - and finally check current non-comment text. - - -- Function: git-commit-propertize-diff - - Propertize the diff shown inside the commit message buffer. Git - inserts such diffs into the commit message template when the - ‘--verbose’ argument is used. Magit’s commit popup by default does - not offer that argument because the diff that is shown in a - separate buffer is more useful. But some users disagree, which is - why this function exists. - - -- Function: with-editor-usage-message - - Show usage information in the echo area. - - Magit also helps with writing *good* commit messages by complaining -when certain rules are violated. - - -- User Option: git-commit-summary-max-length - - The intended maximal length of the summary line of commit messages. - Characters beyond this column are colorized to indicate that this - preference has been violated. - - -- User Option: git-commit-fill-column - - Column beyond which automatic line-wrapping should happen in commit - message buffers. - - -- User Option: git-commit-finish-query-functions - - List of functions called to query before performing commit. - - The commit message buffer is current while the functions are - called. If any of them returns nil, then the commit is not - performed and the buffer is not killed. The user should then fix - the issue and try again. - - The functions are called with one argument. If it is non-nil then - that indicates that the user used a prefix argument to force - finishing the session despite issues. Functions should usually - honor this wish and return non-nil. - - -- Function: git-commit-check-style-conventions - - Check for violations of certain basic style conventions. For each - violation ask the user if she wants to proceed anyway. This makes - sure the summary line isn’t too long and that the second line is - empty. - - To show no diff while committing remove ‘magit-commit-diff’ from -‘server-switch-hook’. - - -File: magit.info, Node: Branching, Next: Merging, Prev: Committing, Up: Manipulating - -6.5 Branching -============= - -Also see *note (gitman)git-branch:: and *note (gitman)git-checkout:: . - -‘b’ (‘magit-branch-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘b b’ (‘magit-checkout’) - - Checkout a revision read in the minibuffer and defaulting to the - branch or arbitrary revision at point. If the revision is a local - branch then that becomes the current branch. If it is something - else then ‘HEAD’ becomes detached. Checkout fails if the working - tree or the staging area contain changes. - -‘b c’ (‘magit-branch’) - - Create a new branch. The user is asked for a branch or arbitrary - revision to use as the starting point of the new branch. When a - branch name is provided, then that becomes the upstream branch of - the new branch. The name of the new branch is also read in the - minibuffer. - -‘b B’ (‘magit-branch-and-checkout’) - - This command creates a new branch like ‘magit-branch’, but then - also checks it out. - -‘b s’ (‘magit-branch-spinoff’) - - This command creates and checks out a new branch starting at and - tracking the current branch. That branch in turn is reset to the - last commit it shares with its upstream. If the current branch has - no upstream or no unpushed commits, then the new branch is created - anyway and the previously current branch is not touched. - - This is useful to create a feature branch after work has already - began on the old branch (likely but not necessarily "master"). - -‘b x’ (‘magit-branch-reset’) - - This command resets a branch, defaulting to the branch at point, to - the tip of another branch or any other commit. - - When resetting to another branch, then that branch is also set as - the upstream of the branch being reset. - - When the branch being reset is the current branch, then a hard - reset is performed. If there are any uncommitted changes, then the - user has to confirming the reset because those changes would be - lost. - - This is useful when you have started work on a feature branch but - realize it’s all crap and want to start over. - -‘b d’ (‘magit-branch-delete’) - - Delete one or multiple branches. If the region marks multiple - branches, then offer to delete those. Otherwise, prompt for a - single branch to be deleted, defaulting to the branch at point. - -‘b u’ (‘magit-branch-set-upstream’) - - Change the upstream branch of a branch. Both branches are read in - the minibuffer, while providing reasonable defaults. - -‘b U’ (‘magit-branch-unset-upstream’) - - Unset the upstream branch of a branch read in the minibuffer and - defaulting to the branch at point or the current branch. - -‘b r’ (‘magit-branch-rename’) - - Rename a branch. The branch and the new name are read in the - minibuffer. With prefix argument the branch is renamed even if - that name conflicts with an existing branch. - -‘b e’ (‘magit-branch-edit-description’) - - Edit the description of a branch. The branch is read in the - minibuffer defaulting to the branch at point or the current branch. - The description is edited in a regular buffer similar to how commit - messages are edited. - - -- User Option: magit-branch-read-upstream-first - - When creating a branch, whether to read the upstream branch before - the name of the branch that is to be created. - - -File: magit.info, Node: Merging, Next: Rebasing, Prev: Branching, Up: Manipulating - -6.6 Merging -=========== - -Also see *note (gitman)git-merge:: . - -‘m’ (‘magit-merge-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - - When no merge is in progress, then the popup buffer features the -following commands. - -‘m m’ (‘magit-merge’) - - Merge another branch or an arbitrary revision into the current - branch. The branch or revision to be merged is read in the - minibuffer and defaults to the one at point. - - Unless there are conflicts or a prefix argument is used, the - resulting merge commit uses a generic commit message, and the user - does not get a chance to inspect or change it before the commit is - created. With a prefix argument this does not actually create the - merge commit, which makes it possible to inspect how conflicts were - resolved and to adjust the commit message. - -‘m e’ (‘magit-merge-editmsg’) - - Merge another branch or an arbitrary revision into the current - branch and open a commit message buffer, so that the user can make - adjustments. The commit is not actually created until the user - finishes with ‘C-c C-c’. - -‘m n’ (‘magit-merge-nocommit’) - - Merge another branch or an arbitrary revision into the current - branch, but do not actually create the commit. The user can then - further adjust the merge, even when automatic conflict resolution - succeeded and/or adjust the commit message. - -‘m p’ (‘magit-merge-preview’) - - Preview result of merging another branch or an arbitrary revision - into the current branch. - - When a merge is in progress, then the popup buffer features these -commands instead. - -‘m m’ (‘magit-merge’) - - After resolving conflicts, proceed with the merge. If there are - still conflicts, then this fails. - -‘m a’ (‘magit-merge-abort’) - - Abort the current merge operation. - - -File: magit.info, Node: Rebasing, Next: Cherry picking, Prev: Merging, Up: Manipulating - -6.7 Rebasing -============ - -Also see *note (gitman)git-rebase:: . - -‘r’ (‘magit-rebase-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - - When no rebase is in progress, then the popup buffer features the -following commands. - -‘r r’ (‘magit-rebase’) - - Start a non-interactive rebase sequence. All commits not in - UPSTREAM are rebased. - -‘r o’ (‘magit-rebase-subset’) - - Start a non-interactive rebase sequence with commits from START to - ‘HEAD’ onto NEWBASE. START has to be selected from a list of recent - commits. - - Note that the popup also features the infix argument ‘--interactive’. -This can be used to turn one of the above non-interactive rebase -variants into an interactive rebase. - - For example if you want to clean up a feature branch and at the same -time rebase it onto ‘master’, then you could use ‘r-ir’. But we -recommend that you instead do that in two steps. First use ‘rs’ to -cleanup the feature branch, and then in a second step ‘rl’ to rebase it -onto ‘master’. That way if things turn out to be more complicated than -you thought and/or you make a mistake and have to start over, then you -only have to redo half the work. - - Explicitly enabling ‘--interactive’ won’t have an effect on the -following commands as they always use that argument anyway, even if it -is not enabled in the popup. - -‘r i’ (‘magit-rebase-interactive’) - - Start an interactive rebase sequence. - -‘r l’ (‘magit-rebase-unpushed’) - - Start an interactive rebase sequence of unpushed commits. This is - like ‘magit-rebase-interactive’, but if the upstream of the current - branch is configured, then all commits since the merge-base are - rebased. If there is no upstream or no merge-base, then the user - has to select the first commit to be rebased like for - ‘magit-rebase-interactive’. - -‘r f’ (‘magit-rebase-autosquash’) - - Combine squash and fixup commits with their intended targets. - -‘r e’ (‘magit-rebase-edit-commit’) - - Edit a single older commit using rebase. - -‘r w’ (‘magit-rebase-reword-commit’) - - Reword a single older commit using rebase. - - When a rebase is in progress, then the popup buffer features these -commands instead. - -‘r r’ (‘magit-rebase-continue’) - - Restart the current rebasing operation. - -‘r s’ (‘magit-rebase-skip’) - - Skip the current commit and restart the current rebase operation. - -‘r e’ (‘magit-rebase-edit’) - - Edit the todo list of the current rebase operation. - -‘r a’ (‘magit-rebase-abort’) - - Abort the current rebase operation, restoring the original branch. - -* Menu: - -* Editing rebase sequences:: -* Rebase sequence log:: - - -File: magit.info, Node: Editing rebase sequences, Next: Rebase sequence log, Up: Rebasing - -6.7.1 Editing rebase sequences ------------------------------- - -‘C-c C-c’ (‘with-editor-finish’) - - Finish the current editing session by returning with exit code 0. - Git then creates the commit using the message it finds in the file. - -‘C-c C-k’ (‘with-editor-cancel’) - - Cancel the current editing session by returning with exit code 1. - Git then cancels the commit, but leaves the file untouched. - -‘RET’ (‘git-rebase-show-commit’) - - Show the commit on the current line in another buffer and select - that buffer. - -‘SPC’ (‘magit-diff-show-or-scroll-up’) - - Show the commit on the current line in another buffer without - selecting that buffer. If the revision buffer is already visible - in another window of the current frame, then instead scroll that - window up. - -‘DEL’ (‘magit-diff-show-or-scroll-down’) - - Show the commit on the current line in another buffer without - selecting that buffer. If the revision buffer is already visible - in another window of the current frame, then instead scroll that - window down. - -‘p’ (‘git-rebase-backward-line’) - - Move to previous line. - -‘n’ (‘forward-line’) - - Move to next line. - -‘M-p’ (‘git-rebase-move-line-up’) - - Move the current commit (or command) up. - -‘M-n’ (‘git-rebase-move-line-down’) - - Move the current commit (or command) down. - -‘r’ (‘git-rebase-reword’) - - Edit message of commit on current line. - -‘e’ (‘git-rebase-edit’) - - Stop at the commit on the current line. - -‘s’ (‘git-rebase-squash’) - - Meld commit on current line into previous commit, and edit message. - -‘f’ (‘git-rebase-fixup’) - - Meld commit on current line into previous commit, discarding the - current commit’s message. - -‘k’ (‘git-rebase-kill-line’) - - Kill the current action line. - -‘c’ (‘git-rebase-pick’) - - Use commit on current line. - -‘x’ (‘git-rebase-exec’) - - Insert a shell command to be run after the proceeding commit. - - If there already is such a command on the current line, then edit - that instead. With a prefix argument insert a new command even - when there already is one on the current line. With empty input - remove the command on the current line, if any. - -‘y’ (‘git-rebase-insert’) - - Read an arbitrary commit and insert it below current line. - -‘C-x u’ (‘git-rebase-undo’) - - Undo some previous changes. Like ‘undo’ but works in read-only - buffers. - - -- User Option: git-rebase-auto-advance - - Whether to move to next line after changing a line. - - -- User Option: git-rebase-show-instructions - - Whether to show usage instructions inside the rebase buffer. - - -- User Option: git-rebase-confirm-cancel - - Whether confirmation is required to cancel. - - -File: magit.info, Node: Rebase sequence log, Prev: Editing rebase sequences, Up: Rebasing - -6.7.2 Rebase sequence log -------------------------- - -While a rebase sequence is in progress, the status buffer features a -section which lists the commits that have already been applied as well -as the commits that still have to be applied. - - The commits are split in two halves. When rebase stops at a commit, -either because the user has to deal with a conflict or explicitly -requested that rebase stops at that commit, then point is placed on the -commit that separates the two groups, i.e. on ‘HEAD’. The commits -above it have not been applied yet, while it and the commits below it -have already been applied. In between these two groups or applied and -yet-to-be applied commits, there sometimes is a commit which has been -dropped. - - Each commit is prefixed with a word and these words are additionally -shown in different colors to indicate the status of the commits. - - The following colors are used: - - • Yellow commits have not been applied yet. - - • Gray commits have already been applied. - - • The blue commit is the ‘HEAD’ commit. - - • The green commit is the commit the rebase sequence stopped at. If - this is the same commit as ‘HEAD’ (e.g. because you haven’t done - anything yet after rebase stopped at the commit, then this commit - is shown in blue, not green. There can only be a green and a blue - commit at the same time, if you create one or more new commits - after rebase stops at a commit. - - • Red commits have been dropped. They are shown for reference only, - e.g. to make it easier to diff. - - Of course these colors are subject to the color-theme in use. - - The following words are used: - - • Commits prefixed with ‘pick’, ‘reword’, ‘edit’, ‘squash’, and - ‘fixup’ have not been applied yet. These words have the same - meaning here as they do in the buffer used to edit the rebase - sequence. See *note Editing rebase sequences: Editing rebase - sequences. - - • The commit prefixed with ‘onto’ is the commit on top of which all - the other commits are being re-applied. Like the commits that have - already been re-applied, it is reachable from ‘HEAD’, but unlike - those it has not actually been re-applied during the current - session - it wasn’t touched at all. - - • Commits prefixed with ‘done’ have already been re-applied. Not all - commits that have already been applied are prefixed with this word, - though. - - • When a commit is prefixed with ‘void’, then that indicates that - Magit knows for sure that all the changes in that commit have been - applied using several new commits. This commit is no longer - reachable from ‘HEAD’, and it also isn’t one of the commits that - will be applied when resuming the session. - - • When a commit is prefixed with ‘join’, then that indicates that the - rebase sequence stopped at that commit due to a conflict - you now - have to join (merge) the changes with what has already been - applied. In a sense this is the commit rebase stopped at, but - while its effect is already in the index and in the worktree (with - conflict markers), the commit itself has not actually been applied - yet (it isn’t the ‘HEAD’). So it is shown in yellow, like the - other commits that still have to be applied. - - • When a commit is prefixed with ‘goal’, ‘same’, or ‘work’, then that - indicates that you reset to an earlier commit (and that this commit - therefore is no longer reachable from ‘HEAD’), but that it might - still be possible to create a new commit with the exact same tree - or at least the same patch-id, without manually editing any file. - Or at the very least that there are some uncommitted remaining, - which may or may not originate from that commit. - - • When a commit is prefixed with ‘goal’, then that indicates - that it is still possible to create a commit with the exact - same tree (the "goal") without manually editing a file, by - simply committing the index (or, provided nothing is already - staged, by staging all unstaged changes and then committing - that). This is the case when the original tree exists in the - index or worktree in untainted form. - - • When a commit is prefixed with ‘same’, then that indicates - that it is no longer possible to create a commit with the - exact same tree, but that it is still possible to create a - commit with the same patch-id. This would be the case if you - created a new commit with other changes, but the changes from - the original commit still exist in the index and/or working - tree in untainted form. - - • When a commit is prefixed with ‘work’, then that indicates - that you are working with the changes from that commit after - resetting to an earlier commit. There are changes in the - index and/or working tree and some of them likely originate - from that commit. - - • When a commit is prefixed with ‘poof’ or ‘gone’, then that - indicates that you reset to an earlier commit (and that this commit - therefore is no longer reachable from ‘HEAD’), and that there are - no uncommitted changes remaining which might allow you to create a - new commit with the same tree or at least the same patch-id. - - • When a commit is prefixed with ‘poof’, then that indicates - that it is no longer reachable from ‘HEAD’, but that it has - been replaced with one or more commits, which together have - the exact same effect. - - • When a commit is prefixed with ‘gone’, then that indicates - that it is no longer reachable from ‘HEAD’ and that we also - cannot determine whether its changes are still in effect in - one or more new commits. They might be, but if so, then there - must also be other changes which makes it impossible to know - for sure. - - Do not worry if you do not fully understand the above. That’s okay, -you will acquire a good enough understanding through practice. - - For other sequence operations such as cherry-picking, a similar -section is displayed, but they lack some of the features described -below, due to limitations in the git commands used to implement them. -Most importantly these sequences only support "picking" a commit but not -other actions such as "rewording", and they do not keep track of the -commits which have already been applied. - - -File: magit.info, Node: Cherry picking, Next: Resetting, Prev: Rebasing, Up: Manipulating - -6.8 Cherry picking -================== - -Also see *note (gitman)git-cherry-pick:: . - -‘A’ (‘magit-cherry-pick-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - - When no cherry-pick or revert is in progress, then the popup buffer -features the following commands. - -‘A A’ (‘magit-cherry-pick’) - - Cherry-pick a commit. Prompt for a commit, defaulting to the - commit at point. If the region selects multiple commits, then pick - all of them, without prompting. - -‘A a’ (‘magit-cherry-apply’) - - Apply the changes in a commit to the working tree, but do not - commit them. Prompt for a commit, defaulting to the commit at - point. If the region selects multiple commits, then apply all of - them, without prompting. - - This command also has a top-level binding, which can be invoked - without using the popup by typing ‘a’ at the top-level. - - When a cherry-pick or revert is in progress, then the popup buffer -features these commands instead. - -‘A A’ (‘magit-sequence-continue’) - - Resume the current cherry-pick or revert sequence. - -‘A s’ (‘magit-sequence-skip’) - - Skip the stopped at commit during a cherry-pick or revert sequence. - -‘A a’ (‘magit-sequence-abort’) - - Abort the current cherry-pick or revert sequence. This discards - all changes made since the sequence started. - -* Menu: - -* Reverting:: - - -File: magit.info, Node: Reverting, Up: Cherry picking - -6.8.1 Reverting ---------------- - -‘V’ (‘magit-revert-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - - When no cherry-pick or revert is in progress, then the popup buffer -features the following commands. - -‘V V’ (‘magit-revert’) - - Revert a commit by creating a new commit. Prompt for a commit, - defaulting to the commit at point. If the region selects multiple - commits, then revert all of them, without prompting. - -‘V v’ (‘magit-revert-no-commit’) - - Revert a commit by applying it in reverse to the working tree. - Prompt for a commit, defaulting to the commit at point. If the - region selects multiple commits, then revert all of them, without - prompting. - - When a cherry-pick or revert is in progress, then the popup buffer -features these commands instead. - -‘V A’ (‘magit-sequence-continue’) - - Resume the current cherry-pick or revert sequence. - -‘V s’ (‘magit-sequence-skip’) - - Skip the stopped at commit during a cherry-pick or revert sequence. - -‘V a’ (‘magit-sequence-abort’) - - Abort the current cherry-pick or revert sequence. This discards - all changes made since the sequence started. - - -File: magit.info, Node: Resetting, Next: Stashing, Prev: Cherry picking, Up: Manipulating - -6.9 Resetting -============= - -Also see *note (gitman)git-reset:: . - -‘x’ (‘magit-reset’) - - Reset the head and index to some commit read from the user and - defaulting to the commit at point. The working tree is kept as-is. - With a prefix argument also reset the working tree. - -‘M-x magit-reset-index’ (‘magit-reset-index’) - - Reset the index to some commit read from the user and defaulting to - the commit at point. Keep the ‘HEAD’ and working tree as-is, so if - the commit refers to the ‘HEAD’, then this effectively unstages all - changes. - -‘M-x magit-reset-head’ (‘magit-reset-head’) - - Reset the ‘HEAD’ and index to some commit read from the user and - defaulting to the commit at point. The working tree is kept as-is. - -‘M-x magit-reset-soft’ (‘magit-reset-soft’) - - Reset the ‘HEAD’ to some commit read from the user and defaulting - to the commit at point. The index and the working tree are kept - as-is. - -‘M-x magit-reset-hard’ (‘magit-reset-hard’) - - Reset the ‘HEAD’, index, and working tree to some commit read from - the user and defaulting to the commit at point. - -‘M-x magit-checkout-file’ (‘magit-checkout-file’) - - Update file in the working tree and index to the contents from a - revision. - - Both the revision and file are read from the user. - - -File: magit.info, Node: Stashing, Prev: Resetting, Up: Manipulating - -6.10 Stashing -============= - -Also see *note (gitman)git-stash:: . - -‘z’ (‘magit-stash-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘z z’ (‘magit-stash’) - - Create a stash of the index and working tree. Untracked files are - included according to popup arguments. One prefix argument is - equivalent to ‘--include-untracked’ while two prefix arguments are - equivalent to ‘--all’. - -‘z i’ (‘magit-stash-index’) - - Create a stash of the index only. Unstaged and untracked changes - are not stashed. - -‘z w’ (‘magit-stash-worktree’) - - Create a stash of the working tree only. Untracked files are - included according to popup arguments. One prefix argument is - equivalent to ‘--include-untracked’ while two prefix arguments are - equivalent to ‘--all’. - -‘z x’ (‘magit-stash-keep-index’) - - Create a stash of the index and working tree, keeping index intact. - Untracked files are included according to popup arguments. One - prefix argument is equivalent to ‘--include-untracked’ while two - prefix arguments are equivalent to ‘--all’. - -‘z Z’ (‘magit-snapshot’) - - Create a snapshot of the index and working tree. Untracked files - are included according to popup arguments. One prefix argument is - equivalent to ‘--include-untracked’ while two prefix arguments are - equivalent to ‘--all’. - -‘z I’ (‘magit-snapshot-index’) - - Create a snapshot of the index only. Unstaged and untracked - changes are not stashed. - -‘z W’ (‘magit-snapshot-worktree’) - - Create a snapshot of the working tree only. Untracked files are - included according to popup arguments. One prefix argument is - equivalent to ‘--include-untracked’ while two prefix arguments are - equivalent to ‘--all’-. - -‘z a’ (‘magit-stash-apply’) - - Apply a stash to the working tree. Try to preserve the stash - index. If that fails because there are staged changes, apply - without preserving the stash index. - -‘z p’ (‘magit-stash-pop’) - - Apply a stash to the working tree and remove it from stash list. - Try to preserve the stash index. If that fails because there are - staged changes, apply without preserving the stash index and forgo - removing the stash. - -‘z d’ (‘magit-stash-drop’) - - Remove a stash from the stash list. When the region is active, - offer to drop all contained stashes. - -‘z l’ (‘magit-stash-list’) - - List all stashes in a buffer. - -‘z v’ (‘magit-stash-show’) - - Show all diffs of a stash in a buffer. - -‘z b’ (‘magit-stash-branch’) - - Create and checkout a new BRANCH from STASH. - -‘z f’ (‘magit-stash-format-patch’) - - Create a patch from STASH. - -‘k’ (‘magit-stash-clear’) - - Remove all stashes saved in REF’s reflog by deleting REF. - - -File: magit.info, Node: Transferring, Next: Miscellaneous, Prev: Manipulating, Up: Top - -7 Transferring -************** - -* Menu: - -* Remotes:: -* Fetching:: -* Pulling:: -* Pushing:: -* Creating and sending patches:: -* Applying patches:: - - -File: magit.info, Node: Remotes, Next: Fetching, Up: Transferring - -7.1 Remotes -=========== - -Also see *note (gitman)git-remote:: . - -‘M’ (‘magit-remote-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘M a’ (‘magit-remote-add’) - - Add a remote and fetch it. The remote name and url are read in the - minibuffer. - -‘M r’ (‘magit-remote-rename’) - - Rename a remote. Both the old and the new names are read in the - minibuffer. - -‘M u’ (‘magit-remote-set-url’) - - Change the url of a remote. Both the remote and the new url are - read in the minibuffer. - -‘M k’ (‘magit-remote-remove’) - - Delete a remote, read from the minibuffer. - - -File: magit.info, Node: Fetching, Next: Pulling, Prev: Remotes, Up: Transferring - -7.2 Fetching -============ - -Also see *note (gitman)git-fetch:: . - -‘f’ (‘magit-fetch-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘f f’ (‘magit-fetch-current’) - - Fetch from the upstream repository of the current branch. If - ‘HEAD’ is detached or if the upstream is not configured, then read - the remote. - -‘f o’ (‘magit-fetch’) - - Fetch from another repository. - -‘f a’ (‘magit-fetch-all’) - - Fetch from all configured remotes. - -‘f m’ (‘magit-submodule-fetch’) - - Fetch all submodules. With a prefix argument fetch all remotes or - all submodules. - - -File: magit.info, Node: Pulling, Next: Pushing, Prev: Fetching, Up: Transferring - -7.3 Pulling -=========== - -Also see *note (gitman)git-pull:: . - -‘F’ (‘magit-pull-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘F F’ (‘magit-pull-current’) - - Fetch and merge into current branch. - -‘F o’ (‘magit-pull’) - - Fetch from another repository and merge a fetched branch. - - -File: magit.info, Node: Pushing, Next: Creating and sending patches, Prev: Pulling, Up: Transferring - -7.4 Pushing -=========== - -Also see *note (gitman)git-push:: . - -‘P’ (‘magit-push-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘P P’ (‘magit-push-current’) - - Push the current branch to its upstream branch. If the upstream - isn’t set, then read the remote branch. - -‘P o’ (‘magit-push’) - - Push a branch to its upstream branch. If the upstream isn’t set, - then read the remote branch. - -‘P e’ (‘magit-push-elsewhere’) - - Push a branch or commit to some remote branch. Read the local and - remote branch. - -‘P Q’ (‘magit-push-quickly’) - - Push the current branch to some remote. When the Git variable - ‘magit.pushRemote’ is set, then push to that remote. If that - variable is undefined or the remote does not exist, then push to - "origin". If that also doesn’t exist then raise an error. The - local branch is pushed to the remote branch with the same name. - -‘P i’ (‘magit-push-implicitly’) - - Push without explicitly specifying what to push. This runs ‘git - push -v’. What is being pushed depends on various Git variables as - described in the *note (gitman)git-push:: and *note - (gitman)git-config:: - - manpages. - -‘P m’ (‘magit-push-matching’) - - Push all matching branches to another repository. If multiple - remotes exit, then read one from the user. If just one exists, use - that without requiring confirmation. - -‘P t’ (‘magit-push-tags’) - - Push all tags to another repository. If only one remote exists, - then push to that. Otherwise prompt for a remote, offering the - remote configured for the current branch as default. - -‘P T’ (‘magit-push-tag’) - - Push a tag to another repository. - - -- User Option: magit-push-always-verify - - Whether certain commands require verification before pushing. - - Starting with ‘v2.1.0’ some of the push commands are supposed to - push to the configured upstream branch without requiring user - confirmation or offering to push somewhere else. - - This has taken a few users by surprise, and they suggested that we - force users to opt-in to this behavior. Unfortunately adding this - option means that now other users will complain about us needlessly - forcing them to set an option. This is an attempt to make everyone - happy and like all such attempts it is prone to fail. Before - complaining about having to set this option, please consider that - other users are less experienced than you and have different needs. - - You should set the value of this option to nil, causing all push - commands to behave as intended. But first read the description of - each command above. - - -File: magit.info, Node: Creating and sending patches, Next: Applying patches, Prev: Pushing, Up: Transferring - -7.5 Creating and sending patches -================================ - -‘W’ (‘magit-patch-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘W p’ (‘magit-format-patch’) - - Create patches for a set commits. If the region marks commits, - then create patches for those. Otherwise prompt for a range or a - single commit, defaulting to the commit at point. - -‘W r’ (‘magit-request-pull’) - - Request that upstream pulls from your public repository. - - -File: magit.info, Node: Applying patches, Prev: Creating and sending patches, Up: Transferring - -7.6 Applying patches -==================== - -Also see *note (gitman)git-am:: . - -‘w’ (‘magit-am-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘w w’ (‘magit-am-apply-patches’) - - Apply one or more patches. If the region marks files, then apply - those patches. Otherwise read a file name in the minibuffer - defaulting to the file at point. - -‘w m’ (‘magit-am-apply-maildir’) - - Apply the patches from a maildir. - -‘w w’ (‘magit-am-continue’) - - Resume the current patch applying sequence. - -‘w s’ (‘magit-am-skip’) - - Skip the stopped at patch during a patch applying sequence. - -‘w a’ (‘magit-am-abort’) - - Abort the current patch applying sequence. This discards all - changes made since the sequence started. - - -File: magit.info, Node: Miscellaneous, Next: Customizing, Prev: Transferring, Up: Top - -8 Miscellaneous -*************** - -* Menu: - -* Tagging:: -* Notes:: -* Submodules:: -* Common commands:: -* Wip modes:: -* Minor mode for buffers visiting files:: -* Minor mode for buffers visiting blobs:: - - -File: magit.info, Node: Tagging, Next: Notes, Up: Miscellaneous - -8.1 Tagging -=========== - -Also see *note (gitman)git-tag:: . - -‘t’ (‘magit-tag-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘t t’ (‘magit-tag’) - - Create a new tag with the given NAME at REV. With a prefix argument - annotate the tag. - -‘t k’ (‘magit-tag-delete’) - - Delete one or more tags. If the region marks multiple tags (and - nothing else), then offer to delete those. Otherwise, prompt for a - single tag to be deleted, defaulting to the tag at point. - -‘t p’ (‘magit-tag-prune’) - - Offer to delete tags missing locally from REMOTE, and vice versa. - - -File: magit.info, Node: Notes, Next: Submodules, Prev: Tagging, Up: Miscellaneous - -8.2 Notes -========= - -Also see *note (gitman)git-notes:: . - -‘T’ (‘magit-notes-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘T T’ (‘magit-notes-edit’) - - Edit the note attached to a commit, defaulting to the commit at - point. - - By default use the value of Git variable ‘core.notesRef’ or - "refs/notes/commits" if that is undefined. - -‘T r’ (‘magit-notes-remove’) - - Remove the note attached to a commit, defaulting to the commit at - point. - - By default use the value of Git variable ‘core.notesRef’ or - "refs/notes/commits" if that is undefined. - -‘T p’ (‘magit-notes-prune’) - - Remove notes about unreachable commits. - -‘T s’ (‘magit-notes-set-ref’) - - Set the current notes ref to a the value read from the user. The - ref is made current by setting the value of the Git variable - ‘core.notesRef’. With a prefix argument change the global value - instead of the value in the current repository. When this is - undefined, then "refs/notes/commit" is used. - - Other ‘magit-notes-*’ commands, as well as the sub-commands of - Git’s ‘note’ command, default to operate on that ref. - -‘T S’ (‘magit-notes-set-display-refs’) - - Set notes refs to be display in addition to "core.notesRef". This - reads a colon separated list of notes refs from the user. The - values are stored in the Git variable ‘notes.displayRef’. With a - prefix argument GLOBAL change the global values instead of the - values in the current repository. - - It is possible to merge one note ref into another. That may result -in conflicts which have to resolved in the temporary worktree -".git/NOTES_MERGE_WORKTREE". - -‘T m’ (‘magit-notes-merge’) - - Merge the notes of a ref read from the user into the current notes - ref. The current notes ref is the value of Git variable - ‘core.notesRef’ or "refs/notes/commits" if that is undefined. - - When a notes merge is in progress then the popup features the -following suffix commands, instead of those listed above. - -‘T c’ (‘magit-notes-merge-commit’) - - Commit the current notes ref merge, after manually resolving - conflicts. - -‘T a’ (‘magit-notes-merge-abort’) - - Abort the current notes ref merge. - - -File: magit.info, Node: Submodules, Next: Common commands, Prev: Notes, Up: Miscellaneous - -8.3 Submodules -============== - -Also see *note (gitman)git-submodule:: . - -‘o’ (‘magit-submodule-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘o a’ (‘magit-submodule-add’) - - Add the repository at URL as a submodule. Optional PATH is the - path to the submodule relative to the root of the super-project. - If it is nil then the path is determined based on URL. - -‘o b’ (‘magit-submodule-setup’) - - Clone and register missing submodules and checkout appropriate - commits. - -‘o i’ (‘magit-submodule-init’) - - Register submodules listed in ".gitmodules" into ".git/config". - -‘o u’ (‘magit-submodule-update’) - - Clone missing submodules and checkout appropriate commits. With a - prefix argument also register submodules in ".git/config". - -‘o s’ (‘magit-submodule-sync’) - - Update each submodule’s remote URL according to ".gitmodules". - -‘o f’ (‘magit-submodule-fetch’) - - Fetch submodule. With a prefix argument fetch all remotes. - -‘o i’ (‘magit-submodule-init’) - - Unregister the submodule at PATH. - - -File: magit.info, Node: Common commands, Next: Wip modes, Prev: Submodules, Up: Miscellaneous - -8.4 Common commands -=================== - -These are some of the commands that can be used in all buffers whose -major-modes derive from ‘magit-mode’. There are other common commands -beside the ones below, but these didn’t fit well anywhere else. - -‘M-w’ (‘magit-copy-section-value’) - - This command saves the value of the current section to the - ‘kill-ring’, and, provided that the current section is a commit, - branch, or tag section, it also pushes the (referenced) revision to - the ‘magit-revision-stack’. - - When the current section is a branch or a tag, and a prefix - argument is used, then it saves the revision at its tip to the - ‘kill-ring’ instead of the reference name. - -‘C-w’ (‘magit-copy-buffer-revision’) - - This command save the revision being displayed in the current - buffer to the ‘kill-ring’ and also pushes it to the - ‘magit-revision-stack’. It is mainly intended for use in - ‘magit-revision-mode’ buffers, the only buffers where it is always - unambiguous exactly which revision should be saved. - - Most other Magit buffers usually show more than one revision, in - some way or another, so this command has to select one of them, and - that choice might not always be the one you think would have been - the best pick. - - Outside of Magit ‘M-w’ and ‘C-w’ are usually bound to -‘kill-ring-save’ and ‘kill-region’, and these commands would also be -useful in Magit buffers. Therefore when the region is active, then both -of these commands behave like ‘kill-ring-save’ instead of as described -above. - - -File: magit.info, Node: Wip modes, Next: Minor mode for buffers visiting files, Prev: Common commands, Up: Miscellaneous - -8.5 Wip modes -============= - -Git keeps *committed* changes around long enough for users to recover -changes they have accidentally deleted. It does so by not garbage -collecting any committed but no longer referenced objects for a certain -period of time, by default 30 days. - - But Git does *not* keep track of *uncommitted* changes in the working -tree and not even the index (the staging area). Because Magit makes it -so convenient to modify uncommitted changes, it also makes it easy to -shoot yourself in the foot in the process. - - For that reason Magit provides three global modes that save *tracked* -files to work-in-progress references after or before certain actions. -(Untracked files are never saved and these modes also only work after -the first commit has been created). - - Two separate work-in-progress references are used to track the state -of the index and of the working tree: "refs/wip/index/" and -"refs/wip/wtree/", where ‘’ is the full ref of the -current branch, e.g. "refs/heads/master". When the ‘HEAD’ is detached -then "HEAD" is in place of ‘’. - - Checking out another branch (or detaching ‘HEAD’) causes the use of -different wip refs for subsequent changes, but the old refs are not -deleted. - - Creating a commit and then making a change causes the wip refs to be -recreated to fork from the new commit. But the old commits on the wip -refs are not lost. They are still available from the reflog. To make -it easier to see when the fork point of a wip ref was changed, an -additional commit with the message "restart autosaving" is created on it -(‘xxO’ commits below are such boundary commits). - - Starting with - - BI0---BI1 refs/wip/index/refs/heads/master - / -A---B refs/heads/master - \ - BW0---BW1 refs/wip/wtree/refs/heads/master - - and committing the staged changes and editing and saving a file would -result in - - BI0---BI1 refs/wip/index/refs/heads/master - / -A---B---C refs/heads/master - \ \ - \ CW0---CW1 refs/wip/wtree/refs/heads/master - \ - BW0---BW1 refs/wip/wtree/refs/heads/master@{2} - - The fork-point of the index wip ref is not changed until some change -is being staged. Likewise just checking out a branch or creating a -commit does not change the fork-point of the working tree wip ref. The -fork-points are not adjusted until there actually is a change that -should be committed to the respective wip ref. - - To view the log for the a branch and its wip refs use the commands -‘magit-wip-log’ and ‘magit-wip-log-current’. You should use ‘--graph’ -when using these commands. Alternatively you can use the reflog to show -all commits that ever existed on a wip ref. You can then recover lost -changes from the commits shown in the log or reflog. - - -- Command: magit-wip-log - - This command shows the log for a branch and its wip refs. - - With a negative prefix argument only the worktree wip ref is shown. - The absolute numeric value of the prefix argument controls how many - "branches" of each wip ref are shown. - - -- Command: magit-wip-log-current - - This command shows the log for the current branch and its wip refs. - - With a negative prefix argument only the worktree wip ref is shown. - The absolute numeric value of the prefix argument controls how many - "branches" of each wip ref are shown. - - There exists a total of three global modes that save to the wip refs, -which might seem excessive, but allows fine tuning of when exactly -changes are being committed to the wip refs. Enabling all modes makes -it less likely that a change slips through the cracks. - - Setting the below variable directly does not take effect; either -customize them or call the respective mode function. - - -- User Option: magit-wip-after-save-mode - - When this mode is enabled, then saving a buffer that visits a file - tracked in a Git repository causes its current state to be - committed to the working tree wip ref for the current branch. - - -- User Option: magit-wip-after-apply-mode - - When this mode is enabled, then applying (i.e. staging, unstaging, - discarding, reversing, and regularly applying) a change to a file - tracked in a Git repository causes its current state to be - committed to the index and/or working tree wip refs for the current - branch. - - If you only ever edit files using Emacs and only ever interact with -Git using Magit, then the above two modes should be enough to protect -each and every change from accidental loss. In practice nobody does -that. So an additional mode exists that does commit to the wip refs -before making changes that could cause the loss of earlier changes. - - -- User Option: magit-wip-before-change-mode - - When this mode is enabled, then certain commands commit the - existing changes to the files they are about to make changes to. - - Note that even if you enable all three modes this won’t give you -perfect protection. The most likely scenario for losing changes despite -the use of these modes is making a change outside Emacs and then -destroying it also outside Emacs. In such a scenario, Magit, being an -Emacs package, didn’t get the opportunity to keep you from shooting -yourself in the foot. - - When you are unsure whether Magit did commit a change to the wip -refs, then you can explicitly request that all changes to all tracked -files are being committed. - -‘M-x magit-wip-commit’ (‘magit-wip-commit’) - - This command commits all changes to all tracked files to the index - and working tree work-in-progress refs. Like the modes described - above, it does not commit untracked files, but it does check all - tracked files for changes. Use this command when you suspect that - the modes might have overlooked a change made outside Emacs/Magit. - - -- User Option: magit-wip-after-save-local-mode-lighter - - Mode-line lighter for ‘magit-wip-after-save-local-mode’. - - -- User Option: magit-wip-after-apply-mode-lighter - - Mode-line lighter for ‘magit-wip-after-apply-mode’. - - -- User Option: magit-wip-before-change-mode-lighter - - Mode-line lighter for ‘magit-wip-before-change-mode’. - - -- User Option: magit-wip-namespace - - The namespace used for work-in-progress refs. It has to end with a - slash. The wip refs are named "index/" and - "wtree/". When snapshots are created while - the ‘HEAD’ is detached then "HEAD" is used in place of - ‘’. - - -File: magit.info, Node: Minor mode for buffers visiting files, Next: Minor mode for buffers visiting blobs, Prev: Wip modes, Up: Miscellaneous - -8.6 Minor mode for buffers visiting files -========================================= - -The ‘magit-file-mode’ enables certain Magit features in file-visiting -buffers belonging to a Git repository. It should be enabled globally -using ‘global-magit-file-mode’. Currently this mode only establishes a -few key bindings, but this might be extended in the future. - - -- User Option: global-magit-file-mode - - Whether to establish certain Magit key bindings in all - file-visiting buffers belonging to a Git repository. This - establishes the bindings suggested in *note Getting started: - Getting started. (but only for file-visiting buffers), and - additionally binds ‘C-c M-g’ to ‘magit-file-popup’. - -‘C-c M-g’ (‘magit-file-popup’) - - This prefix command shows a popup buffer featuring suffix commands - that operate on the file being visited in the current buffer. - -‘C-c M-g s’ (‘magit-stage-file’) - - Stage all changes to the file being visited in the current buffer. - -‘C-c M-g u’ (‘magit-unstage-file’) - - Unstage all changes to the file being visited in the current - buffer. - -‘C-c M-g l’ (‘magit-log-buffer-file’) - - This command shows the log for the file of blob that the current - buffer visits. Renames are followed when a prefix argument is used - or when ‘--follow’ is part of ‘magit-log-arguments’. - -‘C-c M-g b’ (‘magit-blame-popup’) - - This prefix command shows the ‘magit-blame’ suffix command along - with the appropriate infix arguments in a popup buffer. See *note - Initiating a commit: Initiating a commit. - -‘C-c M-g p’ (‘magit-blob-previous’) - - Visit the previous blob which modified the current file. - -‘C-c M-g c’ (‘magit-commit-popup’) - - This prefix command shows suffix commands along with the - appropriate infix arguments in a popup buffer. See *note - Initiating a commit: Initiating a commit. - - -File: magit.info, Node: Minor mode for buffers visiting blobs, Prev: Minor mode for buffers visiting files, Up: Miscellaneous - -8.7 Minor mode for buffers visiting blobs -========================================= - -The ‘magit-blob-mode’ enables certain Magit features in blob-visiting -buffers. Such buffers can be created using ‘magit-find-file’ and some -of the commands mentioned below, which also take care of turning on this -minor mode. Currently this mode only establishes a few key bindings, -but this might be e - -‘p’ (‘magit-blob-previous’) - - Visit the previous blob which modified the current file. - -‘n’ (‘magit-blob-next’) - - Visit the next blob which modified the current file. - -‘q’ (‘magit-kill-this-buffer’) - - Kill the current buffer. - - -File: magit.info, Node: Customizing, Next: Plumbing, Prev: Miscellaneous, Up: Top - -9 Customizing -************* - -Both Git and Emacs are highly customizable. Magit is both a Git -porcelain as well as an Emacs package, so it makes sense to customize it -using both Git variables as well as Emacs options. However this -flexibility doesn’t come without problems, including but not limited to -the following. - - • Some Git variables automatically have an effect in Magit without - requiring any explicit support. Sometimes that is desirable - in - other cases, it breaks Magit. - - When a certain Git setting breaks Magit but you want to keep using - that setting on the command line, then that can be accomplished by - overriding the value for Magit only by appending something like - ‘("-c" "some.variable=compatible-value")’ to - ‘magit-git-global-arguments’. - - • Certain settings like ‘fetch.prune=true’ are respected by Magit - commands (because they simply call the respective Git command) but - their value is not reflected in the respective popup buffers. In - this case the ‘--prune’ argument in ‘magit-fetch-popup’ might be - active or inactive depending on the value of - ‘magit-fetch-arguments’ only, but that doesn’t keep the Git - variable from being honored by the suffix commands anyway. So - pruning might happen despite the the ‘--prune’ arguments being - displayed in a way that seems to indicate that no pruning will - happen. - - I intend to address these and similar issues in a future release. - -* Menu: - -* Per-repository configuration:: -* Essential settings:: - - -File: magit.info, Node: Per-repository configuration, Next: Essential settings, Up: Customizing - -9.1 Per-repository configuration -================================ - -Magit can be configured on a per-repository level using both Git -variables as well as Emacs options. - - To set a Git variable for one repository only, simply set it in -‘/path/to/repo/.git/config’ instead of ‘$HOME/.gitconfig’ or -‘/etc/gitconfig’. See *note (gitman)git-config:: . - - Similarly, Emacs options can be set for one repository only by -editing ‘/path/to/repo/.dir-locals.el’. See *note (emacs)Directory -Variables::. For example to disable automatic refreshes of -file-visiting buffers in just one huge repository use this: - - • ‘/path/to/huge/repo/.dir-locals.el’ - - ((nil . ((magit-refresh-buffers . nil)) - - If you want to apply the same settings to several, but not all, -repositories then keeping the repository-local config files in sync -would quickly become annoying. To avoid that you can create config -files for certain classes of repositories (e.g. "huge repositories") -and then include those files in the per-repository config files. For -example: - - • ‘/path/to/huge/repo/.git/config’ - - [include] - path = /path/to/huge-gitconfig - - • ‘/path/to/huge-gitconfig’ - - [status] - showUntrackedFiles = no - - • ‘$HOME/.emacs.d/init.el’ - - (dir-locals-set-class-variables 'huge-git-repository - '((nil . ((magit-refresh-buffers . nil))))) - - (dir-locals-set-directory-class - "/path/to/huge/repo/" 'huge-git-repository) - - -File: magit.info, Node: Essential settings, Prev: Per-repository configuration, Up: Customizing - -9.2 Essential settings -====================== - -The next two sections list and discuss several variables that many users -might want to customize, for safety and/or performance reasons. - -* Menu: - -* Safety:: -* Performance:: - - -File: magit.info, Node: Safety, Next: Performance, Up: Essential settings - -9.2.1 Safety ------------- - -This section discusses various variables that you might want to change -(or *not* change) for safety reasons. - - Git keeps *committed* changes around long enough for users to recover -changes they have accidentally deleted. It does not do the same for -*uncommitted* changes in the working tree and not even the index (the -staging area). Because Magit makes it so easy to modify uncommitted -changes, it also makes it easy to shoot yourself in the foot in the -process. For that reason Magit provides three global modes that save -*tracked* files to work-in-progress references after or before certain -actions. See *note Wip modes: Wip modes. - - These modes are not enabled by default because of performance -concerns. Instead a lot of potentially destructive commands require -confirmation every time they are used. In many cases this can be -disabled by adding a symbol to ‘magit-no-confirm’ (see *note Completion -and confirmation: Completion and confirmation.). If you enable the -various wip modes then you should add ‘safe-with-wip’ to this list. - - Similarly it isn’t necessary to require confirmation before moving a -file to the system trash - if you trashed a file by mistake then you can -recover it from the there. Option ‘magit-delete-by-moving-to-trash’ -controls whether the system trash is used, which is the case by default. -Nevertheless, ‘trash’ isn’t a member of ‘magit-no-confirm’ - you might -want to change that. - - Buffers visiting files tracked in the current repository are being -refreshed before certain actions. See *note Automatic refresh and -revert: Automatic refresh and revert. This isn’t as risky as it might -seem. If a buffer is modified (i.e. it contains changes that haven’t -been saved yet), then Emacs/Magit would refuse to revert it. If the -buffer has been saved resulting in what is seen by Git as an uncommitted -change, then Git in turn would refuse to carry out the action that would -cause these changes to be lost. Since Git doesn’t do anything, the file -doesn’t change on disk, and Emacs/Magit has nothing to revert. - - However if you do modify some files, visit the respective files in -Emacs, somehow discard the changes (not using Magit and probably even -outside Emacs), and then expect the respective file-visiting buffers to -retain the uncommitted changes, then the automatic reverting would -actually be harmful. In other words if you use file-visiting buffers as -a sort of "staging area", then you should set ‘magit-revert-buffers’ to -‘nil’. - - So far I have only heard from one user who uses such a workflow. But -because there might be some other users doing such things, and I don’t -want to be responsible for data loss, these reverts by default happen -quite verbosely, allowing these few users to undo the reverts using the -‘undo’ command and then disabling the automatic reverts for the future. -Most users should however keep automatic reverts turned on and instead -configure it to be less verbose by setting ‘magit-revert-buffers’ to ‘t’ -or even ‘silent’. - - -File: magit.info, Node: Performance, Prev: Safety, Up: Essential settings - -9.2.2 Performance ------------------ - -Magit is slower than raw Git because it does more. For example ‘git -commit’ creates a commit and that’s it. ‘magit-commit’ also updates the -current Magit buffer to make sure you are not looking at outdated -information without noticing it. To refresh the status buffer, Magit -has to run Git a dozen times or more, making it slower than ‘git -status’, but also much more informative. Magit also optionally reverts -file-visiting buffers, creates backups, runs hooks where third-party -extensions can do their slow thing, etc. - - I do care about performance and try to optimize for it as much as -possible, but many features simply come with an inherent performance -penalty. When a feature is just too slow given certain usage and -repository characteristics, then it often can be disabled, globally or -on a per-repository basis. - - But first a short list of performance issues that cannot easily be -worked around: - - • Creating a new process on MS Windows is much slower than on - POSIX-compatible systems. This is a problem because Magit creates - a lot of child processes to retrieve information from Git. In the - short run, only switching to a POSIX system can fix this. Of - course this could also be fixed in Windows itself, but I am just - one unpaid person while Microsoft is a billion dollar company, so I - will leave it to them to fix this grave flaw in their OS. - - • When showing logs, Magit limits the number of commits initially - shown in the hope that this avoids unnecessary work. When using - ‘--graph’ this unfortunately does not have the desired effect for - large histories. Junio said on the git mailing list - (): "‘--graph’ - wants to compute the whole history and the max-count only affects - the output phase after ‘--graph’ does its computation". - - In other words, it’s not that Git is slow at outputting the - differences, or that Magit is slow at parsing the output - the - problem is that Git first goes outside and has a smoke. - - We actually work around this issue by limiting the commit not only - using ‘-’ but also using a range. But unfortunately that’s not - always possible. - - • Whenever "something changes", Magit "refreshes" the status buffer - and the current Magit buffer by recreating them from scratch. This - is an old design decision that we couldn’t depart from easily. And - it has its benefits too - most importantly it’s much simpler and - less error prone to do it this way than to only refreshing "what - actually has changed" (that would basically be a huge collection of - special cases). So for now at least, we don’t avoid recreating the - buffer content and instead focus on making doing so faster. - - Now for the things that you can do to improve performance: - - Most optional features which can have a negative effect on -performance are disabled by default. So start by checking the options -you have explicitly enabled. Even the potentially slow features are -expected to only lead to barely noticeable delays, but your mileage may -vary. Also note that it is now possible to set options on a -per-repository or per-repository-class basis. See *note Per-repository -configuration: Per-repository configuration. - - You should check the values of at least the following variables: - - • ‘magit-after-revert-hook’ - - • ‘magit-diff-auto-show’ - - • ‘magit-diff-highlight-hunk-body’ - - • ‘magit-diff-highlight-indentation’ - - • ‘magit-diff-highlight-trailing’ - - • ‘magit-diff-paint-whitespace’ - - • ‘magit-diff-refine-hunk’ - - • ‘magit-log-arguments’, ‘magit-log-select-arguments’, and - ‘magit-log-section-arguments’ - - In repositories with more than a few thousand commits ‘--graph’ - should never be a member of ‘magit-log-section-arguments’. That - variable is in the status buffer which is refreshed every time you - run any Magit command. - - Using ‘--color --graph’ is even slower. Magit uses code that is - part of Emacs to turn control characters into faces. That code is - pretty slow and this is quite noticeable when showing a log with - many branches and merges. For that reason ‘--color’ is not enabled - by default anymore. Consider leaving it at that. - - • ‘magit-not-reverted-hook’ - - • ‘magit-refresh-buffer-hook’ - - • ‘magit-refs-sections-hook’ - - When refreshing the "references buffer" is slow, then that’s - usually because several hundred refs are being displayed. The best - way to address that is to display fewer refs, obviously. - - If you are not, or only mildly, interested in seeing the list of - tags, then start by not displaying them: - - (remove-hook 'magit-refs-sections-hook 'magit-insert-tags) - - Then you should also make sure that the listed remote branches - actually all exist. You can do so by pruning branches which no - longer exist using ‘f-pa’. - - • ‘magit-status-refresh-hook’ - - • ‘magit-wip-after-apply-mode’ - - • ‘magit-wip-after-save-mode’ - - • ‘magit-wip-before-change-mode’ - - Also note that everything involving "cherry commits" is slow. - - If, after actually trying the above suggestions, performance is still -bad, and the above does not contain a statement explaining why that is -so in that particular case and that there is nothing that we can -currently do about it, then comment on the appropriate existing issue -(see ), or if -necessary open a new issue. Note that "something is slow, I am using -v2.2" is not helpful, you have to be a bit more specific. Benchmarks -are a start. - - -File: magit.info, Node: Plumbing, Next: FAQ, Prev: Customizing, Up: Top - -10 Plumbing -*********** - -The following sections describe how to use several of Magit’s core -abstractions to extend Magit itself or implement a separate extension. - - A few of the low-level features used by Magit have been factored out -into separate libraries/packages, so that they can be used by other -packages, without having to depend on Magit. These libraries are -described in separate manuals, see *note (with-editor)Top:: and *note -(magit-popup)Top::. - -* Menu: - -* Calling Git:: -* Section plumbing:: -* Refreshing buffers:: -* Conventions:: - - -File: magit.info, Node: Calling Git, Next: Section plumbing, Up: Plumbing - -10.1 Calling Git -================ - -Magit provides many specialized functions for calling Git. All of these -functions are defined in either ‘magit-git.el’ or ‘magit-process.el’ and -have one of the prefixes ‘magit-run-’, ‘magit-call-’, ‘magit-start-’, or -‘magit-git-’ (which is also used for other things). - - All of these functions accept an indefinite number of arguments, -which are strings that specify command line arguments for git (or in -some cases an arbitrary executable). These arguments are flattened -before being passed on to the executable; so instead of strings they can -also be lists of strings and arguments that are ‘nil’ are silently -dropped. Some of these functions also require a single mandatory -argument before these command line arguments. - - Roughly speaking these functions run Git either to get some value or -for side-effect. The functions that return a value are useful to -collect the information necessary to populate a Magit buffer, while the -others are used to implement Magit commands. - - The functions in the value-only group always run synchronously, and -they never trigger a refresh. The function in the side-effect group can -be further divided into subgroups depending on whether they run Git -synchronously or asynchronously, and depending on whether they trigger a -refresh when the executable has finished. - -* Menu: - -* Getting a value from Git:: -* Calling Git for effect:: - - -File: magit.info, Node: Getting a value from Git, Next: Calling Git for effect, Up: Calling Git - -10.1.1 Getting a value from Git -------------------------------- - -These functions run Git in order to get a value, either its exit status -or its output. Of course you could also use them to run Git commands -that have side-effects, but that should be avoided. - - -- Function: magit-git-exit-code &rest args - - Executes git with ARGS and returns its exit code. - - -- Function: magit-git-success &rest args - - Executes git with ARGS and returns ‘t’ if the exit code is ‘0’, - ‘nil’ otherwise. - - -- Function: magit-git-failure &rest args - - Executes git with ARGS and returns ‘t’ if the exit code is ‘1’, - ‘nil’ otherwise. - - -- Function: magit-git-true &rest args - - Executes git with ARGS and returns ‘t’ if the first line printed by - git is the string "true", ‘nil’ otherwise. - - -- Function: magit-git-false &rest args - - Executes git with ARGS and returns ‘t’ if the first line printed by - git is the string "false", ‘nil’ otherwise. - - -- Function: magit-git-insert &rest args - - Executes git with ARGS and inserts its output at point. - - -- Function: magit-git-string &rest args - - Executes git with ARGS and returns the first line of its output. - If there is no output or if it begins with a newline character, - then this returns ‘nil’. - - -- Function: magit-git-lines &rest args - - Executes git with ARGS and returns its output as a list of lines. - Empty lines anywhere in the output are omitted. - - -- Function: magit-git-items &rest args - - Executes git with ARGS and returns its null-separated output as a - list. Empty items anywhere in the output are omitted. - - If the value of option ‘magit-git-debug’ is non-nil and git exits - with a non-zero exit status, then warn about that in the echo area - and add a section containing git’s standard error in the current - repository’s process buffer. - - When an error occurs when using one of the above functions, then that -is usually due to a bug, i.e. the use of an argument which is not -actually supported. Such errors are usually not reported, but when they -occur we need to be able to debug them. - - -- User Option: magit-git-debug - - Whether to report errors that occur when using ‘magit-git-insert’, - ‘magit-git-string’, ‘magit-git-lines’, or ‘magit-git-items’. This - does not actually raise an error. Instead a message is shown in - the echo area, and git’s standard error is insert into a new - section in the current repository’s process buffer. - - -- Function: magit-git-str &rest args - - This is a variant of ‘magit-git-string’ that ignores the option - ‘magit-git-debug’. It is mainly intended to be used while handling - errors in functions that do respect that option. Using such a - function while handing an error could cause yet another error and - therefore lead to an infinite recursion. You probably won’t ever - need to use this function. - - -File: magit.info, Node: Calling Git for effect, Prev: Getting a value from Git, Up: Calling Git - -10.1.2 Calling Git for effect ------------------------------ - -These functions are used to run git to produce some effect. Most Magit -commands that actually run git do so by using such a function. - - Because we do not need to consume git’s output when using these -functions, their output is instead logged into a per-repository buffer, -which can be shown using ‘$’ from a Magit buffer or ‘M-x magit-process’ -elsewhere. - - These functions can have an effect in two distinct ways. Firstly, -running git may change something, i.e. create or push a new commit. -Secondly, that change may require that Magit buffers are refreshed to -reflect the changed state of the repository. But refreshing isn’t -always desirable, so only some of these functions do perform such a -refresh after git has returned. - - Sometimes it is useful to run git asynchronously. For example, when -the user has just initiated a push, then there is no reason to make her -wait until that has completed. In other cases it makes sense to wait -for git to complete before letting the user do something else. For -example after staging a change it is useful to wait until after the -refresh because that also automatically moves to the next change. - - -- Function: magit-call-git &rest args - - Calls git synchronously with ARGS. - - -- Function: magit-call-process program &rest args - - Calls PROGRAM synchronously with ARGS. - - -- Function: magit-run-git &rest args - - Calls git synchronously with ARGS and then refreshes. - - -- Function: magit-run-git-with-input input &rest args - - Calls git synchronously with ARGS and sends it INPUT on standard - input. - - INPUT should be a buffer or the name of an existing buffer. The - content of that buffer is used as the process’ standard input. - After the process returns a refresh is performed. - - As a special case, INPUT may also be nil. In that case the content - of the current buffer is used as standard input and *no* refresh is - performed. - - This function actually runs git asynchronously. But then it waits - for the process to return, so the function itself is synchronous. - - -- Function: magit-run-git-with-logfile file &rest args - - Calls git synchronously with ARGS. The process’ output is saved in - FILE. This is rarely useful and so this function might be removed - in the future. - - This function actually runs git asynchronously. But then it waits - for the process to return, so the function itself is synchronous. - - -- Function: magit-git &rest args - - Calls git synchronously with ARGS for side-effects only. This - function does not refresh the buffer. - - -- Function: magit-git-wash washer &rest args - - Execute Git with ARGS, inserting washed output at point. Actually - first insert the raw output at point. If there is no output call - ‘magit-cancel-section’. Otherwise temporarily narrow the buffer to - the inserted text, move to its beginning, and then call function - WASHER with no argument. - - And now for the asynchronous variants. - - -- Function: magit-run-git-async &rest args - - Start Git, prepare for refresh, and return the process object. - ARGS is flattened and then used as arguments to Git. - - Display the command line arguments in the echo area. - - After Git returns some buffers are refreshed: the buffer that was - current when this function was called (if it is a Magit buffer and - still alive), as well as the respective Magit status buffer. - Unmodified buffers visiting files that are tracked in the current - repository are reverted if ‘magit-revert-buffers’ is non-nil. - - -- Function: magit-run-git-with-editor &rest args - - Export GIT_EDITOR and start Git. Also prepare for refresh and - return the process object. ARGS is flattened and then used as - arguments to Git. - - Display the command line arguments in the echo area. - - After Git returns some buffers are refreshed: the buffer that was - current when this function was called (if it is a Magit buffer and - still alive), as well as the respective Magit status buffer. - - -- Function: magit-start-git &rest args - - Start Git, prepare for refresh, and return the process object. - - If INPUT is non-nil, it has to be a buffer or the name of an - existing buffer. The buffer content becomes the processes standard - input. - - Option ‘magit-git-executable’ specifies the Git executable and - option ‘magit-git-global-arguments’ specifies constant arguments. - The remaining arguments ARGS specify arguments to Git. They are - flattened before use. - - After Git returns, some buffers are refreshed: the buffer that was - current when this function was called (if it is a Magit buffer and - still alive), as well as the respective Magit status buffer. - Unmodified buffers visiting files that are tracked in the current - repository are reverted if ‘magit-revert-buffers’ is non-nil. - - -- Function: magit-start-process &rest args - - Start PROGRAM, prepare for refresh, and return the process object. - - If optional argument INPUT is non-nil, it has to be a buffer or the - name of an existing buffer. The buffer content becomes the - processes standard input. - - The process is started using ‘start-file-process’ and then setup to - use the sentinel ‘magit-process-sentinel’ and the filter - ‘magit-process-filter’. Information required by these functions is - stored in the process object. When this function returns the - process has not started to run yet so it is possible to override - the sentinel and filter. - - After the process returns, ‘magit-process-sentinel’ refreshes the - buffer that was current when ‘magit-start-process’ was called (if - it is a Magit buffer and still alive), as well as the respective - Magit status buffer. Unmodified buffers visiting files that are - tracked in the current repository are reverted if - ‘magit-revert-buffers’ is non-nil. - - -- Variable: magit-this-process - - The child process which is about to start. This can be used to - change the filter and sentinel. - - -- Variable: magit-process-raise-error - - When this is non-nil, then ‘magit-process-sentinel’ raises an error - if git exits with a non-zero exit status. For debugging purposes. - - -File: magit.info, Node: Section plumbing, Next: Refreshing buffers, Prev: Calling Git, Up: Plumbing - -10.2 Section plumbing -===================== - -* Menu: - -* Creating sections:: -* Section selection:: -* Matching sections:: - - -File: magit.info, Node: Creating sections, Next: Section selection, Up: Section plumbing - -10.2.1 Creating sections ------------------------- - - -- Macro: magit-insert-section &rest args - - Insert a section at point. - - TYPE is the section type, a symbol. Many commands that act on the - current section behave differently depending on that type. Also if - a variable ‘magit-TYPE-section-map’ exists, then use that as the - text-property ‘keymap’ of all text belonging to the section (but - this may be overwritten in subsections). - - Optional VALUE is the value of the section, usually a string that - is required when acting on the section. - - When optional HIDE is non-nil collapse the section body by default, - i.e. when first creating the section, but not when refreshing the - buffer. Otherwise, expand it by default. This can be overwritten - using ‘magit-section-set-visibility-hook’. When a section is - recreated during a refresh, then the visibility of predecessor is - inherited and HIDE is ignored (but the hook is still honored). - - BODY is any number of forms that actually insert the section’s - heading and body. Optional NAME, if specified, has to be a symbol, - which is then bound to the struct of the section being inserted. - - Before BODY is evaluated the ‘start’ of the section object is set - to the value of ‘point’ and after BODY was evaluated its ‘end’ is - set to the new value of ‘point’; BODY is responsible for moving - ‘point’ forward. - - If it turns out inside BODY that the section is empty, then - ‘magit-cancel-section’ can be used to abort and remove all traces - of the partially inserted section. This can happen when creating a - section by washing Git’s output and Git didn’t actually output - anything this time around. - - -- Function: magit-insert-heading &rest args - - Insert the heading for the section currently being inserted. - - This function should only be used inside ‘magit-insert-section’. - - When called without any arguments, then just set the ‘content’ slot - of the object representing the section being inserted to a marker - at ‘point’. The section should only contain a single line when - this function is used like this. - - When called with arguments ARGS, which have to be strings, then - insert those strings at point. The section should not contain any - text before this happens and afterwards it should again only - contain a single line. If the ‘face’ property is set anywhere - inside any of these strings, then insert all of them unchanged. - Otherwise use the ‘magit-section-heading’ face for all inserted - text. - - The ‘content’ property of the section struct is the end of the - heading (which lasts from ‘start’ to ‘content’) and the beginning - of the body (which lasts from ‘content’ to ‘end’). If the value of - ‘content’ is nil, then the section has no heading and its body - cannot be collapsed. If a section does have a heading then its - height must be exactly one line, including a trailing newline - character. This isn’t enforced; you are responsible for getting it - right. The only exception is that this function does insert a - newline character if necessary. - - -- Function: magit-cancel-section - - Cancel the section currently being inserted. This exits the - innermost call to ‘magit-insert-section’ and removes all traces of - what has already happened inside that call. - - -- Function: magit-define-section-jumper sym title &optional value - - Define an interactive function to go to section SYM. TITLE is the - displayed title of the section. - - -File: magit.info, Node: Section selection, Next: Matching sections, Prev: Creating sections, Up: Section plumbing - -10.2.2 Section selection ------------------------- - - -- Function: magit-current-section - - Return the section at point. - - -- Function: magit-region-sections - - Return a list of the selected sections. - - When the region is active and constitutes a valid section - selection, then return a list of all selected sections. This is - the case when the region begins in the heading of a section and - ends in the heading of a sibling of that first section. When the - selection is not valid then return nil. Most commands that can act - on the selected sections, then instead just act on the current - section, the one point is in. - - When the region looks like it would in any other buffer then the - selection is invalid. When the selection is valid then the region - uses the ‘magit-section-highlight’. This does not apply to diffs - where things get a bit more complicated, but even here if the - region looks like it usually does, then that’s not a valid - selection as far as this function is concerned. - - -- Function: magit-region-values &rest types - - Return a list of the values of the selected sections. - - Also see ‘magit-region-sections’ whose doc-string explains when a - region is a valid section selection. If the region is not active - or is not a valid section selection, then return nil. If optional - TYPES is non-nil then the selection not only has to be valid; the - types of all selected sections additionally have to match one of - TYPES, or nil is returned. - - -File: magit.info, Node: Matching sections, Prev: Section selection, Up: Section plumbing - -10.2.3 Matching sections ------------------------- - -‘M-x magit-describe-section’ (‘magit-describe-section’) - - Show information about the section at point. This command is - intended for debugging purposes. - - -- Function: magit-section-ident - - Return an unique identifier for SECTION. The return value has the - form ‘((TYPE . VALUE)...)’. - - -- Function: magit-get-section - - Return the section identified by IDENT. IDENT has to be a list as - returned by ‘magit-section-ident’. - - -- Function: magit-section-match condition &optional section - - Return ‘t’ if SECTION matches CONDITION. SECTION defaults to the - section at point. - - Conditions can take the following forms: - • ‘(CONDITION...)’ - - matches if any of the CONDITIONs matches. - - • ‘[TYPE...]’ - - matches if the first TYPE matches the type of the section at - point, the second matches that of its parent, and so on. - - • ‘[* TYPE...]’ - - matches sections that match [TYPE…] and also recursively all - their child sections. - - • ‘TYPE’ - - matches TYPE regardless of its parents. - Each TYPE is a symbol. Note that is not necessary to specify all - TYPEs up to the root section as printed by ‘magit-describe-type’, - unless of course your want to be that precise. - - -- Function: magit-section-when condition &rest body - - If the section at point matches CONDITION evaluate BODY. - - If the section matches evaluate BODY forms sequentially and return - the value of the last one, or if there are no BODY forms return the - value of the section. If the section does not match return nil. - - See ‘magit-section-match’ for the forms CONDITION can take. - - -- Function: magit-section-case &rest clauses - - Choose among clauses on the type of the section at point. - - Each clause looks like (CONDITION BODY…). The type of the section - is compared against each CONDITION; the BODY forms of the first - match are evaluated sequentially and the value of the last form is - returned. Inside BODY the symbol ‘it’ is bound to the section at - point. If no clause succeeds or if there is no section at point - return nil. - - See ‘magit-section-match’ for the forms CONDITION can take. - Additionally a CONDITION of t is allowed in the final clause and - matches if no other CONDITION match, even if there is no section at - point. - - -- Variable: magit-root-section - - The root section in the current buffer. All other sections are - descendants of this section. The value of this variable is set by - ‘magit-insert-section’ and you should never modify it. - - For diff related sections a few additional tools exist. - - -- Function: magit-diff-type &optional section - - Return the diff type of SECTION. - - The returned type is one of the symbols ‘staged’, ‘unstaged’, - ‘committed’, or ‘undefined’. This type serves a similar purpose as - the general type common to all sections (which is stored in the - ‘type’ slot of the corresponding ‘magit-section’ struct) but takes - additional information into account. When the SECTION isn’t - related to diffs and the buffer containing it also isn’t a - diff-only buffer, then return nil. - - Currently the type can also be one of ‘tracked’ and ‘untracked’, - but these values are not handled explicitly in every place they - should be. A possible fix could be to just return nil here. - - The section has to be a ‘diff’ or ‘hunk’ section, or a section - whose children are of type ‘diff’. If optional SECTION is nil, - return the diff type for the current section. In buffers whose - major mode is ‘magit-diff-mode’ SECTION is ignored and the type is - determined using other means. In ‘magit-revision-mode’ buffers the - type is always ‘committed’. - - -- Function: magit-diff-scope &optional section strict - - Return the diff scope of SECTION or the selected section(s). - - A diff’s "scope" describes what part of a diff is selected, it is a - symbol, one of ‘region’, ‘hunk’, ‘hunks’, ‘file’, ‘files’, or - ‘list’. Do not confuse this with the diff "type", as returned by - ‘magit-diff-type’. - - If optional SECTION is non-nil, then return the scope of that, - ignoring the sections selected by the region. Otherwise return the - scope of the current section, or if the region is active and - selects a valid group of diff related sections, the type of these - sections, i.e. ‘hunks’ or ‘files’. If SECTION (or if the current - section that is nil) is a ‘hunk’ section and the region starts and - ends inside the body of a that section, then the type is ‘region’. - - If optional STRICT is non-nil then return nil if the diff type of - the section at point is ‘untracked’ or the section at point is not - actually a ‘diff’ but a ‘diffstat’ section. - - -File: magit.info, Node: Refreshing buffers, Next: Conventions, Prev: Section plumbing, Up: Plumbing - -10.3 Refreshing buffers -======================= - -All commands that create a new Magit buffer or change what is being -displayed in an existing buffer do so by calling ‘magit-mode-setup’. -Among other things, that function sets the buffer local values of -‘default-directory’ (to the top-level of the repository), -‘magit-refresh-function’, and ‘magit-refresh-args’. - - Buffers are refreshed by calling the function that is the local value -of ‘magit-refresh-function’ (a function named ‘magit-*-refresh-buffer’, -where ‘*’ may be something like ‘diff’) with the value of -‘magit-refresh-args’ as arguments. - - -- Macro: magit-mode-setup buffer switch-func mode refresh-func - &optional refresh-args - - This function displays and selects BUFFER, turns on MODE, and - refreshes a first time. - - This function displays and optionally selects BUFFER by calling - ‘magit-mode-display-buffer’ with BUFFER, MODE and SWITCH-FUNC as - arguments. Then it sets the local value of - ‘magit-refresh-function’ to REFRESH-FUNC and that of - ‘magit-refresh-args’ to REFRESH-ARGS. Finally it creates the buffer - content by calling REFRESH-FUNC with REFRESH-ARGS as arguments. - - All arguments are evaluated before switching to BUFFER. - - -- Function: magit-mode-display-buffer buffer mode &optional - switch-function - - This function display BUFFER in some window and select it. BUFFER - may be a buffer or a string, the name of a buffer. The buffer is - returned. - - Unless BUFFER is already displayed in the selected frame, store the - previous window configuration as a buffer local value, so that it - can later be restored by ‘magit-mode-bury-buffer’. - - The buffer is displayed and selected using SWITCH-FUNCTION. If that - is ‘nil’ then ‘pop-to-buffer’ is used if the current buffer’s major - mode derives from ‘magit-mode’. Otherwise ‘switch-to-buffer’ is - used. - - -- Variable: magit-refresh-function - - The value of this buffer-local variable is the function used to - refresh the current buffer. It is called with ‘magit-refresh-args’ - as arguments. - - -- Variable: magit-refresh-args - - The list of arguments used by ‘magit-refresh-function’ to refresh - the current buffer. ‘magit-refresh-function’ is called with these - arguments. - - The value is usually set using ‘magit-mode-setup’, but in some - cases it’s also useful to provide commands which can change the - value. For example, the ‘magit-diff-refresh-popup’ can be used to - change any of the arguments used to display the diff, without - having to specify again which differences should be shown. - ‘magit-diff-more-context’, ‘magit-diff-less-context’, and - ‘magit-diff-default-context’ change just the ‘-U’ argument. In - both case this is done by changing the value of this variable and - then calling this ‘magit-refresh-function’. - - -File: magit.info, Node: Conventions, Prev: Refreshing buffers, Up: Plumbing - -10.4 Conventions -================ - -* Menu: - -* Confirmation and completion:: -* Theming Faces:: - - -File: magit.info, Node: Confirmation and completion, Next: Theming Faces, Up: Conventions - -10.4.1 Confirmation and completion ----------------------------------- - -Dangerous operations that may lead to data loss have to be confirmed by -default. With a multi-section selection, this is done using questions -that can be answered with "yes" or "no". When the region isn’t active, -or if it doesn’t constitute a valid section selection, then such -commands instead read a single item in the minibuffer. When the value -of the current section is among the possible choices, then that is -presented as default choice. To confirm the action on a single item, -the user has to answer ‘RET’ (instead of "yes"), and to abort, ‘C-g’ -(instead of "no"). But alternatively the user may also select another -item, just like if the command had been invoked with no suitable section -at point at all. - - -File: magit.info, Node: Theming Faces, Prev: Confirmation and completion, Up: Conventions - -10.4.2 Theming Faces --------------------- - -The default theme uses blue for local branches, green for remote -branches, and goldenrod (brownish yellow) for tags. When creating a new -theme, you should probably follow that example. If your theme already -uses other colors, then stick to that. - - In older releases these reference faces used to have a background -color and a box around them. The basic default faces no longer do so, -to make Magit buffers much less noisy, and you should follow that -example at least with regards to boxes. (Boxes were used in the past to -work around a conflict between the highlighting overlay and text -property backgrounds. That’s no longer necessary because highlighting -no longer causes other background colors to disappear.) Alternatively -you can keep the background color and/or box, but then have to take -special care to adjust ‘magit-branch-current’ accordingly. By default -it looks mostly like ‘magit-branch-local’, but with a box (by default -the former is the only face that uses a box, exactly so that it sticks -out). If the former also uses a box, then you have to make sure that it -differs in some other way from the latter. - - The most difficult faces to theme are those related to diffs, -headings, highlighting, and the region. There are faces that fall into -all four groups - expect to spend some time getting this right. - - The ‘region’ face in the default theme, in both the light and dark -variants, as well as in many other themes, distributed with Emacs or by -third-parties, is very ugly. It is common to use a background color -that really sticks out, which is ugly but if that were the only problem -then it would be acceptable. Unfortunately many themes also set the -foreground color, which ensures that all text within the region is -readable. Without doing that there might be cases where some foreground -color is too close to the region background color to still be readable. -But it also means that text within the region loses all syntax -highlighting. - - I consider the work that went into getting the ‘region’ face right to -be a good indicator for the general quality of a theme. My -recommendation for the ‘region’ face is this: use a background color -slightly different from the background color of the ‘default’ face, and -do not set the foreground color at all. So for a light theme you might -use a light (possibly tinted) gray as the background color of ‘default’ -and a somewhat darker gray for the background of ‘region’. That should -usually be enough to not collide with the foreground color of any other -face. But if some other faces also set a light gray as background -color, then you should also make sure it doesn’t collide with those (in -some cases it might be acceptable though). - - Magit only uses the ‘region’ face when the region is "invalid" by its -own definition. In a Magit buffer the region is used to either select -multiple sibling sections, so that commands which support it act on all -of these sections instead of just the current section, or to select -lines within a single hunk section. In all other cases, the section is -considered invalid and Magit won’t act on it. But such invalid sections -happen, either because the user has not moved point enough yet to make -it valid or because she wants to use a non-magit command to act on the -region, e.g. ‘kill-region’. - - So using the regular ‘region’ face for invalid sections is a feature. -It tells the user that Magit won’t be able to act on it. It’s -acceptable if that face looks a bit odd and even (but less so) if it -collides with the background colors of section headings and other things -that have a background color. - - Magit highlights the current section. If a section has subsections, -then all of them are highlighted. This is done using faces that have -"highlight" in their names. For most sections, -‘magit-section-highlight’ is used for both the body and the heading. -Like the ‘region’ face, it should only set the background color to -something similar to that of ‘default’. The highlight background color -must be different from both the ‘region’ background color and the -‘default’ background color. - - For diff related sections Magit uses various faces to highlight -different parts of the selected section(s). Note that hunk headings, -unlike all other section headings, by default have a background color, -because it is useful to have very visible separators between hunks. -That face ‘magit-diff-hunk-heading’, should be different from both -‘magit-diff-hunk-heading-highlight’ and ‘magit-section-highlight’, as -well as from ‘magit-diff-context’ and ‘magit-diff-context-highlight’. -By default we do that by changing the foreground color. Changing the -background color would lead to complications, and there are already -enough we cannot get around. (Also note that it is generally a good -idea for section headings to always be bold, but only for sections that -have subsections). - - When there is a valid region selecting diff-related sibling sections, -i.e. multiple files or hunks, then the bodies of all these sections use -the respective highlight faces, but additionally the headings instead -use one of the faces ‘magit-diff-file-heading-selection’ or -‘magit-diff-hunk-heading-selection’. These faces have to be different -from the regular highlight variants to provide explicit visual -indication that the region is active. - - When theming diff related faces, start by setting the option -‘magit-diff-refine-hunk’ to ‘all’. You might personally prefer to only -refine the current hunk or not use hunk refinement at all, but some of -the users of your theme want all hunks to be refined, so you have to -cater to that. - - (Also turn on ‘magit-diff-highlight-indentation’, -‘magit-diff-highlight-trailing’, and ‘magit-diff-paint-whitespace’; and -insert some whitespace errors into the code you use for testing.) - - For e.g. "added lines" you have to adjust three faces: -‘magit-diff-added’, ‘magit-diff-added-highlight’, and -‘smerge-refined-added’. Make sure that the latter works well with both -of the former, as well as ‘smerge-other’ and ‘diff-added’. Then do the -same for the removed lines, context lines, lines added by us, and lines -added by them. Also make sure the respective added, removed, and -context faces use approximately the same saturation for both the -highlighted and unhighlighted variants. Also make sure the file and -diff headings work nicely with context lines (e.g. make them look -different). Line faces should set both the foreground and the -background color. For example, for added lines use two different -greens. - - It’s best if the foreground color of both the highlighted and the -unhighlighted variants are the same, so you will need to have to find a -color that works well on the highlight and unhighlighted background, the -refine background, and the highlight context background. When there is -an hunk internal region, then the added- and removed-lines background -color is used only within that region. Outside the region the -highlighted context background color is used. This makes it easier to -see what is being staged. With an hunk internal region the hunk heading -is shown using ‘magit-diff-hunk-heading-selection’, and so are the thin -lines that are added around the lines that fall within the region. The -background color of that has to be distinct enough from the various -other involved background colors. - - Nobody said this would be easy. If your theme restricts itself to a -certain set of colors, then you should make an exception here. -Otherwise it would be impossible to make the diffs look good in each and -every variation. Actually you might want to just stick to the default -definitions for these faces. You have been warned. Also please note -that if you do not get this right, this will in some cases look to users -like bugs in Magit - so please do it right or not at all. - - -File: magit.info, Node: FAQ, Next: Keystroke Index, Prev: Plumbing, Up: Top - -Appendix A FAQ -************** - -Below you find a list of frequently asked questions. For a list of -frequently *and recently* asked questions, i.e. questions that haven’t -made it into the manual yet, see -. - -* Menu: - -* Magit is slow:: -* I changed several thousand files at once and now Magit is unusable:: -* I am having problems committing:: -* I don't like how branching and pushing works:: -* I cannot install the pre-requisits for Magit v2:: -* I am using an Emacs release older than v24.4: I am using an Emacs release older than v244. -* I am using a Git release older than v1.9.4: I am using a Git release older than v194. -* I am using MS Windows and cannot push with Magit:: -* How to install the gitman info manual?:: -* How can I show Git's output?:: -* Expanding a file to show the diff causes it to disappear:: -* Point is wrong in the COMMIT_EDITMSG buffer:: -* Can Magit be used as ediff-version-control-package?:: -* How to show diffs for gpg-encrypted files?:: -* Emacs 24.5 hangs when loading Magit: Emacs 245 hangs when loading Magit. - - -File: magit.info, Node: Magit is slow, Next: I changed several thousand files at once and now Magit is unusable, Up: FAQ - -A.1 Magit is slow -================= - -See *note Performance: Performance. - - -File: magit.info, Node: I changed several thousand files at once and now Magit is unusable, Next: I am having problems committing, Prev: Magit is slow, Up: FAQ - -A.2 I changed several thousand files at once and now Magit is unusable -====================================================================== - -Magit is *currently* not expected to work under such conditions. It -sure would be nice if it did, and v2.5 will hopefully be a big step into -that direction. But it might take until v3.1 to accomplish fully -satisfactory performance, because that requires some heavy refactoring. - - But for now we recommend you use the command line to complete this -one commit. Also see *note Performance: Performance. - - -File: magit.info, Node: I am having problems committing, Next: I don't like how branching and pushing works, Prev: I changed several thousand files at once and now Magit is unusable, Up: FAQ - -A.3 I am having problems committing -=================================== - -That likely means that Magit is having problems finding an appropriate -emacsclient executable. See *note (with-editor)Configuring -With-Editor:: and *note (with-editor)Debugging::. - - -File: magit.info, Node: I don't like how branching and pushing works, Next: I cannot install the pre-requisits for Magit v2, Prev: I am having problems committing, Up: FAQ - -A.4 I don’t like how branching and pushing works -================================================ - -In v2.1 the default behavior of the branch and push commands changed, -which has taken a few users by surprise and left more unsatisfied. The -next release, v2.4, will try to address these concerns. - - -File: magit.info, Node: I cannot install the pre-requisits for Magit v2, Next: I am using an Emacs release older than v244, Prev: I don't like how branching and pushing works, Up: FAQ - -A.5 I cannot install the pre-requisits for Magit v2 -=================================================== - -An Elpa archive featuring obsolete Magit v1.4.2 and its dependencies is -available from . But note that v1.4.2 is -obsolete and no longer maintained. - - -File: magit.info, Node: I am using an Emacs release older than v244, Next: I am using a Git release older than v194, Prev: I cannot install the pre-requisits for Magit v2, Up: FAQ - -A.6 I am using an Emacs release older than v24.4 -================================================ - -At least Emacs v24.4 is required. There is no way around it, if you -want to use Magit v2. - - If you own the machine you work on, then consider updating to the -latest release provided by your distribution. If it doesn’t feature a -recent enough release, then you will have to use a backport package or -build Emacs from source. - - Installing Emacs from source is quite simple. See the instructions -at and - to get an -idea of that this involves. But when you perform the installation then -use the instructions for the release you are actually installing. - - Unfortunately these instructions do not cover the hardest part (which -is the hardest part exactly because it is not covered there): installing -the build time dependencies. - - For that you’ll need to perform a web search and find an appropriate -tutorial for your distribution. If you think you should not have had to -do that yourself, then consider informing me about the resources that -helped you figure what to do for your specific setup, so that I can post -a link here. That way those coming after you have it easier. - - An Elpa archive featuring obsolete Magit v1.4.2 and its dependencies -is available from . - - -File: magit.info, Node: I am using a Git release older than v194, Next: I am using MS Windows and cannot push with Magit, Prev: I am using an Emacs release older than v244, Up: FAQ - -A.7 I am using a Git release older than v1.9.4 -============================================== - -At least Git v1.9.4 is required. There is no way around it, if you want -to use Magit v2. - - If you own the machine, then consider updating to the latest release -provided by your distribution. If it doesn’t feature a recent enough -release, then you will have to use a backport package or build Git from -source. - - Installing Git from source is quite simple. See the instructions at - to get an idea of that -this involves. But when you perform the installation then use the -instructions for the release you are actually installing. - - An Elpa archive featuring obsolete Magit v1.4.2 and its dependencies -is available from . - - -File: magit.info, Node: I am using MS Windows and cannot push with Magit, Next: How to install the gitman info manual?, Prev: I am using a Git release older than v194, Up: FAQ - -A.8 I am using MS Windows and cannot push with Magit -==================================================== - -It’s almost certain that Magit is only incidental to this issue. It is -much more likely that this is a configuration issue, even if you can -push on the command line. - - Detailed setup instructions can be found at -. - - -File: magit.info, Node: How to install the gitman info manual?, Next: How can I show Git's output?, Prev: I am using MS Windows and cannot push with Magit, Up: FAQ - -A.9 How to install the gitman info manual? -========================================== - -Git’s manpages can be exported as an info manual called ‘gitman’. -Magit’s own info manual links to nodes in that manual instead of the -actual manpages because texinfo sadly doesn’t support linking to -manpages. - - Unfortunately many distributions do not install the ‘gitman’ manual -by default. Some distributions may provide a separate package -containing the info manual. Please let me know the name of that package -for your distribution, so that I can mention here. - - If the distribution you are using does not offer a package that -contains the ‘gitman’ manual, then you have to install it manually. -Clone Git’s own Git repository, checkout the tag corresponding to the -Git release you have installed, and follow the instructions in -‘INSTALL’. The relevant make targets are ‘info’ and ‘install-info’. - - Alternatively you may add this advice to your ‘init.el’ file. - - (defadvice Info-follow-nearest-node (around gitman activate) - "When encountering a cross reference to the `gitman' info - manual, then instead of following that cross reference show - the actual manpage using the function `man'." - (let ((node (Info-get-token - (point) "\\*note[ \n\t]+" - "\\*note[ \n\t]+\\([^:]*\\):\\(:\\|[ \n\t]*(\\)?"))) - (if (and node (string-match "^(gitman)\\(.+\\)" node)) - (progn (require 'man) - (man (match-string 1 node))) - ad-do-it))) - - Or if you are using MS Windows and ‘man’ is not available, use this -variation with used the Emacs Lisp implementation provided by the -‘woman’ package. - - (defadvice Info-follow-nearest-node (around gitman activate) - "When encountering a cross reference to the `gitman' info - manual, then instead of following that cross reference show - the actual manpage using the function `woman'." - (let ((node (Info-get-token - (point) "\\*note[ \n\t]+" - "\\*note[ \n\t]+\\([^:]*\\):\\(:\\|[ \n\t]*(\\)?"))) - (if (and node (string-match "^(gitman)\\(.+\\)" node)) - (progn (require 'woman) - (woman (match-string 1 node))) - ad-do-it))) - - Did I mention that texinfo cross reference are just awful? (This is -just one of many issues.) - - -File: magit.info, Node: How can I show Git's output?, Next: Expanding a file to show the diff causes it to disappear, Prev: How to install the gitman info manual?, Up: FAQ - -A.10 How can I show Git’s output? -================================= - -To show the output of recently run git commands, press ‘$’ (or, if that -isn’t available, ‘M-x magit-process-buffer’). This will show a buffer -containing a section per git invocation; as always press ‘TAB’ to expand -or collapse them. - - By default git’s output is only inserted into the process buffer if -it is run for side-effects. When the output is consumed in some way -then also inserting it into the process buffer would be to expensive. -For debugging purposes it’s possible to do so anyway by setting -‘magit-git-debug’ to ‘t’. - - -File: magit.info, Node: Expanding a file to show the diff causes it to disappear, Next: Point is wrong in the COMMIT_EDITMSG buffer, Prev: How can I show Git's output?, Up: FAQ - -A.11 Expanding a file to show the diff causes it to disappear -============================================================= - -This is probably caused by a change of a ‘diff.*’ Git variable. You -probably set that variable for a reason, and should therefore only undo -that setting in Magit by customizing ‘magit-git-global-arguments’. - - -File: magit.info, Node: Point is wrong in the COMMIT_EDITMSG buffer, Next: Can Magit be used as ediff-version-control-package?, Prev: Expanding a file to show the diff causes it to disappear, Up: FAQ - -A.12 Point is wrong in the COMMIT_EDITMSG buffer -================================================ - -Neither Magit nor ‘git-commit‘ fiddle with point in the buffer used to -write commit messages, so something else must be doing it. - - You have probably globally enabled a mode which does restore point in -file-visiting buffers. It might be a bit surprising, but when you write -a commit message, then you are actually editing a file. - - So you have to figure out which package is doing. ‘saveplace’, -‘pointback’, and ‘session’ are likely candidates. These snippets might -help: - - (setq session-name-disable-regexp "\\(?:\\`'\\.git/[A-Z_]+\\'\\)") - - (with-eval-after-load 'pointback - (lambda () - (when (or git-commit-mode git-rebase-mode) - (pointback-mode -1)))) - - -File: magit.info, Node: Can Magit be used as ediff-version-control-package?, Next: How to show diffs for gpg-encrypted files?, Prev: Point is wrong in the COMMIT_EDITMSG buffer, Up: FAQ - -A.13 Can Magit be used as ediff-version-control-package? -======================================================== - -No, it cannot. For that to work the functions ‘ediff-magit-internal’ -and ‘ediff-magit-merge-internal’ would have to be implemented, and they -are not. These two functions are only used by the three commands -‘ediff-revision’, ‘ediff-merge-revisions-with-ancestor’, and -‘ediff-merge-revisions’. - - These commands only delegate the task of populating buffers with -certain revisions to the "internal" functions. The equally important -task of determining which revisions are to be compared/merged is not -delegated. Instead this is done without any support whatsoever, from -the version control package/system - meaning that the user has to enter -the revisions explicitly. Instead of implementing -‘ediff-magit-internal’ we provide ‘magit-ediff-compare’, which handles -both tasks like it is 2005. - - The other commands ‘ediff-merge-revisions’ and -‘ediff-merge-revisions-with-ancestor’ are normally not what you want -when using a modern version control system like Git. Instead of letting -the user resolve only those conflicts which Git could not resolve on its -own, they throw away all work done by Git and then expect the user to -manually merge all conflicts, including those that had already been -resolved. That made sense back in the days when version control systems -couldn’t merge (or so I have been told), but not anymore. Once in a -blue moon you might actually want to see all conflicts, in which case -you *can* use these commands, which then use ‘ediff-vc-merge-internal’. -So we don’t actually have to implement ‘ediff-magit-merge-internal’. -Instead we provide the more useful command ‘magit-ediff-resolve’ which -only shows yet-to-be resolved conflicts. - - -File: magit.info, Node: How to show diffs for gpg-encrypted files?, Next: Emacs 245 hangs when loading Magit, Prev: Can Magit be used as ediff-version-control-package?, Up: FAQ - -A.14 How to show diffs for gpg-encrypted files? -=============================================== - -Git supports showing diffs for encrypted files, but has to be told to do -so. Since Magit just uses Git to get the diffs, configuring Git also -affects the diffs displayed inside Magit. - - git config --global diff.gpg.textconv "gpg --no-tty --decrypt" - echo "*.gpg filter=gpg diff=gpg" > .gitattributes - - -File: magit.info, Node: Emacs 245 hangs when loading Magit, Prev: How to show diffs for gpg-encrypted files?, Up: FAQ - -A.15 Emacs 24.5 hangs when loading Magit -======================================== - -This is actually triggered by loading Tramp. See - for details. You -can work around the problem by setting -‘tramp-ssh-controlmaster-options’. Changing your DNS server (e.g. to -Google’s ‘8.8.8.8’) may also be sufficient to work around the issue. - - -File: magit.info, Node: Keystroke Index, Next: Command Index, Prev: FAQ, Up: Top - -Appendix B Keystroke Index -************************** - -[index] -* Menu: - -* !: Running Git manually. - (line 12) -* ! !: Running Git manually. - (line 19) -* ! a: Running Git manually. - (line 51) -* ! b: Running Git manually. - (line 55) -* ! g: Running Git manually. - (line 59) -* ! k: Running Git manually. - (line 47) -* ! p: Running Git manually. - (line 24) -* ! s: Running Git manually. - (line 33) -* ! S: Running Git manually. - (line 38) -* $: Viewing Git output. (line 11) -* +: Log Buffer. (line 53) -* + <1>: Refreshing diffs. (line 58) -* -: Refreshing diffs. (line 54) -* 0: Refreshing diffs. (line 62) -* 1: Section visibility. (line 26) -* 2: Section visibility. (line 26) -* 3: Section visibility. (line 26) -* 4: Section visibility. (line 26) -* =: Log Buffer. (line 47) -* = <1>: Log Buffer. (line 57) -* ^: Section movement. (line 31) -* a: Applying. (line 33) -* A: Cherry picking. (line 8) -* A A: Cherry picking. (line 16) -* A a: Cherry picking. (line 22) -* A A <1>: Cherry picking. (line 35) -* A a <1>: Cherry picking. (line 43) -* A s: Cherry picking. (line 39) -* B: Bisecting. (line 8) -* b: Branching. (line 8) -* B b: Bisecting. (line 31) -* b b: Branching. (line 13) -* b B: Branching. (line 29) -* b c: Branching. (line 21) -* b d: Branching. (line 61) -* b e: Branching. (line 83) -* B g: Bisecting. (line 36) -* B k: Bisecting. (line 41) -* B r: Bisecting. (line 47) -* b r: Branching. (line 77) -* B s: Bisecting. (line 16) -* b s: Branching. (line 34) -* B u: Bisecting. (line 24) -* b u: Branching. (line 67) -* b U: Branching. (line 72) -* b x: Branching. (line 45) -* c: Initiating a commit. (line 8) -* c <1>: Editing rebase sequences. - (line 72) -* c a: Initiating a commit. (line 18) -* c A: Initiating a commit. (line 66) -* c c: Initiating a commit. (line 13) -* c e: Initiating a commit. (line 22) -* c f: Initiating a commit. (line 42) -* c F: Initiating a commit. (line 50) -* c s: Initiating a commit. (line 54) -* c S: Initiating a commit. (line 62) -* c w: Initiating a commit. (line 32) -* C-: Diff buffer. (line 21) -* C-: Section visibility. (line 13) -* C-c C-a: Editing commit messages. - (line 128) -* C-c C-b: Log Buffer. (line 19) -* C-c C-b <1>: Refreshing diffs. (line 80) -* C-c C-c: Popup buffers and prefix commands. - (line 20) -* C-c C-c <1>: Select from log. (line 14) -* C-c C-c <2>: Editing commit messages. - (line 19) -* C-c C-c <3>: Editing rebase sequences. - (line 6) -* C-c C-d: Refreshing diffs. (line 70) -* C-c C-d <1>: Editing commit messages. - (line 57) -* C-c C-f: Log Buffer. (line 23) -* C-c C-f <1>: Refreshing diffs. (line 84) -* C-c C-i: Editing commit messages. - (line 153) -* C-c C-k: Select from log. (line 20) -* C-c C-k <1>: Editing commit messages. - (line 24) -* C-c C-k <2>: Editing rebase sequences. - (line 11) -* C-c C-o: Editing commit messages. - (line 144) -* C-c C-p: Editing commit messages. - (line 148) -* C-c C-r: Editing commit messages. - (line 132) -* C-c C-s: Editing commit messages. - (line 136) -* C-c C-t: Editing commit messages. - (line 140) -* C-c C-w: Editing commit messages. - (line 63) -* C-c M-g: Minor mode for buffers visiting files. - (line 19) -* C-c M-g b: Minor mode for buffers visiting files. - (line 39) -* C-c M-g c: Minor mode for buffers visiting files. - (line 49) -* C-c M-g l: Minor mode for buffers visiting files. - (line 33) -* C-c M-g p: Minor mode for buffers visiting files. - (line 45) -* C-c M-g s: Minor mode for buffers visiting files. - (line 24) -* C-c M-g u: Minor mode for buffers visiting files. - (line 28) -* C-s M-s: Editing commit messages. - (line 35) -* C-w: Common commands. (line 21) -* C-x g: Status buffer. (line 22) -* C-x u: Editing rebase sequences. - (line 89) -* d: Diffing. (line 20) -* D: Refreshing diffs. (line 11) -* d c: Diffing. (line 75) -* d d: Diffing. (line 25) -* D f: Refreshing diffs. (line 45) -* D g: Refreshing diffs. (line 16) -* d p: Diffing. (line 59) -* d r: Diffing. (line 29) -* D r: Refreshing diffs. (line 40) -* d s: Diffing. (line 49) -* D s: Refreshing diffs. (line 21) -* d t: Diffing. (line 80) -* D t: Refreshing diffs. (line 36) -* d u: Diffing. (line 55) -* d w: Diffing. (line 43) -* D w: Refreshing diffs. (line 28) -* DEL: Log Buffer. (line 37) -* DEL <1>: Diff buffer. (line 48) -* DEL <2>: Blaming. (line 44) -* DEL <3>: Editing rebase sequences. - (line 28) -* e: Ediffing. (line 6) -* E: Ediffing. (line 18) -* e <1>: Editing rebase sequences. - (line 55) -* E c: Ediffing. (line 62) -* E i: Ediffing. (line 54) -* E m: Ediffing. (line 32) -* E r: Ediffing. (line 23) -* E s: Ediffing. (line 45) -* E u: Ediffing. (line 50) -* E w: Ediffing. (line 58) -* f: Editing rebase sequences. - (line 63) -* f <1>: Fetching. (line 8) -* F: Pulling. (line 8) -* f a: Fetching. (line 23) -* f f: Fetching. (line 13) -* F F: Pulling. (line 13) -* f m: Fetching. (line 27) -* f o: Fetching. (line 19) -* F o: Pulling. (line 17) -* g: Automatic refresh and revert. - (line 66) -* G: Automatic refresh and revert. - (line 75) -* j: Diff buffer. (line 38) -* k: Viewing Git output. (line 19) -* k <1>: Applying. (line 37) -* k <2>: Editing rebase sequences. - (line 68) -* k <3>: Stashing. (line 92) -* l: Logging. (line 24) -* L: Refreshing logs. (line 11) -* L <1>: Log Buffer. (line 6) -* l a: Logging. (line 54) -* l b: Logging. (line 50) -* L g: Refreshing logs. (line 16) -* l h: Logging. (line 42) -* l H: Reflog. (line 19) -* l l: Logging. (line 29) -* l L: Logging. (line 46) -* l o: Logging. (line 35) -* l O: Reflog. (line 15) -* l r: Reflog. (line 11) -* L s: Refreshing logs. (line 21) -* L t: Refreshing logs. (line 36) -* L w: Refreshing logs. (line 28) -* m: Merging. (line 8) -* M: Remotes. (line 8) -* m a: Merging. (line 56) -* M a: Remotes. (line 13) -* m e: Merging. (line 29) -* M k: Remotes. (line 28) -* m m: Merging. (line 16) -* m m <1>: Merging. (line 51) -* m n: Merging. (line 36) -* m p: Merging. (line 43) -* M r: Remotes. (line 18) -* M u: Remotes. (line 23) -* M-1: Section visibility. (line 34) -* M-2: Section visibility. (line 34) -* M-3: Section visibility. (line 34) -* M-4: Section visibility. (line 34) -* M-: Section visibility. (line 17) -* M-n: Section movement. (line 26) -* M-n <1>: Editing commit messages. - (line 45) -* M-n <2>: Editing rebase sequences. - (line 47) -* M-p: Section movement. (line 20) -* M-p <1>: Editing commit messages. - (line 39) -* M-p <2>: Editing rebase sequences. - (line 43) -* M-w: Blaming. (line 75) -* M-w <1>: Common commands. (line 10) -* M-x magit-blame: Blaming. (line 8) -* M-x magit-blame-popup: Blaming. (line 24) -* M-x magit-checkout-file: Resetting. (line 37) -* M-x magit-clone: Repository setup. (line 16) -* M-x magit-describe-section: Section types and values. - (line 13) -* M-x magit-describe-section <1>: Matching sections. (line 6) -* M-x magit-diff-unpulled: Diffing. (line 67) -* M-x magit-diff-unpushed: Diffing. (line 63) -* M-x magit-find-file: Visiting blobs. (line 6) -* M-x magit-find-file-other-window: Visiting blobs. (line 11) -* M-x magit-init: Repository setup. (line 6) -* M-x magit-log-buffer-file: Logging. (line 65) -* M-x magit-reset-hard: Resetting. (line 32) -* M-x magit-reset-head: Resetting. (line 21) -* M-x magit-reset-index: Staging and unstaging. - (line 45) -* M-x magit-reset-index <1>: Resetting. (line 14) -* M-x magit-reset-soft: Resetting. (line 26) -* M-x magit-stage-file: Staging from file-visiting buffers. - (line 10) -* M-x magit-toggle-buffer-lock: Modes and Buffers. (line 17) -* M-x magit-unstage-file: Staging from file-visiting buffers. - (line 18) -* M-x magit-version: Git executable. (line 17) -* M-x magit-wip-commit: Wip modes. (line 129) -* n: Section movement. (line 16) -* n <1>: Blaming. (line 54) -* N: Blaming. (line 58) -* n <2>: Editing rebase sequences. - (line 39) -* n <3>: Minor mode for buffers visiting blobs. - (line 16) -* o: Submodules. (line 8) -* o a: Submodules. (line 13) -* o b: Submodules. (line 19) -* o f: Submodules. (line 37) -* o i: Submodules. (line 24) -* o i <1>: Submodules. (line 41) -* o s: Submodules. (line 33) -* o u: Submodules. (line 28) -* p: Section movement. (line 10) -* p <1>: Blaming. (line 62) -* P: Blaming. (line 66) -* p <2>: Editing rebase sequences. - (line 35) -* P <1>: Pushing. (line 8) -* p <3>: Minor mode for buffers visiting blobs. - (line 12) -* P e: Pushing. (line 23) -* P i: Pushing. (line 36) -* P m: Pushing. (line 45) -* P o: Pushing. (line 18) -* P P: Pushing. (line 13) -* P Q: Pushing. (line 28) -* P t: Pushing. (line 51) -* P T: Pushing. (line 57) -* q: Quitting Windows. (line 6) -* q <1>: Log Buffer. (line 12) -* q <2>: Blaming. (line 70) -* q <3>: Minor mode for buffers visiting blobs. - (line 20) -* r: Rebasing. (line 8) -* r <1>: Editing rebase sequences. - (line 51) -* r a: Rebasing. (line 83) -* r e: Rebasing. (line 60) -* r e <1>: Rebasing. (line 79) -* r f: Rebasing. (line 56) -* r i: Rebasing. (line 43) -* r l: Rebasing. (line 47) -* r o: Rebasing. (line 21) -* r r: Rebasing. (line 16) -* r r <1>: Rebasing. (line 71) -* r s: Rebasing. (line 75) -* r w: Rebasing. (line 64) -* RET: Diff buffer. (line 6) -* RET <1>: References buffer. (line 99) -* RET <2>: Blaming. (line 29) -* RET <3>: Editing rebase sequences. - (line 16) -* s: Staging and unstaging. - (line 26) -* S: Staging and unstaging. - (line 30) -* s <1>: Editing rebase sequences. - (line 59) -* s-: Section visibility. (line 22) -* SPC: Log Buffer. (line 27) -* SPC <1>: Diff buffer. (line 44) -* SPC <2>: Blaming. (line 34) -* SPC <3>: Editing rebase sequences. - (line 21) -* t: Blaming. (line 79) -* t <1>: Tagging. (line 8) -* T: Notes. (line 8) -* T a: Notes. (line 70) -* T c: Notes. (line 65) -* t k: Tagging. (line 18) -* T m: Notes. (line 56) -* t p: Tagging. (line 24) -* T p: Notes. (line 29) -* T r: Notes. (line 21) -* T s: Notes. (line 33) -* T S: Notes. (line 44) -* t t: Tagging. (line 13) -* T T: Notes. (line 13) -* TAB: Section visibility. (line 9) -* u: Staging and unstaging. - (line 37) -* U: Staging and unstaging. - (line 41) -* v: Applying. (line 41) -* V: Reverting. (line 6) -* V A: Reverting. (line 30) -* V a: Reverting. (line 38) -* V s: Reverting. (line 34) -* V V: Reverting. (line 14) -* V v: Reverting. (line 20) -* W: Creating and sending patches. - (line 6) -* w: Applying patches. (line 8) -* w a: Applying patches. (line 31) -* w m: Applying patches. (line 19) -* W p: Creating and sending patches. - (line 11) -* W r: Creating and sending patches. - (line 17) -* w s: Applying patches. (line 27) -* w w: Applying patches. (line 13) -* w w <1>: Applying patches. (line 23) -* x: Editing rebase sequences. - (line 76) -* x <1>: Resetting. (line 8) -* Y: Logging. (line 60) -* y: References buffer. (line 6) -* y <1>: Editing rebase sequences. - (line 85) -* y c: References buffer. (line 19) -* y o: References buffer. (line 24) -* y y: References buffer. (line 14) -* z: Stashing. (line 8) -* z a: Stashing. (line 58) -* z b: Stashing. (line 84) -* z d: Stashing. (line 71) -* z f: Stashing. (line 88) -* z i: Stashing. (line 20) -* z I: Stashing. (line 46) -* z l: Stashing. (line 76) -* z p: Stashing. (line 64) -* z v: Stashing. (line 80) -* z w: Stashing. (line 25) -* z W: Stashing. (line 51) -* z x: Stashing. (line 32) -* z z: Stashing. (line 13) -* z Z: Stashing. (line 39) - - -File: magit.info, Node: Command Index, Next: Function Index, Prev: Keystroke Index, Up: Top - -Appendix C Command Index -************************ - -[index] -* Menu: - -* forward-line: Editing rebase sequences. - (line 39) -* git-commit-ack: Editing commit messages. - (line 128) -* git-commit-cc: Editing commit messages. - (line 144) -* git-commit-next-message: Editing commit messages. - (line 45) -* git-commit-prev-message: Editing commit messages. - (line 39) -* git-commit-reported: Editing commit messages. - (line 148) -* git-commit-review: Editing commit messages. - (line 132) -* git-commit-save-message: Editing commit messages. - (line 35) -* git-commit-signoff: Editing commit messages. - (line 136) -* git-commit-suggested: Editing commit messages. - (line 153) -* git-commit-test: Editing commit messages. - (line 140) -* git-rebase-backward-line: Editing rebase sequences. - (line 35) -* git-rebase-edit: Editing rebase sequences. - (line 55) -* git-rebase-exec: Editing rebase sequences. - (line 76) -* git-rebase-fixup: Editing rebase sequences. - (line 63) -* git-rebase-insert: Editing rebase sequences. - (line 85) -* git-rebase-kill-line: Editing rebase sequences. - (line 68) -* git-rebase-move-line-down: Editing rebase sequences. - (line 47) -* git-rebase-move-line-up: Editing rebase sequences. - (line 43) -* git-rebase-pick: Editing rebase sequences. - (line 72) -* git-rebase-reword: Editing rebase sequences. - (line 51) -* git-rebase-show-commit: Editing rebase sequences. - (line 16) -* git-rebase-squash: Editing rebase sequences. - (line 59) -* git-rebase-undo: Editing rebase sequences. - (line 89) -* ido-enter-magit-status: Status buffer. (line 42) -* magit-am-abort: Applying patches. (line 31) -* magit-am-apply-maildir: Applying patches. (line 19) -* magit-am-apply-patches: Applying patches. (line 13) -* magit-am-continue: Applying patches. (line 23) -* magit-am-popup: Applying patches. (line 8) -* magit-am-skip: Applying patches. (line 27) -* magit-apply: Applying. (line 33) -* magit-bisect-bad: Bisecting. (line 31) -* magit-bisect-good: Bisecting. (line 36) -* magit-bisect-popup: Bisecting. (line 8) -* magit-bisect-reset: Bisecting. (line 47) -* magit-bisect-run: Bisecting. (line 24) -* magit-bisect-skip: Bisecting. (line 41) -* magit-bisect-start: Bisecting. (line 16) -* magit-blame: Blaming. (line 8) -* magit-blame-copy-hash: Blaming. (line 75) -* magit-blame-next-chunk: Blaming. (line 54) -* magit-blame-next-chunk-same-commit: Blaming. (line 58) -* magit-blame-popup: Blaming. (line 24) -* magit-blame-popup <1>: Minor mode for buffers visiting files. - (line 39) -* magit-blame-previous-chunk: Blaming. (line 62) -* magit-blame-previous-chunk-same-commit: Blaming. (line 66) -* magit-blame-quit: Blaming. (line 70) -* magit-blame-toggle-headings: Blaming. (line 79) -* magit-blob-next: Minor mode for buffers visiting blobs. - (line 16) -* magit-blob-previous: Minor mode for buffers visiting files. - (line 45) -* magit-blob-previous <1>: Minor mode for buffers visiting blobs. - (line 12) -* magit-branch: Branching. (line 21) -* magit-branch-and-checkout: Branching. (line 29) -* magit-branch-delete: Branching. (line 61) -* magit-branch-edit-description: Branching. (line 83) -* magit-branch-popup: Branching. (line 8) -* magit-branch-rename: Branching. (line 77) -* magit-branch-reset: Branching. (line 45) -* magit-branch-set-upstream: Branching. (line 67) -* magit-branch-spinoff: Branching. (line 34) -* magit-branch-unset-upstream: Branching. (line 72) -* magit-checkout: Branching. (line 13) -* magit-checkout-file: Resetting. (line 37) -* magit-cherry: Logging. (line 60) -* magit-cherry-apply: Cherry picking. (line 22) -* magit-cherry-pick: Cherry picking. (line 16) -* magit-cherry-pick-popup: Cherry picking. (line 8) -* magit-clone: Repository setup. (line 16) -* magit-commit: Initiating a commit. (line 13) -* magit-commit-amend: Initiating a commit. (line 18) -* magit-commit-augment: Initiating a commit. (line 66) -* magit-commit-extend: Initiating a commit. (line 22) -* magit-commit-fixup: Initiating a commit. (line 42) -* magit-commit-instant-fixup: Initiating a commit. (line 50) -* magit-commit-instant-squash: Initiating a commit. (line 62) -* magit-commit-popup: Initiating a commit. (line 8) -* magit-commit-popup <1>: Minor mode for buffers visiting files. - (line 49) -* magit-commit-reword: Initiating a commit. (line 32) -* magit-commit-squash: Initiating a commit. (line 54) -* magit-copy-buffer-revision: Common commands. (line 21) -* magit-copy-section-value: Common commands. (line 10) -* magit-describe-section: Section types and values. - (line 13) -* magit-describe-section <1>: Matching sections. (line 6) -* magit-diff: Diffing. (line 29) -* magit-diff-default-context: Refreshing diffs. (line 62) -* magit-diff-dwim: Diffing. (line 25) -* magit-diff-flip-revs: Refreshing diffs. (line 45) -* magit-diff-less-context: Refreshing diffs. (line 54) -* magit-diff-more-context: Refreshing diffs. (line 58) -* magit-diff-paths: Diffing. (line 59) -* magit-diff-popup: Diffing. (line 20) -* magit-diff-refresh: Refreshing diffs. (line 16) -* magit-diff-refresh-popup: Refreshing diffs. (line 11) -* magit-diff-save-default-arguments: Refreshing diffs. (line 28) -* magit-diff-set-default-arguments: Refreshing diffs. (line 21) -* magit-diff-show-or-scroll-down: Log Buffer. (line 37) -* magit-diff-show-or-scroll-down <1>: Blaming. (line 44) -* magit-diff-show-or-scroll-down <2>: Editing rebase sequences. - (line 28) -* magit-diff-show-or-scroll-up: Log Buffer. (line 27) -* magit-diff-show-or-scroll-up <1>: Blaming. (line 34) -* magit-diff-show-or-scroll-up <2>: Editing rebase sequences. - (line 21) -* magit-diff-staged: Diffing. (line 49) -* magit-diff-switch-range-type: Refreshing diffs. (line 40) -* magit-diff-toggle-refine-hunk: Refreshing diffs. (line 36) -* magit-diff-unpulled: Diffing. (line 67) -* magit-diff-unpushed: Diffing. (line 63) -* magit-diff-unstaged: Diffing. (line 55) -* magit-diff-visit-file: Diff buffer. (line 6) -* magit-diff-visit-file-worktree: Diff buffer. (line 21) -* magit-diff-while-committing: Refreshing diffs. (line 70) -* magit-diff-while-committing <1>: Editing commit messages. - (line 57) -* magit-diff-worktree: Diffing. (line 43) -* magit-discard: Applying. (line 37) -* magit-dispatch-popup: Popup buffers and prefix commands. - (line 20) -* magit-ediff-compare: Ediffing. (line 23) -* magit-ediff-dwim: Ediffing. (line 6) -* magit-ediff-popup: Ediffing. (line 18) -* magit-ediff-resolve: Ediffing. (line 32) -* magit-ediff-show-commit: Ediffing. (line 62) -* magit-ediff-show-staged: Ediffing. (line 54) -* magit-ediff-show-unstaged: Ediffing. (line 50) -* magit-ediff-show-working-tree: Ediffing. (line 58) -* magit-ediff-stage: Ediffing. (line 45) -* magit-fetch: Fetching. (line 19) -* magit-fetch-all: Fetching. (line 23) -* magit-fetch-current: Fetching. (line 13) -* magit-fetch-popup: Fetching. (line 8) -* magit-file-popup: Minor mode for buffers visiting files. - (line 19) -* magit-find-file: Visiting blobs. (line 6) -* magit-find-file-other-window: Visiting blobs. (line 11) -* magit-format-patch: Creating and sending patches. - (line 11) -* magit-git-command: Running Git manually. - (line 24) -* magit-git-command-topdir: Running Git manually. - (line 19) -* magit-go-backward: Log Buffer. (line 19) -* magit-go-backward <1>: Refreshing diffs. (line 80) -* magit-go-forward: Log Buffer. (line 23) -* magit-go-forward <1>: Refreshing diffs. (line 84) -* magit-init: Repository setup. (line 6) -* magit-jump-to-diffstat-or-diff: Diff buffer. (line 38) -* magit-kill-this-buffer: Minor mode for buffers visiting blobs. - (line 20) -* magit-log: Logging. (line 35) -* magit-log-all: Logging. (line 54) -* magit-log-all-branches: Logging. (line 50) -* magit-log-branches: Logging. (line 46) -* magit-log-buffer-file: Logging. (line 65) -* magit-log-buffer-file <1>: Minor mode for buffers visiting files. - (line 33) -* magit-log-bury-buffer: Log Buffer. (line 12) -* magit-log-current: Logging. (line 29) -* magit-log-double-commit-limit: Log Buffer. (line 53) -* magit-log-half-commit-limit: Log Buffer. (line 57) -* magit-log-head: Logging. (line 42) -* magit-log-popup: Logging. (line 24) -* magit-log-refresh: Refreshing logs. (line 16) -* magit-log-refresh-popup: Refreshing logs. (line 11) -* magit-log-refresh-popup <1>: Log Buffer. (line 6) -* magit-log-save-default-arguments: Refreshing logs. (line 28) -* magit-log-select-pick: Select from log. (line 14) -* magit-log-select-quit: Select from log. (line 20) -* magit-log-set-default-arguments: Refreshing logs. (line 21) -* magit-log-toggle-commit-limit: Log Buffer. (line 47) -* magit-merge: Merging. (line 16) -* magit-merge <1>: Merging. (line 51) -* magit-merge-abort: Merging. (line 56) -* magit-merge-editmsg: Merging. (line 29) -* magit-merge-nocommit: Merging. (line 36) -* magit-merge-popup: Merging. (line 8) -* magit-merge-preview: Merging. (line 43) -* magit-mode-bury-buffer: Quitting Windows. (line 6) -* magit-notes-edit: Notes. (line 13) -* magit-notes-merge: Notes. (line 56) -* magit-notes-merge-abort: Notes. (line 70) -* magit-notes-merge-commit: Notes. (line 65) -* magit-notes-popup: Notes. (line 8) -* magit-notes-prune: Notes. (line 29) -* magit-notes-remove: Notes. (line 21) -* magit-notes-set-display-refs: Notes. (line 44) -* magit-notes-set-ref: Notes. (line 33) -* magit-patch-popup: Creating and sending patches. - (line 6) -* magit-pop-revision-stack: Editing commit messages. - (line 63) -* magit-process: Viewing Git output. (line 11) -* magit-process-kill: Viewing Git output. (line 19) -* magit-pull: Pulling. (line 17) -* magit-pull-current: Pulling. (line 13) -* magit-pull-popup: Pulling. (line 8) -* magit-push: Pushing. (line 18) -* magit-push-current: Pushing. (line 13) -* magit-push-elsewhere: Pushing. (line 23) -* magit-push-implicitly: Pushing. (line 36) -* magit-push-matching: Pushing. (line 45) -* magit-push-popup: Pushing. (line 8) -* magit-push-quickly: Pushing. (line 28) -* magit-push-tag: Pushing. (line 57) -* magit-push-tags: Pushing. (line 51) -* magit-rebase: Rebasing. (line 16) -* magit-rebase-abort: Rebasing. (line 83) -* magit-rebase-autosquash: Rebasing. (line 56) -* magit-rebase-continue: Rebasing. (line 71) -* magit-rebase-edit: Rebasing. (line 79) -* magit-rebase-edit-commit: Rebasing. (line 60) -* magit-rebase-interactive: Rebasing. (line 43) -* magit-rebase-popup: Rebasing. (line 8) -* magit-rebase-reword-commit: Rebasing. (line 64) -* magit-rebase-skip: Rebasing. (line 75) -* magit-rebase-subset: Rebasing. (line 21) -* magit-rebase-unpushed: Rebasing. (line 47) -* magit-reflog-current: Reflog. (line 11) -* magit-reflog-head: Reflog. (line 19) -* magit-reflog-other: Reflog. (line 15) -* magit-refresh: Automatic refresh and revert. - (line 66) -* magit-refresh-all: Automatic refresh and revert. - (line 75) -* magit-remote-add: Remotes. (line 13) -* magit-remote-popup: Remotes. (line 8) -* magit-remote-remove: Remotes. (line 28) -* magit-remote-rename: Remotes. (line 18) -* magit-remote-set-url: Remotes. (line 23) -* magit-request-pull: Creating and sending patches. - (line 17) -* magit-reset: Resetting. (line 8) -* magit-reset-hard: Resetting. (line 32) -* magit-reset-head: Resetting. (line 21) -* magit-reset-index: Staging and unstaging. - (line 45) -* magit-reset-index <1>: Resetting. (line 14) -* magit-reset-soft: Resetting. (line 26) -* magit-reverse: Applying. (line 41) -* magit-revert: Reverting. (line 14) -* magit-revert-no-commit: Reverting. (line 20) -* magit-revert-popup: Reverting. (line 6) -* magit-run-git-gui: Running Git manually. - (line 59) -* magit-run-gitk: Running Git manually. - (line 47) -* magit-run-gitk-all: Running Git manually. - (line 51) -* magit-run-gitk-branches: Running Git manually. - (line 55) -* magit-run-popup: Running Git manually. - (line 12) -* magit-section-backward: Section movement. (line 10) -* magit-section-backward-siblings: Section movement. (line 20) -* magit-section-cycle: Section visibility. (line 13) -* magit-section-cycle-diffs: Section visibility. (line 17) -* magit-section-cycle-global: Section visibility. (line 22) -* magit-section-forward: Section movement. (line 16) -* magit-section-forward-siblings: Section movement. (line 26) -* magit-section-hide: Section visibility. (line 51) -* magit-section-hide-children: Section visibility. (line 66) -* magit-section-show: Section visibility. (line 47) -* magit-section-show-children: Section visibility. (line 60) -* magit-section-show-headings: Section visibility. (line 55) -* magit-section-show-level-1: Section visibility. (line 26) -* magit-section-show-level-1-all: Section visibility. (line 34) -* magit-section-show-level-2: Section visibility. (line 27) -* magit-section-show-level-2-all: Section visibility. (line 35) -* magit-section-show-level-3: Section visibility. (line 28) -* magit-section-show-level-3-all: Section visibility. (line 36) -* magit-section-show-level-4: Section visibility. (line 29) -* magit-section-show-level-4-all: Section visibility. (line 37) -* magit-section-toggle: Section visibility. (line 9) -* magit-section-toggle-children: Section visibility. (line 70) -* magit-section-up: Section movement. (line 31) -* magit-sequence-abort: Cherry picking. (line 43) -* magit-sequence-abort <1>: Reverting. (line 38) -* magit-sequence-continue: Cherry picking. (line 35) -* magit-sequence-continue <1>: Reverting. (line 30) -* magit-sequence-skip: Cherry picking. (line 39) -* magit-sequence-skip <1>: Reverting. (line 34) -* magit-shell-command: Running Git manually. - (line 38) -* magit-shell-command-topdir: Running Git manually. - (line 33) -* magit-show-commit: Diffing. (line 75) -* magit-show-commit <1>: Blaming. (line 29) -* magit-show-refs: References buffer. (line 24) -* magit-show-refs-current: References buffer. (line 19) -* magit-show-refs-head: References buffer. (line 14) -* magit-show-refs-popup: References buffer. (line 6) -* magit-snapshot: Stashing. (line 39) -* magit-snapshot-index: Stashing. (line 46) -* magit-snapshot-worktree: Stashing. (line 51) -* magit-stage: Staging and unstaging. - (line 26) -* magit-stage-file: Staging from file-visiting buffers. - (line 10) -* magit-stage-file <1>: Minor mode for buffers visiting files. - (line 24) -* magit-stage-modified: Staging and unstaging. - (line 30) -* magit-stash: Stashing. (line 13) -* magit-stash-apply: Stashing. (line 58) -* magit-stash-branch: Stashing. (line 84) -* magit-stash-clear: Stashing. (line 92) -* magit-stash-drop: Stashing. (line 71) -* magit-stash-format-patch: Stashing. (line 88) -* magit-stash-index: Stashing. (line 20) -* magit-stash-keep-index: Stashing. (line 32) -* magit-stash-list: Stashing. (line 76) -* magit-stash-pop: Stashing. (line 64) -* magit-stash-popup: Stashing. (line 8) -* magit-stash-show: Diffing. (line 80) -* magit-stash-show <1>: Stashing. (line 80) -* magit-stash-worktree: Stashing. (line 25) -* magit-status: Status buffer. (line 22) -* magit-submodule-add: Submodules. (line 13) -* magit-submodule-fetch: Fetching. (line 27) -* magit-submodule-fetch <1>: Submodules. (line 37) -* magit-submodule-init: Submodules. (line 24) -* magit-submodule-init <1>: Submodules. (line 41) -* magit-submodule-popup: Submodules. (line 8) -* magit-submodule-setup: Submodules. (line 19) -* magit-submodule-sync: Submodules. (line 33) -* magit-submodule-update: Submodules. (line 28) -* magit-tag: Tagging. (line 13) -* magit-tag-delete: Tagging. (line 18) -* magit-tag-popup: Tagging. (line 8) -* magit-tag-prune: Tagging. (line 24) -* magit-toggle-buffer-lock: Modes and Buffers. (line 17) -* magit-toggle-margin: Refreshing logs. (line 36) -* magit-unstage: Staging and unstaging. - (line 37) -* magit-unstage-all: Staging and unstaging. - (line 41) -* magit-unstage-file: Staging from file-visiting buffers. - (line 18) -* magit-unstage-file <1>: Minor mode for buffers visiting files. - (line 28) -* magit-version: Git executable. (line 17) -* magit-visit-ref: References buffer. (line 99) -* magit-wip-commit: Wip modes. (line 129) -* magit-wip-log: Wip modes. (line 69) -* magit-wip-log-current: Wip modes. (line 77) -* scroll-down: Diff buffer. (line 48) -* scroll-up: Diff buffer. (line 44) -* with-editor-cancel: Editing commit messages. - (line 24) -* with-editor-cancel <1>: Editing rebase sequences. - (line 11) -* with-editor-finish: Editing commit messages. - (line 19) -* with-editor-finish <1>: Editing rebase sequences. - (line 6) - - -File: magit.info, Node: Function Index, Next: Variable Index, Prev: Command Index, Up: Top - -Appendix D Function Index -************************* - -[index] -* Menu: - -* git-commit-check-style-conventions: Editing commit messages. - (line 247) -* git-commit-propertize-diff: Editing commit messages. - (line 206) -* git-commit-save-message: Editing commit messages. - (line 187) -* git-commit-setup-changelog-support: Editing commit messages. - (line 191) -* git-commit-turn-on-auto-fill: Editing commit messages. - (line 196) -* git-commit-turn-on-flyspell: Editing commit messages. - (line 201) -* ido-enter-magit-status: Status buffer. (line 42) -* magit-add-section-hook: Section hooks. (line 18) -* magit-after-save-refresh-status: Automatic refresh and revert. - (line 84) -* magit-builtin-completing-read: Completion and confirmation. - (line 23) -* magit-call-git: Calling Git for effect. - (line 28) -* magit-call-process: Calling Git for effect. - (line 32) -* magit-cancel-section: Creating sections. (line 70) -* magit-current-section: Section selection. (line 6) -* magit-define-section-jumper: Creating sections. (line 76) -* magit-diff-scope: Matching sections. (line 105) -* magit-diff-type: Matching sections. (line 82) -* magit-display-buffer: Switching Buffers. (line 6) -* magit-display-buffer-traditional: Switching Buffers. (line 37) -* magit-generate-buffer-name-default-function: Naming Buffers. - (line 17) -* magit-get-section: Matching sections. (line 16) -* magit-git: Calling Git for effect. - (line 65) -* magit-git-exit-code: Getting a value from Git. - (line 10) -* magit-git-failure: Getting a value from Git. - (line 19) -* magit-git-false: Getting a value from Git. - (line 29) -* magit-git-insert: Getting a value from Git. - (line 34) -* magit-git-items: Getting a value from Git. - (line 49) -* magit-git-lines: Getting a value from Git. - (line 44) -* magit-git-str: Getting a value from Git. - (line 72) -* magit-git-string: Getting a value from Git. - (line 38) -* magit-git-success: Getting a value from Git. - (line 14) -* magit-git-true: Getting a value from Git. - (line 24) -* magit-git-wash: Calling Git for effect. - (line 70) -* magit-hunk-set-window-start: Section movement. (line 44) -* magit-ido-completing-read: Completion and confirmation. - (line 28) -* magit-insert-am-sequence: Status sections. (line 28) -* magit-insert-bisect-log: Status sections. (line 46) -* magit-insert-bisect-output: Status sections. (line 38) -* magit-insert-bisect-rest: Status sections. (line 42) -* magit-insert-head-header: Status header sections. - (line 27) -* magit-insert-heading: Creating sections. (line 41) -* magit-insert-local-branches: References sections. (line 17) -* magit-insert-merge-log: Status sections. (line 18) -* magit-insert-rebase-sequence: Status sections. (line 23) -* magit-insert-recent-commits: Status sections. (line 91) -* magit-insert-remote-branches: References sections. (line 21) -* magit-insert-remote-header: Status header sections. - (line 45) -* magit-insert-repo-header: Status header sections. - (line 41) -* magit-insert-section: Creating sections. (line 6) -* magit-insert-sequencer-sequence: Status sections. (line 33) -* magit-insert-staged-changes: Status sections. (line 59) -* magit-insert-stashes: Status sections. (line 63) -* magit-insert-status-headers: Status header sections. - (line 11) -* magit-insert-tags: References sections. (line 25) -* magit-insert-tags-header: Status header sections. - (line 35) -* magit-insert-tracked-files: Status sections. (line 80) -* magit-insert-unpulled-cherries: Status sections. (line 102) -* magit-insert-unpulled-commits: Status sections. (line 70) -* magit-insert-unpulled-module-commits: Status sections. (line 109) -* magit-insert-unpulled-or-recent-commits: Status sections. (line 84) -* magit-insert-unpushed-cherries: Status sections. (line 114) -* magit-insert-unpushed-commits: Status sections. (line 74) -* magit-insert-unpushed-module-commits: Status sections. (line 122) -* magit-insert-unstaged-changes: Status sections. (line 55) -* magit-insert-untracked-files: Status sections. (line 50) -* magit-insert-upstream-header: Status header sections. - (line 31) -* magit-insert-user-header: Status header sections. - (line 53) -* magit-log-maybe-show-more-commits: Section movement. (line 57) -* magit-log-maybe-update-blob-buffer: Section movement. (line 69) -* magit-log-maybe-update-revision-buffer: Section movement. (line 63) -* magit-maybe-set-dedicated: Switching Buffers. (line 66) -* magit-mode-display-buffer: Refreshing buffers. (line 32) -* magit-mode-quit-window: Quitting Windows. (line 31) -* magit-mode-setup: Refreshing buffers. (line 17) -* magit-region-sections: Section selection. (line 10) -* magit-region-values: Section selection. (line 29) -* magit-restore-window-configuration: Quitting Windows. (line 20) -* magit-revert-buffers: Editing commit messages. - (line 178) -* magit-run-git: Calling Git for effect. - (line 36) -* magit-run-git-async: Calling Git for effect. - (line 80) -* magit-run-git-with-editor: Calling Git for effect. - (line 93) -* magit-run-git-with-input: Calling Git for effect. - (line 40) -* magit-run-git-with-logfile: Calling Git for effect. - (line 56) -* magit-save-window-configuration: Switching Buffers. (line 55) -* magit-section-case: Matching sections. (line 58) -* magit-section-hide: Section visibility. (line 51) -* magit-section-hide-children: Section visibility. (line 66) -* magit-section-ident: Matching sections. (line 11) -* magit-section-match: Matching sections. (line 21) -* magit-section-set-window-start: Section movement. (line 50) -* magit-section-show: Section visibility. (line 47) -* magit-section-show-children: Section visibility. (line 60) -* magit-section-show-headings: Section visibility. (line 55) -* magit-section-show-level-1: Section visibility. (line 26) -* magit-section-show-level-1-all: Section visibility. (line 34) -* magit-section-show-level-2: Section visibility. (line 27) -* magit-section-show-level-2-all: Section visibility. (line 35) -* magit-section-show-level-3: Section visibility. (line 28) -* magit-section-show-level-3-all: Section visibility. (line 36) -* magit-section-show-level-4: Section visibility. (line 29) -* magit-section-show-level-4-all: Section visibility. (line 37) -* magit-section-toggle-children: Section visibility. (line 70) -* magit-section-when: Matching sections. (line 48) -* magit-start-git: Calling Git for effect. - (line 105) -* magit-start-process: Calling Git for effect. - (line 124) -* magit-status-maybe-update-blob-buffer: Section movement. (line 81) -* magit-status-maybe-update-revision-buffer: Section movement. - (line 75) -* magit-wip-log: Wip modes. (line 69) -* magit-wip-log-current: Wip modes. (line 77) -* with-editor-usage-message: Editing commit messages. - (line 215) - diff --git a/elpa/magit-20151119.202/magit.info-2 b/elpa/magit-20151119.202/magit.info-2 deleted file mode 100644 index 2cf10161..00000000 Binary files a/elpa/magit-20151119.202/magit.info-2 and /dev/null differ diff --git a/elpa/magit-20151223.1425/AUTHORS.md b/elpa/magit-20151223.1425/AUTHORS.md new file mode 100644 index 00000000..4425770b --- /dev/null +++ b/elpa/magit-20151223.1425/AUTHORS.md @@ -0,0 +1,240 @@ +Authors +======= + +The following people have contributed to Magit, including the +libraries `git-commit.el`, `magit-popup.el`, and `with-editor.el` +which are distributed as separate Elpa packages. + +For statistics see http://magit.vc/stats/authors.html. + +Names below are sorted alphabetically. + +Author +------ + +- Marius Vollmer + +Maintainer +---------- + +- Jonas Bernoulli + +Developers +---------- + +- Kyle Meyer +- Noam Postavsky + +Retired Maintainers and Developers +---------------------------------- + +- Nicolas Dudebout +- Peter J. Weisberg +- Pieter Praet +- Phil Jackson +- Rémi Vanicat +- Yann Hodique + +Contributors +------------ + +- Aaron Culich +- Abdo Roig-Maranges +- acple +- Adam Spiers +- Adeodato Simó +- Ævar Arnfjörð Bjarmason +- Alan Falloon +- Alex Dunn +- Alexey Voinov +- Alex Kost +- Alex Ott +- Andreas Fuchs +- Andreas Liljeqvist +- Andreas Rottmann +- Andrei Chițu +- Andrew Kirkpatrick +- Andrew Schwartzmeyer +- Andrey Smirnov +- Andriy Kmit' +- Andy Sawyer +- Barak A. Pearlmutter +- Bastian Beischer +- Ben Walton +- Bradley Wright +- Brandon W Maister +- Brian Warner +- Bryan Shell +- Carl Lieberman +- Chris Bernard +- Chris Done +- Chris Moore +- Chris Ring +- Christian Dietrich +- Christian Kluge +- Christopher Monsanto +- Cornelius Mika +- Craig Andera +- Dale Hagglund +- Damien Cassou +- Daniel Brockman +- Daniel Farina +- Daniel Hackney +- Dan LaManna +- David Abrahams +- David Hull +- David L. Rager +- David Wallin +- Dennis Paskorz +- Divye Kapoor +- Dominique Quatravaux +- Eli Barzilay +- Eric Davis +- Eric Schulte +- Evgkeni Sampelnikof +- Felix Geller +- Feng Li +- Florian Ragwitz +- Geoff Shannon +- George Kadianakis +- Graham Clark +- Greg A. Woods +- Greg Lucas +- Greg Sexton +- Guillaume Martres +- Hannu Koivisto +- Hans-Peter Deifel +- Ian Eure +- Ingo Lohmar +- Jan Tatarik +- Jasper St. Pierre +- Jeff Bellegarde +- Jeff Dairiki +- Jesse Alama +- Johann Klähn +- John Mastro +- John Wiegley +- Jonas Bernoulli +- Jonathan Roes +- Jordan Greenberg +- Josiah Schwab +- Julien Danjou +- Justin Caratzas +- Kan-Ru Chen +- Kan-Ru Chen +- Kimberly Wolk +- Kyle Meyer +- Laurent Laffont +- Leandro Facchinetti +- Lele Gaifax +- Leo Liu +- Leonardo Etcheverry +- Lingchao Xin +- Lluís Vilanova +- Loic Dachary +- Luís Borges de Oliveira +- Luke Amdor +- Manuel Vázquez Acosta +- Marcel Wolf +- Marc Herbert +- Marcin Bachry +- Marco Craveiro +- Marian Schubert +- Marius Vollmer +- Mark Hepburn +- Mark Karpov +- Mark Oteiza +- Matus Goljer +- Michael Fogleman +- Michael Griffiths +- Michael Heerdegen +- Michal Sojka +- Miles Bader +- Miloš Mošić +- Mitchel Humpherys +- Moritz Bunkus +- Natalie Weizenbaum +- Nguyễn Tuấn Anh +- Nic Ferier +- Nick Alcock +- Nick Alexander +- Nick Dimiduk +- Nicklas Lindgren +- Nicolas Dudebout +- Nicolas Petton +- Nicolas Richard +- Nikolay Martynov +- Noam Postavsky +- Ole Arndt +- Oleh Krehel +- Óscar Fuentes +- Paul Stadig +- Pavel Holejsovsky +- Pekka Pessi +- Peter Eisentraut +- Peter Jaros +- Peter J. Weisberg +- Peter Vasil +- Philippe Vaucher +- Philipp Haselwarter +- Philip Weaver +- Phil Jackson +- Phil Sainty +- Pieter Praet +- Prathamesh Sonpatki +- rabio +- Rafael Laboissiere +- Raimon Grau +- Ramkumar Ramachandra +- Remco van 't Veer +- Rémi Vanicat +- René Stadler +- Richard Kim +- Robert Boone +- Robin Green +- Roger Crew +- Romain Francoise +- Ron Parker +- Roy Crihfield +- Rüdiger Sonderfeld +- Ryan C. Thompson +- Samuel Bronson +- Sanjoy Das +- Sean Bryant +- Sebastian Wiesner +- Sébastien Gross +- Seong-Kook Shin +- Sergey Pashinin +- Sergey Vinokurov +- Servilio Afre Puentes +- Štěpán Němec +- Steven Chow +- Steven E. Harris +- Steven Thomas +- Steven Vancoillie +- Steve Purcell +- Suhail Shergill +- Sylvain Rousseau +- Syohei Yoshida +- Takafumi Arakaki +- Teemu Likonen +- Teruki Shigitani +- Thierry Volpiatto +- Thomas A Caswell +- Thomas Frössman +- Thomas Jost +- Thomas Riccardi +- Tibor Simko +- Timo Juhani Lindfors +- Tim Perkins +- Tim Wraight +- Ting-Yu Lin +- Tom Feist +- Vineet Naik +- Wei Huang +- Wilfred Hughes +- Win Treese +- Xavier Noria +- Yann Hodique +- York Zhao +- Yuichi Higashi diff --git a/elpa/magit-20151223.1425/COPYING b/elpa/magit-20151223.1425/COPYING new file mode 100644 index 00000000..44325404 --- /dev/null +++ b/elpa/magit-20151223.1425/COPYING @@ -0,0 +1,676 @@ + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. + + + Copyright (C) + + 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 . + +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: + + Copyright (C) + 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 +. + + 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 +. + diff --git a/elpa/magit-20151223.1425/dir b/elpa/magit-20151223.1425/dir new file mode 100644 index 00000000..5fec5439 --- /dev/null +++ b/elpa/magit-20151223.1425/dir @@ -0,0 +1,18 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "?" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Emacs +* Magit: (magit). Using Git from Emacs with Magit. diff --git a/elpa/magit-20151223.1425/git-rebase.el b/elpa/magit-20151223.1425/git-rebase.el new file mode 100644 index 00000000..1ef275f0 --- /dev/null +++ b/elpa/magit-20151223.1425/git-rebase.el @@ -0,0 +1,461 @@ +;;; git-rebase.el --- Edit Git rebase files -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Phil Jackson +;; Maintainer: Jonas Bernoulli + +;; This file is not part of GNU Emacs. + +;; This file 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. + +;; This file 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 file. If not, see . + +;;; Commentary: + +;; This package assists the user in editing the list of commits to be +;; rewritten during an interactive rebase. + +;; When the user initiates an interactive rebase, e.g. using "r e" in +;; a Magit buffer or on the command line using "git rebase -i REV", +;; Git invokes the `$GIT_SEQUENCE_EDITOR' (or if that is undefined +;; `$GIT_EDITOR' or even `$EDITOR') letting the user rearrange, drop, +;; reword, edit, and squash commits. + +;; This package provides the major-mode `git-rebase-mode' which makes +;; doing so much more fun, by making the buffer more colorful and +;; providing the following commands: +;; +;; C-c C-c Tell Git to make it happen. +;; C-c C-k Tell Git that you changed your mind, i.e. abort. +;; +;; p Move point to previous line. +;; n Move point to next line. +;; +;; M-p Move the commit at point up. +;; M-n Move the commit at point down. +;; +;; k Drop the commit at point. +;; c Don't drop the commit at point. +;; r Change the message of the commit at point. +;; e Edit the commit at point. +;; s Squash the commit at point, into the one above. +;; f Like "s" but don't also edit the commit message. +;; x Add a script to be run with the commit at point +;; being checked out. +;; +;; RET Show the commit at point in another buffer. +;; C-/ Undo last change. + +;; You should probably also read the `git-rebase' manpage. + +;;; Code: + +(require 'dash) +(require 'easymenu) +(require 'server) +(require 'with-editor) +(require 'magit) + +(eval-when-compile (require 'recentf)) + +;;; Options +;;;; Variables + +(defgroup git-rebase nil + "Edit Git rebase sequences." + :group 'tools) + +(defcustom git-rebase-auto-advance t + "Whether to move to next line after changing a line." + :group 'git-rebase + :type 'boolean) + +(defcustom git-rebase-show-instructions t + "Whether to show usage instructions inside the rebase buffer." + :group 'git-rebase + :type 'boolean) + +(defcustom git-rebase-confirm-cancel t + "Whether confirmation is required to cancel." + :group 'git-rebase + :type 'boolean) + +;;;; Faces + +(defgroup git-rebase-faces nil + "Faces used by Git-Rebase mode." + :group 'faces + :group 'git-rebase) + +(defface git-rebase-hash + '((((class color) (background light)) :foreground "grey60") + (((class color) (background dark)) :foreground "grey40")) + "Face for commit hashes." + :group 'git-rebase-faces) + +(defface git-rebase-description nil + "Face for commit descriptions." + :group 'git-rebase-faces) + +(defface git-rebase-killed-action + '((t (:inherit font-lock-comment-face :strike-through t))) + "Face for commented action and exec lines." + :group 'git-rebase-faces) + +;;; Keymaps + +(defvar git-rebase-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map special-mode-map) + (define-key map (kbd "q") 'undefined) + (define-key map [remap undo] 'git-rebase-undo) + (define-key map (kbd "RET") 'git-rebase-show-commit) + (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up) + (define-key map (kbd "x") 'git-rebase-exec) + (define-key map (kbd "c") 'git-rebase-pick) + (define-key map (kbd "r") 'git-rebase-reword) + (define-key map (kbd "w") 'git-rebase-reword) + (define-key map (kbd "e") 'git-rebase-edit) + (define-key map (kbd "s") 'git-rebase-squash) + (define-key map (kbd "f") 'git-rebase-fixup) + (define-key map (kbd "y") 'git-rebase-insert) + (define-key map (kbd "k") 'git-rebase-kill-line) + (define-key map (kbd "C-k") 'git-rebase-kill-line) + (define-key map (kbd "p") 'git-rebase-backward-line) + (define-key map (kbd "n") 'forward-line) + (define-key map (kbd "M-p") 'git-rebase-move-line-up) + (define-key map (kbd "M-n") 'git-rebase-move-line-down) + (define-key map (kbd "M-") 'git-rebase-move-line-up) + (define-key map (kbd "M-") 'git-rebase-move-line-down) + (define-key map (kbd "C-x C-t") 'git-rebase-move-line-up) + map) + "Keymap for Git-Rebase mode.") + +(put 'git-rebase-reword :advertised-binding "r") +(put 'git-rebase-move-line-up :advertised-binding (kbd "M-p")) + +(easy-menu-define git-rebase-mode-menu git-rebase-mode-map + "Git-Rebase mode menu" + '("Rebase" + ["Pick" git-rebase-pick t] + ["Reword" git-rebase-reword t] + ["Edit" git-rebase-edit t] + ["Squash" git-rebase-squash t] + ["Fixup" git-rebase-fixup t] + ["Kill" git-rebase-kill-line t] + ["Execute" git-rebase-exec t] + ["Move Down" git-rebase-move-line-down t] + ["Move Up" git-rebase-move-line-up t] + "---" + ["Cancel" with-editor-cancel t] + ["Finish" with-editor-finish t])) + +(defvar git-rebase-command-descriptions + '((with-editor-finish . "tell Git to make it happen") + (with-editor-cancel . "tell Git that you changed your mind, i.e. abort") + (previous-line . "move point to previous line") + (next-line . "move point to next line") + (git-rebase-move-line-up . "move the commit at point up") + (git-rebase-move-line-down . "move the commit at point down") + (git-rebase-show-commit . "show the commit at point in another buffer") + (undo . "undo last change") + (git-rebase-kill-line . "drop the commit at point"))) + +;;; Commands + +(defun git-rebase-pick () + "Use commit on current line." + (interactive) + (git-rebase-set-action "pick")) + +(defun git-rebase-reword () + "Edit message of commit on current line." + (interactive) + (git-rebase-set-action "reword")) + +(defun git-rebase-edit () + "Stop at the commit on the current line." + (interactive) + (git-rebase-set-action "edit")) + +(defun git-rebase-squash () + "Meld commit on current line into previous commit, edit message." + (interactive) + (git-rebase-set-action "squash")) + +(defun git-rebase-fixup () + "Meld commit on current line into previous commit, discard its message." + (interactive) + (git-rebase-set-action "fixup")) + +(defconst git-rebase-line + "^\\(#?\\(?:[fprse]\\|pick\\|reword\\|edit\\|squash\\|fixup\\|exec\\)\\) \ +\\(?:\\([^ \n]+\\) \\(.*\\)\\)?") + +(defun git-rebase-set-action (action) + (goto-char (line-beginning-position)) + (if (and (looking-at git-rebase-line) + (not (string-match-p "\\(e\\|exec\\)$" (match-string 1)))) + (let ((inhibit-read-only t)) + (replace-match action t t nil 1) + (when git-rebase-auto-advance + (forward-line))) + (ding))) + +(defun git-rebase-line-p (&optional pos) + (save-excursion + (when pos (goto-char pos)) + (goto-char (line-beginning-position)) + (looking-at-p git-rebase-line))) + +(defun git-rebase-region-bounds () + (when (use-region-p) + (let ((beg (save-excursion (goto-char (region-beginning)) + (line-beginning-position))) + (end (save-excursion (goto-char (region-end)) + (line-end-position)))) + (when (and (git-rebase-line-p beg) + (git-rebase-line-p end)) + (list beg (1+ end)))))) + +(defun git-rebase-move-line-down (n) + "Move the current commit (or command) N lines down. +If N is negative, move the commit up instead. With an active +region, move all the lines that the region touches, not just the +current line." + (interactive "p") + (-let* (((beg end) (or (git-rebase-region-bounds) + (list (line-beginning-position) + (1+ (line-end-position))))) + (pt-offset (- (point) beg)) + (mark-offset (and mark-active (- (mark) beg)))) + (save-restriction + (narrow-to-region + (point-min) + (1+ (save-excursion + (goto-char (point-min)) + (while (re-search-forward git-rebase-line nil t)) + (point)))) + (if (or (and (< n 0) (= beg (point-min))) + (and (> n 0) (= end (point-max))) + (> end (point-max))) + (ding) + (goto-char (if (< n 0) beg end)) + (forward-line n) + (atomic-change-group + (let ((inhibit-read-only t)) + (insert (delete-and-extract-region beg end))) + (let ((new-beg (- (point) (- end beg)))) + (when (use-region-p) + (setq deactivate-mark nil) + (set-mark (+ new-beg mark-offset))) + (goto-char (+ new-beg pt-offset)))))))) + +(defun git-rebase-move-line-up (n) + "Move the current commit (or command) N lines up. +If N is negative, move the commit down instead. With an active +region, move all the lines that the region touches, not just the +current line." + (interactive "p") + (git-rebase-move-line-down (- n))) + +(defun git-rebase-highlight-region (start end window rol) + (let ((inhibit-read-only t) + (deactivate-mark nil) + (bounds (git-rebase-region-bounds))) + (mapc #'delete-overlay magit-section-highlight-overlays) + (when bounds + (magit-section-make-overlay (car bounds) (cadr bounds) + 'magit-section-heading-selection)) + (if (and bounds (not magit-keep-region-overlay)) + (funcall (default-value 'redisplay-unhighlight-region-function) rol) + (funcall (default-value 'redisplay-highlight-region-function) + start end window rol)))) + +(defun git-rebase-unhighlight-region (rol) + (mapc #'delete-overlay magit-section-highlight-overlays) + (funcall (default-value 'redisplay-unhighlight-region-function) rol)) + +(defun git-rebase-kill-line () + "Kill the current action line." + (interactive) + (goto-char (line-beginning-position)) + (when (and (looking-at git-rebase-line) + (not (eq (char-after) ?#))) + (let ((inhibit-read-only t)) + (insert ?#)) + (when git-rebase-auto-advance + (forward-line)))) + +(defun git-rebase-insert (rev) + "Read an arbitrary commit and insert it below current line." + (interactive (list (magit-read-branch-or-commit "Insert revision"))) + (forward-line) + (--if-let (magit-rev-format "%h %s" rev) + (let ((inhibit-read-only t)) + (insert "pick " it ?\n)) + (user-error "Unknown revision"))) + +(defun git-rebase-exec (arg) + "Insert a shell command to be run after the proceeding commit. + +If there already is such a command on the current line, then edit +that instead. With a prefix argument insert a new command even +when there already is one on the current line. With empty input +remove the command on the current line, if any." + (interactive "P") + (let ((inhibit-read-only t) initial command) + (unless arg + (goto-char (line-beginning-position)) + (when (looking-at "^#?\\(e\\|exec\\) \\(.*\\)") + (setq initial (match-string-no-properties 2)))) + (setq command (read-shell-command "Execute: " initial)) + (pcase (list command initial) + (`("" nil) (ding)) + (`("" ,_) + (delete-region (match-beginning 0) (1+ (match-end 0)))) + (`(,_ nil) + (forward-line) + (insert (concat "exec " command "\n")) + (unless git-rebase-auto-advance + (forward-line -1))) + (_ + (replace-match (concat "exec " command) t t) + (if git-rebase-auto-advance + (forward-line) + (goto-char (line-beginning-position))))))) + +(defun git-rebase-undo (&optional arg) + "Undo some previous changes. +Like `undo' but works in read-only buffers." + (interactive "P") + (let ((inhibit-read-only t)) + (undo arg))) + +(defun git-rebase-show-commit () + "Show the commit on the current line if any." + (interactive) + (save-excursion + (goto-char (line-beginning-position)) + (--if-let (and (looking-at git-rebase-line) + (match-string 2)) + (apply #'magit-show-commit it (magit-diff-arguments)) + (ding)))) + +(defun git-rebase-backward-line (&optional n) + "Move N lines backward (forward if N is negative). +Like `forward-line' but go into the opposite direction." + (interactive "p") + (forward-line (- n))) + +;;; Mode + +;;;###autoload +(define-derived-mode git-rebase-mode special-mode "Git Rebase" + "Major mode for editing of a Git rebase file. + +Rebase files are generated when you run 'git rebase -i' or run +`magit-interactive-rebase'. They describe how Git should perform +the rebase. See the documentation for git-rebase (e.g., by +running 'man git-rebase' at the command line) for details." + :group 'git-rebase + (setq font-lock-defaults '(git-rebase-mode-font-lock-keywords t t)) + (unless git-rebase-show-instructions + (let ((inhibit-read-only t)) + (flush-lines "^\\($\\|#\\)"))) + (with-editor-mode 1) + (when git-rebase-confirm-cancel + (add-hook 'with-editor-cancel-query-functions + 'git-rebase-cancel-confirm nil t)) + (setq-local redisplay-highlight-region-function 'git-rebase-highlight-region) + (setq-local redisplay-unhighlight-region-function 'git-rebase-unhighlight-region) + (add-hook 'with-editor-pre-cancel-hook 'git-rebase-autostash-save nil t) + (add-hook 'with-editor-post-cancel-hook 'git-rebase-autostash-apply nil t)) + +(defun git-rebase-cancel-confirm (force) + (or (not (buffer-modified-p)) force (y-or-n-p "Abort this rebase? "))) + +(defun git-rebase-autostash-save () + (--when-let (magit-file-line (magit-git-dir "rebase-merge/autostash")) + (push (cons 'stash it) with-editor-cancel-alist))) + +(defun git-rebase-autostash-apply () + (--when-let (cdr (assq 'stash with-editor-cancel-alist)) + (magit-stash-apply it))) + +(defconst git-rebase-mode-font-lock-keywords + `(("^\\([efprs]\\|pick\\|reword\\|edit\\|squash\\|fixup\\) \\([^ \n]+\\) \\(.*\\)" + (1 'font-lock-keyword-face) + (2 'git-rebase-hash) + (3 'git-rebase-description)) + ("^\\(exec\\) \\(.*\\)" + (1 'font-lock-keyword-face) + (2 'git-rebase-description)) + ("^#.*" 0 'font-lock-comment-face) + ("^#[^ \n].*" 0 'git-rebase-killed-action t)) + "Font lock keywords for Git-Rebase mode.") + +(defun git-rebase-mode-show-keybindings () + "Modify the \"Commands:\" section of the comment Git generates +at the bottom of the file so that in place of the one-letter +abbreviation for the command, it shows the command's keybinding. +By default, this is the same except for the \"pick\" command." + (let ((inhibit-read-only t)) + (save-excursion + (goto-char (point-min)) + (when (and git-rebase-show-instructions + (re-search-forward "^# Commands:\n" nil t)) + (--each git-rebase-command-descriptions + (insert (format "# %-8s %s\n" + (substitute-command-keys (format "\\[%s]" (car it))) + (cdr it)))) + (while (re-search-forward "^#\\( ?\\)\\([^,],\\) \\([^ ]+\\) = " nil t) + (let ((cmd (intern (concat "git-rebase-" (match-string 3))))) + (if (not (fboundp cmd)) + (delete-region (line-beginning-position) (1+ (line-end-position))) + (replace-match " " t t nil 1) + (replace-match + (format "%-8s" + (mapconcat #'key-description + (--filter (not (eq (elt it 0) 'menu-bar)) + (reverse (where-is-internal cmd))) + ", ")) + t t nil 2)))))))) + +(add-hook 'git-rebase-mode-hook 'git-rebase-mode-show-keybindings t) + +(defun git-rebase-mode-disable-before-save-hook () + (set (make-local-variable 'before-save-hook) nil)) + +(add-hook 'git-rebase-mode-hook 'git-rebase-mode-disable-before-save-hook) + +;;;###autoload +(defconst git-rebase-filename-regexp "/git-rebase-todo\\'") +;;;###autoload +(add-to-list 'auto-mode-alist + (cons git-rebase-filename-regexp 'git-rebase-mode)) + +(add-to-list 'with-editor-server-window-alist + (cons git-rebase-filename-regexp 'switch-to-buffer)) + +(eval-after-load 'recentf + '(add-to-list 'recentf-exclude git-rebase-filename-regexp)) + +(provide 'git-rebase) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; git-rebase.el ends here diff --git a/elpa/magit-20151223.1425/magit-apply.el b/elpa/magit-20151223.1425/magit-apply.el new file mode 100644 index 00000000..850a83cb --- /dev/null +++ b/elpa/magit-20151223.1425/magit-apply.el @@ -0,0 +1,520 @@ +;;; magit-apply.el --- apply Git diffs -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library implements commands for applying Git diffs or parts +;; of such a diff. The supported "apply variants" are apply, stage, +;; unstage, discard, and reverse - more than Git itself knows about, +;; at least at the porcelain level. + +;;; Code: + +(require 'magit-core) +(require 'magit-diff) +(require 'magit-wip) + +;; For `magit-apply' +(declare-function magit-am-popup 'magit-sequence) +;; For `magit-discard-files' +(declare-function magit-checkout-stage 'magit) +(declare-function magit-checkout-read-stage 'magit) +(defvar auto-revert-verbose) + +(require 'dired) + +;;; Options + +(defcustom magit-delete-by-moving-to-trash t + "Whether Magit uses the system's trash can." + :package-version '(magit . "2.1.0") + :group 'magit + :type 'boolean) + +;;; Commands +;;;; Apply + +(defun magit-apply (&rest args) + "Apply the change at point. +With a prefix argument and if necessary, attempt a 3-way merge." + (interactive (and current-prefix-arg (list "--3way"))) + (--when-let (magit-apply--get-selection) + (pcase (list (magit-diff-type) (magit-diff-scope)) + (`(,(or `unstaged `staged) ,_) + (user-error "Change is already in the working tree")) + (`(untracked ,(or `file `files)) + (magit-am-popup)) + (`(,_ region) (magit-apply-region it args)) + (`(,_ hunk) (magit-apply-hunk it args)) + (`(,_ hunks) (magit-apply-hunks it args)) + (`(,_ file) (magit-apply-diff it args)) + (`(,_ files) (magit-apply-diffs it args))))) + +(defun magit-apply-diffs (sections &rest args) + (setq sections (magit-apply--get-diffs sections)) + (magit-apply-patch sections args + (mapconcat + (lambda (s) + (concat (magit-diff-file-header s) + (buffer-substring (magit-section-content s) + (magit-section-end s)))) + sections ""))) + +(defun magit-apply-diff (section &rest args) + (setq section (car (magit-apply--get-diffs (list section)))) + (magit-apply-patch section args + (concat (magit-diff-file-header section) + (buffer-substring (magit-section-content section) + (magit-section-end section))))) + +(defun magit-apply-hunks (sections &rest args) + (let ((section (magit-section-parent (car sections)))) + (when (string-match "^diff --cc" (magit-section-value section)) + (user-error "Cannot un-/stage resolution hunks. Stage the whole file")) + (magit-apply-patch section args + (concat (magit-section-diff-header section) + (mapconcat + (lambda (s) + (buffer-substring (magit-section-start s) + (magit-section-end s))) + sections ""))))) + +(defun magit-apply-hunk (section &rest args) + (when (string-match "^diff --cc" (magit-section-parent-value section)) + (user-error "Cannot un-/stage resolution hunks. Stage the whole file")) + (magit-apply-patch (magit-section-parent section) args + (concat (magit-diff-file-header section) + (buffer-substring (magit-section-start section) + (magit-section-end section))))) + +(defun magit-apply-region (section &rest args) + (unless (magit-diff-context-p) + (user-error "Not enough context to apply region. Increase the context")) + (when (string-match "^diff --cc" (magit-section-parent-value section)) + (user-error "Cannot un-/stage resolution hunks. Stage the whole file")) + (magit-apply-patch (magit-section-parent section) args + (concat (magit-diff-file-header section) + (magit-diff-hunk-region-patch section args)))) + +(defun magit-apply-patch (section:s args patch) + (let* ((files (if (atom section:s) + (list (magit-section-value section:s)) + (mapcar 'magit-section-value section:s))) + (command (symbol-name this-command)) + (command (if (and command (string-match "^magit-\\([^-]+\\)" command)) + (match-string 1 command) + "apply"))) + (when (and magit-wip-before-change-mode (not inhibit-magit-refresh)) + (magit-wip-commit-before-change files (concat " before " command))) + (with-temp-buffer + (insert patch) + (magit-run-git-with-input nil + "apply" args "-p0" + (unless (magit-diff-context-p) "--unidiff-zero") + "--ignore-space-change" "-")) + (unless inhibit-magit-refresh + (when magit-wip-after-apply-mode + (magit-wip-commit-after-apply files (concat " after " command))) + (magit-refresh)))) + +(defun magit-apply--get-selection () + (or (magit-region-sections 'hunk 'file) + (let ((section (magit-current-section))) + (pcase (magit-section-type section) + ((or `hunk `file) section) + ((or `staged `unstaged `untracked + `stashed-index `stashed-worktree `stashed-untracked) + (magit-section-children section)) + (_ (user-error "Cannot apply this, it's not a change")))))) + +(defun magit-apply--get-diffs (sections) + (magit-section-case + ([file diffstat] + (--map (or (magit-get-section + (append `((file . ,(magit-section-value it))) + (magit-section-ident magit-root-section))) + (error "Cannot get required diff headers")) + sections)) + (t sections))) + +;;;; Stage + +(defun magit-stage () + "Add the change at point to the staging area." + (interactive) + (--when-let (magit-apply--get-selection) + (let ((inhibit-magit-revert t)) + (pcase (list (magit-diff-type) (magit-diff-scope)) + (`(untracked ,_) (magit-stage-untracked)) + (`(unstaged region) (magit-apply-region it "--cached")) + (`(unstaged hunk) (magit-apply-hunk it "--cached")) + (`(unstaged hunks) (magit-apply-hunks it "--cached")) + (`(unstaged file) (magit-stage-1 "-u" (list (magit-section-value it)))) + (`(unstaged files) (magit-stage-1 "-u" (magit-region-values))) + (`(unstaged list) (magit-stage-1 "-u")) + (`(staged ,_) (user-error "Already staged")) + (`(committed ,_) (user-error "Cannot stage committed changes")) + (`(undefined ,_) (user-error "Cannot stage this change")))))) + +;;;###autoload +(defun magit-stage-file (file) + "Stage all changes to FILE. +With a prefix argument or when there is no file at point ask for +the file to be staged. Otherwise stage the file at point without +requiring confirmation." + (interactive + (let* ((atpoint (magit-section-when (file))) + (current (magit-file-relative-name)) + (choices (nconc (magit-modified-files) + (magit-untracked-files))) + (default (car (member (or atpoint current) choices)))) + (list (if (or current-prefix-arg (not default)) + (magit-completing-read "Stage file" choices + nil t nil nil default) + default)))) + (magit-with-toplevel + (magit-stage-1 nil (list file)))) + +;;;###autoload +(defun magit-stage-modified (&optional all) + "Stage all changes to files modified in the worktree. +Stage all new content of tracked files and remove tracked files +that no longer exist in the working tree from the index also. +With a prefix argument also stage previously untracked (but not +ignored) files. +\('git add --update|--all .')." + (interactive (progn (unless (or (not (magit-anything-staged-p)) + (magit-confirm 'stage-all-changes)) + (user-error "Abort")) + (list current-prefix-arg))) + (magit-with-toplevel + (magit-stage-1 (if all "--all" "-u")))) + +(defun magit-stage-1 (arg &optional files) + (magit-wip-commit-before-change files " before stage") + (magit-run-git-no-revert "add" arg (if files (cons "--" files) ".")) + (magit-wip-commit-after-apply files " after stage")) + +(defun magit-stage-untracked () + (let* ((section (magit-current-section)) + (files (pcase (magit-diff-scope) + (`file (list (magit-section-value section))) + (`files (magit-region-values)) + (`list (magit-untracked-files)))) + plain repos) + (dolist (file files) + (if (magit-git-repo-p file t) + (push file repos) + (push file plain))) + (magit-wip-commit-before-change files " before stage") + (when plain + (magit-run-git-no-revert "add" "--" plain)) + (dolist (repo repos) + (let ((inhibit-magit-revert t)) + (save-excursion + (goto-char (magit-section-start + (magit-get-section + `((file . ,repo) (untracked) (status))))) + (call-interactively 'magit-submodule-add)))) + (magit-wip-commit-after-apply files " after stage"))) + +;;;; Unstage + +(defun magit-unstage () + "Remove the change at point from the staging area." + (interactive) + (--when-let (magit-apply--get-selection) + (let ((inhibit-magit-revert t)) + (pcase (list (magit-diff-type) (magit-diff-scope)) + (`(untracked ,_) (user-error "Cannot unstage untracked changes")) + (`(unstaged ,_) (user-error "Already unstaged")) + (`(staged region) (magit-apply-region it "--reverse" "--cached")) + (`(staged hunk) (magit-apply-hunk it "--reverse" "--cached")) + (`(staged hunks) (magit-apply-hunks it "--reverse" "--cached")) + (`(staged file) (magit-unstage-1 (list (magit-section-value it)))) + (`(staged files) (magit-unstage-1 (magit-region-values))) + (`(staged list) (magit-unstage-all)) + (`(committed ,_) (user-error "Cannot unstage committed changes")) + (`(undefined ,_) (user-error "Cannot unstage this change")))))) + +;;;###autoload +(defun magit-unstage-file (file) + "Unstage all changes to FILE. +With a prefix argument or when there is no file at point ask for +the file to be unstaged. Otherwise unstage the file at point +without requiring confirmation." + (interactive + (let* ((atpoint (magit-section-when (file))) + (current (magit-file-relative-name)) + (choices (magit-staged-files)) + (default (car (member (or atpoint current) choices)))) + (list (if (or current-prefix-arg (not default)) + (magit-completing-read "Unstage file" choices + nil t nil nil default) + default)))) + (magit-with-toplevel + (magit-unstage-1 (list file)))) + +(defun magit-unstage-1 (files) + (magit-wip-commit-before-change files " before unstage") + (if (magit-no-commit-p) + (magit-run-git "rm" "--cached" "--" files) + (magit-run-git "reset" "HEAD" "--" files)) + (magit-wip-commit-after-apply files " after unstage")) + +;;;###autoload +(defun magit-unstage-all () + "Remove all changes from the staging area." + (interactive) + (when (or (and (not (magit-anything-unstaged-p)) + (not (magit-untracked-files))) + (magit-confirm 'unstage-all-changes)) + (magit-wip-commit-before-change nil " before unstage") + (magit-run-git "reset" "HEAD" "--") + (magit-wip-commit-after-apply nil " after unstage"))) + +;;;; Discard + +(defun magit-discard () + "Remove the change at point." + (interactive) + (--when-let (magit-apply--get-selection) + (pcase (list (magit-diff-type) (magit-diff-scope)) + (`(committed ,_) (user-error "Cannot discard committed changes")) + (`(undefined ,_) (user-error "Cannot discard this change")) + (`(,_ region) (magit-discard-region it)) + (`(,_ hunk) (magit-discard-hunk it)) + (`(,_ hunks) (magit-discard-hunks it)) + (`(,_ file) (magit-discard-file it)) + (`(,_ files) (magit-discard-files it)) + (`(,_ list) (magit-discard-files it))))) + +(defun magit-discard-region (section) + (when (magit-confirm 'discard "Discard region") + (magit-discard-apply section 'magit-apply-region))) + +(defun magit-discard-hunk (section) + (when (magit-confirm 'discard "Discard hunk") + (magit-discard-apply section 'magit-apply-hunk))) + +(defun magit-discard-apply (section apply) + (if (eq (magit-diff-type section) 'unstaged) + (funcall apply section "--reverse") + (if (magit-anything-unstaged-p + nil (if (eq (magit-section-type section) 'file) + (magit-section-value section) + (magit-section-parent-value section))) + (progn (let ((inhibit-magit-refresh t)) + (funcall apply section "--reverse" "--cached") + (funcall apply section "--reverse")) + (magit-refresh)) + (funcall apply section "--reverse" "--index")))) + +(defun magit-discard-hunks (sections) + (when (magit-confirm 'discard + (format "Discard %s hunks from %s" + (length sections) + (magit-section-parent-value (car sections)))) + (magit-discard-apply-n sections 'magit-apply-hunks))) + +(defun magit-discard-apply-n (sections apply) + (let ((section (car sections))) + (if (eq (magit-diff-type section) 'unstaged) + (funcall apply sections "--reverse") + (if (magit-anything-unstaged-p + nil (if (eq (magit-section-type section) 'file) + (magit-section-value section) + (magit-section-parent-value section))) + (progn (let ((inhibit-magit-refresh t)) + (funcall apply sections "--reverse" "--cached") + (funcall apply sections "--reverse")) + (magit-refresh)) + (funcall apply sections "--reverse" "--index"))))) + +(defun magit-discard-file (section) + (magit-discard-files (list section))) + +(defun magit-discard-files (sections) + (let ((auto-revert-verbose nil) + (type (magit-diff-type (car sections))) + (status (magit-file-status)) + files delete resurrect rename discard discard-new resolve) + (dolist (section sections) + (let ((file (magit-section-value section))) + (push file files) + (pcase (cons (pcase type + (`staged ?X) + (`unstaged ?Y) + (`untracked ?Z)) + (cddr (assoc file status))) + (`(?Z) (--each (magit-untracked-files nil file) + (push it delete))) + ((or `(?Z ?? ??) `(?Z ?! ?!)) (push file delete)) + ((or `(?Z ?D ? ) `(,_ ?D ?D)) (push file delete)) + ((or `(,_ ?U ,_) `(,_ ,_ ?U)) (push file resolve)) + (`(,_ ?A ?A) (push file resolve)) + (`(?X ?M ,(or ? ?M ?D)) (push section discard)) + (`(?Y ,_ ?M ) (push section discard)) + (`(?X ?A ?M ) (push file discard-new)) + (`(?X ?C ?M ) (push file discard-new)) + (`(?X ?A ,(or ? ?D)) (push file delete)) + (`(?X ?C ,(or ? ?D)) (push file delete)) + (`(?X ?D ,(or ? ?M )) (push file resurrect)) + (`(?Y ,_ ?D ) (push file resurrect)) + (`(?X ?R ,(or ? ?M ?D)) (push file rename))))) + (unwind-protect + (let ((inhibit-magit-refresh t)) + (magit-wip-commit-before-change files " before discard") + (when resolve + (dolist (file (nreverse resolve)) + (magit-checkout-stage file (magit-checkout-read-stage file)))) + (magit-discard-files--resurrect (nreverse resurrect)) + (magit-discard-files--delete (nreverse delete) status) + (magit-discard-files--rename (nreverse rename) status) + (magit-discard-files--discard (nreverse discard) + (nreverse discard-new)) + (magit-wip-commit-after-apply files " after discard")) + (magit-refresh)))) + +(defun magit-discard-files--resurrect (files) + (when (magit-confirm-files 'resurrect files) + (if (eq (magit-diff-type) 'staged) + (magit-call-git "reset" "--" files) + (magit-call-git "checkout" "--" files)))) + +(defun magit-discard-files--delete (files status) + (when (if magit-delete-by-moving-to-trash + (magit-confirm-files 'trash files) + (magit-confirm-files 'delete files)) + (let ((delete-by-moving-to-trash magit-delete-by-moving-to-trash)) + (dolist (file files) + (if (memq (magit-diff-type) '(unstaged untracked)) + (dired-delete-file file dired-recursive-deletes + magit-delete-by-moving-to-trash) + (pcase (nth 3 (assoc file status)) + (? (delete-file file t) + (magit-call-git "rm" "--cached" "--" file)) + (?M (let ((temp (magit-git-string "checkout-index" "--temp" file))) + (string-match + (format "\\(.+?\\)\t%s" (regexp-quote file)) temp) + (rename-file (match-string 1 temp) + (setq temp (concat file ".~{index}~"))) + (delete-file temp t)) + (magit-call-git "rm" "--cached" "--force" "--" file)) + (?D (magit-call-git "checkout" "--" file) + (delete-file file t) + (magit-call-git "rm" "--cached" "--force" "--" file)))))))) + +(defun magit-discard-files--rename (files status) + (when (magit-confirm 'rename "Undo rename %s" "Undo %i renames" + (mapcar (lambda (file) + (setq file (assoc file status)) + (format "%s -> %s" (cadr file) (car file))) + files)) + (dolist (file files) + (let ((orig (cadr (assoc file status)))) + (if (file-exists-p file) + (magit-call-git "mv" file orig) + (magit-call-git "rm" "--cached" "--" file) + (magit-call-git "reset" "--" orig)))))) + +(defun magit-discard-files--discard (sections new-files) + (let ((files (mapcar #'magit-section-value sections))) + (when (magit-confirm-files + 'discard (append files new-files) + (format "Discard %s changes in" (magit-diff-type))) + (if (eq (magit-diff-type (car sections)) 'unstaged) + (magit-call-git "checkout" "--" files) + (when new-files + (magit-call-git "add" "--" new-files) + (magit-call-git "reset" "--" new-files)) + (let ((binaries (magit-staged-binary-files))) + (when binaries + (setq sections + (--filter (not (member (magit-section-value it) binaries)) + sections))) + (if (= (length sections) 1) + (magit-discard-apply (car sections) 'magit-apply-diff) + (magit-discard-apply-n sections 'magit-apply-diffs)) + (when binaries + (let ((modified (magit-modified-files t))) + (setq binaries (--separate (member it modified) binaries))) + (when (cadr binaries) + (magit-call-git "reset" "--" (cadr binaries))) + (when (car binaries) + (user-error + (concat + "Cannot discard staged changes to binary files, " + "which also have unstaged changes. Unstage instead."))))))))) + +;;;; Reverse + +(defun magit-reverse (&rest args) + "Reverse the change at point in the working tree." + (interactive (and current-prefix-arg (list "--3way"))) + (--when-let (magit-apply--get-selection) + (pcase (list (magit-diff-type) (magit-diff-scope)) + (`(untracked ,_) (user-error "Cannot reverse untracked changes")) + (`(unstaged ,_) (user-error "Cannot reverse unstaged changes")) + (`(,_ region) (magit-reverse-region it args)) + (`(,_ hunk) (magit-reverse-hunk it args)) + (`(,_ hunks) (magit-reverse-hunks it args)) + (`(,_ file) (magit-reverse-file it args)) + (`(,_ files) (magit-reverse-files it args)) + (`(,_ list) (magit-reverse-files it args))))) + +(defun magit-reverse-region (section args) + (when (magit-confirm 'reverse "Reverse region") + (apply 'magit-apply-region section "--reverse" args))) + +(defun magit-reverse-hunk (section args) + (when (magit-confirm 'reverse "Reverse hunk") + (apply 'magit-apply-hunk section "--reverse" args))) + +(defun magit-reverse-hunks (sections args) + (when (magit-confirm 'reverse + (format "Reverse %s hunks from %s" + (length sections) + (magit-section-parent-value (car sections)))) + (magit-apply-hunks sections "--reverse" args))) + +(defun magit-reverse-file (section args) + (magit-reverse-files (list section) args)) + +(defun magit-reverse-files (sections args) + (-let [(binaries sections) + (let ((bs (magit-staged-binary-files))) + (--separate (member (magit-section-value it) bs) sections))] + (when (magit-confirm-files 'reverse (mapcar #'magit-section-value sections)) + (if (= (length sections) 1) + (magit-apply-diff (car sections) "--reverse" args) + (magit-apply-diffs sections "--reverse" args))) + (when binaries + (user-error "Cannot reverse binary files")))) + +;;; magit-apply.el ends soon +(provide 'magit-apply) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-apply.el ends here diff --git a/elpa/magit-20151223.1425/magit-autoloads.el b/elpa/magit-20151223.1425/magit-autoloads.el new file mode 100644 index 00000000..c5347fd8 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-autoloads.el @@ -0,0 +1,1502 @@ +;;; magit-autoloads.el --- automatically extracted autoloads +;; +;;; Code: +(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +;;;### (autoloads nil "git-rebase" "git-rebase.el" (22140 7080 0 +;;;;;; 0)) +;;; Generated autoloads from git-rebase.el + +(autoload 'git-rebase-mode "git-rebase" "\ +Major mode for editing of a Git rebase file. + +Rebase files are generated when you run 'git rebase -i' or run +`magit-interactive-rebase'. They describe how Git should perform +the rebase. See the documentation for git-rebase (e.g., by +running 'man git-rebase' at the command line) for details. + +\(fn)" t nil) + +(defconst git-rebase-filename-regexp "/git-rebase-todo\\'") + +(add-to-list 'auto-mode-alist (cons git-rebase-filename-regexp 'git-rebase-mode)) + +;;;*** + +;;;### (autoloads nil "magit" "magit.el" (22140 7080 0 0)) +;;; Generated autoloads from magit.el + +(autoload 'magit-status "magit" "\ +Show the status of the current Git repository in a buffer. +With a prefix argument prompt for a repository to be shown. +With two prefix arguments prompt for an arbitrary directory. +If that directory isn't the root of an existing repository +then offer to initialize it as a new repository. + +\(fn &optional DIRECTORY)" t nil) + +(autoload 'magit-status-internal "magit" "\ + + +\(fn DIRECTORY)" nil nil) + (autoload 'magit-show-refs-popup "magit" nil t) + +(autoload 'magit-show-refs-head "magit" "\ +List and compare references in a dedicated buffer. +Refs are compared with `HEAD'. + +\(fn &optional ARGS)" t nil) + +(autoload 'magit-show-refs-current "magit" "\ +List and compare references in a dedicated buffer. +Refs are compared with the current branch or `HEAD' if +it is detached. + +\(fn &optional ARGS)" t nil) + +(autoload 'magit-show-refs "magit" "\ +List and compare references in a dedicated buffer. +Refs are compared with a branch read form the user. + +\(fn &optional REF ARGS)" t nil) + +(autoload 'magit-find-file "magit" "\ +View FILE from REV. +Switch to a buffer visiting blob REV:FILE, +creating one if none already exists. + +\(fn REV FILE)" t nil) + +(autoload 'magit-find-file-other-window "magit" "\ +View FILE from REV, in another window. +Like `magit-find-file', but create a new window or reuse an +existing one. + +\(fn REV FILE)" t nil) + +(autoload 'magit-dired-jump "magit" "\ +Visit file at point using Dired. +With a prefix argument, visit in other window. If there +is no file at point then instead visit `default-directory'. + +\(fn &optional OTHER-WINDOW)" t nil) + +(autoload 'magit-checkout-file "magit" "\ +Checkout FILE from REV. + +\(fn REV FILE)" t nil) + +(autoload 'magit-init "magit" "\ +Initialize a Git repository, then show its status. + +If the directory is below an existing repository, then the user +has to confirm that a new one should be created inside. If the +directory is the root of the existing repository, then the user +has to confirm that it should be reinitialized. + +Non-interactively DIRECTORY is (re-)initialized unconditionally. + +\(fn DIRECTORY)" t nil) + (autoload 'magit-branch-popup "magit" nil t) + +(autoload 'magit-checkout "magit" "\ +Checkout REVISION, updating the index and the working tree. +If REVISION is a local branch then that becomes the current +branch. If it is something else then `HEAD' becomes detached. +Checkout fails if the working tree or the staging area contain +changes. + +\(git checkout REVISION). + +\(fn REVISION)" t nil) + +(autoload 'magit-branch "magit" "\ +Create BRANCH at branch or revision START-POINT. + +\(git branch [ARGS] BRANCH START-POINT). + +\(fn BRANCH START-POINT &optional ARGS)" t nil) + +(autoload 'magit-branch-and-checkout "magit" "\ +Create and checkout BRANCH at branch or revision START-POINT. + +\(git checkout [ARGS] -b BRANCH START-POINT). + +\(fn BRANCH START-POINT &optional ARGS)" t nil) + +(autoload 'magit-branch-spinoff "magit" "\ +Create new branch from the unpushed commits. + +Create and checkout a new branch starting at and tracking the +current branch. That branch in turn is reset to the last commit +it shares with its upstream. If the current branch has no +upstream or no unpushed commits, then the new branch is created +anyway and the previously current branch is not touched. + +This is useful to create a feature branch after work has already +began on the old branch (likely but not necessarily \"master\"). + +If the current branch is a member of the value of option +`magit-branch-prefer-remote-upstream' (which see), then the +current branch will be used as the starting point as usual, but +the upstream of the starting-point may be used as the upstream +of the new branch, instead of the starting-point itself. + +\(fn BRANCH &rest ARGS)" t nil) + +(autoload 'magit-branch-reset "magit" "\ +Reset a branch to the tip of another branch or any other commit. + +When resetting to another branch, then also set that branch as +the upstream of the branch being reset. + +When the branch being reset is the current branch, then do a +hard reset. If there are any uncommitted changes, then the user +has to confirming the reset because those changes would be lost. + +This is useful when you have started work on a feature branch but +realize it's all crap and want to start over. + +\(fn BRANCH TO &optional ARGS)" t nil) + +(autoload 'magit-branch-delete "magit" "\ +Delete one or multiple branches. +If the region marks multiple branches, then offer to delete +those, otherwise prompt for a single branch to be deleted, +defaulting to the branch at point. + +\(fn BRANCHES &optional FORCE)" t nil) + +(autoload 'magit-branch-rename "magit" "\ +Rename branch OLD to NEW. +With prefix, forces the rename even if NEW already exists. + +\(git branch -m|-M OLD NEW). + +\(fn OLD NEW &optional FORCE)" t nil) + +(autoload 'magit-edit-branch*description "magit" "\ +Edit the description of the current branch. +With a prefix argument edit the description of another branch. + +The description for the branch named NAME is stored in the Git +variable `branch..description'. + +\(fn BRANCH)" t nil) + +(autoload 'magit-set-branch*merge/remote "magit" "\ +Set or unset the upstream of the current branch. +With a prefix argument do so for another branch. + +When the branch in question already has an upstream then simply +unsets it. Invoke this command again to set another upstream. + +Together the Git variables `branch..remote' and +`branch..merge' define the upstream branch of the local +branch named NAME. The value of `branch..remote' is the +name of the upstream remote. The value of `branch..merge' +is the full reference of the upstream branch, on the remote. + +\(fn BRANCH UPSTREAM)" t nil) + +(autoload 'magit-cycle-branch*rebase "magit" "\ +Cycle the value of `branch..rebase' for the current branch. +With a prefix argument cycle the value for another branch. + +The Git variables `branch..rebase' controls whether pulling +into the branch named NAME is done by rebasing that branch onto +the fetched branch or by merging that branch. + +When `true' then pulling is done by rebasing. +When `false' then pulling is done by merging. + +When that variable is undefined then the value of `pull.rebase' +is used instead. It defaults to `false'. + +\(fn BRANCH)" t nil) + +(autoload 'magit-cycle-branch*pushRemote "magit" "\ +Cycle the value of `branch..pushRemote' for the current branch. +With a prefix argument cycle the value for another branch. + +The Git variable `branch..pushRemote' specifies the remote +that the branch named NAME is usually pushed to. The value has +to be the name of an existing remote. + +If that variable is undefined, then the value of the Git variable +`remote.pushDefault' is used instead, provided that it is defined, +which by default it is not. + +\(fn BRANCH)" t nil) + +(autoload 'magit-cycle-pull\.rebase "magit" "\ +Cycle the repository-local value of `pull.rebase'. + +The Git variable `pull.rebase' specifies whether pulling is done +by rebasing or by merging. It can be overwritten using the Git +variable `branch..rebase'. + +When `true' then pulling is done by rebasing. +When `false' (the default) then pulling is done by merging. + +\(fn)" t nil) + +(autoload 'magit-cycle-remote\.pushDefault "magit" "\ +Cycle the repository-local value of `remote.pushDefault'. + +The Git variable `remote.pushDefault' specifies the remote that +local branches are usually pushed to. It can be overwritten +using the Git variable `branch..pushRemote'. + +\(fn)" t nil) + +(autoload 'magit-cycle-branch*autoSetupMerge "magit" "\ +Cycle the repository-local value of `branch.autoSetupMerge'. + +The Git variable `branch.autoSetupMerge' under what circumstances +creating a branch (named NAME) should result in the variables +`branch..merge' and `branch..remote' being set +according to the starting point used to create the branch. If +the starting point isn't a branch, then these variables are never +set. + +When `always' then the variables are set regardless of whether +the starting point is a local or a remote branch. + +When `true' (the default) then the variable are set when the +starting point is a remote branch, but not when it is a local +branch. + +When `false' then the variables are never set. + +\(fn)" t nil) + +(autoload 'magit-cycle-branch*autoSetupRebase "magit" "\ +Cycle the repository-local value of `branch.autoSetupRebase'. + +The Git variable `branch.autoSetupRebase' specifies whether +creating a branch (named NAME) should result in the variable +`branch..rebase' being set to `true'. + +When `always' then the variable is set regardless of whether the +starting point is a local or a remote branch. + +When `local' then the variable are set when the starting point +is a local branch, but not when it is a remote branch. + +When `remote' then the variable are set when the starting point +is a remote branch, but not when it is a local branch. + +When `never' (the default) then the variable is never set. + +\(fn)" t nil) + (autoload 'magit-merge-popup "magit" nil t) + +(autoload 'magit-merge "magit" "\ +Merge commit REV into the current branch; using default message. + +Unless there are conflicts or a prefix argument is used create a +merge commit using a generic commit message and without letting +the user inspect the result. With a prefix argument pretend the +merge failed to give the user the opportunity to inspect the +merge. + +\(git merge --no-edit|--no-commit [ARGS] REV) + +\(fn REV &optional ARGS NOCOMMIT)" t nil) + +(autoload 'magit-merge-editmsg "magit" "\ +Merge commit REV into the current branch; and edit message. +Perform the merge and prepare a commit message but let the user +edit it. + +\(git merge --edit [ARGS] rev) + +\(fn REV &optional ARGS)" t nil) + +(autoload 'magit-merge-nocommit "magit" "\ +Merge commit REV into the current branch; pretending it failed. +Pretend the merge failed to give the user the opportunity to +inspect the merge and change the commit message. + +\(git merge --no-commit [ARGS] rev) + +\(fn REV &optional ARGS)" t nil) + +(autoload 'magit-merge-preview "magit" "\ +Preview result of merging REV into the current branch. + +\(fn REV)" t nil) + +(autoload 'magit-merge-abort "magit" "\ +Abort the current merge operation. + +\(git merge --abort) + +\(fn)" t nil) + +(autoload 'magit-reset-index "magit" "\ +Reset the index to COMMIT. +Keep the head and working tree as-is, so if COMMIT refers to the +head this effectively unstages all changes. + +\(git reset COMMIT) + +\(fn COMMIT)" t nil) + +(autoload 'magit-reset "magit" "\ +Reset the head and index to COMMIT, but not the working tree. +With a prefix argument also reset the working tree. + +\(git reset --mixed|--hard COMMIT) + +\(fn COMMIT &optional HARD)" t nil) + +(autoload 'magit-reset-head "magit" "\ +Reset the head and index to COMMIT, but not the working tree. + +\(git reset --mixed COMMIT) + +\(fn COMMIT)" t nil) + +(autoload 'magit-reset-soft "magit" "\ +Reset the head to COMMIT, but not the index and working tree. + +\(git reset --soft REVISION) + +\(fn COMMIT)" t nil) + +(autoload 'magit-reset-hard "magit" "\ +Reset the head, index, and working tree to COMMIT. + +\(git reset --hard REVISION) + +\(fn COMMIT)" t nil) + (autoload 'magit-tag-popup "magit" nil t) + +(autoload 'magit-tag "magit" "\ +Create a new tag with the given NAME at REV. +With a prefix argument annotate the tag. + +\(git tag [--annotate] NAME REV) + +\(fn NAME REV &optional ARGS)" t nil) + +(autoload 'magit-tag-delete "magit" "\ +Delete one or more tags. +If the region marks multiple tags (and nothing else), then offer +to delete those, otherwise prompt for a single tag to be deleted, +defaulting to the tag at point. + +\(git tag -d TAGS) + +\(fn TAGS)" t nil) + (autoload 'magit-notes-popup "magit" nil t) + (autoload 'magit-submodule-popup "magit" nil t) + +(autoload 'magit-submodule-add "magit" "\ +Add the repository at URL as a submodule. +Optional PATH is the path to the submodule relative to the root +of the superproject. If it is nil then the path is determined +based on URL. + +\(fn URL &optional PATH)" t nil) + +(autoload 'magit-submodule-setup "magit" "\ +Clone and register missing submodules and checkout appropriate commits. + +\(fn)" t nil) + +(autoload 'magit-submodule-init "magit" "\ +Register submodules listed in \".gitmodules\" into \".git/config\". + +\(fn)" t nil) + +(autoload 'magit-submodule-update "magit" "\ +Clone missing submodules and checkout appropriate commits. +With a prefix argument also register submodules in \".git/config\". + +\(fn &optional INIT)" t nil) + +(autoload 'magit-submodule-sync "magit" "\ +Update each submodule's remote URL according to \".gitmodules\". + +\(fn)" t nil) + +(autoload 'magit-submodule-fetch "magit" "\ +Fetch all submodules. +With a prefix argument fetch all remotes. + +\(fn &optional ALL)" t nil) + +(autoload 'magit-submodule-deinit "magit" "\ +Unregister the submodule at PATH. + +\(fn PATH)" t nil) + +(defvar global-magit-file-mode nil "\ +Non-nil if Global-Magit-File mode is enabled. +See the command `global-magit-file-mode' for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-magit-file-mode'.") + +(custom-autoload 'global-magit-file-mode "magit" nil) + +(autoload 'global-magit-file-mode "magit" "\ +Toggle Magit-File mode in all buffers. +With prefix ARG, enable Global-Magit-File mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Magit-File mode is enabled in all buffers where +`magit-file-mode-turn-on' would do it. +See `magit-file-mode' for more information on Magit-File mode. + +\(fn &optional ARG)" t nil) + (autoload 'magit-dispatch-popup "magit" nil t) + (autoload 'magit-run-popup "magit" nil t) + +(autoload 'magit-git-command "magit" "\ +Execute a Git subcommand asynchronously, displaying the output. +With a prefix argument run Git in the root of the current +repository, otherwise in `default-directory'. + +\(fn ARGS DIRECTORY)" t nil) + +(autoload 'magit-git-command-topdir "magit" "\ +Execute a Git subcommand asynchronously, displaying the output. +Run Git in the top-level directory of the current repository. + +\(fn)" t nil) + +(autoload 'magit-shell-command "magit" "\ +Execute a shell command asynchronously, displaying the output. +With a prefix argument run the command in the root of the current +repository, otherwise in `default-directory'. + +\(fn ARGS DIRECTORY)" t nil) + +(autoload 'magit-shell-command-topdir "magit" "\ +Execute a shell command asynchronously, displaying the output. +Run the command in the top-level directory of the current repository. + +\(fn)" t nil) + +(autoload 'magit-version "magit" "\ +Return the version of Magit currently in use. +When called interactive also show the used versions of Magit, +Git, and Emacs in the echo area. + +\(fn)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-apply" "magit-apply.el" (22140 7080 +;;;;;; 0 0)) +;;; Generated autoloads from magit-apply.el + +(autoload 'magit-stage-file "magit-apply" "\ +Stage all changes to FILE. +With a prefix argument or when there is no file at point ask for +the file to be staged. Otherwise stage the file at point without +requiring confirmation. + +\(fn FILE)" t nil) + +(autoload 'magit-stage-modified "magit-apply" "\ +Stage all changes to files modified in the worktree. +Stage all new content of tracked files and remove tracked files +that no longer exist in the working tree from the index also. +With a prefix argument also stage previously untracked (but not +ignored) files. +\('git add --update|--all .'). + +\(fn &optional ALL)" t nil) + +(autoload 'magit-unstage-file "magit-apply" "\ +Unstage all changes to FILE. +With a prefix argument or when there is no file at point ask for +the file to be unstaged. Otherwise unstage the file at point +without requiring confirmation. + +\(fn FILE)" t nil) + +(autoload 'magit-unstage-all "magit-apply" "\ +Remove all changes from the staging area. + +\(fn)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-bisect" "magit-bisect.el" (22140 7080 +;;;;;; 0 0)) +;;; Generated autoloads from magit-bisect.el + (autoload 'magit-bisect-popup "magit-bisect" nil t) + +(autoload 'magit-bisect-start "magit-bisect" "\ +Start a bisect session. + +Bisecting a bug means to find the commit that introduced it. +This command starts such a bisect session by asking for a know +good and a bad commit. To move the session forward use the +other actions from the bisect popup (\\\\[magit-bisect-popup]). + +\(fn BAD GOOD)" t nil) + +(autoload 'magit-bisect-reset "magit-bisect" "\ +After bisecting, cleanup bisection state and return to original `HEAD'. + +\(fn)" t nil) + +(autoload 'magit-bisect-good "magit-bisect" "\ +While bisecting, mark the current commit as good. +Use this after you have asserted that the commit does not contain +the bug in question. + +\(fn)" t nil) + +(autoload 'magit-bisect-bad "magit-bisect" "\ +While bisecting, mark the current commit as bad. +Use this after you have asserted that the commit does contain the +bug in question. + +\(fn)" t nil) + +(autoload 'magit-bisect-skip "magit-bisect" "\ +While bisecting, skip the current commit. +Use this if for some reason the current commit is not a good one +to test. This command lets Git choose a different one. + +\(fn)" t nil) + +(autoload 'magit-bisect-run "magit-bisect" "\ +Bisect automatically by running commands after each step. + +Unlike `git bisect run' this can be used before bisecting has +begun. In that case it behaves like `git bisect start; git +bisect run'. + +\(fn CMDLINE &optional BAD GOOD)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-blame" "magit-blame.el" (22140 7080 +;;;;;; 0 0)) +;;; Generated autoloads from magit-blame.el + (autoload 'magit-blame-popup "magit-blame" nil t) + +(autoload 'magit-blame "magit-blame" "\ +Display edit history of FILE up to REVISION. + +Interactively blame the file being visited in the current buffer. +If the buffer visits a revision of that file, then blame up to +that revision, otherwise blame the file's full history, including +uncommitted changes. + +If Magit-Blame mode is already turned on then blame recursively, by +visiting REVISION:FILE (using `magit-find-file'), where revision +is the revision before the revision that added the lines at +point. + +ARGS is a list of additional arguments to pass to `git blame'; +only arguments available from `magit-blame-popup' should be used. + +\(fn REVISION FILE &optional ARGS)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-commit" "magit-commit.el" (22140 7080 +;;;;;; 0 0)) +;;; Generated autoloads from magit-commit.el + +(autoload 'magit-commit "magit-commit" "\ +Create a new commit on HEAD. +With a prefix argument amend to the commit at HEAD instead. + +\(git commit [--amend] ARGS) + +\(fn &optional ARGS)" t nil) + +(autoload 'magit-commit-amend "magit-commit" "\ +Amend the last commit. + +\(git commit --amend ARGS) + +\(fn &optional ARGS)" t nil) + +(autoload 'magit-commit-extend "magit-commit" "\ +Amend the last commit, without editing the message. + +With a prefix argument keep the committer date, otherwise change +it. The option `magit-commit-extend-override-date' can be used +to inverse the meaning of the prefix argument. +\(git commit +--amend --no-edit) + +\(fn &optional ARGS OVERRIDE-DATE)" t nil) + +(autoload 'magit-commit-reword "magit-commit" "\ +Reword the last commit, ignoring staged changes. + +With a prefix argument keep the committer date, otherwise change +it. The option `magit-commit-reword-override-date' can be used +to inverse the meaning of the prefix argument. + +Non-interactively respect the optional OVERRIDE-DATE argument +and ignore the option. + +\(git commit --amend --only) + +\(fn &optional ARGS OVERRIDE-DATE)" t nil) + +(autoload 'magit-commit-fixup "magit-commit" "\ +Create a fixup commit. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'. + +\(fn &optional COMMIT ARGS)" t nil) + +(autoload 'magit-commit-squash "magit-commit" "\ +Create a squash commit, without editing the squash message. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'. + +\(fn &optional COMMIT ARGS)" t nil) + +(autoload 'magit-commit-augment "magit-commit" "\ +Create a squash commit, editing the squash message. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'. + +\(fn &optional COMMIT ARGS)" t nil) + +(autoload 'magit-commit-instant-fixup "magit-commit" "\ +Create a fixup commit targeting COMMIT and instantly rebase. + +\(fn &optional COMMIT ARGS)" t nil) + +(autoload 'magit-commit-instant-squash "magit-commit" "\ +Create a squash commit targeting COMMIT and instantly rebase. + +\(fn &optional COMMIT ARGS)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-diff" "magit-diff.el" (22140 7080 0 +;;;;;; 0)) +;;; Generated autoloads from magit-diff.el + +(autoload 'magit-diff-dwim "magit-diff" "\ +Show changes for the thing at point. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-diff "magit-diff" "\ +Show differences between two commits. + +REV-OR-RANGE should be a RANGE or a single revision. If it is a +revision, then show changes in the working tree relative to that +revision. If it is a range, but one side is omitted, then show +changes relative to `HEAD'. + +If the region is active, use the revisions on the first and last +line of the region as the two sides of the range. With a prefix +argument, instead of diffing the revisions, choose a revision to +view changes along, starting at the common ancestor of both +revisions (i.e., use a \"...\" range). + +\(fn REV-OR-RANGE &optional ARGS FILES)" t nil) + +(autoload 'magit-diff-working-tree "magit-diff" "\ +Show changes between the current working tree and the `HEAD' commit. +With a prefix argument show changes between the working tree and +a commit read from the minibuffer. + +\(fn &optional REV ARGS FILES)" t nil) + +(autoload 'magit-diff-staged "magit-diff" "\ +Show changes between the index and the `HEAD' commit. +With a prefix argument show changes between the index and +a commit read from the minibuffer. + +\(fn &optional REV ARGS FILES)" t nil) + +(autoload 'magit-diff-unstaged "magit-diff" "\ +Show changes between the working tree and the index. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-diff-while-committing "magit-diff" "\ +While committing, show the changes that are about to be committed. +While amending, invoking the command again toggles between +showing just the new changes or all the changes that will +be committed. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-diff-paths "magit-diff" "\ +Show changes between any two files on disk. + +\(fn A B)" t nil) + +(autoload 'magit-show-commit "magit-diff" "\ +Show the revision at point. +If there is no revision at point or with a prefix argument prompt +for a revision. + +\(fn REV &optional ARGS FILES MODULE)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-ediff" "magit-ediff.el" (22140 7080 +;;;;;; 0 0)) +;;; Generated autoloads from magit-ediff.el + (autoload 'magit-ediff-popup "magit-ediff" nil t) + +(autoload 'magit-ediff-resolve "magit-ediff" "\ +Resolve outstanding conflicts in FILE using Ediff. +FILE has to be relative to the top directory of the repository. + +In the rare event that you want to manually resolve all +conflicts, including those already resolved by Git, use +`ediff-merge-revisions-with-ancestor'. + +\(fn FILE)" t nil) + +(autoload 'magit-ediff-stage "magit-ediff" "\ +Stage and unstage changes to FILE using Ediff. +FILE has to be relative to the top directory of the repository. + +\(fn FILE)" t nil) + +(autoload 'magit-ediff-compare "magit-ediff" "\ +Compare REVA:FILEA with REVB:FILEB using Ediff. + +FILEA and FILEB have to be relative to the top directory of the +repository. If REVA or REVB is nil then this stands for the +working tree state. + +If the region is active, use the revisions on the first and last +line of the region. With a prefix argument, instead of diffing +the revisions, choose a revision to view changes along, starting +at the common ancestor of both revisions (i.e., use a \"...\" +range). + +\(fn REVA REVB FILEA FILEB)" t nil) + +(autoload 'magit-ediff-dwim "magit-ediff" "\ +Compare, stage, or resolve using Ediff. +This command tries to guess what file, and what commit or range +the user wants to compare, stage, or resolve using Ediff. It +might only be able to guess either the file, or range or commit, +in which case the user is asked about the other. It might not +always guess right, in which case the appropriate `magit-ediff-*' +command has to be used explicitly. If it cannot read the user's +mind at all, then it asks the user for a command to run. + +\(fn)" t nil) + +(autoload 'magit-ediff-show-staged "magit-ediff" "\ +Show staged changes using Ediff. + +This only allows looking at the changes; to stage, unstage, +and discard changes using Ediff, use `magit-ediff-stage'. + +FILE must be relative to the top directory of the repository. + +\(fn FILE)" t nil) + +(autoload 'magit-ediff-show-unstaged "magit-ediff" "\ +Show unstaged changes using Ediff. + +This only allows looking at the changes; to stage, unstage, +and discard changes using Ediff, use `magit-ediff-stage'. + +FILE must be relative to the top directory of the repository. + +\(fn FILE)" t nil) + +(autoload 'magit-ediff-show-working-tree "magit-ediff" "\ +Show changes between HEAD and working tree using Ediff. +FILE must be relative to the top directory of the repository. + +\(fn FILE)" t nil) + +(autoload 'magit-ediff-show-commit "magit-ediff" "\ +Show changes introduced by COMMIT using Ediff. + +\(fn COMMIT)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-extras" "magit-extras.el" (22140 7080 +;;;;;; 0 0)) +;;; Generated autoloads from magit-extras.el + +(autoload 'magit-run-git-gui "magit-extras" "\ +Run `git gui' for the current git repository. + +\(fn)" t nil) + +(autoload 'magit-run-git-gui-blame "magit-extras" "\ +Run `git gui blame' on the given FILENAME and COMMIT. +Interactively run it for the current file and the HEAD, with a +prefix or when the current file cannot be determined let the user +choose. When the current buffer is visiting FILENAME instruct +blame to center around the line point is on. + +\(fn COMMIT FILENAME &optional LINENUM)" t nil) + +(autoload 'magit-run-gitk "magit-extras" "\ +Run `gitk' in the current repository. + +\(fn)" t nil) + +(autoload 'magit-run-gitk-branches "magit-extras" "\ +Run `gitk --branches' in the current repository. + +\(fn)" t nil) + +(autoload 'magit-run-gitk-all "magit-extras" "\ +Run `gitk --all' in the current repository. + +\(fn)" t nil) + +(autoload 'magit-clean "magit-extras" "\ +Remove untracked files from the working tree. +With a prefix argument also remove ignored files, +with two prefix arguments remove ignored files only. + +\(git clean -f -d [-x|-X]) + +\(fn &optional ARG)" t nil) + +(autoload 'magit-gitignore "magit-extras" "\ +Instruct Git to ignore FILE-OR-PATTERN. +With a prefix argument only ignore locally. + +\(fn FILE-OR-PATTERN &optional LOCAL)" t nil) + +(autoload 'magit-gitignore-locally "magit-extras" "\ +Instruct Git to locally ignore FILE-OR-PATTERN. + +\(fn FILE-OR-PATTERN)" t nil) + +(autoload 'magit-add-change-log-entry "magit-extras" "\ +Find change log file and add date entry and item for current change. +This differs from `add-change-log-entry' (which see) in that +it acts on the current hunk in a Magit buffer instead of on +a position in a file-visiting buffer. + +\(fn &optional WHOAMI FILE-NAME OTHER-WINDOW)" t nil) + +(autoload 'magit-add-change-log-entry-other-window "magit-extras" "\ +Find change log file in other window and add entry and item. +This differs from `add-change-log-entry-other-window' (which see) +in that it acts on the current hunk in a Magit buffer instead of +on a position in a file-visiting buffer. + +\(fn &optional WHOAMI FILE-NAME)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-log" "magit-log.el" (22140 7080 0 0)) +;;; Generated autoloads from magit-log.el + +(autoload 'magit-log-current "magit-log" "\ +Show log for the current branch. +When `HEAD' is detached or with a prefix argument show log for +one or more revs read from the minibuffer. + +\(fn REVS &optional ARGS FILES)" t nil) + +(autoload 'magit-log "magit-log" "\ +Show log for one or more revs read from the minibuffer. +The user can input any revision or revisions separated by a +space, or even ranges, but only branches and tags, and a +representation of the commit at point, are available as +completion candidates. + +\(fn REVS &optional ARGS FILES)" t nil) + +(autoload 'magit-log-head "magit-log" "\ +Show log for `HEAD'. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-log-branches "magit-log" "\ +Show log for all local branches and `HEAD'. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-log-all-branches "magit-log" "\ +Show log for all local and remote branches and `HEAD'. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-log-all "magit-log" "\ +Show log for all references and `HEAD'. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-log-buffer-file "magit-log" "\ +Show log for the blob or file visited in the current buffer. +With a prefix argument or when `--follow' is part of +`magit-log-arguments', then follow renames. + +\(fn &optional FOLLOW BEG END)" t nil) + +(autoload 'magit-reflog-current "magit-log" "\ +Display the reflog of the current branch. + +\(fn)" t nil) + +(autoload 'magit-reflog "magit-log" "\ +Display the reflog of a branch. + +\(fn REF)" t nil) + +(autoload 'magit-reflog-head "magit-log" "\ +Display the `HEAD' reflog. + +\(fn)" t nil) + +(autoload 'magit-cherry "magit-log" "\ +Show commits in a branch that are not merged in the upstream branch. + +\(fn HEAD UPSTREAM)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-remote" "magit-remote.el" (22140 7080 +;;;;;; 0 0)) +;;; Generated autoloads from magit-remote.el + +(autoload 'magit-clone "magit-remote" "\ +Clone the REPOSITORY to DIRECTORY. +Then show the status buffer for the new repository. + +\(fn REPOSITORY DIRECTORY)" t nil) + (autoload 'magit-remote-popup "magit-remote" nil t) + +(autoload 'magit-remote-add "magit-remote" "\ +Add a remote named REMOTE and fetch it. + +\(fn REMOTE URL)" t nil) + +(autoload 'magit-remote-rename "magit-remote" "\ +Rename the remote named OLD to NEW. + +\(fn OLD NEW)" t nil) + +(autoload 'magit-remote-set-url "magit-remote" "\ +Change the url of the remote named REMOTE to URL. + +\(fn REMOTE URL)" t nil) + +(autoload 'magit-remote-remove "magit-remote" "\ +Delete the remote named REMOTE. + +\(fn REMOTE)" t nil) + (autoload 'magit-fetch-popup "magit-remote" nil t) + +(autoload 'magit-fetch-from-pushremote "magit-remote" "\ +Fetch from the push-remote of the current branch. + +\(fn ARGS)" t nil) + +(autoload 'magit-fetch-from-upstream "magit-remote" "\ +Fetch from the upstream repository of the current branch. + +\(fn ARGS)" t nil) + +(autoload 'magit-fetch "magit-remote" "\ +Fetch from another repository. + +\(fn REMOTE ARGS)" t nil) + +(autoload 'magit-fetch-all "magit-remote" "\ +Fetch from all remotes. + +\(fn ARGS)" t nil) + +(autoload 'magit-fetch-all-prune "magit-remote" "\ +Fetch from all remotes, and prune. +Prune remote tracking branches for branches that have been +removed on the respective remote. + +\(fn)" t nil) + +(autoload 'magit-fetch-all-no-prune "magit-remote" "\ +Fetch from all remotes. + +\(fn)" t nil) + (autoload 'magit-pull-popup "magit-remote" nil t) + (autoload 'magit-pull-and-fetch-popup "magit-remote" nil t) + +(autoload 'magit-pull-from-pushremote "magit-remote" "\ +Pull from the push-remote of the current branch. + +\(fn ARGS)" t nil) + +(autoload 'magit-pull-from-upstream "magit-remote" "\ +Pull from the upstream of the current branch. + +\(fn ARGS)" t nil) + +(autoload 'magit-pull "magit-remote" "\ +Pull from a branch read in the minibuffer. + +\(fn SOURCE ARGS)" t nil) + (autoload 'magit-push-popup "magit-remote" nil t) + +(autoload 'magit-push-current-to-pushremote "magit-remote" "\ +Push the current branch to `branch..pushRemote'. +If that variable is unset, then push to `remote.pushDefault'. + +When `magit-push-current-set-remote-if-missing' is non-nil and +the push-remote is not configured, then read the push-remote from +the user, set it, and then push to it. With a prefix argument +the push-remote can be changed before pushed to it. + +\(fn ARGS &optional PUSH-REMOTE)" t nil) + +(autoload 'magit-push-current-to-upstream "magit-remote" "\ +Push the current branch to its upstream branch. + +When `magit-push-current-set-remote-if-missing' is non-nil and +the upstream is not configured, then read the upstream from the +user, set it, and then push to it. With a prefix argument the +upstream can be changed before pushed to it. + +\(fn ARGS &optional UPSTREAM)" t nil) + +(autoload 'magit-push-current "magit-remote" "\ +Push the current branch to a branch read in the minibuffer. + +\(fn TARGET ARGS)" t nil) + +(autoload 'magit-push "magit-remote" "\ +Push an arbitrary branch or commit somewhere. +Both the source and the target are read in the minibuffer. + +\(fn SOURCE TARGET ARGS)" t nil) + +(autoload 'magit-push-matching "magit-remote" "\ +Push all matching branches to another repository. +If multiple remotes exist, then read one from the user. +If just one exists, use that without requiring confirmation. + +\(fn REMOTE &optional ARGS)" t nil) + +(autoload 'magit-push-tags "magit-remote" "\ +Push all tags to another repository. +If only one remote exists, then push to that. Otherwise prompt +for a remote, offering the remote configured for the current +branch as default. + +\(fn REMOTE &optional ARGS)" t nil) + +(autoload 'magit-push-tag "magit-remote" "\ +Push a tag to another repository. + +\(fn TAG REMOTE &optional ARGS)" t nil) + +(autoload 'magit-push-implicitly "magit-remote" "\ +Push somewhere without using an explicit refspec. + +This command simply runs \"git push -v [ARGS]\". ARGS are the +arguments specified in the popup buffer. No explicit refspec +arguments are used. Instead the behavior depends on at least +these Git variables: `push.default', `branch.pushDefault', +`branch..pushRemote', `branch..remote', +`branch..merge', and `remote..push'. + +To add this command to the push popup add this to your init file: + + (with-eval-after-load \\='magit-remote + (magit-define-popup-action \\='magit-push-popup ?P + 'magit-push-implicitly--desc + 'magit-push-implicitly ?p t)) + +The function `magit-push-implicitly--desc' attempts to predict +what this command will do, the value it returns is displayed in +the popup buffer. + +\(fn ARGS)" t nil) + +(autoload 'magit-push-to-remote "magit-remote" "\ +Push to REMOTE without using an explicit refspec. +The REMOTE is read in the minibuffer. + +This command simply runs \"git push -v [ARGS] REMOTE\". ARGS +are the arguments specified in the popup buffer. No refspec +arguments are used. Instead the behavior depends on at least +these Git variables: `push.default', `branch.pushDefault', +`branch..pushRemote', `branch..remote', +`branch..merge', and `remote..push'. + +To add this command to the push popup add this to your init file: + + (with-eval-after-load \\='magit-remote + (magit-define-popup-action \\='magit-push-popup ?r + 'magit-push-to-remote--desc + 'magit-push-to-remote ?p t)) + +\(fn REMOTE ARGS)" t nil) + (autoload 'magit-patch-popup "magit-remote" nil t) + +(autoload 'magit-format-patch "magit-remote" "\ +Create patches for the commits in RANGE. +When a single commit is given for RANGE, create a patch for the +changes introduced by that commit (unlike 'git format-patch' +which creates patches for all commits that are reachable from +HEAD but not from the specified commit). + +\(fn RANGE ARGS)" t nil) + +(autoload 'magit-request-pull "magit-remote" "\ +Request upstream to pull from you public repository. + +URL is the url of your publically accessible repository. +START is a commit that already is in the upstream repository. +END is the last commit, usually a branch name, which upstream +is asked to pull. START has to be reachable from that commit. + +\(fn URL START END)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-sequence" "magit-sequence.el" (22140 +;;;;;; 7080 0 0)) +;;; Generated autoloads from magit-sequence.el + +(autoload 'magit-sequencer-continue "magit-sequence" "\ +Resume the current cherry-pick or revert sequence. + +\(fn)" t nil) + +(autoload 'magit-sequencer-skip "magit-sequence" "\ +Skip the stopped at commit during a cherry-pick or revert sequence. + +\(fn)" t nil) + +(autoload 'magit-sequencer-abort "magit-sequence" "\ +Abort the current cherry-pick or revert sequence. +This discards all changes made since the sequence started. + +\(fn)" t nil) + (autoload 'magit-cherry-pick-popup "magit-sequence" nil t) + +(autoload 'magit-cherry-pick "magit-sequence" "\ +Cherry-pick COMMIT. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then pick all of them, +without prompting. + +\(fn COMMIT &optional ARGS)" t nil) + +(autoload 'magit-cherry-apply "magit-sequence" "\ +Apply the changes in COMMIT but do not commit them. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then apply all of them, +without prompting. + +\(fn COMMIT &optional ARGS)" t nil) + (autoload 'magit-revert-popup "magit-sequence" nil t) + +(autoload 'magit-revert "magit-sequence" "\ +Revert COMMIT by creating a new commit. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then revert all of them, +without prompting. + +\(fn COMMIT &optional ARGS)" t nil) + +(autoload 'magit-revert-no-commit "magit-sequence" "\ +Revert COMMIT by applying it in reverse to the worktree. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then revert all of them, +without prompting. + +\(fn COMMIT &optional ARGS)" t nil) + (autoload 'magit-am-popup "magit-sequence" nil t) + +(autoload 'magit-am-apply-patches "magit-sequence" "\ +Apply the patches FILES. + +\(fn &optional FILES ARGS)" t nil) + +(autoload 'magit-am-apply-maildir "magit-sequence" "\ +Apply the patches from MAILDIR. + +\(fn &optional MAILDIR ARGS)" t nil) + +(autoload 'magit-am-continue "magit-sequence" "\ +Resume the current patch applying sequence. + +\(fn)" t nil) + +(autoload 'magit-am-skip "magit-sequence" "\ +Skip the stopped at patch during a patch applying sequence. + +\(fn)" t nil) + +(autoload 'magit-am-abort "magit-sequence" "\ +Abort the current patch applying sequence. +This discards all changes made since the sequence started. + +\(fn)" t nil) + (autoload 'magit-rebase-popup "magit-sequence" nil t) + +(autoload 'magit-rebase-onto-pushremote "magit-sequence" "\ +Rebase the current branch onto `branch..pushRemote'. +If that variable is unset, then rebase onto `remote.pushDefault'. + +\(fn ARGS)" t nil) + +(autoload 'magit-rebase-onto-upstream "magit-sequence" "\ +Rebase the current branch onto its upstream branch. + +\(fn ARGS)" t nil) + +(autoload 'magit-rebase "magit-sequence" "\ +Rebase the current branch onto a branch read in the minibuffer. +All commits that are reachable from head but not from the +selected branch TARGET are being rebased. + +\(fn TARGET ARGS)" t nil) + +(autoload 'magit-rebase-subset "magit-sequence" "\ +Rebase a subset of the current branches history onto a new base. +Rebase commits from START to `HEAD' onto NEWBASE. +START has to be selected from a list of recent commits. + +\(fn NEWBASE START ARGS)" t nil) + +(autoload 'magit-rebase-interactive "magit-sequence" "\ +Start an interactive rebase sequence. + +\(fn COMMIT ARGS)" t nil) + +(autoload 'magit-rebase-autosquash "magit-sequence" "\ +Combine squash and fixup commits with their intended targets. + +\(fn ARGS)" t nil) + +(autoload 'magit-rebase-edit-commit "magit-sequence" "\ +Edit a single older commit using rebase. + +\(fn COMMIT ARGS)" t nil) + +(autoload 'magit-rebase-reword-commit "magit-sequence" "\ +Reword a single older commit using rebase. + +\(fn COMMIT ARGS)" t nil) + +(autoload 'magit-rebase-continue "magit-sequence" "\ +Restart the current rebasing operation. + +\(fn)" t nil) + +(autoload 'magit-rebase-skip "magit-sequence" "\ +Skip the current commit and restart the current rebase operation. + +\(fn)" t nil) + +(autoload 'magit-rebase-edit "magit-sequence" "\ +Edit the todo list of the current rebase operation. + +\(fn)" t nil) + +(autoload 'magit-rebase-abort "magit-sequence" "\ +Abort the current rebase operation, restoring the original branch. + +\(fn)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-stash" "magit-stash.el" (22140 7080 +;;;;;; 0 0)) +;;; Generated autoloads from magit-stash.el + (autoload 'magit-stash-popup "magit-stash" nil t) + +(autoload 'magit-stash "magit-stash" "\ +Create a stash of the index and working tree. +Untracked files are included according to popup arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'. + +\(fn MESSAGE &optional INCLUDE-UNTRACKED)" t nil) + +(autoload 'magit-stash-index "magit-stash" "\ +Create a stash of the index only. +Unstaged and untracked changes are not stashed. The stashed +changes are applied in reverse to both the index and the +worktree. This command can fail when the worktree is not clean. +Applying the resulting stash has the inverse effect. + +\(fn MESSAGE)" t nil) + +(autoload 'magit-stash-worktree "magit-stash" "\ +Create a stash of the working tree only. +Untracked files are included according to popup arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'. + +\(fn MESSAGE &optional INCLUDE-UNTRACKED)" t nil) + +(autoload 'magit-stash-keep-index "magit-stash" "\ +Create a stash of the index and working tree, keeping index intact. +Untracked files are included according to popup arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'. + +\(fn MESSAGE &optional INCLUDE-UNTRACKED)" t nil) + +(autoload 'magit-snapshot "magit-stash" "\ +Create a snapshot of the index and working tree. +Untracked files are included according to popup arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'. + +\(fn &optional INCLUDE-UNTRACKED)" t nil) + +(autoload 'magit-snapshot-index "magit-stash" "\ +Create a snapshot of the index only. +Unstaged and untracked changes are not stashed. + +\(fn)" t nil) + +(autoload 'magit-snapshot-worktree "magit-stash" "\ +Create a snapshot of the working tree only. +Untracked files are included according to popup arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'. + +\(fn &optional INCLUDE-UNTRACKED)" t nil) + +(autoload 'magit-stash-apply "magit-stash" "\ +Apply a stash to the working tree. +Try to preserve the stash index. If that fails because there +are staged changes, apply without preserving the stash index. + +\(fn STASH)" t nil) + +(autoload 'magit-stash-drop "magit-stash" "\ +Remove a stash from the stash list. +When the region is active offer to drop all contained stashes. + +\(fn STASH)" t nil) + +(autoload 'magit-stash-clear "magit-stash" "\ +Remove all stashes saved in REF's reflog by deleting REF. + +\(fn REF)" t nil) + +(autoload 'magit-stash-branch "magit-stash" "\ +Create and checkout a new BRANCH from STASH. + +\(fn STASH BRANCH)" t nil) + +(autoload 'magit-stash-format-patch "magit-stash" "\ +Create a patch from STASH + +\(fn STASH)" t nil) + +(autoload 'magit-stash-list "magit-stash" "\ +List all stashes in a buffer. + +\(fn)" t nil) + +(autoload 'magit-stash-show "magit-stash" "\ +Show all diffs of a stash in a buffer. + +\(fn STASH &optional ARGS FILES)" t nil) + +;;;*** + +;;;### (autoloads nil "magit-wip" "magit-wip.el" (22140 7080 0 0)) +;;; Generated autoloads from magit-wip.el + +(defvar magit-wip-after-save-mode nil "\ +Non-nil if Magit-Wip-After-Save mode is enabled. +See the command `magit-wip-after-save-mode' for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `magit-wip-after-save-mode'.") + +(custom-autoload 'magit-wip-after-save-mode "magit-wip" nil) + +(autoload 'magit-wip-after-save-mode "magit-wip" "\ +Toggle Magit-Wip-After-Save-Local mode in all buffers. +With prefix ARG, enable Magit-Wip-After-Save mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Magit-Wip-After-Save-Local mode is enabled in all buffers where +`magit-wip-after-save-local-mode-turn-on' would do it. +See `magit-wip-after-save-local-mode' for more information on Magit-Wip-After-Save-Local mode. + +\(fn &optional ARG)" t nil) + +(defvar magit-wip-after-apply-mode nil "\ +Non-nil if Magit-Wip-After-Apply mode is enabled. +See the command `magit-wip-after-apply-mode' for a description of this minor mode.") + +(custom-autoload 'magit-wip-after-apply-mode "magit-wip" nil) + +(autoload 'magit-wip-after-apply-mode "magit-wip" "\ +Commit to work-in-progress refs. + +After applying a change using any \"apply variant\" +command (apply, stage, unstage, discard, and reverse) commit the +affected files to the current wip refs. For each branch there +may be two wip refs; one contains snapshots of the files as found +in the worktree and the other contains snapshots of the entries +in the index. + +\(fn &optional ARG)" t nil) + +(defvar magit-wip-before-change-mode nil "\ +Non-nil if Magit-Wip-Before-Change mode is enabled. +See the command `magit-wip-before-change-mode' for a description of this minor mode.") + +(custom-autoload 'magit-wip-before-change-mode "magit-wip" nil) + +(autoload 'magit-wip-before-change-mode "magit-wip" "\ +Commit to work-in-progress refs before certain destructive changes. + +Before invoking a revert command or an \"apply variant\" +command (apply, stage, unstage, discard, and reverse) commit the +affected tracked files to the current wip refs. For each branch +there may be two wip refs; one contains snapshots of the files +as found in the worktree and the other contains snapshots of the +entries in the index. + +Only changes to files which could potentially be affected by the +command which is about to be called are committed. + +\(fn &optional ARG)" t nil) + +;;;*** + +;;;### (autoloads nil nil ("magit-core.el" "magit-git.el" "magit-mode.el" +;;;;;; "magit-pkg.el" "magit-process.el" "magit-section.el" "magit-utils.el") +;;;;;; (22140 7080 159081 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; End: +;;; magit-autoloads.el ends here diff --git a/elpa/magit-20151223.1425/magit-bisect.el b/elpa/magit-20151223.1425/magit-bisect.el new file mode 100644 index 00000000..8a7702cb --- /dev/null +++ b/elpa/magit-20151223.1425/magit-bisect.el @@ -0,0 +1,203 @@ +;;; magit-bisect.el --- bisect support for Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2011-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; Use a binary search to find the commit that introduced a bug. + +;;; Code: + +(require 'magit) + +(defface magit-bisect-good + '((t :foreground "DarkOliveGreen")) + "Face for good bisect revisions." + :group 'magit-faces) + +(defface magit-bisect-skip + '((t :foreground "DarkGoldenrod")) + "Face for skipped bisect revisions." + :group 'magit-faces) + +(defface magit-bisect-bad + '((t :foreground "IndianRed4")) + "Face for bad bisect revisions." + :group 'magit-faces) + +;;;###autoload (autoload 'magit-bisect-popup "magit-bisect" nil t) +(magit-define-popup magit-bisect-popup + "Popup console for bisect commands." + 'magit-commands + :man-page "git-bisect" + :actions '((?B "Start" magit-bisect-start) + (?s "Start script" magit-bisect-run)) + :sequence-actions '((?b "Bad" magit-bisect-bad) + (?g "Good" magit-bisect-good) + (?k "Skip" magit-bisect-skip) + (?r "Reset" magit-bisect-reset) + (?s "Run script" magit-bisect-run)) + :sequence-predicate 'magit-bisect-in-progress-p) + +;;;###autoload +(defun magit-bisect-start (bad good) + "Start a bisect session. + +Bisecting a bug means to find the commit that introduced it. +This command starts such a bisect session by asking for a know +good and a bad commit. To move the session forward use the +other actions from the bisect popup (\ +\\\\[magit-bisect-popup])." + (interactive (if (magit-bisect-in-progress-p) + (user-error "Already bisecting") + (magit-bisect-start-read-args))) + (magit-bisect-async "start" (list bad good) t)) + +(defun magit-bisect-start-read-args () + (let ((b (magit-read-branch-or-commit "Start bisect with bad revision"))) + (list b (magit-read-other-branch-or-commit "Good revision" b)))) + +;;;###autoload +(defun magit-bisect-reset () + "After bisecting, cleanup bisection state and return to original `HEAD'." + (interactive) + (when (magit-confirm 'reset-bisect) + (magit-run-git "bisect" "reset") + (ignore-errors (delete-file (magit-git-dir "BISECT_CMD_OUTPUT"))))) + +;;;###autoload +(defun magit-bisect-good () + "While bisecting, mark the current commit as good. +Use this after you have asserted that the commit does not contain +the bug in question." + (interactive) + (magit-bisect-async "good")) + +;;;###autoload +(defun magit-bisect-bad () + "While bisecting, mark the current commit as bad. +Use this after you have asserted that the commit does contain the +bug in question." + (interactive) + (magit-bisect-async "bad")) + +;;;###autoload +(defun magit-bisect-skip () + "While bisecting, skip the current commit. +Use this if for some reason the current commit is not a good one +to test. This command lets Git choose a different one." + (interactive) + (magit-bisect-async "skip")) + +;;;###autoload +(defun magit-bisect-run (cmdline &optional bad good) + "Bisect automatically by running commands after each step. + +Unlike `git bisect run' this can be used before bisecting has +begun. In that case it behaves like `git bisect start; git +bisect run'." + (interactive (let ((args (and (not (magit-bisect-in-progress-p)) + (magit-bisect-start-read-args)))) + (cons (read-shell-command "Bisect shell command: ") args))) + (when (and bad good) + (magit-bisect-start bad good)) + (magit-bisect-async "run" (list cmdline))) + +(defun magit-bisect-async (subcommand &optional args no-assert) + (unless (or no-assert (magit-bisect-in-progress-p)) + (user-error "Not bisecting")) + (magit-with-toplevel + (let ((file (magit-git-dir "BISECT_CMD_OUTPUT"))) + (ignore-errors (delete-file file)) + (magit-run-git-with-logfile file "bisect" subcommand args)) + (magit-process-wait) + (magit-refresh))) + +(defun magit-bisect-in-progress-p () + (file-exists-p (magit-git-dir "BISECT_LOG"))) + +(defun magit-insert-bisect-output () + "While bisecting, insert section with output from `git bisect'." + (when (magit-bisect-in-progress-p) + (let ((lines + (or (magit-file-lines (magit-git-dir "BISECT_CMD_OUTPUT")) + (list "Bisecting: (no saved bisect output)" + "It appears you have invoked `git bisect' from a shell." + "There is nothing wrong with that, we just cannot display" + "anything useful here. Consult the shell output instead."))) + (done-re "^[a-z0-9]\\{40\\} is the first bad commit$")) + (magit-insert-section (bisect-output t) + (magit-insert-heading + (propertize (or (and (string-match done-re (car lines)) (pop lines)) + (--first (string-match done-re it) lines) + (pop lines)) + 'face 'magit-section-heading)) + (dolist (line lines) + (insert line "\n")))) + (insert "\n"))) + +(defun magit-insert-bisect-rest () + "While bisecting, insert section visualizing the bisect state." + (when (magit-bisect-in-progress-p) + (magit-insert-section (bisect-view) + (magit-insert-heading "Bisect Rest:") + (magit-git-wash (apply-partially 'magit-log-wash-log 'bisect-vis) + "bisect" "visualize" "git" "log" + "--format=%h%d %s" "--decorate=full")))) + +(defun magit-insert-bisect-log () + "While bisecting, insert section logging bisect progress." + (when (magit-bisect-in-progress-p) + (magit-insert-section (bisect-log) + (magit-insert-heading "Bisect Log:") + (magit-git-wash #'magit-wash-bisect-log "bisect" "log") + (insert ?\n)))) + +(defun magit-wash-bisect-log (_args) + (let (beg) + (while (progn (setq beg (point-marker)) + (re-search-forward "^\\(git bisect [^\n]+\n\\)" nil t)) + (magit-bind-match-strings (heading) nil + (magit-delete-match) + (save-restriction + (narrow-to-region beg (point)) + (goto-char (point-min)) + (magit-insert-section (bisect-log heading t) + (insert (propertize heading 'face 'magit-section-secondary-heading)) + (magit-insert-heading) + (magit-wash-sequence + (apply-partially 'magit-log-wash-rev 'bisect-log + (magit-abbrev-length))) + (insert ?\n))))) + (when (re-search-forward + "# first bad commit: \\[\\([a-z0-9]\\{40\\}\\)\\] [^\n]+\n" nil t) + (magit-bind-match-strings (hash) nil + (magit-delete-match) + (magit-insert-section (bisect-log) + (insert hash " is the first bad commit\n")))))) + +;;; magit-bisect.el ends soon +(provide 'magit-bisect) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-bisect.el ends here diff --git a/elpa/magit-20151223.1425/magit-blame.el b/elpa/magit-20151223.1425/magit-blame.el new file mode 100644 index 00000000..983e4dd8 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-blame.el @@ -0,0 +1,518 @@ +;;; magit-blame.el --- blame support for Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2012-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; Annotates each line in file-visiting buffer with information from +;; the revision which last modified the line. + +;;; Code: + +(require 'magit) + +;;; Options + +(defgroup magit-blame nil + "Blame support for Magit." + :group 'magit-extensions) + +(defcustom magit-blame-heading-format "%-20a %C %s" + "Format string used for blame headings. + +The following placeholders are recognized: + + %H hash + %s summary + %a author + %A author time + %c committer + %C committer time + +The author and committer time formats can be specified with +`magit-blame-time-format'." + :group 'magit-blame + :type 'string) + +(defcustom magit-blame-time-format "%F %H:%M" + "Format for time strings in blame headings." + :group 'magit-blame + :type 'string) + +(defcustom magit-blame-show-headings t + "Whether to initially show blame block headings. +The headings can also be toggled locally using command +`magit-blame-toggle-headings'." + :group 'magit-blame + :type 'boolean) + +(defcustom magit-blame-disable-modes '(fci-mode yascroll-bar-mode) + "List of modes not compatible with Magit-Blame mode. +This modes are turned off when Magit-Blame mode is turned on, +and then turned on again when turning off the latter." + :group 'magit-blame + :type '(repeat (symbol :tag "Mode"))) + +(make-variable-buffer-local 'magit-blame-disabled-modes) + +(defcustom magit-blame-mode-lighter " Blame" + "The mode-line lighter of the Magit-Blame mode." + :group 'magit-blame + :type '(choice (const :tag "No lighter" "") string)) + +(unless (find-lisp-object-file-name 'magit-blame-goto-chunk-hook 'defvar) + (add-hook 'magit-blame-goto-chunk-hook 'magit-blame-maybe-update-revision-buffer)) +(defcustom magit-blame-goto-chunk-hook '(magit-blame-maybe-update-revision-buffer) + "Hook run by `magit-blame-next-chunk' and `magit-blame-previous-chunk'." + :package-version '(magit . "2.1.0") + :group 'magit-blame + :type 'hook + :options '(magit-blame-maybe-update-revision-buffer)) + +(defface magit-blame-heading + '((((class color) (background light)) + :background "grey80" + :foreground "black") + (((class color) (background dark)) + :background "grey25" + :foreground "black")) + "Face for blame headings." + :group 'magit-faces) + +(defface magit-blame-summary + '((t :inherit magit-blame-heading)) + "Face used for commit summary in blame headings." + :group 'magit-faces) + +(defface magit-blame-hash + '((t :inherit magit-blame-heading)) + "Face used for commit hash in blame headings." + :group 'magit-faces) + +(defface magit-blame-name + '((t :inherit magit-blame-heading)) + "Face used for author and committer names in blame headings." + :group 'magit-faces) + +(defface magit-blame-date + '((t :inherit magit-blame-heading)) + "Face used for dates in blame headings." + :group 'magit-faces) + +;;; Code + +(defvar magit-blame-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\r" 'magit-show-commit) + (define-key map "\s" 'magit-diff-show-or-scroll-up) + (define-key map "\d" 'magit-diff-show-or-scroll-down) + (define-key map "b" 'magit-blame-popup) + (define-key map "n" 'magit-blame-next-chunk) + (define-key map "N" 'magit-blame-next-chunk-same-commit) + (define-key map "p" 'magit-blame-previous-chunk) + (define-key map "P" 'magit-blame-previous-chunk-same-commit) + (define-key map "q" 'magit-blame-quit) + (define-key map "t" 'magit-blame-toggle-headings) + (define-key map "\M-w" 'magit-blame-copy-hash) + map) + "Keymap for `magit-blame-mode'.") + +(defun magit-blame-put-keymap-before-view-mode () + "Put `magit-blame-mode' ahead of `view-mode' in `minor-mode-map-alist'." + (--when-let (assq 'magit-blame-mode + (cl-member 'view-mode minor-mode-map-alist :key #'car)) + (setq minor-mode-map-alist + (cons it (delq it minor-mode-map-alist)))) + (remove-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode)) + +(add-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode) + +(defvar-local magit-blame-buffer-read-only nil) +(defvar-local magit-blame-cache nil) +(defvar-local magit-blame-process nil) +(defvar-local magit-blame-recursive-p nil) +(defvar-local magit-blame-separator nil) + +(define-minor-mode magit-blame-mode + "Display blame information inline." + :lighter magit-blame-mode-lighter + (cond (magit-blame-mode + (when (called-interactively-p 'any) + (setq magit-blame-mode nil) + (user-error + (concat "Don't call `magit-blame-mode' directly; " + "instead use `magit-blame' or `magit-blame-popup'"))) + (setq magit-blame-buffer-read-only buffer-read-only) + (read-only-mode 1) + (dolist (mode magit-blame-disable-modes) + (when (and (boundp mode) (symbol-value mode)) + (funcall mode -1) + (push mode magit-blame-disabled-modes))) + (setq magit-blame-separator (magit-blame-format-separator))) + (t + (unless magit-blame-buffer-read-only + (read-only-mode -1)) + (dolist (mode magit-blame-disabled-modes) + (funcall mode 1)) + (when (process-live-p magit-blame-process) + (kill-process magit-blame-process)) + (save-excursion + (save-restriction + (widen) + (dolist (ov (overlays-in (point-min) (point-max))) + (when (overlay-get ov 'magit-blame) + (delete-overlay ov)))))))) + +(defun auto-revert-handler--unless-magit-blame-mode () + "If Magit-Blame mode is on, then do nothing. See #1731." + magit-blame-mode) + +(advice-add 'auto-revert-handler :before-until + 'auto-revert-handler--unless-magit-blame-mode) + +;;;###autoload (autoload 'magit-blame-popup "magit-blame" nil t) +(magit-define-popup magit-blame-popup + "Popup console for blame commands." + 'magit-commands + :man-page "git-blame" + :switches '((?w "Ignore whitespace" "-w") + (?r "Do not treat root commits as boundaries" "--root")) + :options '((?C "Detect lines moved or copied within a file" "-C") + (?M "Detect lines moved or copied between files" "-M")) + :actions '((?b "Blame" magit-blame)) + :default-arguments '("-w") + :default-action 'magit-blame) + +;;;###autoload +(defun magit-blame (revision file &optional args line) + "Display edit history of FILE up to REVISION. + +Interactively blame the file being visited in the current buffer. +If the buffer visits a revision of that file, then blame up to +that revision, otherwise blame the file's full history, including +uncommitted changes. + +If Magit-Blame mode is already turned on then blame recursively, by +visiting REVISION:FILE (using `magit-find-file'), where revision +is the revision before the revision that added the lines at +point. + +ARGS is a list of additional arguments to pass to `git blame'; +only arguments available from `magit-blame-popup' should be used. +\n(fn REVISION FILE &optional ARGS)" ; LINE is for internal use + (interactive + (let ((args (magit-blame-arguments))) + (if magit-blame-mode + (--if-let (magit-blame-chunk-get :previous-hash) + (list it (magit-blame-chunk-get :previous-file) + args (magit-blame-chunk-get :previous-start)) + (user-error "Block has no further history")) + (--if-let (magit-file-relative-name nil 'tracked) + (list (or magit-buffer-refname magit-buffer-revision) it args) + (if buffer-file-name + (user-error "Buffer isn't visiting a tracked file") + (user-error "Buffer isn't visiting a file")))))) + (magit-with-toplevel + (if revision + (magit-find-file revision file) + (let ((default-directory default-directory)) + (--if-let (find-buffer-visiting file) + (progn (switch-to-buffer it) + (save-buffer)) + (find-file file)))) + ;; ^ Make sure this doesn't affect the value used below. b640c6f + (widen) + (when line + (setq magit-blame-recursive-p t) + (goto-char (point-min)) + (forward-line (1- line))) + (unless magit-blame-mode + (setq magit-blame-cache (make-hash-table :test 'equal)) + (let ((show-headings magit-blame-show-headings)) + (magit-blame-mode 1) + (setq-local magit-blame-show-headings show-headings)) + (message "Blaming...") + (let ((magit-process-popup-time -1) + (inhibit-magit-refresh t)) + (magit-run-git-async + "blame" "--incremental" args + "-L" (format "%s,%s" + (line-number-at-pos (window-start)) + (line-number-at-pos (1- (window-end nil t)))) + revision "--" file)) + (setq magit-blame-process magit-this-process) + (set-process-filter magit-this-process 'magit-blame-process-filter) + (set-process-sentinel + magit-this-process + `(lambda (process event) + (when (memq (process-status process) '(exit signal)) + (magit-process-sentinel process event) + (magit-blame-assert-buffer process) + (with-current-buffer (process-get process 'command-buf) + (when magit-blame-mode + (let ((magit-process-popup-time -1) + (inhibit-magit-refresh t) + (default-directory ,default-directory)) + (magit-run-git-async "blame" "--incremental" ,@args + ,revision "--" ,file)) + (setq magit-blame-process magit-this-process) + (set-process-filter + magit-this-process 'magit-blame-process-filter) + (set-process-sentinel + magit-this-process 'magit-blame-process-sentinel))))))))) + +(defun magit-blame-process-sentinel (process event) + (let ((status (process-status process))) + (when (memq status '(exit signal)) + (magit-process-sentinel process event) + (if (eq status 'exit) + (message "Blaming...done") + (magit-blame-assert-buffer process) + (with-current-buffer (process-get process 'command-buf) + (magit-blame-mode -1)) + (message "Blaming...failed"))))) + +(defvar magit-blame-log nil + "Whether to log blame output to the process buffer. +This is intended for debugging purposes.") + +(defun magit-blame-process-filter (process string) + (when magit-blame-log + (magit-process-filter process string)) + (--when-let (process-get process 'partial-line) + (setq string (concat it string)) + (setf (process-get process 'partial-line) nil)) + (magit-blame-assert-buffer process) + (with-current-buffer (process-get process 'command-buf) + (when magit-blame-mode + (let ((chunk (process-get process 'chunk)) + (lines (split-string string "\n" t))) + (unless (string-match-p "\n\\'" string) + (process-put process 'chunk chunk) + (process-put process 'partial-line (car (last lines))) + (setq lines (butlast lines))) + (dolist (line lines) + (cond + ((equal line "")) + ((not chunk) + (string-match + "^\\(.\\{40\\}\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\)" line) + (setq chunk + (list :hash (let ((hash (match-string 1 line))) + (unless (equal hash (make-string 40 ?0)) + hash)) + :previous-start (string-to-number (match-string 2 line)) + :start (string-to-number (match-string 3 line)) + :lines (string-to-number (match-string 4 line))))) + ((string-match "^filename \\(.+\\)" line) + (let* ((hash (plist-get chunk :hash)) + (file (match-string 1 line))) + (--if-let (gethash hash magit-blame-cache) + (setq chunk (nconc chunk it)) + (plist-put chunk :filename file) + (puthash hash chunk magit-blame-cache))) + (magit-blame-make-overlay chunk) + (setq chunk nil)) + ((string-match "^previous \\(.\\{40\\}\\) \\(.+\\)" line) + (plist-put chunk :previous-hash (match-string 1 line)) + (plist-put chunk :previous-file (match-string 2 line))) + ((string-match "^\\([^ ]+?-mail\\) <\\([^>]+\\)>" line) + (plist-put chunk (intern (concat ":" (match-string 1 line))) + (string-to-number (match-string 2 line)))) + ((string-match "^\\([^ ]+?-\\(?:time\\|tz\\)\\) \\(.+\\)" line) + (plist-put chunk (intern (concat ":" (match-string 1 line))) + (string-to-number (match-string 2 line)))) + ((string-match "^\\([^ ]+\\) \\(.+\\)" line) + (plist-put chunk (intern (concat ":" (match-string 1 line))) + (match-string 2 line)))) + (process-put process 'chunk chunk)))))) + +(defun magit-blame-assert-buffer (process) + (unless (buffer-live-p (process-get process 'command-buf)) + (kill-process process) + (user-error "Buffer being blamed has been killed"))) + +(defun magit-blame-make-overlay (chunk) + (let ((ov (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (forward-line (1- (plist-get chunk :start))) + (--when-let (--first (overlay-get it 'magit-blame) + (overlays-at (point))) + (delete-overlay it)) + (make-overlay (point) + (progn (forward-line + (plist-get chunk :lines)) + (point)))))) + (heading (magit-blame-format-heading chunk))) + (overlay-put ov 'magit-blame chunk) + (overlay-put ov 'magit-blame-heading heading) + (overlay-put ov 'before-string + (if magit-blame-show-headings + heading + magit-blame-separator)))) + +(defun magit-blame-format-separator () + (propertize + (concat (propertize " " 'display '(space :height (2))) + (propertize "\n" 'line-height t)) + 'face (list :background (face-attribute 'magit-blame-heading :background)))) + +(defun magit-blame-format-heading (chunk) + (with-temp-buffer + (insert (format-spec + (concat magit-blame-heading-format "\n") + `((?H . ,(propertize (or (plist-get chunk :hash) "") + 'face 'magit-blame-hash)) + (?s . ,(propertize (or (plist-get chunk :summary) "") + 'face 'magit-blame-summary)) + (?a . ,(propertize (or (plist-get chunk :author) "") + 'face 'magit-blame-name)) + (?A . ,(propertize (magit-blame-format-time-string + magit-blame-time-format + (plist-get chunk :author-time) + (plist-get chunk :author-tz)) + 'face 'magit-blame-date)) + (?c . ,(propertize (or (plist-get chunk :committer) "") + 'face 'magit-blame-name)) + (?C . ,(propertize (magit-blame-format-time-string + magit-blame-time-format + (plist-get chunk :committer-time) + (plist-get chunk :committer-tz)) + 'face 'magit-blame-date))))) + (goto-char (point-min)) + (while (not (eobp)) + (let ((face (get-text-property (point) 'face)) + (next (or (next-single-property-change (point) 'face) + (point-max)))) + (unless face + (put-text-property (point) next 'face 'magit-blame-heading)) + (goto-char next))) + (buffer-string))) + +(defun magit-blame-format-time-string (format time tz) + (format-time-string + format (seconds-to-time (+ time (* (/ tz 100) 60 60) (* (% tz 100) 60))))) + +(defun magit-blame-quit () + "Turn off Magit-Blame mode. +If the buffer was created during a recursive blame, +then also kill the buffer." + (interactive) + (if magit-blame-recursive-p + (kill-buffer) + (magit-blame-mode -1))) + +(defun magit-blame-next-chunk () + "Move to the next chunk." + (interactive) + (--if-let (next-single-char-property-change (point) 'magit-blame) + (progn (goto-char it) + (run-hooks 'magit-blame-goto-chunk-hook)) + (user-error "No more chunks"))) + +(defun magit-blame-previous-chunk () + "Move to the previous chunk." + (interactive) + (--if-let (previous-single-char-property-change (point) 'magit-blame) + (progn (goto-char it) + (run-hooks 'magit-blame-goto-chunk-hook)) + (user-error "No more chunks"))) + +(defun magit-blame-next-chunk-same-commit (&optional previous) + "Move to the next chunk from the same commit.\n\n(fn)" + (interactive) + (-if-let (hash (magit-blame-chunk-get :hash)) + (let ((pos (point)) ov) + (save-excursion + (while (and (not ov) + (not (= pos (if previous (point-min) (point-max)))) + (setq pos (funcall + (if previous + 'previous-single-char-property-change + 'next-single-char-property-change) + pos 'magit-blame))) + (--when-let (magit-blame-overlay-at pos) + (when (equal (magit-blame-chunk-get :hash pos) hash) + (setq ov it))))) + (if ov + (goto-char (overlay-start ov)) + (user-error "No more chunks from same commit"))) + (user-error "This chunk hasn't been blamed yet"))) + +(defun magit-blame-previous-chunk-same-commit () + "Move to the previous chunk from the same commit." + (interactive) + (magit-blame-next-chunk-same-commit 'previous-single-char-property-change)) + +(defun magit-blame-toggle-headings () + "Show or hide blame chunk headings." + (interactive) + (setq-local magit-blame-show-headings (not magit-blame-show-headings)) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (while (not (eobp)) + (let ((next (next-single-char-property-change (point) 'magit-blame))) + (--when-let (magit-blame-overlay-at (point)) + (overlay-put it 'before-string + (if magit-blame-show-headings + (overlay-get it 'magit-blame-heading) + magit-blame-separator))) + (goto-char (or next (point-max)))))))) + +(defun magit-blame-copy-hash () + "Save hash of the current chunk's commit to the kill ring." + (interactive) + (kill-new (message "%s" (magit-blame-chunk-get :hash)))) + +(defun magit-blame-chunk-get (key &optional pos) + (--when-let (magit-blame-overlay-at pos) + (plist-get (overlay-get it 'magit-blame) key))) + +(defun magit-blame-overlay-at (&optional pos) + (--first (overlay-get it 'magit-blame) + (overlays-at (or pos (point))))) + +(defun magit-blame-maybe-update-revision-buffer () + (unless magit--update-revision-buffer + (setq magit--update-revision-buffer nil) + (-when-let* ((commit (magit-blame-chunk-get :hash)) + (buffer (magit-mode-get-buffer 'magit-revision-mode nil t))) + (setq magit--update-revision-buffer (list commit buffer)) + (run-with-idle-timer + magit-update-other-window-delay nil + (lambda () + (-let [(rev buf) magit--update-revision-buffer] + (setq magit--update-revision-buffer nil) + (when (buffer-live-p buf) + (let ((magit-display-buffer-noselect t)) + (apply #'magit-show-commit rev (magit-diff-arguments)))))))))) + +;;; magit-blame.el ends soon +(provide 'magit-blame) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-blame.el ends here diff --git a/elpa/magit-20151223.1425/magit-commit.el b/elpa/magit-20151223.1425/magit-commit.el new file mode 100644 index 00000000..7a36c89a --- /dev/null +++ b/elpa/magit-20151223.1425/magit-commit.el @@ -0,0 +1,396 @@ +;;; magit-commit.el --- create Git commits -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library implements commands for creating Git commits. These +;; commands just initiate the commit, support for writing the commit +;; messages is implemented in `git-commit.el'. + +;;; Code: + +(require 'magit) +(require 'magit-sequence) + +(eval-when-compile (require 'epa)) ; for `epa-protocol' +(eval-when-compile (require 'epg)) +(declare-function epg-sub-key-id 'epg) +(declare-function epg-key-sub-key-list 'epg) +(declare-function epg-key-user-id-list 'epg) +(declare-function epg-user-id-string 'epg) +(declare-function epg-decode-dn 'epg) +(declare-function epg-list-keys 'epg) + +;;; Options + +(defcustom magit-commit-arguments nil + "The arguments used when committing." + :group 'magit-commands + :type '(repeat (string :tag "Argument"))) + +(defcustom magit-commit-ask-to-stage 'verbose + "Whether to ask to stage everything when committing and nothing is staged." + :package-version '(magit . "2.3.0") + :group 'magit-commands + :type '(choice (const :tag "Ask showing diff" verbose) + (const :tag "Ask" t) + (const :tag "Don't ask" nil))) + +(defcustom magit-commit-show-diff t + "Whether the relevant diff is automatically shown when committing." + :package-version '(magit . "2.3.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-commit-extend-override-date t + "Whether using `magit-commit-extend' changes the committer date." + :package-version '(magit . "2.3.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-commit-reword-override-date t + "Whether using `magit-commit-reword' changes the committer date." + :package-version '(magit . "2.3.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-commit-squash-confirm t + "Whether the commit targeted by squash and fixup has to be confirmed. +When non-nil then the commit at point (if any) is used as default +choice, otherwise it has to be confirmed. This option only +affects `magit-commit-squash' and `magit-commit-fixup'. The +\"instant\" variants always require confirmation because making +an error while using those is harder to recover from." + :package-version '(magit . "2.1.0") + :group 'magit-commands + :type 'boolean) + +;;; Code + +(defun magit-commit-popup (&optional arg) + "Popup console for commit commands." + (interactive "P") + (--if-let (magit-commit-message-buffer) + (switch-to-buffer it) + (magit-invoke-popup 'magit-commit-popup nil arg))) + +(defvar magit-commit-popup + '(:variable magit-commit-arguments + :man-page "git-commit" + :switches ((?a "Stage all modified and deleted files" "--all") + (?e "Allow empty commit" "--allow-empty") + (?v "Show diff of changes to be committed" "--verbose") + (?n "Bypass git hooks" "--no-verify") + (?s "Add Signed-off-by line" "--signoff") + (?R "Claim authorship and reset author date" "--reset-author")) + :options ((?A "Override the author" "--author=") + (?S "Sign using gpg" "--gpg-sign=" magit-read-gpg-secret-key) + (?C "Reuse commit message" "--reuse-message=")) + :actions ((?c "Commit" magit-commit) + (?e "Extend" magit-commit-extend) + (?f "Fixup" magit-commit-fixup) + (?F "Instant Fixup" magit-commit-instant-fixup) nil + (?w "Reword" magit-commit-reword) + (?s "Squash" magit-commit-squash) + (?S "Instant Squash" magit-commit-instant-squash) nil + (?a "Amend" magit-commit-amend) + (?A "Augment" magit-commit-augment)) + :max-action-columns 4 + :default-action 'magit-commit)) + +(magit-define-popup-keys-deferred 'magit-commit-popup) + +(defun magit-commit-arguments nil + (if (eq magit-current-popup 'magit-commit-popup) + magit-current-popup-args + magit-commit-arguments)) + +(defun magit-commit-message-buffer () + (let* ((find-file-visit-truename t) ; git uses truename of COMMIT_EDITMSG + (topdir (magit-toplevel))) + (--first (equal topdir (with-current-buffer it + (and git-commit-mode (magit-toplevel)))) + (append (buffer-list (selected-frame)) + (buffer-list))))) + +;;;###autoload +(defun magit-commit (&optional args) + "Create a new commit on HEAD. +With a prefix argument amend to the commit at HEAD instead. +\n(git commit [--amend] ARGS)" + (interactive (if current-prefix-arg + (list (cons "--amend" (magit-commit-arguments))) + (list (magit-commit-arguments)))) + (when (setq args (magit-commit-assert args)) + (magit-run-git-with-editor "commit" args))) + +;;;###autoload +(defun magit-commit-amend (&optional args) + "Amend the last commit. +\n(git commit --amend ARGS)" + (interactive (list (magit-commit-arguments))) + (magit-run-git-with-editor "commit" "--amend" args)) + +;;;###autoload +(defun magit-commit-extend (&optional args override-date) + "Amend the last commit, without editing the message. + +With a prefix argument keep the committer date, otherwise change +it. The option `magit-commit-extend-override-date' can be used +to inverse the meaning of the prefix argument. \n(git commit +--amend --no-edit)" + (interactive (list (magit-commit-arguments) + (if current-prefix-arg + (not magit-commit-extend-override-date) + magit-commit-extend-override-date))) + (when (setq args (magit-commit-assert args (not override-date))) + (let ((process-environment process-environment)) + (unless override-date + (setenv "GIT_COMMITTER_DATE" (magit-rev-format "%cD"))) + (magit-run-git-with-editor "commit" "--amend" "--no-edit" args)))) + +;;;###autoload +(defun magit-commit-reword (&optional args override-date) + "Reword the last commit, ignoring staged changes. + +With a prefix argument keep the committer date, otherwise change +it. The option `magit-commit-reword-override-date' can be used +to inverse the meaning of the prefix argument. + +Non-interactively respect the optional OVERRIDE-DATE argument +and ignore the option. +\n(git commit --amend --only)" + (interactive (list (magit-commit-arguments) + (if current-prefix-arg + (not magit-commit-reword-override-date) + magit-commit-reword-override-date))) + (let ((process-environment process-environment)) + (unless override-date + (setenv "GIT_COMMITTER_DATE" (magit-rev-format "%cD"))) + (magit-run-git-with-editor "commit" "--amend" "--only" args))) + +;;;###autoload +(defun magit-commit-fixup (&optional commit args) + "Create a fixup commit. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'." + (interactive (list (magit-commit-at-point) + (magit-commit-arguments))) + (magit-commit-squash-internal "--fixup" commit args)) + +;;;###autoload +(defun magit-commit-squash (&optional commit args) + "Create a squash commit, without editing the squash message. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'." + (interactive (list (magit-commit-at-point) + (magit-commit-arguments))) + (magit-commit-squash-internal "--squash" commit args)) + +;;;###autoload +(defun magit-commit-augment (&optional commit args) + "Create a squash commit, editing the squash message. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'." + (interactive (list (magit-commit-at-point) + (magit-commit-arguments))) + (magit-commit-squash-internal "--squash" commit args nil t)) + +;;;###autoload +(defun magit-commit-instant-fixup (&optional commit args) + "Create a fixup commit targeting COMMIT and instantly rebase." + (interactive (list (magit-commit-at-point) + (magit-commit-arguments))) + (magit-commit-squash-internal "--fixup" commit args t)) + +;;;###autoload +(defun magit-commit-instant-squash (&optional commit args) + "Create a squash commit targeting COMMIT and instantly rebase." + (interactive (list (magit-commit-at-point) + (magit-commit-arguments))) + (magit-commit-squash-internal "--squash" commit args t)) + +(defun magit-commit-squash-internal + (option commit &optional args rebase edit confirmed) + (-when-let (args (magit-commit-assert args t)) + (if (and commit + (or confirmed + (not (or rebase + current-prefix-arg + magit-commit-squash-confirm)))) + (let ((magit-commit-show-diff nil)) + (magit-run-git-with-editor "commit" + (unless edit "--no-edit") + (concat option "=" commit) + args)) + (magit-log-select + `(lambda (commit) + (magit-commit-squash-internal ,option commit ',args ,rebase ,edit t) + ,@(when rebase + `((magit-rebase-interactive-1 commit + (list "--autosquash" "--autostash") + "" "true")))) + (format "Type %%p on a commit to %s into it," + (substring option 2))) + (when magit-commit-show-diff + (let ((magit-display-buffer-noselect t)) + (apply #'magit-diff-staged nil (magit-diff-arguments))))))) + +(defun magit-commit-assert (args &optional strict) + (cond + ((or (magit-anything-staged-p) + (and (magit-anything-unstaged-p) + ;; ^ Everything of nothing is still nothing. + (member "--all" args)) + (and (not strict) + ;; ^ For amend variants that don't make sense otherwise. + (or (member "--amend" args) + (member "--allow-empty" args)))) + (or args (list "--"))) + ((and (magit-rebase-in-progress-p) + (not (magit-anything-unstaged-p)) + (y-or-n-p "Nothing staged. Continue in-progress rebase? ")) + (magit-run-git-sequencer "rebase" "--continue") + nil) + ((and (file-exists-p (magit-git-dir "MERGE_MSG")) + (not (magit-anything-unstaged-p))) + (or args (list "--"))) + ((not (magit-anything-unstaged-p)) + (user-error "Nothing staged (or unstaged)")) + (magit-commit-ask-to-stage + (when (eq magit-commit-ask-to-stage 'verbose) + (magit-diff-unstaged)) + (prog1 (when (y-or-n-p "Nothing staged. Stage and commit everything? ") + (magit-run-git "add" "-u" ".") + (or args (list "--"))) + (when (and (eq magit-commit-ask-to-stage 'verbose) + (derived-mode-p 'magit-diff-mode)) + (magit-mode-bury-buffer)))) + (t + (user-error "Nothing staged")))) + +(defun magit-commit-diff () + (--when-let (and git-commit-mode + magit-commit-show-diff + (pcase last-command + (`magit-commit + (apply-partially 'magit-diff-staged nil)) + (`magit-commit-amend 'magit-diff-while-amending) + (`magit-commit-reword 'magit-diff-while-amending))) + (let ((magit-inhibit-save-previous-winconf 'unset) + (magit-display-buffer-noselect t)) + (funcall it (car (magit-diff-arguments)))))) + +(add-hook 'server-switch-hook 'magit-commit-diff) + +(add-to-list 'with-editor-server-window-alist + (cons git-commit-filename-regexp 'switch-to-buffer)) + +(defvar magit-gpg-secret-key-hist nil) + +(defun magit-read-gpg-secret-key (prompt &optional _initial-input) + (require 'epa) + (let ((keys (--map (list (epg-sub-key-id (car (epg-key-sub-key-list it))) + (-when-let (id-obj (car (epg-key-user-id-list it))) + (let ((id-str (epg-user-id-string id-obj))) + (if (stringp id-str) + id-str + (epg-decode-dn id-obj))))) + (epg-list-keys (epg-make-context epa-protocol) nil t)))) + (magit-completing-read prompt keys nil nil nil 'magit-gpg-secret-key-hist + (car (or magit-gpg-secret-key-hist keys))))) + +(defvar magit-commit-add-log-insert-function 'magit-commit-add-log-insert + "Used by `magit-commit-add-log' to insert a single entry.") + +(defun magit-commit-add-log () + "Add a stub for the current change into the commit message buffer. +If no commit is in progress, then initiate it. Use the function +specified by variable `magit-commit-add-log-insert-function' to +actually insert the entry." + (interactive) + (let ((hunk (magit-section-when 'hunk it)) + (log (magit-commit-message-buffer)) buf pos) + (save-window-excursion + (call-interactively #'magit-diff-visit-file) + (setq buf (current-buffer) + pos (point))) + (unless log + (unless (magit-commit-assert nil) + (user-error "Abort")) + (magit-commit) + (while (not (setq log (magit-commit-message-buffer))) + (sit-for 0.01))) + (save-excursion + (with-current-buffer buf + (goto-char pos) + (funcall magit-commit-add-log-insert-function log + (magit-file-relative-name) + (and hunk (add-log-current-defun))))))) + +(defun magit-commit-add-log-insert (buffer file defun) + (with-current-buffer buffer + (undo-boundary) + (goto-char (point-max)) + (while (re-search-backward (concat "^" comment-start) nil t)) + (cond ((re-search-backward (format "* %s\\(?: (\\([^)]+\\))\\)?: " file) + nil t) + (when (equal (match-string 1) defun) + (setq defun nil)) + (re-search-forward ": ")) + (t + (when (re-search-backward "^[\\*(].+\n" nil t) + (goto-char (match-end 0))) + (while (re-search-forward "^[^\\*#\n].*\n" nil t)) + (if defun + (progn (insert (format "* %s (%s): \n" file defun)) + (setq defun nil)) + (insert (format "* %s: \n" file))) + (backward-char) + (unless (looking-at "\n[\n\\']") + (insert ?\n) + (backward-char)))) + (when defun + (forward-line) + (let ((limit (save-excursion + (and (re-search-forward "^\\*" nil t) + (point))))) + (unless (or (looking-back (format "(%s): " defun) + (line-beginning-position)) + (re-search-forward (format "^(%s): " defun) limit t)) + (while (re-search-forward "^[^\\*#\n].*\n" limit t)) + (insert (format "(%s): \n" defun)) + (backward-char)))))) + +;;; magit-commit.el ends soon +(provide 'magit-commit) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-commit.el ends here diff --git a/elpa/magit-20151223.1425/magit-core.el b/elpa/magit-20151223.1425/magit-core.el new file mode 100644 index 00000000..418fc693 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-core.el @@ -0,0 +1,76 @@ +;;; magit-core.el --- core functionality -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library requires several other libraries, so that yet other +;; libraries can just require this one, instead of having to require +;; all the other ones. In other words this separates the low-level +;; stuff from the rest. It also defines some Custom groups. + +;;; Code: + +(require 'magit-utils) +(require 'magit-section) +(require 'magit-git) +(require 'magit-mode) +(require 'magit-popup) +(require 'magit-process) + +(defgroup magit nil + "Controlling Git from Emacs." + :group 'tools) + +(defgroup magit-commands nil + "Options controlling behavior of certain commands." + :group 'magit) + +(defgroup magit-modes nil + "Modes used or provided by Magit." + :group 'magit) + +(defgroup magit-extensions nil + "Extensions to Magit." + :group 'magit) + +(defgroup magit-faces nil + "Faces used by Magit." + :group 'magit + :group 'faces) + +(custom-add-to-group 'magit-modes 'magit-popup 'custom-group) +(custom-add-to-group 'magit-faces 'magit-popup-faces 'custom-group) +(custom-add-to-group 'magit-modes 'git-commit 'custom-group) +(custom-add-to-group 'magit-faces 'git-commit-faces 'custom-group) +(custom-add-to-group 'magit-modes 'git-rebase 'custom-group) +(custom-add-to-group 'magit-faces 'git-rebase-faces 'custom-group) +(custom-add-to-group 'magit-process 'with-editor 'custom-group) + +(custom-add-to-group 'magit 'vc-follow-symlinks 'custom-variable) + +;;; magit-core.el ends soon +(provide 'magit-core) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-core.el ends here diff --git a/elpa/magit-20151223.1425/magit-diff.el b/elpa/magit-20151223.1425/magit-diff.el new file mode 100644 index 00000000..5b1e409c --- /dev/null +++ b/elpa/magit-20151223.1425/magit-diff.el @@ -0,0 +1,2058 @@ +;;; magit-diff.el --- inspect Git diffs -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library implements support for looking at Git diffs and +;; commits. + +;;; Code: + +(require 'git-commit) +(require 'magit-core) + +;; For `magit-diff-popup' +(declare-function magit-stash-show 'magit-stash) +;; For `magit-diff-visit-file' +(declare-function magit-dired-jump 'magit) +(declare-function magit-find-file-noselect 'magit) +(declare-function magit-status-internal 'magit) +;; For `magit-diff-wash-revision' +(declare-function magit-insert-tags-header 'magit) +;; For `magit-diff-while-committing' +(declare-function magit-commit-message-buffer 'magit) +;; For `magit-insert-revision-gravatar' +(defvar gravatar-size) +;; For `magit-show-commit' and `magit-diff-show-or-scroll' +(declare-function magit-blame-chunk-get 'magit-blame) +(declare-function magit-blame-mode 'magit-blame) +(defvar magit-blame-mode) +(defvar git-rebase-line) + +(require 'diff-mode) +(require 'smerge-mode) + +;;; Options +;;;; Diff Mode + +(defgroup magit-diff nil + "Inspect and manipulate Git diffs." + :group 'magit-modes) + +(custom-add-to-group 'magit-diff 'smerge-refine-ignore-whitespace + 'custom-variable) + +(defcustom magit-diff-mode-hook nil + "Hook run after entering Magit-Diff mode." + :group 'magit-diff + :type 'hook) + +(defcustom magit-diff-sections-hook + '(magit-insert-diff + magit-insert-xref-buttons) + "Hook run to insert sections into a `magit-diff-mode' buffer." + :package-version '(magit . "2.3.0") + :group 'magit-revision + :type 'hook) + +(defcustom magit-diff-expansion-threshold 1.0 + "After how many seconds not to expand anymore diffs. + +Except in status buffers, diffs are usually start out fully +expanded. Because that can take a long time, all diffs that +haven't been fontified during a refresh before the threshold +defined here are instead displayed with their bodies collapsed. + +Note that this can cause sections that were previously expanded +to be collapsed. So you should not pick a very low value here. + +The hook function `magit-diff-expansion-threshold' has to be a +member of `magit-section-set-visibility-hook' for this option +to have any effect" + :package-version '(magit . "2.1.0") + :group 'magit-diff + :type 'float) + +(defcustom magit-diff-highlight-hunk-body t + "Whether to highlight bodies of selected hunk sections. +This only has an effect if `magit-diff-highlight' is a +member of `magit-section-highlight-hook', which see." + :package-version '(magit . "2.1.0") + :group 'magit-diff + :type 'boolean) + +(defcustom magit-diff-show-lines-boundary t + "Whether to delimit hunk-internal region with thin lines. + +When a hunk-internal region (used to stage just the lines that +fall into the region instead of the complete hunk) only covers +context lines, then these lines are the only visual indicator +for the region. In character-only terminals it's not possible +to draw thin lines." + :package-version '(magit . "2.1.0") + :group 'magit-diff + :type 'boolean) + +(defcustom magit-diff-refine-hunk nil + "Whether to show word-granularity differences within diff hunks. + +nil never show fine differences. +t show fine differences for the current diff hunk only. +`all' show fine differences for all displayed diff hunks." + :group 'magit-diff + :safe (lambda (val) (memq val '(nil t all))) + :type '(choice (const :tag "Never" nil) + (const :tag "Current" t) + (const :tag "All" all))) + +(put 'magit-diff-refine-hunk 'permanent-local t) + +(defcustom magit-diff-paint-whitespace t + "Specify where to highlight whitespace errors. +See `magit-highlight-trailing-whitespace', +`magit-highlight-indentation'. The symbol t means in all diffs, +`status' means only in the status buffer, and nil means nowhere." + :group 'magit-diff + :safe (lambda (val) (memq val '(t nil status))) + :type '(choice (const :tag "Always" t) + (const :tag "Never" nil) + (const :tag "In status buffer" status))) + +(defcustom magit-diff-highlight-trailing t + "Whether to highlight whitespace at the end of a line in diffs. +Used only when `magit-diff-paint-whitespace' is non-nil." + :group 'magit-diff + :safe 'booleanp + :type 'boolean) + +(defcustom magit-diff-highlight-indentation nil + "Highlight the \"wrong\" indentation style. +Used only when `magit-diff-paint-whitespace' is non-nil. + +The value is a list of cons cells. The car is a regular +expression, and the cdr is the value that applies to repositories +whose directory matches the regular expression. If more than one +element matches, then the *last* element in the list applies. +The default value should therefore come first in the list. + +If the value is `tabs', highlight indentation with tabs. If the +value is an integer, highlight indentation with at least that +many spaces. Otherwise, highlight neither." + :group 'magit-diff + :type `(repeat (cons (string :tag "Directory regexp") + (choice (const :tag "Tabs" tabs) + (integer :tag "Spaces" :value ,tab-width) + (const :tag "Neither" nil))))) + +;;;; Revision Mode + +(defgroup magit-revision nil + "Inspect and manipulate Git commits." + :group 'magit-modes) + +(defcustom magit-revision-mode-hook nil + "Hook run after entering Magit-Revision mode." + :group 'magit-revision + :type 'hook) + +(defcustom magit-revision-sections-hook + '(magit-insert-revision-tag + magit-insert-revision-headers + magit-insert-revision-message + magit-insert-revision-notes + magit-insert-revision-diff + magit-insert-xref-buttons) + "Hook run to insert sections into a `magit-revision-mode' buffer." + :package-version '(magit . "2.3.0") + :group 'magit-revision + :type 'hook) + +(defcustom magit-revision-headers-format "\ +Author: %aN <%aE> +AuthorDate: %ad +Commit: %cN <%cE> +CommitDate: %cd +" + "Format string used to insert headers in revision buffers. + +All headers in revision buffers are inserted by the section +inserter `magit-insert-revision-headers'. Some of the headers +are created by calling `git show --format=FORMAT' where FORMAT +is the format specified here. Other headers are hard coded or +subject to option `magit-revision-insert-related-refs'." + :package-version '(magit . "2.3.0") + :group 'magit-revision + :type 'string) + +(defcustom magit-revision-insert-related-refs t + "Whether to show related refs in revision buffers." + :package-version '(magit . "2.1.0") + :group 'magit-revision + :type 'boolean) + +(defcustom magit-revision-show-gravatars nil + "Whether to show gravatar images in revision buffers. + +If non-nil, then the value has to be a cons-cell which specifies +where the gravatar images for the author and/or the committer are +inserted inside the text that was previously inserted according +to `magit-revision-header-format'. + +Both cells are regular expressions. The car specifies where to +insert the author gravatar image. The top halve of the image is +inserted right after the matched text, the bottom halve on the +next line at the same offset. The cdr specifies where to insert +the committer image, accordingly. Either the car or the cdr may +be nil." + :package-version '(magit . "2.3.0") + :group 'magit-revision + :type '(choice (const :tag "Don't show gravatars" nil) + (cons :tag "Show gravatars" + (regexp :tag "Author regexp" "^Author: ") + (regexp :tag "Committer regexp" "^Commit: ")))) + +(defcustom magit-revision-use-gravatar-kludge nil + "Whether to work around a bug which affects display of gravatars. + +Gravatar images are spliced into two halves which are then +displayed on separate lines. On OS X the splicing has a bug in +some Emacs builds, which causes the top and bottom halves to be +interchanged. Enabling this option works around this issue by +interchanging the halves once more, which cancels out the effect +of the bug. + +See https://github.com/magit/magit/issues/2265 +and https://debbugs.gnu.org/cgi/bugreport.cgi?bug=7847." + :package-version '(magit . "2.3.0") + :group 'magit-revision + :type 'boolean) + +;;; Faces + +(defface magit-diff-file-heading + '((t :weight bold)) + "Face for diff file headings." + :group 'magit-faces) + +(defface magit-diff-file-heading-highlight + '((t :inherit (magit-diff-file-heading magit-section-highlight))) + "Face for current diff file headings." + :group 'magit-faces) + +(defface magit-diff-file-heading-selection + '((((class color) (background light)) + :inherit magit-diff-file-heading-highlight + :foreground "salmon4") + (((class color) (background dark)) + :inherit magit-diff-file-heading-highlight + :foreground "LightSalmon3")) + "Face for selected diff file headings." + :group 'magit-faces) + +(defface magit-diff-hunk-heading + '((((class color) (background light)) + :background "grey80" + :foreground "grey30") + (((class color) (background dark)) + :background "grey25" + :foreground "grey70")) + "Face for diff hunk headings." + :group 'magit-faces) + +(defface magit-diff-hunk-heading-highlight + '((((class color) (background light)) + :background "grey75" + :foreground "grey30") + (((class color) (background dark)) + :background "grey35" + :foreground "grey70")) + "Face for current diff hunk headings." + :group 'magit-faces) + +(defface magit-diff-hunk-heading-selection + '((((class color) (background light)) + :inherit magit-diff-hunk-heading-highlight + :foreground "salmon4") + (((class color) (background dark)) + :inherit magit-diff-hunk-heading-highlight + :foreground "LightSalmon3")) + "Face for selected diff hunk headings." + :group 'magit-faces) + +(defface magit-diff-lines-heading + '((((class color) (background light)) + :inherit magit-diff-hunk-heading-highlight + :background "LightSalmon3") + (((class color) (background dark)) + :inherit magit-diff-hunk-heading-highlight + :foreground "grey80" + :background "salmon4")) + "Face for diff hunk heading when lines are marked." + :group 'magit-faces) + +(defface magit-diff-lines-boundary + '((t :inherit magit-diff-lines-heading)) + "Face for boundary of marked lines in diff hunk." + :group 'magit-faces) + +(defface magit-diff-conflict-heading + '((t :inherit magit-diff-hunk-heading)) + "Face for conflict markers." + :group 'magit-faces) + +(defface magit-diff-added + '((((class color) (background light)) + :background "#ddffdd" + :foreground "#22aa22") + (((class color) (background dark)) + :background "#335533" + :foreground "#ddffdd")) + "Face for lines in a diff that have been added." + :group 'magit-faces) + +(defface magit-diff-removed + '((((class color) (background light)) + :background "#ffdddd" + :foreground "#aa2222") + (((class color) (background dark)) + :background "#553333" + :foreground "#ffdddd")) + "Face for lines in a diff that have been removed." + :group 'magit-faces) + +(defface magit-diff-our + '((t :inherit magit-diff-removed)) + "Face for lines in a diff for our side in a conflict." + :group 'magit-faces) + +(defface magit-diff-base + '((((class color) (background light)) + :background "#ffffcc" + :foreground "#aaaa11") + (((class color) (background dark)) + :background "#555522" + :foreground "#ffffcc")) + "Face for lines in a diff for the base side in a conflict." + :group 'magit-faces) + +(defface magit-diff-their + '((t :inherit magit-diff-added)) + "Face for lines in a diff for their side in a conflict." + :group 'magit-faces) + +(defface magit-diff-context + '((((class color) (background light)) :foreground "grey50") + (((class color) (background dark)) :foreground "grey70")) + "Face for lines in a diff that are unchanged." + :group 'magit-faces) + +(defface magit-diff-added-highlight + '((((class color) (background light)) + :background "#cceecc" + :foreground "#22aa22") + (((class color) (background dark)) + :background "#336633" + :foreground "#cceecc")) + "Face for lines in a diff that have been added." + :group 'magit-faces) + +(defface magit-diff-removed-highlight + '((((class color) (background light)) + :background "#eecccc" + :foreground "#aa2222") + (((class color) (background dark)) + :background "#663333" + :foreground "#eecccc")) + "Face for lines in a diff that have been removed." + :group 'magit-faces) + +(defface magit-diff-our-highlight + '((t :inherit magit-diff-removed-highlight)) + "Face for lines in a diff for our side in a conflict." + :group 'magit-faces) + +(defface magit-diff-base-highlight + '((((class color) (background light)) + :background "#eeeebb" + :foreground "#aaaa11") + (((class color) (background dark)) + :background "#666622" + :foreground "#eeeebb")) + "Face for lines in a diff for the base side in a conflict." + :group 'magit-faces) + +(defface magit-diff-their-highlight + '((t :inherit magit-diff-added-highlight)) + "Face for lines in a diff for their side in a conflict." + :group 'magit-faces) + +(defface magit-diff-context-highlight + '((((class color) (background light)) + :background "grey95" + :foreground "grey50") + (((class color) (background dark)) + :background "grey20" + :foreground "grey70")) + "Face for lines in a diff that have been removed." + :group 'magit-faces) + +(defface magit-diff-whitespace-warning + '((t :inherit trailing-whitespace)) + "Face for highlighting whitespace errors added lines." + :group 'magit-faces) + +(defface magit-diffstat-added + '((((class color) (background light)) :foreground "#22aa22") + (((class color) (background dark)) :foreground "#448844")) + "Face for plus sign in diffstat." + :group 'magit-faces) + +(defface magit-diffstat-removed + '((((class color) (background light)) :foreground "#aa2222") + (((class color) (background dark)) :foreground "#aa4444")) + "Face for minus sign in diffstat." + :group 'magit-faces) + +;;; Commands + +(defconst magit-diff-popup-common + '(:variable magit-diff-arguments + :man-page "git-diff" + :options ((?f "Limit to files" "-- " magit-read-files) + (?u "Context lines" "-U") + (?m "Detect renames" "-M") + (?c "Detect copies" "-C") + (?a "Diff algorithm" "--diff-algorithm=" + magit-diff-select-algorithm)))) + +(defvar magit-diff-popup + `(,@magit-diff-popup-common + :switches ((?f "Show surrounding functions" "--function-context") + (?b "Ignore whitespace changes" "--ignore-space-change") + (?w "Ignore all whitespace" "--ignore-all-space") + (?x "Disallow external diff drivers" "--no-ext-diff") + (?s "Show stats" "--stat")) + :actions ((?d "Dwim" magit-diff-dwim) + (?u "Diff unstaged" magit-diff-unstaged) + (?c "Show commit" magit-show-commit) + (?r "Diff range" magit-diff) + (?s "Diff staged" magit-diff-staged) + (?t "Show stash" magit-stash-show) + (?p "Diff paths" magit-diff-paths) + (?w "Diff worktree" magit-diff-working-tree)) + :default-action magit-diff-dwim + :max-action-columns 3)) + +(defvar magit-diff-refresh-popup + `(,@magit-diff-popup-common + :switches ((?f "Show surrounding functions" "--function-context") + (?b "Ignore whitespace changes" "--ignore-space-change") + (?w "Ignore all whitespace" "--ignore-all-space") + (?x "Disallow external diff drivers" "--no-ext-diff")) + :actions ((?g "Refresh" magit-diff-refresh) + (?t "Toggle hunk refinement" magit-diff-toggle-refine-hunk) + (?s "Set defaults" magit-diff-set-default-arguments) nil + (?w "Save defaults" magit-diff-save-default-arguments)) + :max-action-columns 2)) + +(defvar magit-diff-mode-refresh-popup + `(,@magit-diff-popup-common + :switches ((?f "Show surrounding functions" "--function-context") + (?b "Ignore whitespace changes" "--ignore-space-change") + (?w "Ignore all whitespace" "--ignore-all-space") + (?x "Disallow external diff drivers" "--no-ext-diff") + (?s "Show stats" "--stat")) + :actions ((?g "Refresh" magit-diff-refresh) + (?t "Toggle hunk refinement" magit-diff-toggle-refine-hunk) + (?s "Set defaults" magit-diff-set-default-arguments) + (?r "Switch range type" magit-diff-switch-range-type) + (?w "Save defaults" magit-diff-save-default-arguments) + (?f "Flip revisions" magit-diff-flip-revs)) + :max-action-columns 2)) + +(defvar magit-revision-mode-refresh-popup + `(,@magit-diff-popup-common + :switches ((?f "Show surrounding functions" "--function-context") + (?b "Ignore whitespace changes" "--ignore-space-change") + (?w "Ignore all whitespace" "--ignore-all-space") + (?x "Disallow external diff drivers" "--no-ext-diff") + (?s "Show stats" "--stat")) + :actions ((?g "Refresh" magit-diff-refresh) + (?t "Toggle hunk refinement" magit-diff-toggle-refine-hunk) + (?s "Set defaults" magit-diff-set-default-arguments) nil + (?w "Save defaults" magit-diff-save-default-arguments)) + :max-action-columns 2)) + +(magit-define-popup-keys-deferred 'magit-diff-popup) +(magit-define-popup-keys-deferred 'magit-diff-refresh-popup) +(magit-define-popup-keys-deferred 'magit-diff-mode-refresh-popup) +(magit-define-popup-keys-deferred 'magit-revision-mode-refresh-popup) + +(defcustom magit-diff-arguments '("--stat" "--no-ext-diff") + "The diff arguments used in buffers whose mode derives from `magit-diff-mode'." + :group 'magit-diff + :group 'magit-commands + :type '(repeat (string :tag "Argument"))) + +(defcustom magit-diff-section-arguments '("--no-ext-diff") + "The diff arguments used in buffers that show other things besides diffs." + :group 'magit-diff + :group 'magit-status + :type '(repeat (string :tag "Argument"))) + +(defvar magit-diff-section-file-args nil) +(put 'magit-diff-section-file-args 'permanent-local t) +(put 'magit-diff-section-arguments 'permanent-local t) + +(defun magit-diff-arguments (&optional refresh) + (cond ((memq magit-current-popup '(magit-diff-popup magit-diff-refresh-popup)) + (magit-popup-export-file-args magit-current-popup-args)) + ((derived-mode-p 'magit-diff-mode) + (list (nth 2 magit-refresh-args) + (nth 3 magit-refresh-args))) + (refresh + (list magit-diff-section-arguments + magit-diff-section-file-args)) + (t + (-if-let (buffer (magit-mode-get-buffer 'magit-diff-mode)) + (with-current-buffer buffer + (list (nth 2 magit-refresh-args) + (nth 3 magit-refresh-args))) + (list (default-value 'magit-diff-arguments) nil))))) + +(defun magit-diff-popup (arg) + "Popup console for diff commands." + (interactive "P") + (let ((magit-diff-arguments + ;; We cannot possibly know what suffix command the user is + ;; about to invoke, so we also don't know from which buffer + ;; we should get the current values. However it is much + ;; more likely that we will end up updating the diff buffer, + ;; and we therefore use the value from that buffer. + (-if-let (buffer (magit-mode-get-buffer 'magit-diff-mode)) + (with-current-buffer buffer + (magit-popup-import-file-args (nth 2 magit-refresh-args) + (nth 3 magit-refresh-args))) + (default-value 'magit-diff-arguments)))) + (magit-invoke-popup 'magit-diff-popup nil arg))) + +(defun magit-diff-refresh-popup (arg) + "Popup console for changing diff arguments in the current buffer." + (interactive "P") + (let ((magit-diff-refresh-popup + (pcase major-mode + (`magit-revision-mode magit-revision-mode-refresh-popup) + (`magit-diff-mode magit-diff-mode-refresh-popup) + (_ magit-diff-refresh-popup))) + (magit-diff-arguments + (if (derived-mode-p 'magit-diff-mode) + (magit-popup-import-file-args (nth 2 magit-refresh-args) + (nth 3 magit-refresh-args)) + (magit-popup-import-file-args magit-diff-section-arguments + magit-diff-section-file-args)))) + (magit-invoke-popup 'magit-diff-refresh-popup nil arg))) + +(defun magit-diff-select-algorithm (&rest _ignore) + (magit-read-char-case nil t + (?d "[d]efault" "default") + (?m "[m]inimal" "minimal") + (?p "[p]atience" "patience") + (?h "[h]istogram" "histogram"))) + +;;;###autoload +(defun magit-diff-dwim (&optional args files) + "Show changes for the thing at point." + (interactive (magit-diff-arguments)) + (pcase (magit-diff--dwim) + (`unstaged (magit-diff-unstaged args files)) + (`staged (magit-diff-staged nil args files)) + (`(commit . ,value) + (magit-diff (format "%s^..%s" value value) args files)) + (`(stash . ,value) (magit-stash-show value args)) + ((and range (pred stringp)) + (magit-diff range args files)) + (_ + (call-interactively #'magit-diff)))) + +(defun magit-diff--dwim () + "Return information for performing DWIM diff. + +The information can be in three forms: +1. TYPE + A symbol describing a type of diff where no additional information + is needed to generate the diff. Currently, this includes `staged' + and `unstaged'. +2. (TYPE . VALUE) + Like #1 but the diff requires additional information, which is + given by VALUE. Currently, this includes `commit' and `stash', + where VALUE is the given commit or stash, respectively. +3. RANGE + A string indicating a diff range. + +If no DWIM context is found, nil is returned." + (cond + ((--when-let (magit-region-values 'commit 'branch) + (deactivate-mark) + (concat (car (last it)) ".." (car it)))) + (magit-buffer-refname + (cons 'commit magit-buffer-refname)) + ((derived-mode-p 'magit-revision-mode) + (cons 'commit (car magit-refresh-args))) + ((derived-mode-p 'magit-diff-mode) + (nth 0 magit-refresh-args)) + (t + (magit-section-case + ([* unstaged] 'unstaged) + ([* staged] 'staged) + (unpushed (magit-section-value it)) + (unpulled (magit-section-value it)) + (branch (let ((current (magit-get-current-branch)) + (atpoint (magit-section-value it))) + (if (equal atpoint current) + (--if-let (magit-get-upstream-branch) + (format "%s...%s" it current) + (if (magit-anything-modified-p) + current + (cons 'commit current))) + (format "%s..%s" atpoint current)))) + (commit (cons 'commit (magit-section-value it))) + (stash (cons 'stash (magit-section-value it))))))) + +(defun magit-diff-read-range-or-commit (prompt &optional secondary-default mbase) + "Read range or revision with special diff range treatment. +If MBASE is non-nil, prompt for which rev to place at the end of +a \"revA...revB\" range. Otherwise, always construct +\"revA..revB\" range." + (--if-let (magit-region-values 'commit 'branch) + (let ((revA (car (last it))) + (revB (car it))) + (deactivate-mark) + (if mbase + (let ((base (magit-git-string "merge-base" revA revB))) + (cond + ((string= (magit-rev-parse revA) base) + (format "%s..%s" revA revB)) + ((string= (magit-rev-parse revB) base) + (format "%s..%s" revB revA)) + (t + (let ((main (magit-completing-read "View changes along" + (list revA revB) + nil t nil nil revB))) + (format "%s...%s" + (if (string= main revB) revA revB) main))))) + (format "%s..%s" revA revB))) + (magit-read-range prompt + (or (pcase (magit-diff--dwim) + (`(commit . ,value) + (format "%s^..%s" value value)) + ((and range (pred stringp)) + range)) + secondary-default + (magit-get-current-branch))))) + +(defun magit-diff-setup (rev-or-range const args files) + (magit-mode-setup #'magit-diff-mode rev-or-range const args files)) + +;;;###autoload +(defun magit-diff (rev-or-range &optional args files) + "Show differences between two commits. + +REV-OR-RANGE should be a RANGE or a single revision. If it is a +revision, then show changes in the working tree relative to that +revision. If it is a range, but one side is omitted, then show +changes relative to `HEAD'. + +If the region is active, use the revisions on the first and last +line of the region as the two sides of the range. With a prefix +argument, instead of diffing the revisions, choose a revision to +view changes along, starting at the common ancestor of both +revisions (i.e., use a \"...\" range)." + (interactive (cons (magit-diff-read-range-or-commit "Diff for range" + nil current-prefix-arg) + (magit-diff-arguments))) + (magit-diff-setup rev-or-range nil args files)) + +;;;###autoload +(defun magit-diff-working-tree (&optional rev args files) + "Show changes between the current working tree and the `HEAD' commit. +With a prefix argument show changes between the working tree and +a commit read from the minibuffer." + (interactive + (cons (and current-prefix-arg + (magit-read-branch-or-commit "Diff working tree and commit")) + (magit-diff-arguments))) + (magit-diff-setup (or rev "HEAD") nil args files)) + +;;;###autoload +(defun magit-diff-staged (&optional rev args files) + "Show changes between the index and the `HEAD' commit. +With a prefix argument show changes between the index and +a commit read from the minibuffer." + (interactive + (cons (and current-prefix-arg + (magit-read-branch-or-commit "Diff index and commit")) + (magit-diff-arguments))) + (magit-diff-setup rev (list "--cached") args files)) + +;;;###autoload +(defun magit-diff-unstaged (&optional args files) + "Show changes between the working tree and the index." + (interactive (magit-diff-arguments)) + (magit-diff-setup nil nil args files)) + +;;;###autoload +(defun magit-diff-while-committing (&optional args files) + "While committing, show the changes that are about to be committed. +While amending, invoking the command again toggles between +showing just the new changes or all the changes that will +be committed." + (interactive (magit-diff-arguments)) + (let ((toplevel (magit-toplevel)) + (diff-buf (magit-mode-get-buffer 'magit-diff-mode))) + (if (magit-commit-message-buffer) + (if (and (or ;; most likely an explicit amend + (not (magit-anything-staged-p)) + ;; explicitly toggled from within diff + (and (eq (current-buffer) diff-buf))) + (or (not diff-buf) + (with-current-buffer diff-buf + (or ;; default to include last commit + (not (equal (magit-toplevel) toplevel)) + ;; toggle to include last commit + (not (car magit-refresh-args)))))) + (magit-diff-while-amending args files) + (magit-diff-staged nil args files)) + (user-error "No commit in progress")))) + +(define-key git-commit-mode-map + (kbd "C-c C-d") 'magit-diff-while-committing) + +(defun magit-diff-while-amending (&optional args files) + (magit-diff-setup "HEAD^" (list "--cached") args files)) + +;;;###autoload +(defun magit-diff-paths (a b) + "Show changes between any two files on disk." + (interactive (list (read-file-name "First file: " nil nil t) + (read-file-name "Second file: " nil nil t))) + (magit-diff-setup nil (list "--no-index") + nil (list (expand-file-name a) + (expand-file-name b)))) + +;;;###autoload +(defun magit-show-commit (rev &optional args files module) + "Show the revision at point. +If there is no revision at point or with a prefix argument prompt +for a revision." + (interactive + (let* ((mcommit (magit-section-when module-commit)) + (atpoint (or (and (bound-and-true-p magit-blame-mode) + (magit-blame-chunk-get :hash)) + mcommit + (magit-branch-or-commit-at-point) + (magit-tag-at-point)))) + (nconc (cons (or (and (not current-prefix-arg) atpoint) + (magit-read-branch-or-commit "Show commit" atpoint)) + (magit-diff-arguments)) + (and mcommit (list (magit-section-parent-value + (magit-current-section))))))) + (require 'magit) + (magit-with-toplevel + (when module + (setq default-directory + (expand-file-name (file-name-as-directory module)))) + (unless (magit-rev-verify-commit rev) + (user-error "%s is not a commit" rev)) + (-when-let (buffer (magit-mode-get-buffer 'magit-revision-mode)) + (with-current-buffer buffer + (let ((prev (car magit-refresh-args))) + (unless (equal rev prev) + (dolist (child (cdr (magit-section-children magit-root-section))) + (when (eq (magit-section-type child) 'file) + (magit-section-cache-visibility child))))))) + (magit-mode-setup #'magit-revision-mode rev nil args files))) + +(defun magit-diff-refresh (args files) + "Set the local diff arguments for the current buffer." + (interactive (magit-diff-arguments t)) + (cond ((derived-mode-p 'magit-diff-mode) + (setcdr (cdr magit-refresh-args) (list args files))) + (t + (setq-local magit-diff-section-arguments args) + (setq-local magit-diff-section-file-args files))) + (magit-refresh)) + +(defun magit-diff-set-default-arguments (args files) + "Set the global diff arguments for the current buffer." + (interactive (magit-diff-arguments t)) + (cond ((derived-mode-p 'magit-diff-mode) + (customize-set-variable 'magit-diff-arguments args) + (setcdr (cdr magit-refresh-args) (list args files))) + (t + (customize-set-variable 'magit-diff-section-arguments args) + (kill-local-variable 'magit-diff-section-arguments) + (kill-local-variable 'magit-diff-section-file-args))) + (magit-refresh)) + +(defun magit-diff-save-default-arguments (args files) + "Set and save the global diff arguments for the current buffer." + (interactive (magit-diff-arguments t)) + (cond ((derived-mode-p 'magit-diff-mode) + (customize-save-variable 'magit-diff-arguments args) + (setcdr (cdr magit-refresh-args) (list args files))) + (t + (customize-save-variable 'magit-diff-section-arguments args) + (kill-local-variable 'magit-diff-section-arguments) + (kill-local-variable 'magit-diff-section-file-args))) + (magit-refresh)) + +(defun magit-diff-switch-range-type () + "Convert diff range type. +Change \"revA..revB\" to \"revB...revA\", or vice versa." + (interactive) + (let ((range (car magit-refresh-args))) + (if (and range + (derived-mode-p 'magit-diff-mode) + (string-match magit-range-re range)) + (progn + (setcar magit-refresh-args + (concat (match-string 1 range) + (if (string= (match-string 2 range) "..") + "..." + "..") + (match-string 3 range))) + (magit-refresh)) + (user-error "No range to change")))) + +(defun magit-diff-flip-revs () + "Swap revisions in diff range. +Change \"revA..revB\" to \"revB..revA\"." + (interactive) + (let ((range (car magit-refresh-args))) + (if (and range + (derived-mode-p 'magit-diff-mode) + (string-match magit-range-re range)) + (progn + (setcar magit-refresh-args + (concat (match-string 3 range) + (match-string 2 range) + (match-string 1 range))) + (magit-refresh)) + (user-error "No range to swap")))) + +(defun magit-diff-less-context (&optional count) + "Decrease the context for diff hunks by COUNT lines." + (interactive "p") + (magit-diff-set-context `(lambda (cur) (max 0 (- (or cur 0) ,count))))) + +(defun magit-diff-more-context (&optional count) + "Increase the context for diff hunks by COUNT lines." + (interactive "p") + (magit-diff-set-context `(lambda (cur) (+ (or cur 0) ,count)))) + +(defun magit-diff-default-context () + "Reset context for diff hunks to the default height." + (interactive) + (magit-diff-set-context #'ignore)) + +(defun magit-diff-set-context (fn) + (let* ((def (--if-let (magit-get "diff.context") (string-to-number it) 3)) + (val (car (magit-diff-arguments t))) + (arg (--first (string-match "^-U\\([0-9]+\\)?$" it) val)) + (num (--if-let (and arg (match-string 1 arg)) (string-to-number it) def)) + (val (delete arg val)) + (num (funcall fn num)) + (arg (and num (not (= num def)) (format "-U%i" num))) + (val (if arg (cons arg val) val))) + (if (derived-mode-p 'magit-diff-mode) + (setcar (cddr magit-refresh-args) val) + (setq magit-diff-section-arguments val))) + (magit-refresh)) + +(defun magit-diff-context-p () + (--if-let (--first (string-match "^-U\\([0-9]+\\)$" it) + (car (magit-diff-arguments t))) + (not (equal "-U0" it)) + t)) + +(defun magit-diff-toggle-refine-hunk (&optional style) + "Turn diff-hunk refining on or off. + +If hunk refining is currently on, then hunk refining is turned off. +If hunk refining is off, then hunk refining is turned on, in +`selected' mode (only the currently selected hunk is refined). + +With a prefix argument, the \"third choice\" is used instead: +If hunk refining is currently on, then refining is kept on, but +the refining mode (`selected' or `all') is switched. +If hunk refining is off, then hunk refining is turned on, in +`all' mode (all hunks refined). + +Customize variable `magit-diff-refine-hunk' to change the default mode." + (interactive "P") + (setq-local magit-diff-refine-hunk + (if style + (if (eq magit-diff-refine-hunk 'all) t 'all) + (not magit-diff-refine-hunk))) + (magit-diff-update-hunk-refinement)) + +(defun magit-diff-visit-file (file &optional other-window force-worktree) + "From a diff, visit the corresponding file at the appropriate position. + +When the file is already being displayed in another window of the +same frame, then just select that window and adjust point. With +a prefix argument also display in another window. + +If the diff shows changes in the worktree, the index, or `HEAD', +then visit the actual file. Otherwise when the diff is about +an older commit, then visit the respective blob using +`magit-find-file'. Also see `magit-diff-visit-file-worktree' +which, as the name suggests always visits the actual file." + (interactive (list (--if-let (magit-file-at-point) + (expand-file-name it) + (user-error "No file at point")) + current-prefix-arg)) + (if (file-accessible-directory-p file) + (magit-diff-visit-directory file other-window) + (let ((current (magit-current-section)) + (rev (cond (force-worktree nil) + ((derived-mode-p 'magit-revision-mode) + (car magit-refresh-args)) + ((derived-mode-p 'magit-diff-mode) + (--when-let (car magit-refresh-args) + (and (string-match "\\.\\.\\([^.].*\\)?[ \t]*\\'" it) + (match-string 1 it)))))) + (unmerged-p (magit-anything-unmerged-p file)) + hunk line col buffer) + (when (and rev (magit-rev-head-p rev)) + (setq rev nil)) + (setq hunk + (pcase (magit-diff-scope) + ((or `hunk `region) current) + ((or `file `files) (car (magit-section-children current))) + (`list (car (magit-section-children + (car (magit-section-children current))))))) + (when hunk + (setq line (magit-diff-hunk-line hunk) + col (magit-diff-hunk-column hunk))) + (setq buffer (if rev + (magit-find-file-noselect rev file) + (or (get-file-buffer file) + (find-file-noselect file)))) + (magit-display-file-buffer buffer) + (when line + (goto-char (point-min)) + (forward-line (1- line)) + (when col + (move-to-column col))) + (when unmerged-p + (smerge-start-session)) + (with-current-buffer buffer + (run-hooks 'magit-diff-visit-file-hook))))) + +(defvar magit-display-file-buffer-function + 'magit-display-file-buffer-traditional + "The function used by `magit-diff-visit-file' to display blob buffers. + +Other commands such as `magit-find-file' do not use this +function. Instead they use high-level functions to select the +window to be used to display the buffer. This variable and the +related functions are an experimental feature and should be +treated as such.") + +(defun magit-display-file-buffer (buffer) + (funcall magit-display-file-buffer-function buffer)) + +(defun magit-display-file-buffer-traditional (buffer) + (if (or current-prefix-arg (get-buffer-window buffer)) + (pop-to-buffer buffer) + (switch-to-buffer buffer))) + +(defun magit-diff-visit-file-worktree (file &optional other-window) + "From a diff, visit the corresponding file at the appropriate position. + +When the file is already being displayed in another window of the +same frame, then just select that window and adjust point. With +a prefix argument also display in another window. + +The actual file in the worktree is visited. The positions in the +hunk headers get less useful the \"older\" the changes are, and +as a result, jumping to the appropriate position gets less +reliable. + +Also see `magit-diff-visit-file' which visits the respective +blob, unless the diff shows changes in the worktree, the index, +or `HEAD'." + (interactive (list (or (magit-file-at-point) + (user-error "No file at point")) + current-prefix-arg)) + (magit-diff-visit-file file other-window t)) + +(defun magit-diff-hunk-line (section) + (let* ((value (magit-section-value section)) + (prefix (- (length value) 2)) + (cpos (marker-position (magit-section-content section))) + (stop (line-number-at-pos)) + (cstart (save-excursion (goto-char cpos) (line-number-at-pos))) + (line (car (last value)))) + (string-match "^\\+\\([0-9]+\\)" line) + (setq line (string-to-number (match-string 1 line))) + (when (> cstart stop) + (save-excursion + (goto-char cpos) + (re-search-forward "^[-+]") + (setq stop (line-number-at-pos)))) + (save-excursion + (goto-char cpos) + (while (< (line-number-at-pos) stop) + (unless (string-match-p + "-" (buffer-substring (point) (+ (point) prefix))) + (cl-incf line)) + (forward-line))) + line)) + +(defun magit-diff-hunk-column (section) + (if (or (< (point) (magit-section-content section)) + (save-excursion (beginning-of-line) (looking-at-p "-"))) + 0 + (max 0 (- (+ (current-column) 2) + (length (magit-section-value section)))))) + +(defun magit-diff-visit-directory (directory &optional other-window) + (if (equal (magit-toplevel directory) + (magit-toplevel)) + (magit-dired-jump other-window) + (let ((display-buffer-overriding-action + (if other-window + '(nil (inhibit-same-window t)) + '(display-buffer-same-window)))) + (magit-status-internal directory)))) + +(defun magit-diff-show-or-scroll-up () + "Update the commit or diff buffer for the thing at point. + +Either show the commit or stash at point in the appropriate +buffer, or if that buffer is already being displayed in the +current frame and contains information about that commit or +stash, then instead scroll the buffer up. If there is no +commit or stash at point, then prompt for a commit." + (interactive) + (magit-diff-show-or-scroll 'scroll-up)) + +(defun magit-diff-show-or-scroll-down () + "Update the commit or diff buffer for the thing at point. + +Either show the commit or stash at point in the appropriate +buffer, or if that buffer is already being displayed in the +current frame and contains information about that commit or +stash, then instead scroll the buffer down. If there is no +commit or stash at point, then prompt for a commit." + (interactive) + (magit-diff-show-or-scroll 'scroll-down)) + +(defun magit-diff-show-or-scroll (fn) + (let (rev cmd buf win) + (cond + (magit-blame-mode + (setq rev (magit-blame-chunk-get :hash) + cmd 'magit-show-commit + buf (magit-mode-get-buffer 'magit-revision-mode))) + ((derived-mode-p 'git-rebase-mode) + (save-excursion + (goto-char (line-beginning-position)) + (--if-let (and (looking-at git-rebase-line) + (match-string 2)) + (setq rev it + cmd 'magit-show-commit + buf (magit-mode-get-buffer 'magit-revision-mode)) + (user-error "No commit on this line")))) + (t + (magit-section-case + ((commit branch) + (setq rev (magit-section-value it) + cmd 'magit-show-commit + buf (magit-mode-get-buffer 'magit-revision-mode))) + (stash + (setq rev (magit-section-value it) + cmd 'magit-stash-show + buf (magit-mode-get-buffer 'magit-diff-mode)))))) + (if rev + (if (and buf + (setq win (get-buffer-window buf)) + (with-current-buffer buf + (equal (if (eq cmd 'magit-stash-show) + (concat rev "^2^.." rev) + rev) + (car magit-refresh-args)))) + (with-selected-window win + (condition-case nil + (funcall fn) + (error + (goto-char (pcase fn + (`scroll-up (point-min)) + (`scroll-down (point-max))))))) + (let ((magit-display-buffer-noselect t)) + (if (eq cmd 'magit-show-commit) + (apply #'magit-show-commit rev (magit-diff-arguments)) + (funcall cmd rev)))) + (call-interactively #'magit-show-commit)))) + +;;; Diff Mode + +(defvar magit-diff-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + (define-key map "\C-c\C-d" 'magit-diff-while-committing) + (define-key map "\C-c\C-b" 'magit-go-backward) + (define-key map "\C-c\C-f" 'magit-go-forward) + (define-key map "\s" 'scroll-up) + (define-key map "\d" 'scroll-down) + (define-key map "j" 'magit-jump-to-diffstat-or-diff) + map) + "Keymap for `magit-diff-mode'.") + +(define-derived-mode magit-diff-mode magit-mode "Magit Diff" + "Mode for looking at a Git diff. + +This mode is documented in info node `(magit)Diff buffer'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-section-toggle] to expand or hide the section at point. +Type \\[magit-visit-thing] to visit the hunk or file at point. + +Staging and applying changes is documented in info node +`(magit)Staging and unstaging' and info node `(magit)Applying'. + +\\Type \ +\\[magit-apply] to apply the change at point, \ +\\[magit-stage] to stage, +\\[magit-unstage] to unstage, \ +\\[magit-discard] to discard, or \ +\\[magit-reverse] to reverse it. + +\\{magit-diff-mode-map}" + :group 'magit-diff + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-diff-refresh-buffer (rev-or-range const _args files) + "Refresh the current `magit-diff-mode' buffer. + +In such buffers the buffer-local value of `magit-refresh-args' +has the same form as the arguments of this function. The value +is set in `magit-mode-setup'." + (setq header-line-format + (propertize + (if (member "--no-index" const) + (apply #'format " Differences between %s and %s" files) + (concat (if rev-or-range + (if (string-match-p "\\.\\." rev-or-range) + (format " Changes in %s" rev-or-range) + (format " Changes from %s to working tree" rev-or-range)) + (if (member "--cached" const) + " Staged changes" + " Unstaged changes")) + (pcase (length files) + (0) + (1 (concat " in file " (car files))) + (_ (concat " in files " + (mapconcat #'identity files ", ")))))) + 'face 'magit-header-line)) + (magit-insert-section (diffbuf) + (run-hook-with-args 'magit-diff-sections-hook rev-or-range))) + +(defun magit-insert-diff (rev-or-range) + "Insert the diff into this `magit-diff-mode' buffer." + (magit-git-wash #'magit-diff-wash-diffs + "diff" rev-or-range "-p" "--no-prefix" + (and (member "--stat" (nth 2 magit-refresh-args)) "--numstat") + (nth 1 magit-refresh-args) + (nth 2 magit-refresh-args) "--" + (nth 3 magit-refresh-args))) + +(defvar magit-file-section-map + (let ((map (make-sparse-keymap))) + (define-key map [C-return] 'magit-diff-visit-file-worktree) + (define-key map "\C-j" 'magit-diff-visit-file-worktree) + (define-key map [remap magit-visit-thing] 'magit-diff-visit-file) + (define-key map [remap magit-delete-thing] 'magit-discard) + (define-key map [remap magit-revert-no-commit] 'magit-reverse) + (define-key map "a" 'magit-apply) + (define-key map "C" 'magit-commit-add-log) + (define-key map "K" 'magit-file-untrack) + (define-key map "R" 'magit-file-rename) + (define-key map "s" 'magit-stage) + (define-key map "u" 'magit-unstage) + map) + "Keymap for `file' sections.") + +(defvar magit-hunk-section-map + (let ((map (make-sparse-keymap))) + (define-key map [C-return] 'magit-diff-visit-file-worktree) + (define-key map "\C-j" 'magit-diff-visit-file-worktree) + (define-key map [remap magit-visit-thing] 'magit-diff-visit-file) + (define-key map [remap magit-delete-thing] 'magit-discard) + (define-key map [remap magit-revert-no-commit] 'magit-reverse) + (define-key map "a" 'magit-apply) + (define-key map "C" 'magit-commit-add-log) + (define-key map "s" 'magit-stage) + (define-key map "u" 'magit-unstage) + map) + "Keymap for `hunk' sections.") + +(defconst magit-diff-headline-re + (concat "^\\(@@@?\\|diff\\|Submodule\\|" + "\\* Unmerged path\\|merged\\|changed in both\\)")) + +(defconst magit-diff-statline-re + (concat "^ ?" + "\\(.*\\)" ; file + "\\( +| +\\)" ; separator + "\\([0-9]+\\|Bin\\(?: +[0-9]+ -> [0-9]+ bytes\\)?$\\) ?" + "\\(\\+*\\)" ; add + "\\(-*\\)$")) ; del + +(defconst magit-diff-submodule-re + (concat "^Submodule \\([^ ]+\\) \\(?:" + "\\([^ ]+ (new submodule)\\)\\|" + "\\([^ ]+ (submodule deleted)\\)\\|" + "\\(contains \\(?:modified\\|untracked\\) content\\)\\|" + "\\([^ :]+\\)\\( (rewind)\\)?:\\)$")) + +(defun magit-diff-wash-diffs (args &optional limit) + (when (member "--stat" args) + (magit-diff-wash-diffstat)) + (when (re-search-forward magit-diff-headline-re limit t) + (goto-char (line-beginning-position)) + (magit-wash-sequence (apply-partially 'magit-diff-wash-diff args)) + (insert ?\n))) + +(defun magit-jump-to-diffstat-or-diff () + "Jump to the diffstat or diff. +When point is on a file inside the diffstat section, then jump +to the respective diff section, otherwise jump to the diffstat +section or a child thereof." + (interactive) + (--if-let (magit-get-section + (append (magit-section-case + ([file diffstat] `((file . ,(magit-section-value it)))) + (file `((file . ,(magit-section-value it)) (diffstat))) + (t '((diffstat)))) + (magit-section-ident magit-root-section))) + (magit-section-goto it) + (user-error "No diffstat in this buffer"))) + +(defun magit-diff-wash-diffstat () + (let (heading (beg (point))) + (when (re-search-forward "^ ?\\([0-9]+ +files? change[^\n]*\n\\)" nil t) + (setq heading (match-string 1)) + (magit-delete-match) + (goto-char beg) + (magit-insert-section it (diffstat) + (insert (propertize heading 'face 'magit-diff-file-heading)) + (magit-insert-heading) + (let (files) + (while (looking-at "^[-0-9]+\t[-0-9]+\t\\(.+\\)$") + (push (magit-decode-git-path (match-string 1)) files) + (magit-delete-line)) + (setq files (nreverse files)) + (while (looking-at magit-diff-statline-re) + (magit-bind-match-strings (file sep cnt add del) nil + (magit-delete-line) + (when (string-match " +$" file) + (setq sep (concat (match-string 0 file) sep)) + (setq file (substring file 0 (match-beginning 0)))) + (let ((le (length file)) ld) + (setq file (magit-decode-git-path file)) + (setq ld (length file)) + (when (> le ld) + (setq sep (concat (make-string (- le ld) ?\s) sep)))) + (magit-insert-section (file (pop files)) + (insert (propertize file 'face 'magit-filename) sep cnt " ") + (when add + (insert (propertize add 'face 'magit-diffstat-added))) + (when del + (insert (propertize del 'face 'magit-diffstat-removed))) + (insert "\n"))))) + (if (looking-at "^$") (forward-line) (insert "\n")))))) + +(defun magit-diff-wash-diff (args) + (cond + ((looking-at magit-diff-submodule-re) + (magit-diff-wash-submodule)) + ((looking-at "^\\* Unmerged path \\(.*\\)") + (let ((file (magit-decode-git-path (match-string 1)))) + (magit-delete-line) + (unless (and (derived-mode-p 'magit-status-mode) + (not (member "--cached" args))) + (magit-insert-section (file file) + (insert (propertize + (format "unmerged %s%s" file + (pcase (cddr (car (magit-file-status file))) + (`(?D ?D) " (both deleted)") + (`(?D ?U) " (deleted by us)") + (`(?U ?D) " (deleted by them)") + (`(?A ?A) " (both added)") + (`(?A ?U) " (added by us)") + (`(?U ?A) " (added by them)") + (`(?U ?U) ""))) + 'face 'magit-diff-file-heading)) + (insert ?\n)))) + t) + ((looking-at "^\\(merged\\|changed in both\\)") + (let ((status (if (equal (match-string 1) "merged") 'merged 'conflict)) + file orig modes) + (magit-delete-line) + (while (looking-at + "^ \\([^ ]+\\) +[0-9]\\{6\\} \\([a-z0-9]\\{40\\}\\) \\(.+\\)$") + (magit-bind-match-strings (side _blob name) nil + (pcase side + ("result" (setq file name)) + ("our" (setq orig name)) + ("their" (setq file name)))) + (magit-delete-line)) + (setq orig (magit-decode-git-path orig)) + (setq file (magit-decode-git-path file)) + (magit-diff-insert-file-section file orig status modes nil))) + ((looking-at + "^diff --\\(?:\\(git\\) \\(?:\\(.+?\\) \\2\\)?\\|\\(cc\\|combined\\) \\(.+\\)\\)") + (let ((status (cond ((equal (match-string 1) "git") "modified") + ((derived-mode-p 'magit-revision-mode) "resolved") + (t "unmerged"))) + (file (or (match-string 2) (match-string 4))) + (beg (point)) + orig header modes) + (save-excursion + (forward-line 1) + (setq header (buffer-substring + beg (if (re-search-forward magit-diff-headline-re nil t) + (match-beginning 0) + (point-max))))) + (magit-delete-line) + (while (not (or (eobp) (looking-at magit-diff-headline-re))) + (if (looking-at "^old mode \\([^\n]+\\)\nnew mode \\([^\n]+\\)\n") + (progn (setq modes (match-string 0)) + (magit-delete-match)) + (cond + ((looking-at "^--- \\([^/].*?\\)\t?$") ; i.e. not /dev/null + (setq orig (match-string 1))) + ((looking-at "^\\+\\+\\+ \\([^/].*?\\)\t?$") + (setq file (match-string 1))) + ((looking-at "^\\(copy\\|rename\\) from \\(.+\\)$") + (setq orig (match-string 2))) + ((looking-at "^\\(copy\\|rename\\) to \\(.+\\)$") + (setq file (match-string 2)) + (setq status (if (equal (match-string 1) "copy") "new file" "renamed"))) + ((looking-at "^\\(new file\\|deleted\\)") + (setq status (match-string 1)))) + (magit-delete-line))) + (when orig + (setq orig (magit-decode-git-path orig))) + (setq file (magit-decode-git-path file)) + ;; KLUDGE `git-log' ignores `--no-prefix' when `-L' is used. + (when (derived-mode-p 'magit-log-mode) + (setq file (substring file 2)) + (when orig + (setq orig (substring orig 2)))) + (magit-diff-insert-file-section file orig status modes header))))) + +(defun magit-diff-insert-file-section (file orig status modes header) + (magit-insert-section section + (file file (or (equal status "deleted") + (derived-mode-p 'magit-status-mode))) + (insert (propertize (format "%-10s %s\n" status + (if (or (not orig) (equal orig file)) + file + (format "%s -> %s" orig file))) + 'face 'magit-diff-file-heading)) + (magit-insert-heading) + (unless (equal orig file) + (setf (magit-section-source section) orig)) + (setf (magit-section-diff-header section) header) + (when modes + (magit-insert-section (hunk) + (insert modes))) + (magit-wash-sequence #'magit-diff-wash-hunk))) + +(defun magit-diff-wash-submodule () + (magit-bind-match-strings (module new deleted dirty range rewind) nil + (magit-delete-line) + (when (and dirty + (looking-at magit-diff-submodule-re) + (string= (match-string 1) module)) + (setq range (match-string 5)) + (magit-delete-line)) + (while (looking-at "^ \\([<>]\\) \\(.+\\)$") + (magit-delete-line)) + (if range + (let ((default-directory + (file-name-as-directory + (expand-file-name module (magit-toplevel))))) + (setf (magit-section-value + (magit-insert-section (file module t) + (magit-insert-heading + (concat (propertize (concat "modified " module) + 'face 'magit-diff-file-heading) + " (" + (if rewind "rewind" "new commits") + (and dirty ", modified content") + ")")) + (unless rewind + (magit-git-wash + (apply-partially 'magit-log-wash-log 'module) + "log" "--oneline" "--left-right" range) + (delete-char -1)))) + module)) + (magit-insert-section (file module) + (insert (propertize (if new + (concat "new module " module) + (concat "modified " module)) + 'face 'magit-diff-file-heading) + (cond (dirty " (modified content)") + (deleted " (deleted submodule)"))) + (insert ?\n))))) + +(defun magit-diff-wash-hunk () + (when (looking-at "^@\\{2,\\} \\(.+?\\) @\\{2,\\}\\(?: \\(.*\\)\\)?") + (let ((heading (match-string 0)) + (value (cons (match-string 2) (split-string (match-string 1))))) + (magit-delete-line) + (magit-insert-section it (hunk value) + (insert (propertize (concat heading "\n") 'face 'magit-diff-hunk-heading)) + (magit-insert-heading) + (while (not (or (eobp) (looking-at "^[^-+\s\\]"))) + (forward-line)) + (setf (magit-section-end it) (point)) + (setf (magit-section-washer it) #'magit-diff-paint-hunk))) + t)) + +(defun magit-diff-expansion-threshold (section) + "Keep new diff sections collapsed if washing takes too long." + (and (memq (magit-section-type section) '(file)) + (> (float-time (time-subtract (current-time) magit-refresh-start-time)) + magit-diff-expansion-threshold) + 'hide)) + +;;; Revision Mode + +(define-derived-mode magit-revision-mode magit-diff-mode "Magit Rev" + "Mode for looking at a Git commit. + +This mode is documented in info node `(magit)Revision buffer'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-section-toggle] to expand or hide the section at point. +Type \\[magit-visit-thing] to visit the hunk or file at point. + +Staging and applying changes is documented in info node +`(magit)Staging and unstaging' and info node `(magit)Applying'. + +\\Type \ +\\[magit-apply] to apply the change at point, \ +\\[magit-stage] to stage, +\\[magit-unstage] to unstage, \ +\\[magit-discard] to discard, or \ +\\[magit-reverse] to reverse it. + +\\{magit-revision-mode-map}" + :group 'magit-revision + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-revision-refresh-buffer (rev __const _args _files) + (setq header-line-format + (propertize (format " %s %s" (capitalize (magit-object-type rev)) rev) + 'face 'magit-header-line)) + (magit-insert-section (commitbuf) + (run-hook-with-args 'magit-revision-sections-hook rev))) + +(defun magit-insert-revision-diff (rev) + "Insert the diff into this `magit-revision-mode' buffer." + ;; Before v2.2.0, "--format=" did not mean "no output". + ;; Instead the default format was used. So use "--format=%n" + ;; and then delete the empty lines. + (magit-git-wash (lambda (args) + (delete-region (point) (progn (forward-line 3) (point))) + (magit-diff-wash-diffs args)) + "show" "-p" "--cc" "--format=%n" "--no-prefix" + (and (member "--stat" (nth 2 magit-refresh-args)) "--numstat") + (nth 2 magit-refresh-args) (concat rev "^{commit}") "--" + (nth 3 magit-refresh-args))) + +(defun magit-insert-revision-tag (rev) + "Insert tag message and headers into a revision buffer. +This function only inserts anything when `magit-show-commit' is +called with a tag as argument, when that is called with a commit +or a ref which is not a branch, then it inserts nothing." + (when (equal (magit-object-type rev) "tag") + (magit-insert-section (taginfo) + (let ((beg (point))) + (magit-git-insert "cat-file" "tag" rev) + (goto-char beg) + (forward-line 3) + (delete-region beg (point))) + (looking-at "^tagger \\([^<]+\\) <\\([^>]+\\)") + (let ((heading (format "Tagger: %s <%s>" + (match-string 1) + (match-string 2)))) + (magit-delete-line) + (insert (propertize heading 'face 'magit-section-secondary-heading))) + (magit-insert-heading) + (goto-char (point-max)) + (insert ?\n)))) + +(defun magit-insert-revision-message (rev) + "Insert the commit message into a revision buffer." + (magit-insert-section (message) + (let ((beg (point))) + (magit-rev-insert-format "%B" rev) + (if (= (point) (+ beg 2)) + (progn (backward-delete-char 2) + (insert "(no message)\n")) + (goto-char beg) + (forward-line) + (put-text-property beg (point) 'face 'magit-section-secondary-heading) + (magit-insert-heading) + (goto-char (point-max)))))) + +(defun magit-insert-revision-notes (rev) + "Insert commit notes into a revision buffer." + (magit-insert-section (notes) + (let ((beg (point))) + (magit-git-insert "notes" "show" rev) + (if (= (point) beg) + (magit-cancel-section) + (goto-char beg) + (forward-line) + (put-text-property beg (point) 'face 'magit-section-secondary-heading) + (magit-insert-heading) + (goto-char (point-max)) + (insert ?\n))))) + +(defun magit-insert-revision-headers (rev) + "Insert headers about the commit into a revision buffer." + (magit-insert-section (headers) + ;; Before v2.2.0, "%D" was not supported. + (--when-let (magit-rev-format "%d" rev "--decorate=full") + (insert (magit-format-ref-labels (substring it 2 -1)) ?\s)) + (insert (propertize (magit-rev-parse (concat rev "^{commit}")) + 'face 'magit-hash)) + (magit-insert-heading) + (let ((beg (point))) + (magit-rev-insert-format magit-revision-headers-format rev) + (magit-insert-revision-gravatars rev beg)) + (when magit-revision-insert-related-refs + (dolist (parent (magit-commit-parents rev)) + (magit-insert-section (commit parent) + (let ((line (magit-rev-format "%h %s" parent))) + (string-match "^\\([^ ]+\\) \\(.*\\)" line) + (magit-bind-match-strings (hash msg) line + (insert "Parent: ") + (insert (propertize hash 'face 'magit-hash)) + (insert " " msg "\n"))))) + (-when-let (merged (magit-list-merged-branches rev)) + (insert "Merged: ") + (let (branch) + (while (and (< (+ (- (point) (line-beginning-position)) + (length (car merged)) 9) + (window-width)) + (setq branch (pop merged))) + (insert ?\s) + (magit-insert-section (branch branch) + (insert (propertize branch 'face 'magit-branch-local))))) + (when merged + (insert (format " (%s more)" (length merged)))) + (insert ?\n)) + (-when-let (containing (magit-list-containing-branches rev)) + (insert "Containing:") + (let (branch) + (while (and (< (+ (- (point) (line-beginning-position)) + (length (car containing)) 9) + (window-width)) + (setq branch (pop containing))) + (insert ?\s) + (magit-insert-section (branch branch) + (insert (propertize branch 'face 'magit-branch-local))))) + (when containing + (insert (format " (%s more)" (length containing)))) + (insert ?\n)) + (-when-let (follows (magit-get-current-tag rev t)) + (let ((tag (car follows)) + (cnt (cadr follows))) + (magit-insert-section (tag tag) + (insert (format "Follows: %s (%s)\n" + (propertize tag 'face 'magit-tag) + (propertize (number-to-string cnt) + 'face 'magit-branch-local)))))) + (-when-let (precedes (magit-get-next-tag rev t)) + (let ((tag (car precedes)) + (cnt (cadr precedes))) + (magit-insert-section (tag tag) + (insert (format "Precedes: %s (%s)\n" + (propertize tag 'face 'magit-tag) + (propertize (number-to-string cnt) + 'face 'magit-tag)))))) + (insert ?\n)))) + +(defun magit-insert-revision-gravatars (rev beg) + (when (and magit-revision-show-gravatars (window-system)) + (require 'gravatar) + (magit-insert-revision-gravatar beg (magit-rev-format "%aE" rev) + (car magit-revision-show-gravatars)) + (magit-insert-revision-gravatar beg (magit-rev-format "%cE" rev) + (cdr magit-revision-show-gravatars)) + (goto-char (point-max)))) + +(defun magit-insert-revision-gravatar (beg email regexp) + (when (and email (goto-char beg) (re-search-forward regexp nil t)) + (ignore-errors + (let* ((offset (length (match-string 0))) + (font-obj (query-font (font-at (point) (get-buffer-window)))) + (size (* 2 (+ (aref font-obj 4) (aref font-obj 5)))) + (align-to (+ offset (ceiling (/ size (aref font-obj 7) 1.0)))) + (gravatar-size (- size 2)) + (slice1 '(slice .0 .0 1.0 0.5)) + (slice2 '(slice .0 .5 1.0 1.0))) + (gravatar-retrieve + email + (lambda (image offset align-to slice1 slice2) + (unless (eq image 'error) + (insert (propertize " " 'display `((,@image :ascent center :relief 1) + ,slice1))) + (insert (propertize " " 'display `((space :align-to ,align-to)))) + (forward-line) + (forward-char offset) + (insert (propertize " " 'display `((,@image :ascent center :relief 1) + ,slice2))) + (insert (propertize " " 'display `((space :align-to ,align-to)))))) + (list offset align-to + (if magit-revision-use-gravatar-kludge slice2 slice1) + (if magit-revision-use-gravatar-kludge slice1 slice2))))))) + +;;; Diff Sections + +(defvar magit-unstaged-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-diff-unstaged) + (define-key map [remap magit-delete-thing] 'magit-discard) + (define-key map "s" 'magit-stage) + (define-key map "u" 'magit-unstage) + map) + "Keymap for the `unstaged' section.") + +(magit-define-section-jumper magit-jump-to-unstaged "Unstaged changes" unstaged) + +(defun magit-insert-unstaged-changes () + "Insert section showing unstaged changes." + (magit-insert-section (unstaged) + (magit-insert-heading "Unstaged changes:") + (magit-git-wash #'magit-diff-wash-diffs + "diff" magit-diff-section-arguments "--no-prefix" + "--" magit-diff-section-file-args))) + +(defvar magit-staged-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-diff-staged) + (define-key map [remap magit-delete-thing] 'magit-discard) + (define-key map [remap magit-revert-no-commit] 'magit-reverse) + (define-key map "s" 'magit-stage) + (define-key map "u" 'magit-unstage) + map) + "Keymap for the `staged' section.") + +(magit-define-section-jumper magit-jump-to-staged "Staged changes" staged) + +(defun magit-insert-staged-changes () + "Insert section showing staged changes." + (magit-insert-section (staged) + (magit-insert-heading "Staged changes:") + (magit-git-wash #'magit-diff-wash-diffs + "diff" "--cached" magit-diff-section-arguments "--no-prefix" + "--" magit-diff-section-file-args))) + +;;; Diff Type + +(defun magit-diff-type (&optional section) + "Return the diff type of SECTION. + +The returned type is one of the symbols `staged', `unstaged', +`committed', or `undefined'. This type serves a similar purpose +as the general type common to all sections (which is stored in +the `type' slot of the corresponding `magit-section' struct) but +takes additional information into account. When the SECTION +isn't related to diffs and the buffer containing it also isn't +a diff-only buffer, then return nil. + +Currently the type can also be one of `tracked' and `untracked' +but these values are not handled explicitly everywhere they +should be and a possible fix could be to just return nil here. + +The section has to be a `diff' or `hunk' section, or a section +whose children are of type `diff'. If optional SECTION is nil, +return the diff type for the current section. In buffers whose +major mode is `magit-diff-mode' SECTION is ignored and the type +is determined using other means. In `magit-revision-mode' +buffers the type is always `committed'. + +Do not confuse this with `magit-diff-scope' (which see)." + (--when-let (or section (magit-current-section)) + (cond ((derived-mode-p 'magit-revision-mode 'magit-stash-mode) 'committed) + ((derived-mode-p 'magit-diff-mode) + (let ((range (nth 0 magit-refresh-args)) + (const (nth 1 magit-refresh-args))) + (cond ((member "--no-index" const) 'undefined) + ((not range) + (if (member "--cached" const) + 'staged + 'unstaged)) + ((member "--cached" const) + (if (magit-rev-head-p range) + 'staged + 'undefined)) ; i.e. committed and staged + (t 'committed)))) + ((derived-mode-p 'magit-status-mode) + (let ((stype (magit-section-type it))) + (if (memq stype '(staged unstaged tracked untracked)) + stype + (pcase stype + (`file (let* ((parent (magit-section-parent it)) + (type (magit-section-type parent))) + (if (eq type 'file) + (magit-diff-type parent) + type))) + (`hunk (-> it magit-section-parent magit-section-parent + magit-section-type)))))) + ((derived-mode-p 'magit-log-mode) + (if (or (and (magit-section-match 'commit section) + (magit-section-children section)) + (magit-section-match [* file commit] section)) + 'committed + 'undefined)) + (t 'undefined)))) + +(cl-defun magit-diff-scope (&optional (section nil ssection) strict) + "Return the diff scope of SECTION or the selected section(s). + +A diff's \"scope\" describes what part of a diff is selected, it is +a symbol, one of `region', `hunk', `hunks', `file', `files', or +`list'. Do not confuse this with the diff \"type\", as returned by +`magit-diff-type'. + +If optional SECTION is non-nil, then return the scope of that, +ignoring the sections selected by the region. Otherwise return +the scope of the current section, or if the region is active and +selects a valid group of diff related sections, the type of these +sections, i.e. `hunks' or `files'. If SECTION, or if that is nil +the current section, is a `hunk' section; and the region region +starts and ends inside the body of a that section, then the type +is `region'. + +If optional STRICT is non-nil then return nil if the diff type of +the section at point is `untracked' or the section at point is not +actually a `diff' but a `diffstat' section." + (let ((siblings (and (not ssection) (magit-region-sections)))) + (setq section (or section (car siblings) (magit-current-section))) + (when (and section + (or (not strict) + (and (not (eq (magit-diff-type section) 'untracked)) + (not (eq (--when-let (magit-section-parent section) + (magit-section-type it)) + 'diffstat))))) + (pcase (list (magit-section-type section) + (and siblings t) + (and (region-active-p) t) + ssection) + (`(hunk nil t ,_) + (if (magit-section-internal-region-p section) 'region 'hunk)) + (`(hunk t t nil) 'hunks) + (`(hunk ,_ ,_ ,_) 'hunk) + (`(file t t nil) 'files) + (`(file ,_ ,_ ,_) 'file) + (`(,(or `staged `unstaged `untracked) + nil ,_ ,_) 'list))))) + +;;; Diff Highlight + +(defun magit-diff-unhighlight (section selection) + "Remove the highlighting of the diff-related SECTION." + (when (eq (magit-section-type section) 'hunk) + (magit-diff-paint-hunk section selection nil) + t)) + +(defun magit-diff-highlight (section selection) + "Highlight the diff-related SECTION and return t. +If SECTION is not a diff-related section, then do nothing and +return nil. If SELECTION is non-nil then it is a list of sections +selected by the region, including SECTION. All of these sections +are highlighted." + (if (and (magit-section-match 'commit section) + (magit-section-children section)) + (progn (if selection + (dolist (section selection) + (magit-diff-highlight-list section selection)) + (magit-diff-highlight-list section)) + t) + (-when-let (scope (magit-diff-scope section t)) + (cond ((eq scope 'region) + (magit-diff-paint-hunk section selection t)) + (selection + (dolist (section selection) + (magit-diff-highlight-recursive section selection))) + (t + (magit-diff-highlight-recursive section))) + t))) + +(defun magit-diff-highlight-recursive (section &optional selection) + (pcase (magit-diff-scope section) + (`list (magit-diff-highlight-list section selection)) + (`file (magit-diff-highlight-file section selection)) + (`hunk (magit-diff-highlight-heading section selection) + (magit-diff-paint-hunk section selection t)) + (_ (magit-section-highlight section nil)))) + +(defun magit-diff-highlight-list (section &optional selection) + (let ((beg (magit-section-start section)) + (cnt (magit-section-content section)) + (end (magit-section-end section))) + (unless (and (region-active-p) + (= end (1+ (region-end)))) + (magit-section-make-overlay beg cnt 'magit-section-highlight) + (unless (magit-section-hidden section) + (dolist (child (magit-section-children section)) + (magit-diff-highlight-recursive child selection)))) + (when magit-diff-highlight-hunk-body + (magit-section-make-overlay (1- end) end 'magit-section-highlight)))) + +(defun magit-diff-highlight-file (section &optional selection) + (magit-diff-highlight-heading section selection) + (unless (magit-section-hidden section) + (dolist (child (magit-section-children section)) + (magit-diff-highlight-recursive child selection)))) + +(defun magit-diff-highlight-heading (section &optional selection) + (magit-section-make-overlay + (magit-section-start section) + (or (magit-section-content section) + (magit-section-end section)) + (pcase (list (magit-section-type section) + (and (member section selection) t)) + (`(file t) 'magit-diff-file-heading-selection) + (`(file nil) 'magit-diff-file-heading-highlight) + (`(hunk t) 'magit-diff-hunk-heading-selection) + (`(hunk nil) 'magit-diff-hunk-heading-highlight)))) + +;;; Hunk Paint + +(cl-defun magit-diff-paint-hunk + (section &optional selection + (highlight (magit-section-selected-p section selection))) + (let (paint) + (unless magit-diff-highlight-hunk-body + (setq highlight nil)) + (cond (highlight + (unless (magit-section-hidden section) + (add-to-list 'magit-section-highlighted-sections section) + (cond ((memq section magit-section-unhighlight-sections) + (setq magit-section-unhighlight-sections + (delq section magit-section-unhighlight-sections))) + (magit-diff-highlight-hunk-body + (setq paint t))))) + (t + (cond ((and (magit-section-hidden section) + (memq section magit-section-unhighlight-sections)) + (add-to-list 'magit-section-highlighted-sections section) + (setq magit-section-unhighlight-sections + (delq section magit-section-unhighlight-sections))) + (t + (setq paint t))))) + (when paint + (save-excursion + (goto-char (magit-section-start section)) + (let ((end (magit-section-end section)) + (merging (looking-at "@@@")) + (stage nil)) + (forward-line) + (while (< (point) end) + (put-text-property + (point) (1+ (line-end-position)) 'face + (cond + ((looking-at "^\\+\\+?\\([<=|>]\\)\\{7\\}") + (setq stage (pcase (list (match-string 1) highlight) + (`("<" nil) 'magit-diff-our) + (`("<" t) 'magit-diff-our-highlight) + (`("|" nil) 'magit-diff-base) + (`("|" t) 'magit-diff-base-highlight) + (`("=" nil) 'magit-diff-their) + (`("=" t) 'magit-diff-their-highlight) + (`(">" nil) nil))) + 'magit-diff-conflict-heading) + ((looking-at (if merging "^\\(\\+\\| \\+\\)" "^\\+")) + (magit-diff-paint-whitespace merging) + (or stage + (if highlight 'magit-diff-added-highlight 'magit-diff-added))) + ((looking-at (if merging "^\\(-\\| -\\)" "^-")) + (if highlight 'magit-diff-removed-highlight 'magit-diff-removed)) + (t + (if highlight 'magit-diff-context-highlight 'magit-diff-context)))) + (forward-line)))))) + (magit-diff-update-hunk-refinement section)) + +(defun magit-diff-paint-whitespace (merging) + (when (and magit-diff-paint-whitespace + (or (derived-mode-p 'magit-status-mode) + (not (eq magit-diff-paint-whitespace 'status)))) + (let ((prefix (if merging "^[-\\+\s]\\{2\\}" "^[-\\+]")) + (indent + (if (local-variable-p 'magit-diff-highlight-indentation) + magit-diff-highlight-indentation + (setq-local + magit-diff-highlight-indentation + (cdr (--first (string-match-p (car it) default-directory) + (nreverse + (default-value + 'magit-diff-highlight-indentation)))))))) + (when (and magit-diff-highlight-trailing + (looking-at (concat prefix ".*?\\([ \t]+\\)$"))) + (let ((ov (make-overlay (match-beginning 1) (match-end 1) nil t))) + (overlay-put ov 'face 'magit-diff-whitespace-warning) + (overlay-put ov 'evaporate t))) + (when (or (and (eq indent 'tabs) + (looking-at (concat prefix "\\( *\t[ \t]*\\)"))) + (and (integerp indent) + (looking-at (format "%s\\([ \t]* \\{%s,\\}[ \t]*\\)" + prefix indent)))) + (let ((ov (make-overlay (match-beginning 1) (match-end 1) nil t))) + (overlay-put ov 'face 'magit-diff-whitespace-warning) + (overlay-put ov 'evaporate t)))))) + +(defun magit-diff-update-hunk-refinement (&optional section) + (if section + (unless (magit-section-hidden section) + (pcase (list magit-diff-refine-hunk + (magit-section-refined section) + (eq section (magit-current-section))) + ((or `(all nil ,_) `(t nil t)) + (setf (magit-section-refined section) t) + (save-excursion + (goto-char (magit-section-start section)) + ;; `diff-refine-hunk' does not handle combined diffs. + (unless (looking-at "@@@") + (diff-refine-hunk)))) + ((or `(nil t ,_) `(t t nil)) + (setf (magit-section-refined section) nil) + (remove-overlays (magit-section-start section) + (magit-section-end section) + 'diff-mode 'fine)))) + (cl-labels ((recurse (section) + (if (magit-section-match 'hunk section) + (magit-diff-update-hunk-refinement section) + (--each (magit-section-children section) + (recurse it))))) + (recurse magit-root-section)))) + + +;;; Highlight Region + +(defvar magit-diff-unmarked-lines-keep-foreground t) + +(defun magit-diff-update-hunk-region (section) + (when (and (eq (magit-diff-scope section t) 'region) + (not (and (eq this-command 'mouse-drag-region) + (eq (mark) (point))))) + (let ((sbeg (magit-section-start section)) + (cbeg (magit-section-content section)) + (rbeg (save-excursion (goto-char (region-beginning)) + (line-beginning-position))) + (rend (save-excursion (goto-char (region-end)) + (line-end-position))) + (send (magit-section-end section)) + (face (if magit-diff-highlight-hunk-body + 'magit-diff-context-highlight + 'magit-diff-context))) + (when magit-diff-unmarked-lines-keep-foreground + (setq face (list :background (face-attribute face :background)))) + (cl-flet ((ov (start end &rest args) + (let ((ov (make-overlay start end nil t))) + (overlay-put ov 'evaporate t) + (while args (overlay-put ov (pop args) (pop args))) + (push ov magit-region-overlays) + ov))) + (ov sbeg cbeg 'face 'magit-diff-lines-heading + 'display (concat (magit-diff-hunk-region-header section) "\n")) + (ov cbeg rbeg 'face face 'priority 2) + (when (and (window-system) magit-diff-show-lines-boundary) + (ov rbeg (1+ rbeg) 'before-string + (propertize (concat (propertize "\s" 'display '(space :height (1))) + (propertize "\n" 'line-height t)) + 'face 'magit-diff-lines-boundary)) + (ov rend (1+ rend) 'after-string + (propertize (concat (propertize "\s" 'display '(space :height (1))) + (propertize "\n" 'line-height t)) + 'face 'magit-diff-lines-boundary))) + (ov (1+ rend) send 'face face 'priority 2))))) + +;;; Diff Extract + +(defun magit-diff-file-header (section) + (when (eq (magit-section-type section) 'hunk) + (setq section (magit-section-parent section))) + (when (eq (magit-section-type section) 'file) + (magit-section-diff-header section))) + +(defun magit-diff-hunk-region-header (section) + (let ((patch (magit-diff-hunk-region-patch section))) + (string-match "\n" patch) + (substring patch 0 (1- (match-end 0))))) + +(defun magit-diff-hunk-region-patch (section &optional args) + (let ((op (if (member "--reverse" args) "+" "-")) + (sbeg (magit-section-start section)) + (rbeg (save-excursion + (goto-char (region-beginning)) + (line-beginning-position))) + (rend (region-end)) + (send (magit-section-end section)) + (patch nil)) + (save-excursion + (goto-char sbeg) + (while (< (point) send) + (looking-at "\\(.\\)\\([^\n]*\n\\)") + (cond ((or (string-match-p "[@ ]" (match-string-no-properties 1)) + (and (>= (point) rbeg) + (<= (point) rend))) + (push (match-string-no-properties 0) patch)) + ((equal op (match-string-no-properties 1)) + (push (concat " " (match-string-no-properties 2)) patch))) + (forward-line))) + (with-temp-buffer + (insert (mapconcat 'identity (reverse patch) "")) + (diff-fixup-modifs (point-min) (point-max)) + (setq patch (buffer-string))) + patch)) + +;;; magit-diff.el ends soon +(provide 'magit-diff) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-diff.el ends here diff --git a/elpa/magit-20151223.1425/magit-ediff.el b/elpa/magit-20151223.1425/magit-ediff.el new file mode 100644 index 00000000..2fb73349 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-ediff.el @@ -0,0 +1,431 @@ +;;; magit-ediff.el --- Ediff extension for Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library provides basic support for Ediff. + +;;; Code: + +(require 'magit) + +(require 'ediff) +(require 'smerge-mode) + +(defvar smerge-ediff-buf) +(defvar smerge-ediff-windows) + +(defgroup magit-ediff nil + "Ediff support for Magit." + :group 'magit-extensions) + +(unless (find-lisp-object-file-name 'magit-ediff-quit-hook 'defvar) + (add-hook 'magit-ediff-quit-hook 'magit-ediff-restore-previous-winconf) + (add-hook 'magit-ediff-quit-hook 'magit-ediff-cleanup-auxiliary-buffers)) +(defcustom magit-ediff-quit-hook + '(magit-ediff-cleanup-auxiliary-buffers + magit-ediff-restore-previous-winconf) + "Hooks to run after finishing Ediff, when that was invoked using Magit. +The hooks are run in the Ediff control buffer. This is similar +to `ediff-quit-hook' but takes the needs of Magit into account. +The `ediff-quit-hook' is ignored by Ediff sessions which were +invoked using Magit." + :package-version '(magit . "2.2.0") + :group 'magit-ediff + :type 'hook + :options '(magit-ediff-cleanup-auxiliary-buffers + magit-ediff-restore-previous-winconf)) + +(defcustom magit-ediff-dwim-show-on-hunks nil + "Whether `magit-ediff-dwim' runs show variants on hunks. +If non-nil, `magit-ediff-show-staged' or +`magit-ediff-show-unstaged' are called based on what section the +hunk is in. Otherwise, `magit-ediff-dwim' runs +`magit-ediff-stage' when point is on an uncommitted hunk." + :package-version '(magit . "2.2.0") + :group 'magit-ediff + :type 'boolean) + +(defvar magit-ediff-previous-winconf nil) + +;;;###autoload (autoload 'magit-ediff-popup "magit-ediff" nil t) +(magit-define-popup magit-ediff-popup + "Popup console for ediff commands." + 'magit-diff nil nil + :actions '((?E "Dwim" magit-ediff-dwim) + (?u "Show unstaged" magit-ediff-show-unstaged) + (?s "Stage" magit-ediff-stage) + (?i "Show staged" magit-ediff-show-staged) + (?m "Resolve" magit-ediff-resolve) + (?w "Show worktree" magit-ediff-show-working-tree) + (?r "Diff range" magit-ediff-compare) + (?c "Show commit" magit-ediff-show-commit)) + :max-action-columns 2) + +;;;###autoload +(defun magit-ediff-resolve (file) + "Resolve outstanding conflicts in FILE using Ediff. +FILE has to be relative to the top directory of the repository. + +In the rare event that you want to manually resolve all +conflicts, including those already resolved by Git, use +`ediff-merge-revisions-with-ancestor'." + (interactive + (let ((current (magit-current-file)) + (unmerged (magit-unmerged-files))) + (unless unmerged + (user-error "There are no unresolved conflicts")) + (list (magit-completing-read "Resolve file" unmerged nil t nil nil + (car (member current unmerged)))))) + (magit-with-toplevel + (with-current-buffer (find-file-noselect file) + (smerge-ediff) + (setq-local + ediff-quit-hook + (lambda () + (let ((bufC ediff-buffer-C) + (bufS smerge-ediff-buf)) + (with-current-buffer bufS + (when (yes-or-no-p (format "Conflict resolution finished; save %s?" + buffer-file-name)) + (erase-buffer) + (insert-buffer-substring bufC) + (save-buffer)))) + (when (buffer-live-p ediff-buffer-A) (kill-buffer ediff-buffer-A)) + (when (buffer-live-p ediff-buffer-B) (kill-buffer ediff-buffer-B)) + (when (buffer-live-p ediff-buffer-C) (kill-buffer ediff-buffer-C)) + (when (buffer-live-p ediff-ancestor-buffer) + (kill-buffer ediff-ancestor-buffer)) + (let ((magit-ediff-previous-winconf smerge-ediff-windows)) + (run-hooks 'magit-ediff-quit-hook))))))) + +;;;###autoload +(defun magit-ediff-stage (file) + "Stage and unstage changes to FILE using Ediff. +FILE has to be relative to the top directory of the repository." + (interactive + (list (magit-completing-read "Selectively stage file" nil + (magit-tracked-files) nil nil nil + (magit-current-file)))) + (magit-with-toplevel + (let* ((conf (current-window-configuration)) + (bufA (magit-get-revision-buffer "HEAD" file)) + (bufB (get-buffer (concat file ".~{index}~"))) + (bufBrw (and bufB (with-current-buffer bufB (not buffer-read-only)))) + (bufC (get-file-buffer file))) + (ediff-buffers3 + (or bufA (magit-find-file-noselect "HEAD" file)) + (with-current-buffer (magit-find-file-index-noselect file t) + (setq buffer-read-only nil) + (current-buffer)) + (or bufC (find-file-noselect file)) + `((lambda () + (setq-local + ediff-quit-hook + (lambda () + (and (buffer-live-p ediff-buffer-B) + (buffer-modified-p ediff-buffer-B) + (with-current-buffer ediff-buffer-B + (magit-update-index))) + (and (buffer-live-p ediff-buffer-C) + (buffer-modified-p ediff-buffer-C) + (with-current-buffer ediff-buffer-C + (when (y-or-n-p + (format "Save file %s? " buffer-file-name)) + (save-buffer)))) + ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) + ,@(if bufB + (unless bufBrw '((with-current-buffer ediff-buffer-B + (setq buffer-read-only t)))) + '((ediff-kill-buffer-carefully ediff-buffer-B))) + ,@(unless bufC '((ediff-kill-buffer-carefully ediff-buffer-C))) + (let ((magit-ediff-previous-winconf ,conf)) + (run-hooks 'magit-ediff-quit-hook)))))) + 'ediff-buffers3)))) + +;;;###autoload +(defun magit-ediff-compare (revA revB fileA fileB) + "Compare REVA:FILEA with REVB:FILEB using Ediff. + +FILEA and FILEB have to be relative to the top directory of the +repository. If REVA or REVB is nil then this stands for the +working tree state. + +If the region is active, use the revisions on the first and last +line of the region. With a prefix argument, instead of diffing +the revisions, choose a revision to view changes along, starting +at the common ancestor of both revisions (i.e., use a \"...\" +range)." + (interactive (-let [(revA revB) (magit-ediff-compare--read-revisions + nil current-prefix-arg)] + (nconc (list revA revB) + (magit-ediff-compare--read-files revA revB)))) + (magit-with-toplevel + (let ((conf (current-window-configuration)) + (bufA (if revA + (magit-get-revision-buffer revA fileA) + (get-file-buffer fileA))) + (bufB (if revB + (magit-get-revision-buffer revB fileB) + (get-file-buffer fileB)))) + (ediff-buffers + (or bufA (if revA + (magit-find-file-noselect revA fileA) + (find-file-noselect fileA))) + (or bufB (if revB + (magit-find-file-noselect revB fileB) + (find-file-noselect fileB))) + `((lambda () + (setq-local + ediff-quit-hook + (lambda () + ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) + ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) + (let ((magit-ediff-previous-winconf ,conf)) + (run-hooks 'magit-ediff-quit-hook)))))) + 'ediff-revision)))) + +(defun magit-ediff-compare--read-revisions (&optional arg mbase) + (let ((input (or arg (magit-diff-read-range-or-commit "Compare range or commit" + nil mbase))) + revA revB) + (if (string-match magit-range-re input) + (progn (setq revA (or (match-string 1 input) "HEAD") + revB (or (match-string 3 input) "HEAD")) + (when (string= (match-string 2 input) "...") + (setq revA (magit-git-string "merge-base" revA revB)))) + (setq revA input)) + (list revA revB))) + +(defun magit-ediff-compare--read-files (revA revB &optional fileB) + (unless fileB + (setq fileB (magit-read-file-choice + (format "File to compare between %s and %s" + revA (or revB "the working tree")) + (magit-changed-files revA revB) + (format "No changed files between %s and %s" + revA (or revB "the working tree"))))) + (list (or (car (member fileB (magit-revision-files revA))) + (cdr (assoc fileB (magit-renamed-files revB revA))) + (magit-read-file-choice + (format "File in %s to compare with %s in %s" + revA fileB (or revB "the working tree")) + (magit-changed-files revB revA) + (format "File in %s to compare with %s in %s" + revA fileB (or revB "the working tree")))) + fileB)) + +;;;###autoload +(defun magit-ediff-dwim () + "Compare, stage, or resolve using Ediff. +This command tries to guess what file, and what commit or range +the user wants to compare, stage, or resolve using Ediff. It +might only be able to guess either the file, or range or commit, +in which case the user is asked about the other. It might not +always guess right, in which case the appropriate `magit-ediff-*' +command has to be used explicitly. If it cannot read the user's +mind at all, then it asks the user for a command to run." + (interactive) + (magit-section-case + (hunk (save-excursion + (goto-char (magit-section-start (magit-section-parent it))) + (magit-ediff-dwim))) + (t + (let ((range (magit-diff--dwim)) + (file (magit-current-file)) + command revA revB) + (pcase range + ((and (guard (not magit-ediff-dwim-show-on-hunks)) + (or `unstaged `staged)) + (setq command (if (magit-anything-unmerged-p) + #'magit-ediff-resolve + #'magit-ediff-stage))) + (`unstaged (setq command #'magit-ediff-show-unstaged)) + (`staged (setq command #'magit-ediff-show-staged)) + (`(commit . ,value) + (setq command #'magit-ediff-show-commit + revB value)) + ((pred stringp) + (-let [(a b) (magit-ediff-compare--read-revisions range)] + (setq command #'magit-ediff-compare + revA a + revB b))) + (_ + (when (derived-mode-p 'magit-diff-mode) + (pcase (magit-diff-type) + (`committed (-let [(a b) (magit-ediff-compare--read-revisions + (car magit-refresh-args))] + (setq revA a revB b))) + ((guard (not magit-ediff-dwim-show-on-hunks)) + (setq command #'magit-ediff-stage)) + (`unstaged (setq command #'magit-ediff-show-unstaged)) + (`staged (setq command #'magit-ediff-show-staged)) + (`undefined (setq command nil)) + (_ (setq command nil)))))) + (cond ((not command) + (call-interactively + (magit-read-char-case + "Failed to read your mind; do you want to " t + (?c "[c]ommit" 'magit-ediff-show-commit) + (?r "[r]ange" 'magit-ediff-compare) + (?s "[s]tage" 'magit-ediff-stage) + (?v "resol[v]e" 'magit-ediff-resolve)))) + ((eq command 'magit-ediff-compare) + (apply 'magit-ediff-compare revA revB + (magit-ediff-compare--read-files revA revB file))) + ((eq command 'magit-ediff-show-commit) + (magit-ediff-show-commit revB)) + (file + (funcall command file)) + (t + (call-interactively command))))))) + +;;;###autoload +(defun magit-ediff-show-staged (file) + "Show staged changes using Ediff. + +This only allows looking at the changes; to stage, unstage, +and discard changes using Ediff, use `magit-ediff-stage'. + +FILE must be relative to the top directory of the repository." + (interactive + (list (magit-read-file-choice "Show staged changes for file" + (magit-staged-files) + "No staged files"))) + (let ((conf (current-window-configuration)) + (bufA (magit-get-revision-buffer "HEAD" file)) + (bufB (get-buffer (concat file ".~{index}~")))) + (ediff-buffers + (or bufA (magit-find-file-noselect "HEAD" file)) + (or bufB (magit-find-file-index-noselect file t)) + `((lambda () + (setq-local + ediff-quit-hook + (lambda () + ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) + ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) + (let ((magit-ediff-previous-winconf ,conf)) + (run-hooks 'magit-ediff-quit-hook)))))) + 'ediff-buffers))) + +;;;###autoload +(defun magit-ediff-show-unstaged (file) + "Show unstaged changes using Ediff. + +This only allows looking at the changes; to stage, unstage, +and discard changes using Ediff, use `magit-ediff-stage'. + +FILE must be relative to the top directory of the repository." + (interactive + (list (magit-read-file-choice "Show unstaged changes for file" + (magit-modified-files) + "No unstaged files"))) + (magit-with-toplevel + (let ((conf (current-window-configuration)) + (bufA (get-buffer (concat file ".~{index}~"))) + (bufB (get-file-buffer file))) + (ediff-buffers + (or bufA (magit-find-file-index-noselect file t)) + (or bufB (find-file-noselect file)) + `((lambda () + (setq-local + ediff-quit-hook + (lambda () + ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) + ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) + (let ((magit-ediff-previous-winconf ,conf)) + (run-hooks 'magit-ediff-quit-hook)))))) + 'ediff-buffers)))) + +;;;###autoload +(defun magit-ediff-show-working-tree (file) + "Show changes between HEAD and working tree using Ediff. +FILE must be relative to the top directory of the repository." + (interactive + (list (magit-read-file-choice "Show changes in file" + (magit-changed-files "HEAD") + "No changed files"))) + (magit-with-toplevel + (let ((conf (current-window-configuration)) + (bufA (magit-get-revision-buffer "HEAD" file)) + (bufB (get-file-buffer file))) + (ediff-buffers + (or bufA (magit-find-file-noselect "HEAD" file)) + (or bufB (find-file-noselect file)) + `((lambda () + (setq-local + ediff-quit-hook + (lambda () + ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) + ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) + (let ((magit-ediff-previous-winconf ,conf)) + (run-hooks 'magit-ediff-quit-hook)))))) + 'ediff-buffers)))) + +;;;###autoload +(defun magit-ediff-show-commit (commit) + "Show changes introduced by COMMIT using Ediff." + (interactive (list (magit-read-branch-or-commit "Revision"))) + (let ((revA (concat commit "^")) + (revB commit)) + (apply #'magit-ediff-compare + revA revB + (magit-ediff-compare--read-files revA revB (magit-current-file))))) + +(defun magit-ediff-cleanup-auxiliary-buffers () + (let* ((ctl-buf ediff-control-buffer) + (ctl-win (ediff-get-visible-buffer-window ctl-buf)) + (ctl-frm ediff-control-frame) + (main-frame (cond ((window-live-p ediff-window-A) + (window-frame ediff-window-A)) + ((window-live-p ediff-window-B) + (window-frame ediff-window-B))))) + (ediff-kill-buffer-carefully ediff-diff-buffer) + (ediff-kill-buffer-carefully ediff-custom-diff-buffer) + (ediff-kill-buffer-carefully ediff-fine-diff-buffer) + (ediff-kill-buffer-carefully ediff-tmp-buffer) + (ediff-kill-buffer-carefully ediff-error-buffer) + (ediff-kill-buffer-carefully ediff-msg-buffer) + (ediff-kill-buffer-carefully ediff-debug-buffer) + (when (boundp 'ediff-patch-diagnostics) + (ediff-kill-buffer-carefully ediff-patch-diagnostics)) + (cond ((and (ediff-window-display-p) + (frame-live-p ctl-frm)) + (delete-frame ctl-frm)) + ((window-live-p ctl-win) + (delete-window ctl-win))) + (unless (ediff-multiframe-setup-p) + (ediff-kill-bottom-toolbar)) + (ediff-kill-buffer-carefully ctl-buf) + (when (frame-live-p main-frame) + (select-frame main-frame)))) + +(defun magit-ediff-restore-previous-winconf () + (set-window-configuration magit-ediff-previous-winconf)) + +;;; magit-ediff.el ends soon +(provide 'magit-ediff) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-ediff.el ends here diff --git a/elpa/magit-20151223.1425/magit-extras.el b/elpa/magit-20151223.1425/magit-extras.el new file mode 100644 index 00000000..8355901a --- /dev/null +++ b/elpa/magit-20151223.1425/magit-extras.el @@ -0,0 +1,203 @@ +;;; magit-extras.el --- additional functionality for Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; 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: + +;; Additional functionality for Magit. + +;;; Code: + +(require 'magit) + +(defgroup magit-extras nil + "Additional functionality for Magit." + :group 'magit-extensions) + +;;; External Tools + +(defcustom magit-gitk-executable + (or (and (eq system-type 'windows-nt) + (let ((exe (expand-file-name + "gitk" (file-name-nondirectory magit-git-executable)))) + (and (file-executable-p exe) exe))) + (executable-find "gitk") "gitk") + "The Gitk executable." + :group 'magit-extras + :set-after '(magit-git-executable) + :type 'string) + +;;;###autoload +(defun magit-run-git-gui () + "Run `git gui' for the current git repository." + (interactive) + (magit-with-toplevel + (call-process magit-git-executable nil 0 nil "gui"))) + +;;;###autoload +(defun magit-run-git-gui-blame (commit filename &optional linenum) + "Run `git gui blame' on the given FILENAME and COMMIT. +Interactively run it for the current file and the HEAD, with a +prefix or when the current file cannot be determined let the user +choose. When the current buffer is visiting FILENAME instruct +blame to center around the line point is on." + (interactive + (let (revision filename) + (when (or current-prefix-arg + (not (setq revision "HEAD" + filename (magit-file-relative-name nil 'tracked)))) + (setq revision (magit-read-branch-or-commit "Blame from revision") + filename (magit-read-file-from-rev revision "Blame file"))) + (list revision filename + (and (equal filename + (ignore-errors + (magit-file-relative-name buffer-file-name))) + (line-number-at-pos))))) + (magit-with-toplevel + (apply #'call-process magit-git-executable nil 0 nil "gui" "blame" + `(,@(and linenum (list (format "--line=%d" linenum))) + ,commit + ,filename)))) + +;;;###autoload +(defun magit-run-gitk () + "Run `gitk' in the current repository." + (interactive) + (call-process magit-gitk-executable nil 0)) + +;;;###autoload +(defun magit-run-gitk-branches () + "Run `gitk --branches' in the current repository." + (interactive) + (call-process magit-gitk-executable nil 0 nil "--branches")) + +;;;###autoload +(defun magit-run-gitk-all () + "Run `gitk --all' in the current repository." + (interactive) + (call-process magit-gitk-executable nil 0 nil "--all")) + +;;; Clean + +;;;###autoload +(defun magit-clean (&optional arg) + "Remove untracked files from the working tree. +With a prefix argument also remove ignored files, +with two prefix arguments remove ignored files only. +\n(git clean -f -d [-x|-X])" + (interactive "p") + (when (yes-or-no-p (format "Remove %s files? " + (pcase arg + (1 "untracked") + (4 "untracked and ignored") + (_ "ignored")))) + (magit-wip-commit-before-change) + (magit-run-git "clean" "-f" "-d" (pcase arg (4 "-x") (16 "-X"))))) + +(put 'magit-clean 'disabled t) + +;;; Gitignore + +;;;###autoload +(defun magit-gitignore (file-or-pattern &optional local) + "Instruct Git to ignore FILE-OR-PATTERN. +With a prefix argument only ignore locally." + (interactive (list (magit-gitignore-read-pattern current-prefix-arg) + current-prefix-arg)) + (let ((gitignore + (if local + (magit-git-dir (convert-standard-filename "info/exclude")) + (expand-file-name ".gitignore" (magit-toplevel))))) + (make-directory (file-name-directory gitignore) t) + (with-temp-buffer + (when (file-exists-p gitignore) + (insert-file-contents gitignore)) + (goto-char (point-max)) + (unless (bolp) + (insert "\n")) + (insert (replace-regexp-in-string "\\(\\\\*\\)" "\\1\\1" file-or-pattern)) + (insert "\n") + (write-region nil nil gitignore)) + (if local + (magit-refresh) + (magit-run-git "add" ".gitignore")))) + +;;;###autoload +(defun magit-gitignore-locally (file-or-pattern) + "Instruct Git to locally ignore FILE-OR-PATTERN." + (interactive (list (magit-gitignore-read-pattern t))) + (magit-gitignore file-or-pattern t)) + +(defun magit-gitignore-read-pattern (local) + (let* ((default (magit-current-file)) + (choices + (delete-dups + (--mapcat + (cons (concat "/" it) + (-when-let (ext (file-name-extension it)) + (list (concat "/" (file-name-directory "foo") "*." ext) + (concat "*." ext)))) + (magit-untracked-files))))) + (when default + (setq default (concat "/" default)) + (unless (member default choices) + (setq default (concat "*." (file-name-extension default))) + (unless (member default choices) + (setq default nil)))) + (magit-completing-read (concat "File or pattern to ignore" + (and local " locally")) + choices nil nil nil nil default))) + +;;; ChangeLog + +;;;###autoload +(defun magit-add-change-log-entry (&optional whoami file-name other-window) + "Find change log file and add date entry and item for current change. +This differs from `add-change-log-entry' (which see) in that +it acts on the current hunk in a Magit buffer instead of on +a position in a file-visiting buffer." + (interactive (list current-prefix-arg + (prompt-for-change-log-name))) + (let (buf pos) + (save-window-excursion + (call-interactively #'magit-diff-visit-file) + (setq buf (current-buffer) + pos (point))) + (save-excursion + (with-current-buffer buf + (goto-char pos) + (add-change-log-entry whoami file-name other-window))))) + +;;;###autoload +(defun magit-add-change-log-entry-other-window (&optional whoami file-name) + "Find change log file in other window and add entry and item. +This differs from `add-change-log-entry-other-window' (which see) +in that it acts on the current hunk in a Magit buffer instead of +on a position in a file-visiting buffer." + (interactive (and current-prefix-arg + (list current-prefix-arg + (prompt-for-change-log-name)))) + (magit-add-change-log-entry whoami file-name t)) + +;;; magit-extras.el ends soon +(provide 'magit-extras) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-extras.el ends here diff --git a/elpa/magit-20151223.1425/magit-git.el b/elpa/magit-20151223.1425/magit-git.el new file mode 100644 index 00000000..f8274699 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-git.el @@ -0,0 +1,1298 @@ +;;; magit-git.el --- Git functionality -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library implements wrappers for various Git plumbing commands. + +;;; Code: + +(require 'cl-lib) +(require 'dash) + +(require 'magit-utils) +(require 'magit-section) + +(declare-function magit-process-buffer 'magit-process) +(declare-function magit-process-file 'magit-process) +(declare-function magit-process-insert-section 'magit-process) +(defvar magit-process-error-message-re) +(defvar magit-refresh-args) ; from `magit-mode' for `magit-current-file' +(defvar magit-branch-prefer-remote-upstream) + +(defvar magit-tramp-process-environment nil) + +(require 'crm) + +;;; Options + +;; For now this is shared between `magit-process' and `magit-git'. +(defgroup magit-process nil + "Git and other external processes used by Magit." + :group 'magit) + +(defvar magit-git-environment nil + "Prepended to `process-environment' while running git.") + +(defcustom magit-git-executable + ;; Git might be installed in a different location on a remote, so + ;; it is better not to use the full path to the executable, except + ;; on Window were we would otherwise end up using one one of the + ;; wrappers "cmd/git.exe" or "cmd/git.cmd", which are much slower + ;; than using "bin/git.exe" directly. + (or (and (eq system-type 'windows-nt) + (--when-let (executable-find "git.exe") + (or (with-temp-buffer + (when (save-excursion + (= (call-process + it nil '(t t) nil "-c" + "alias.exe=!which git | cygpath -wf -" "exe") 0)) + (prog1 (delete-and-extract-region 1 (line-end-position)) + (save-excursion + (insert "PATH=") + (call-process + it nil '(t t) nil "-c" + "alias.path=!cygpath -wp \"$PATH\"" "path")) + (setq magit-git-environment + (list (buffer-substring-no-properties + (point) (line-end-position))))))) + (let ((alt (directory-file-name (file-name-directory it)))) + (if (and (equal (file-name-nondirectory alt) "cmd") + (setq alt (expand-file-name + (convert-standard-filename "bin/git.exe") + (file-name-directory alt))) + (file-executable-p alt)) + alt + it))))) + "git") + "The Git executable used by Magit." + :group 'magit-process + :type 'string) + +(defcustom magit-git-global-arguments + '("--no-pager" "--literal-pathspecs" "-c" "core.preloadindex=true") + "Global git arguments. + +The arguments set here are used every time the git executable is +run as a subprocess. They are placed right after the executable +itself and before the git command - as in `git HERE... COMMAND +REST'. See the manpage `git(1)' for valid arguments. + +Be careful what you add here, especially if you are using Tramp +to connect to servers with ancient Git versions. Never remove +anything that is part of the default value, unless you really +know what you are doing. And think very hard before adding +something; it will be used every time Magit runs Git for any +purpose." + :package-version '(magit . "2.1.0") + :group 'magit + :type '(repeat string)) + +(define-obsolete-variable-alias 'magit-git-standard-options + 'magit-git-global-arguments "2.1.0") + +(defcustom magit-git-debug nil + "Whether to enable additional reporting of git errors. + +Magit basically calls git for one of these two reasons: for +side-effects or to do something with its standard output. + +When git is run for side-effects then its output, including error +messages, go into the process buffer which is shown when using \ +\\\\[magit-process]. + +When git's output is consumed in some way, then it would be too +expensive to also insert it into this buffer, but when this +option is non-nil and git returns with a non-zero exit status, +then at least its standard error is inserted into this buffer. + +This is only intended for debugging purposes. Do not enable this +permanently, that would negatively affect performance" + :group 'magit + :group 'magit-process + :type 'boolean) + +(defcustom magit-ref-namespaces + '(("^@$" magit-head nil) + ("^refs/tags/\\(.+\\)" magit-tag nil) + ("^refs/heads/\\(.+\\)" magit-branch-local nil) + ("^refs/remotes/\\(.+\\)" magit-branch-remote nil) + ("^refs/bisect/\\(bad\\)" magit-bisect-bad nil) + ("^refs/bisect/\\(skip.*\\)" magit-bisect-skip nil) + ("^refs/bisect/\\(good.*\\)" magit-bisect-good nil) + ("^refs/stash$" magit-refname-stash nil) + ("^refs/wip/\\(.+\\)" magit-refname-wip nil) + ("^\\(bad\\):" magit-bisect-bad nil) + ("^\\(skip\\):" magit-bisect-skip nil) + ("^\\(good\\):" magit-bisect-good nil) + ("\\(.+\\)" magit-refname nil)) + "How refs are formatted for display. + +Each entry controls how a certain type of ref is displayed, and +has the form (REGEXP FACE FORMATTER). REGEXP is a regular +expression used to match full refs. The first entry whose REGEXP +matches the reference is used. The first regexp submatch becomes +the \"label\" that represents the ref and is propertized with +font FONT. If FORMATTER is non-nil it should be a function that +takes two arguments, the full ref and the face. It is supposed +to return a propertized label that represents the ref." + :package-version '(magit . "2.1.0") + :group 'magit-modes + :type '(repeat + (list regexp + face + (choice (const :tag "first submatch is label" nil) + (function :tag "format using function"))))) + +;;; Git + +(defun magit-process-git-arguments (args) + "Prepare ARGS for a function that invokes Git. + +Magit has many specialized functions for running Git; they all +pass arguments through this function before handing them to Git, +to do the following. + +* Flatten ARGS, removing nil arguments. +* Prepend `magit-git-global-arguments' to ARGS." + (append magit-git-global-arguments (-flatten args))) + +(defun magit-git-exit-code (&rest args) + "Execute Git with ARGS, returning its exit code." + (apply #'magit-process-file magit-git-executable nil nil nil + (magit-process-git-arguments args))) + +(defun magit-git-success (&rest args) + "Execute Git with ARGS, returning t if its exit code is 0." + (= (magit-git-exit-code args) 0)) + +(defun magit-git-failure (&rest args) + "Execute Git with ARGS, returning t if its exit code is 1." + (= (magit-git-exit-code args) 1)) + +(defun magit-git-str (&rest args) + "Execute Git with ARGS, returning the first line of its output. +If there is no output return nil. If the output begins with a +newline return an empty string. Like `magit-git-string' but +ignore `magit-git-debug'." + (with-temp-buffer + (apply #'magit-process-file magit-git-executable nil (list t nil) nil + (magit-process-git-arguments args)) + (unless (bobp) + (goto-char (point-min)) + (buffer-substring-no-properties (point) (line-end-position))))) + +(defun magit-git-true (&rest args) + "Execute Git with ARGS, returning t if it prints \"true\". +Return t if the first (and usually only) output line is the +string \"true\", otherwise return nil." + (equal (magit-git-str args) "true")) + +(defun magit-git-false (&rest args) + "Execute Git with ARGS, returning t if it prints \"false\". +Return t if the first (and usually only) output line is the +string \"false\", otherwise return nil." + (equal (magit-git-str args) "false")) + +(defun magit-git-insert (&rest args) + "Execute Git with ARGS, inserting its output at point. +If Git exits with a non-zero exit status, then show a message and +add a section in the respective process buffer." + (setq args (magit-process-git-arguments args)) + (if magit-git-debug + (let (log) + (unwind-protect + (progn + (setq log (make-temp-file "magit-stderr")) + (delete-file log) + (let ((exit (apply #'magit-process-file magit-git-executable + nil (list t log) nil args))) + (when (> exit 0) + (let ((msg "Git failed")) + (when (file-exists-p log) + (setq msg (with-temp-buffer + (insert-file-contents log) + (goto-char (point-max)) + (and (re-search-backward + magit-process-error-message-re nil t) + (match-string 1)))) + (let ((magit-git-debug nil)) + (with-current-buffer (magit-process-buffer t) + (magit-process-insert-section default-directory + magit-git-executable + args exit log)))) + (message "%s" msg))) + exit)) + (ignore-errors (delete-file log)))) + (apply #'magit-process-file magit-git-executable + nil (list t nil) nil args))) + +(defun magit-git-string (&rest args) + "Execute Git with ARGS, returning the first line of its output. +If there is no output return nil. If the output begins with a +newline return an empty string." + (with-temp-buffer + (apply #'magit-git-insert args) + (unless (bobp) + (goto-char (point-min)) + (buffer-substring-no-properties (point) (line-end-position))))) + +(defun magit-git-lines (&rest args) + "Execute Git with ARGS, returning its output as a list of lines. +Empty lines anywhere in the output are omitted. + +If Git exits with a non-zero exit status, then report show a +message and add a section in the respective process buffer." + (with-temp-buffer + (apply #'magit-git-insert args) + (split-string (buffer-string) "\n" t))) + +(defun magit-git-items (&rest args) + "Execute Git with ARGS, returning its null-separated output as a list. +Empty items anywhere in the output are omitted. + +If Git exits with a non-zero exit status, then report show a +message and add a section in the respective process buffer." + (with-temp-buffer + (apply #'magit-git-insert args) + (split-string (buffer-string) "\0" t))) + +(defun magit-git-wash (washer &rest args) + "Execute Git with ARGS, inserting washed output at point. +Actually first insert the raw output at point. If there is no +output call `magit-cancel-section'. Otherwise temporarily narrow +the buffer to the inserted text, move to its beginning, and then +call function WASHER with no argument." + (declare (indent 1)) + (let ((beg (point))) + (setq args (-flatten args)) + (magit-git-insert args) + (if (= (point) beg) + (magit-cancel-section) + (unless (bolp) + (insert "\n")) + (save-restriction + (narrow-to-region beg (point)) + (goto-char beg) + (funcall washer args)) + (when (or (= (point) beg) + (= (point) (1+ beg))) + (magit-cancel-section))))) + +;;; Files + +(defun magit--safe-default-directory (&optional file) + (catch 'unsafe-default-dir + (let ((dir (file-name-as-directory + (expand-file-name (or file default-directory)))) + (previous nil)) + (while (not (file-accessible-directory-p dir)) + (setq dir (file-name-directory (directory-file-name dir))) + (when (equal dir previous) + (throw 'unsafe-default-dir nil)) + (setq previous dir)) + dir))) + +(defmacro magit--with-safe-default-directory (file &rest body) + (declare (indent 1) (debug (form body))) + `(-when-let (default-directory (magit--safe-default-directory ,file)) + ,@body)) + +(defun magit-git-dir (&optional path) + "Return absolute path to the control directory of the current repository. + +All symlinks are followed. If optional PATH is non-nil, then +it has to be a path relative to the control directory and its +absolute path is returned." + (magit--with-safe-default-directory nil + (--when-let (magit-rev-parse-safe "--git-dir") + (setq it (file-name-as-directory (magit-expand-git-file-name it))) + (if path (expand-file-name (convert-standard-filename path) it) it)))) + +(defun magit-toplevel (&optional directory) + "Return the absolute path to the toplevel of the current repository. + +From within the working tree or control directory of a repository +return the absolute path to the toplevel directory of the working +tree. As a special case, from within a bare repository return +the control directory instead. When called outside a repository +then return nil. + +When optional DIRECTORY is non-nil then return the toplevel for +that directory instead of the one for `default-directory'. + +Try to respect the option `find-file-visit-truename', i.e. when +the value of that option is nil, then avoid needlessly returning +the truename. When a symlink to a sub-directory of the working +tree is involved, or when called from within a sub-directory of +the gitdir or from the toplevel of a gitdir, which itself is not +located within the working tree, then it is not possible to avoid +returning the truename." + (magit--with-safe-default-directory directory + (-if-let (topdir (magit-rev-parse-safe "--show-toplevel")) + (let (updir) + (setq topdir (magit-expand-git-file-name topdir)) + (if (and + ;; Always honor these settings. + (not find-file-visit-truename) + (not (getenv "GIT_WORK_TREE")) + ;; `--show-cdup' is the relative path to the toplevel + ;; from `(file-truename default-directory)'. Here we + ;; pretend it is relative to `default-directory', and + ;; go to that directory. Then we check whether + ;; `--show-toplevel' still returns the same value and + ;; whether `--show-cdup' now is the empty string. If + ;; both is the case, then we are at the toplevel of + ;; the same working tree, but also avoided needlessly + ;; following any symlinks. + (progn + (setq updir (file-name-as-directory + (magit-rev-parse-safe "--show-cdup"))) + (setq updir (if (file-name-absolute-p updir) + (concat (file-remote-p default-directory) updir) + (expand-file-name updir))) + (let ((default-directory updir)) + (and (string-equal (magit-rev-parse-safe "--show-cdup") "") + (--when-let (magit-rev-parse-safe "--show-toplevel") + (string-equal (magit-expand-git-file-name it) + topdir)))))) + updir + (concat (file-remote-p default-directory) + (file-name-as-directory topdir)))) + (-when-let (gitdir (magit-rev-parse-safe "--git-dir")) + (setq gitdir (file-name-as-directory + (if (file-name-absolute-p gitdir) + ;; We might have followed a symlink. + (concat (file-remote-p default-directory) + (magit-expand-git-file-name gitdir)) + (expand-file-name gitdir)))) + (if (magit-bare-repo-p) + gitdir + (let* ((link (expand-file-name "gitdir" gitdir)) + (wtree (and (file-exists-p link) + (magit-file-line link)))) + (if (and wtree + ;; Ignore .git/gitdir files that result from a + ;; Git bug. See #2364. + (not (equal wtree ".git"))) + ;; Return the linked working tree. + (file-name-directory wtree) + ;; Step outside the control directory to enter the working tree. + (file-name-directory (directory-file-name gitdir))))))))) + +(defmacro magit-with-toplevel (&rest body) + (declare (indent defun) (debug (body))) + (let ((toplevel (cl-gensym "toplevel"))) + `(let ((,toplevel (magit-toplevel))) + (if ,toplevel + (let ((default-directory ,toplevel)) + ,@body) + (error "Not inside a Git repository: %s" default-directory))))) + +(defun magit-inside-gitdir-p () + "Return t if `default-directory' is below a repository directory." + (magit-rev-parse-p "--is-inside-git-dir")) + +(defun magit-inside-worktree-p () + "Return t if `default-directory' is below the work tree of a repository." + (magit-rev-parse-p "--is-inside-work-tree")) + +(defun magit-bare-repo-p () + "Return t if the current repository is bare." + (magit-rev-parse-p "--is-bare-repository")) + +(defun magit-git-repo-p (directory &optional non-bare) + "Return t if DIRECTORY is a Git repository. +When optional NON-BARE is non-nil also return nil if DIRECTORY is +a bare repositories." + (or (file-regular-p (expand-file-name ".git" directory)) + (file-directory-p (expand-file-name ".git" directory)) + (and (not non-bare) + (file-regular-p (expand-file-name "HEAD" directory)) + (file-directory-p (expand-file-name "refs" directory)) + (file-directory-p (expand-file-name "objects" directory))))) + +(defvar-local magit-buffer-revision nil) +(defvar-local magit-buffer-refname nil) +(defvar-local magit-buffer-file-name nil) +(put 'magit-buffer-revision 'permanent-local t) +(put 'magit-buffer-refname 'permanent-local t) +(put 'magit-buffer-file-name 'permanent-local t) + +(defun magit-file-relative-name (&optional file tracked) + "Return the path of FILE relative to the repository root. + +If optional FILE is nil or omitted return the relative path of +the file being visited in the current buffer, if any, else nil. +If the file is not inside a Git repository then return nil. + +If TRACKED is non-nil, return the path only if it matches a +tracked file." + (unless file + (with-current-buffer (or (buffer-base-buffer) + (current-buffer)) + (setq file (or magit-buffer-file-name buffer-file-name)))) + (when (and file (or (not tracked) + (magit-file-tracked-p (file-relative-name file)))) + (--when-let (magit-toplevel + (magit--safe-default-directory + (directory-file-name (file-name-directory file)))) + (file-relative-name file it)))) + +(defun magit-file-tracked-p (file) + (magit-git-success "ls-files" "--error-unmatch" file)) + +(defun magit-list-files (&rest args) + (apply #'magit-git-items "ls-files" "-z" "--full-name" args)) + +(defun magit-tracked-files () + (magit-list-files "--cached")) + +(defun magit-untracked-files (&optional all files) + (magit-list-files "--other" (unless all "--exclude-standard") "--" files)) + +(defun magit-modified-files (&optional nomodules) + (magit-git-items "diff-files" "-z" "--name-only" + (and nomodules "--ignore-submodules"))) + +(defun magit-staged-files (&optional nomodules files) + (magit-git-items "diff-index" "-z" "--name-only" "--cached" + (and nomodules "--ignore-submodules") + (magit-headish) "--" files)) + +(defun magit-unstaged-files (&optional nomodules files) + (magit-git-items "diff-index" "-z" "--name-only" + (and nomodules "--ignore-submodules") + (magit-headish) "--" files)) + +(defun magit-staged-binary-files () + (--mapcat (and (string-match "^-\t-\t\\(.+\\)" it) + (list (match-string 1 it))) + (magit-git-items "diff" "-z" "--cached" + "--numstat" "--ignore-submodules"))) + +(defun magit-unmerged-files () + (magit-git-items "diff-files" "-z" "--name-only" "--diff-filter=U")) + +(defun magit-revision-files (rev) + (magit-with-toplevel + (magit-git-items "ls-tree" "-z" "-r" "--name-only" rev))) + +(defun magit-changed-files (rev-or-range &optional other-rev) + "Return list of files the have changed between two revisions. +If OTHER-REV is non-nil, REV-OR-RANGE should be a revision, not a +range. Otherwise, it can be any revision or range accepted by +\"git diff\" (i.e., , .., or ...)." + (magit-with-toplevel + (magit-git-items "diff" "-z" "--name-only" rev-or-range other-rev))) + +(defun magit-renamed-files (revA revB) + (--map (cons (nth 1 it) (nth 2 it)) + (-partition 3 (magit-git-items + "diff-tree" "-r" "--diff-filter=R" "-z" "-M" + revA revB)))) + +(defun magit-file-status (&rest args) + (with-temp-buffer + (save-excursion (magit-git-insert "status" "-z" args)) + (let ((pos (point)) status) + (while (> (skip-chars-forward "[:print:]") 0) + (let ((x (char-after pos)) + (y (char-after (1+ pos))) + (file (buffer-substring (+ pos 3) (point)))) + (forward-char) + (if (memq x '(?R ?C)) + (progn + (setq pos (point)) + (skip-chars-forward "[:print:]") + (push (list file (buffer-substring pos (point)) x y) status) + (forward-char)) + (push (list file nil x y) status))) + (setq pos (point))) + status))) + +(defcustom magit-cygwin-mount-points + (when (eq system-type 'windows-nt) + (cl-sort (--map (if (string-match "^\\(.*\\) on \\(.*\\) type" it) + (cons (file-name-as-directory (match-string 2 it)) + (file-name-as-directory (match-string 1 it))) + (lwarn '(magit) :error + "Failed to parse Cygwin mount: %S" it)) + (ignore-errors (process-lines "mount"))) + #'> :key (-lambda ((cyg . _win)) (length cyg)))) + "Alist of (CYGWIN . WIN32) directory names. +Sorted from longest to shortest CYGWIN name." + :package-version '(magit . "2.3.0") + :group 'magit-process + :type '(alist :key-type string :value-type directory)) + +(defun magit-expand-git-file-name (filename) + (unless (file-name-absolute-p filename) + (setq filename (expand-file-name filename))) + (-if-let ((cyg . win) + (cl-assoc filename magit-cygwin-mount-points + :test (lambda (f cyg) (string-prefix-p cyg f)))) + (concat win (substring filename (length cyg))) + filename)) + +(defun magit-convert-git-filename (filename) + (-if-let ((cyg . win) + (cl-rassoc filename magit-cygwin-mount-points + :test (lambda (f win) (string-prefix-p win f)))) + (concat cyg (substring filename (length win))) + filename)) + +(defun magit-decode-git-path (path) + (if (eq (aref path 0) ?\") + (string-as-multibyte (read path)) + path)) + +(defun magit-file-at-point () + (magit-section-case + (file (magit-section-value it)) + (hunk (magit-section-parent-value it)))) + +(defun magit-current-file () + (or (magit-file-relative-name) + (magit-file-at-point) + (and (derived-mode-p 'magit-log-mode) + (nth 3 magit-refresh-args)))) + +;;; Predicates + +(defun magit-no-commit-p () + "Return t if there is no commit in the current Git repository." + (not (magit-rev-verify "HEAD"))) + +(defun magit-anything-staged-p (&optional ignore-submodules &rest files) + "Return t if there are any staged changes. +If optional FILES is non-nil, then only changes to those files +are considered." + (magit-git-failure "diff" "--quiet" "--cached" + (and ignore-submodules "--ignore-submodules") + "--" files)) + +(defun magit-anything-unstaged-p (&optional ignore-submodules &rest files) + "Return t if there are any unstaged changes. +If optional FILES is non-nil, then only changes to those files +are considered." + (magit-git-failure "diff" "--quiet" + (and ignore-submodules "--ignore-submodules") + "--" files)) + +(defun magit-anything-modified-p (&optional ignore-submodules &rest files) + "Return t if there are any staged or unstaged changes. +If optional FILES is non-nil, then only changes to those files +are considered." + (or (apply 'magit-anything-staged-p ignore-submodules files) + (apply 'magit-anything-unstaged-p ignore-submodules files))) + +(defun magit-anything-unmerged-p (&rest files) + "Return t if there are any merge conflicts. +If optional FILES is non-nil, then only conflicts in those files +are considered." + (and (magit-git-string "ls-files" "--unmerged" files) t)) + +;;; Revisions and References + +(defun magit-rev-parse (&rest args) + "Execute `git rev-parse ARGS', returning first line of output. +If there is no output return nil." + (apply #'magit-git-string "rev-parse" args)) + +(defun magit-rev-parse-safe (&rest args) + "Execute `git rev-parse ARGS', returning first line of output. +If there is no output return nil. Like `magit-rev-parse' but +ignore `magit-git-debug'." + (apply #'magit-git-str "rev-parse" args)) + +(defun magit-rev-parse-p (&rest args) + "Execute `git rev-parse ARGS', returning t if it prints \"true\". +Return t if the first (and usually only) output line is the +string \"true\", otherwise return nil." + (magit-git-true "rev-parse" args)) + +(defun magit-rev-verify (rev) + (magit-rev-parse-safe "--verify" rev)) + +(defun magit-rev-verify-commit (rev) + "Return full hash for REV if it names an existing commit." + (magit-rev-verify (concat rev "^{commit}"))) + +(defun magit-rev-equal (a b) + (magit-git-success "diff" "--quiet" a b)) + +(defun magit-rev-ancestor-p (a b) + "Return non-nil if commit A is an ancestor of commit B." + (magit-git-success "merge-base" "--is-ancestor" a b)) + +(defun magit-rev-head-p (rev) + (or (equal rev "HEAD") + (and rev + (not (string-match-p "\\.\\." rev)) + (equal (magit-rev-parse rev) + (magit-rev-parse "HEAD"))))) + +(defun magit-rev-name (rev &optional pattern) + (magit-git-string "name-rev" "--name-only" "--no-undefined" + (and pattern (concat "--refs=" pattern)) + rev)) + +(defun magit-rev-branch (rev) + (--when-let (magit-rev-name rev "refs/heads/*") + (unless (string-match-p "~" it) it))) + +(defun magit-get-shortname (rev) + (let ((fn (apply-partially 'magit-git-string "name-rev" + "--name-only" "--no-undefined" rev))) + (setq rev (or (funcall fn "--refs=refs/tags/*") + (funcall fn "--refs=refs/heads/*") + (funcall fn "--refs=refs/remotes/*" "--always"))) + (if (and (string-match "^\\(?:tags\\|remotes\\)/\\(.+\\)" rev) + (magit-ref-fullname (match-string 1 rev))) + (match-string 1 rev) + rev))) + +(defun magit-name-branch (rev &optional lax) + (or (magit-name-local-branch rev) + (magit-name-remote-branch rev) + (and lax (or (magit-name-local-branch rev t) + (magit-name-remote-branch rev t))))) + +(defun magit-name-local-branch (rev &optional lax) + (--when-let (magit-git-string "name-rev" "--name-only" "--no-undefined" + "--refs=refs/heads/*" rev) + (and (or lax (not (string-match-p "~" it))) it))) + +(defun magit-name-remote-branch (rev &optional lax) + (--when-let (magit-git-string "name-rev" "--name-only" "--no-undefined" + "--refs=refs/remotes/*" rev) + (and (or lax (not (string-match-p "~" it))) + (substring it 8)))) + +(defun magit-name-tag (rev &optional lax) + (--when-let (magit-git-string "name-rev" "--name-only" "--no-undefined" + "--refs=refs/tags/*" rev) + (and (or lax (not (string-match-p "~" it))) + (substring it 5)))) + +(defun magit-ref-fullname (name) + (magit-rev-parse "--symbolic-full-name" name)) + +(defun magit-ref-exists-p (ref) + (magit-git-success "show-ref" "--verify" ref)) + +(defun magit-headish () + "Return \"HEAD\" or if that doesn't exist the hash of the empty tree." + (if (magit-no-commit-p) + (magit-git-string "mktree") + "HEAD")) + +(defun magit-branch-at-point () + (magit-section-case + (branch (magit-section-value it)) + (commit (magit-name-branch (magit-section-value it))))) + +(defun magit-local-branch-at-point () + (magit-section-case + (branch (let ((branch (magit-section-value it))) + (when (member branch (magit-list-local-branch-names)) + branch))) + (commit (magit-name-local-branch (magit-section-value it))))) + +(defun magit-remote-branch-at-point () + (magit-section-case + (branch (let ((branch (magit-section-value it))) + (when (member branch (magit-list-remote-branch-names)) + branch))) + (commit (magit-name-remote-branch (magit-section-value it))))) + +(defun magit-commit-at-point () + (or (magit-section-when commit) + (and (derived-mode-p 'magit-revision-mode) + (car magit-refresh-args)))) + +(defun magit-branch-or-commit-at-point () + (or (magit-section-case + (branch (magit-section-value it)) + (commit (let ((rev (magit-section-value it))) + (or (magit-get-shortname rev) rev)))) + (and (derived-mode-p 'magit-revision-mode) + (car magit-refresh-args)))) + +(defun magit-tag-at-point () + (magit-section-case + (tag (magit-section-value it)) + (commit (magit-name-tag (magit-section-value it))))) + +(defun magit-stash-at-point () + (magit-section-when stash)) + +(defun magit-remote-at-point () + (magit-section-case + (remote (magit-section-value it)) + (branch (magit-section-parent-value it)))) + +(defun magit-get-current-branch () + "Return the refname of the currently checked out branch. +Return nil if no branch is currently checked out." + (magit-git-string "symbolic-ref" "--short" "HEAD")) + +(defun magit-get-previous-branch () + "Return the refname of the previously checked out branch. +Return nil if no branch can be found in the `HEAD' reflog +which is different from the current branch and still exists." + (let ((current (magit-get-current-branch)) + (i 1) prev) + (while (and (setq prev (magit-rev-verify (format "@{-%i}" i))) + (or (not (setq prev (magit-rev-branch prev))) + (equal prev current))) + (cl-incf i)) + prev)) + +(cl-defun magit-get-upstream-ref + (&optional (branch (magit-get-current-branch))) + (when branch + (let ((remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge"))) + (when (and remote merge) + (cond ((string-equal remote ".") merge) + ((string-prefix-p "refs/heads/" merge) + (concat "refs/remotes/" remote "/" (substring merge 11)))))))) + +(cl-defun magit-get-upstream-branch + (&optional (branch (magit-get-current-branch))) + (when branch + (let ((remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge"))) + (when (and remote merge (string-prefix-p "refs/heads/" merge)) + (setq merge (substring merge 11)) + (if (string-equal remote ".") + (propertize merge 'face 'magit-branch-local) + (propertize (concat remote "/" merge) 'face 'magit-branch-remote)))))) + +(defun magit-get-indirect-upstream-branch (branch &optional force) + (let ((remote (magit-get "branch" branch "remote"))) + (and remote (not (equal remote ".")) + ;; The user has opted in... + (or force (member branch magit-branch-prefer-remote-upstream)) + ;; and local BRANCH tracks a remote branch... + (let ((upstream (magit-get-upstream-branch branch))) + ;; whose upstream... + (and upstream + ;; has the same name as BRANCH and... + (equal (substring upstream (1+ (length remote))) branch) + ;; and can be fast-forwarded to BRANCH. + (magit-rev-ancestor-p upstream branch) + upstream))))) + +(cl-defun magit-get-upstream-remote + (&optional (branch (magit-get-current-branch))) + (when branch + (magit-get "branch" branch "remote"))) + +(cl-defun magit-get-push-remote + (&optional (branch (magit-get-current-branch))) + (or (and branch (magit-get "branch" branch "pushRemote")) + (magit-get "remote.pushDefault"))) + +(cl-defun magit-get-push-branch + (&optional (branch (magit-get-current-branch))) + (-when-let (remote (and branch (magit-get-push-remote branch))) + (concat remote "/" branch))) + +(defun magit-get-@{push}-branch (&optional branch) + (let ((ref (magit-rev-parse "--symbolic-full-name" + (concat branch "@{push}")))) + (when (and ref (string-prefix-p "refs/remotes/" ref)) + (substring ref 13)))) + +(defun magit-get-remote (&optional branch) + (when (or branch (setq branch (magit-get-current-branch))) + (let ((remote (magit-get "branch" branch "remote"))) + (unless (equal remote ".") + remote)))) + +(defun magit-split-branch-name (branch) + (cond ((member branch (magit-list-local-branch-names)) + (cons "." branch)) + ((string-match "/" branch) + (let ((remote (substring branch 0 (match-beginning 0)))) + (if (save-match-data (member remote (magit-list-remotes))) + (cons remote (substring branch (match-end 0))) + (error "Invalid branch name %s" branch)))))) + +(defun magit-get-current-tag (&optional rev with-distance) + "Return the closest tag reachable from REV. + +If optional REV is nil then default to \"HEAD\". +If optional WITH-DISTANCE is non-nil then return (TAG COMMITS), +if it is `dirty' return (TAG COMMIT DIRTY). COMMITS is the number +of commits in \"HEAD\" but not in TAG and DIRTY is t if there are +uncommitted changes, nil otherwise." + (--when-let (magit-git-str "describe" "--long" "--tags" + (and (eq with-distance 'dirty) "--dirty") rev) + (save-match-data + (string-match + "\\(.+\\)-\\(?:0[0-9]*\\|\\([0-9]+\\)\\)-g[0-9a-z]+\\(-dirty\\)?$" it) + (if with-distance + `(,(match-string 1 it) + ,(string-to-number (or (match-string 2 it) "0")) + ,@(and (match-string 3 it) (list t))) + (match-string 1 it))))) + +(defun magit-get-next-tag (&optional rev with-distance) + "Return the closest tag from which REV is reachable. + +If optional REV is nil then default to \"HEAD\". +If no such tag can be found or if the distance is 0 (in which +case it is the current tag, not the next) return nil instead. +If optional WITH-DISTANCE is non-nil then return (TAG COMMITS) +where COMMITS is the number of commits in TAG but not in REV." + (--when-let (magit-git-string "describe" "--contains" (or rev "HEAD")) + (save-match-data + (when (string-match "^[^^~]+" it) + (setq it (match-string 0 it)) + (unless (equal it (magit-get-current-tag rev)) + (if with-distance + (list it (car (magit-rev-diff-count it rev))) + it)))))) + +(defvar magit-list-refs-namespaces + '("refs/heads" "refs/remotes" "refs/tags" "refs/pull")) + +(defun magit-list-refs (&rest args) + (magit-git-lines "for-each-ref" "--format=%(refname)" + (or args magit-list-refs-namespaces))) + +(defun magit-list-branches () + (magit-list-refs "refs/heads" "refs/remotes")) + +(defun magit-list-local-branches () + (magit-list-refs "refs/heads")) + +(defun magit-list-remote-branches (&optional remote) + (magit-list-refs (concat "refs/remotes/" remote))) + +(defun magit-list-containing-branches (&optional commit) + (--filter (not (string-match-p "\\`(HEAD" it)) + (--map (substring it 2) + (magit-git-lines "branch" "--contains" commit)))) + +(defun magit-list-merged-branches (&optional commit) + (--filter (not (string-match-p "\\`(HEAD" it)) + (--map (substring it 2) + (magit-git-lines "branch" "--merged" commit)))) + +(defun magit-list-unmerged-branches (&optional commit) + (--filter (not (string-match-p "\\`(HEAD" it)) + (--map (substring it 2) + (magit-git-lines "branch" "--no-merged" commit)))) + +(defun magit-list-unmerged-to-upstream-branches () + (--filter (-when-let (upstream (magit-get-upstream-branch it)) + (member it (magit-list-unmerged-branches upstream))) + (magit-list-local-branch-names))) + +(defun magit-list-refnames (&rest args) + (magit-git-lines "for-each-ref" "--format=%(refname:short)" + (or args magit-list-refs-namespaces))) + +(defun magit-list-branch-names () + (magit-list-refnames "refs/heads" "refs/remotes")) + +(defun magit-list-local-branch-names () + (magit-list-refnames "refs/heads")) + +(defun magit-list-remote-branch-names (&optional remote relative) + (if (and remote relative) + (let ((regexp (format "^refs/remotes/%s/\\(.+\\)" remote))) + (--mapcat (when (string-match regexp it) + (list (match-string 1 it))) + (magit-list-remote-branches remote))) + (magit-list-refnames (concat "refs/remotes/" remote)))) + +(defun magit-format-refs (format &rest args) + (let ((lines (magit-git-lines + "for-each-ref" (concat "--format=" format) + (or args (list "refs/heads" "refs/remotes" "refs/tags"))))) + (if (string-match-p "\f" format) + (--map (split-string it "\f") lines) + lines))) + +(defun magit-list-remotes () + (magit-git-lines "remote")) + +(defun magit-list-tags () + (magit-git-lines "tag")) + +(defun magit-list-notes-refnames () + (--map (substring it 6) (magit-list-refnames "refs/notes"))) + +(defun magit-remote-list-tags (remote) + (--map (substring it 51) + (--filter (not (string-match-p "\\^{}$" it)) + (magit-git-lines "ls-remote" "--tags" remote)))) + +(defun magit-remote-list-branches (remote) + (--map (substring it 52) + (--filter (not (string-match-p "\\^{}$" it)) + (magit-git-lines "ls-remote" "--heads" remote)))) + +(defun magit-get-submodules () + (--mapcat (and (string-match "^160000 [0-9a-z]\\{40\\} 0\t\\(.+\\)$" it) + (list (match-string 1 it))) + (magit-git-items "ls-files" "-z" "--stage"))) + +(defun magit-branch-p (string) + (and (or (member string (magit-list-branches)) + (member string (magit-list-branch-names))) t)) + +(defun magit-local-branch-p (branch) + (and (or (member branch (magit-list-local-branches)) + (member branch (magit-list-local-branch-names))) t)) + +(defun magit-branch-set-face (branch) + (propertize branch 'face (if (magit-local-branch-p branch) + 'magit-branch-local + 'magit-branch-remote))) + +(defun magit-remote-p (string) + (car (member string (magit-list-remotes)))) + +(defun magit-rev-diff-count (a b) + "Return the commits in A but not B and vice versa. +Return a list of two integers: (A>B B>A)." + (mapcar 'string-to-number + (split-string (magit-git-string "rev-list" + "--count" "--left-right" + (concat a "..." b)) + "\t"))) + +(defun magit-abbrev-length () + (string-to-number (or (magit-get "core.abbrev") "7"))) + +(defun magit-abbrev-arg () + (format "--abbrev=%d" (magit-abbrev-length))) + +(defun magit-commit-children (commit &optional args) + (-map #'car + (--filter (member commit (cdr it)) + (--map (split-string it " ") + (magit-git-lines + "log" "--format=%H %P" + (or args (list "--branches" "--tags" "--remotes")) + "--not" commit))))) + +(defun magit-commit-parents (commit) + (--when-let (magit-git-string "rev-list" "-1" "--parents" commit) + (cdr (split-string it)))) + +(defun magit-assert-one-parent (commit command) + (when (> (length (magit-commit-parents commit)) 1) + (user-error "Cannot %s a merge commit" command))) + +(defun magit-patch-id (rev) + (with-temp-buffer + (magit-process-file + shell-file-name nil '(t nil) nil shell-command-switch + (let ((exec (shell-quote-argument magit-git-executable))) + (format "%s diff-tree -u %s | %s patch-id" exec rev exec))) + (car (split-string (buffer-string))))) + +(defun magit-reflog-enable (ref &optional stashish) + (let ((oldrev (magit-rev-verify ref)) + (logfile (magit-git-dir (concat "logs/" ref)))) + (unless (file-exists-p logfile) + (when oldrev + (magit-git-success "update-ref" "-d" ref oldrev)) + (make-directory (file-name-directory logfile) t) + (with-temp-file logfile) + (when (and oldrev (not stashish)) + (magit-git-success "update-ref" "-m" "enable reflog" ref oldrev ""))))) + +(defun magit-rev-format (format &optional rev args) + (let ((str (magit-git-string "show" "--no-patch" + (concat "--format=" format) args + (if rev (concat rev "^{commit}") "HEAD") "--"))) + (unless (string-equal str "") + str))) + +(defun magit-rev-insert-format (format &optional rev args) + (magit-git-insert "show" "--no-patch" + (concat "--format=" format) args + (if rev (concat rev "^{commit}") "HEAD") "--")) + +(defun magit-format-rev-summary (rev) + (--when-let (magit-rev-format "%h %s" rev) + (string-match " " it) + (put-text-property 0 (match-beginning 0) 'face 'magit-hash it) + it)) + +(defun magit-format-ref-label (ref &optional head) + (-let [(_re face fn) + (--first (string-match (car it) ref) magit-ref-namespaces)] + (if fn + (funcall fn ref face) + (propertize (or (match-string 1 ref) ref) + 'face (if (equal ref head) 'magit-branch-current face))))) + +(defun magit-format-ref-labels (string) + (save-match-data + (let ((regexp "\\(, \\|tag: \\| -> \\|[()]\\)") head names) + (if (and (derived-mode-p 'magit-log-mode) + (member "--simplify-by-decoration" (cadr magit-refresh-args))) + (let ((branches (magit-list-local-branch-names)) + (re (format "^%s/.+" (regexp-opt (magit-list-remotes))))) + (setq names + (--map (cond ((string-equal it "HEAD") it) + ((string-prefix-p "refs/" it) it) + ((member it branches) (concat "refs/heads/" it)) + ((string-match re it) (concat "refs/remotes/" it)) + (t (concat "refs/" it))) + (split-string + (replace-regexp-in-string "tag: " "refs/tags/" string) + regexp t)))) + (setq names (split-string string regexp t))) + (when (member "HEAD" names) + (setq head (magit-git-string "symbolic-ref" "HEAD") + names (cons (or head "@") (delete head (delete "HEAD" names))))) + (mapconcat (lambda (it) (magit-format-ref-label it head)) names " ")))) + +(defun magit-object-type (object) + (magit-git-string "cat-file" "-t" object)) + +(defmacro magit-with-blob (commit file &rest body) + (declare (indent 2) + (debug (form form body))) + `(with-temp-buffer + (let ((buffer-file-name ,file)) + (save-excursion + (magit-git-insert "cat-file" "-p" + (concat ,commit ":" buffer-file-name))) + (decode-coding-inserted-region + (point-min) (point-max) buffer-file-name t nil nil t) + ,@body))) + +(defmacro magit-with-temp-index (tree arg &rest body) + (declare (indent 2) (debug (form form body))) + (let ((file (cl-gensym "file"))) + `(let ((,file (magit-git-dir (make-temp-name "index.magit.")))) + (setq ,file (or (file-remote-p ,file 'localname) ,file)) + (unwind-protect + (progn (--when-let ,tree + (or (magit-git-success "read-tree" ,arg it + (concat "--index-output=" ,file)) + (error "Cannot read tree %s" it))) + (if (file-remote-p default-directory) + (let ((magit-tramp-process-environment + (setenv-internal magit-tramp-process-environment + "GIT_INDEX_FILE" ,file t))) + ,@body) + (let ((process-environment process-environment)) + (setenv "GIT_INDEX_FILE" ,file) + ,@body))) + (ignore-errors + (delete-file (concat (file-remote-p default-directory) ,file))))))) + +(defun magit-commit-tree (message &optional tree &rest parents) + (magit-git-string "commit-tree" "-m" message + (--mapcat (list "-p" it) (delq nil parents)) + (or tree (magit-git-string "write-tree")))) + +(defun magit-commit-worktree (message &optional arg &rest other-parents) + (magit-with-temp-index "HEAD" arg + (and (magit-update-files (magit-modified-files)) + (apply #'magit-commit-tree message nil "HEAD" other-parents)))) + +(defun magit-update-files (files) + (magit-git-success "update-index" "--add" "--remove" "--" files)) + +(defconst magit-range-re + (concat "\\`\\([^ \t]*[^.]\\)?" ; revA + "\\(\\.\\.\\.?\\)" ; range marker + "\\([^.][^ \t]*\\)?\\'")) ; revB + +;;; Completion + +(defvar magit-revision-history nil) + +(defun magit-read-branch (prompt &optional default) + (magit-completing-read prompt (magit-list-branch-names) + nil t nil 'magit-revision-history + (or (magit-branch-at-point) + default (magit-get-current-branch)))) + +(defun magit-read-branch-or-commit (prompt &optional secondary-default) + (or (magit-completing-read prompt (cons "HEAD" (magit-list-refnames)) + nil nil nil 'magit-revision-history + (or (magit-branch-or-commit-at-point) + secondary-default + (magit-get-current-branch))) + (user-error "Nothing selected"))) + +(defun magit-read-range-or-commit (prompt &optional secondary-default) + (magit-read-range + prompt + (or (--when-let (magit-region-values 'commit 'branch) + (deactivate-mark) + (concat (car (last it)) ".." (car it))) + (magit-branch-or-commit-at-point) + secondary-default + (magit-get-current-branch)))) + +(defun magit-read-range (prompt &optional default) + (let* ((choose-completion-string-functions + '(crm--choose-completion-string)) + (minibuffer-completion-table #'crm--collection-fn) + (minibuffer-completion-confirm t) + (crm-completion-table (magit-list-refnames)) + (crm-separator "\\.\\.\\.?") + (input (read-from-minibuffer + (concat prompt (and default (format " (%s)" default)) ": ") + nil crm-local-completion-map + nil 'magit-revision-history + default))) + (when (string-equal input "") + (or (setq input default) + (user-error "Nothing selected"))) + input)) + +(defun magit-read-remote-branch + (prompt &optional remote default local-branch require-match) + (let ((choice (magit-completing-read + prompt + (nconc (and local-branch + (if remote + (concat remote "/" local-branch) + (--map (concat it "/" local-branch) + (magit-list-remotes)))) + (magit-list-remote-branch-names remote t)) + nil require-match nil 'magit-revision-history default))) + (if (string-match "\\`\\([^/]+\\)/\\(.+\\)" choice) + choice + (user-error "`%s' doesn't have the form REMOTE/BRANCH" choice)))) + +(defun magit-read-local-branch (prompt &optional secondary-default) + (magit-completing-read prompt (magit-list-local-branch-names) + nil t nil 'magit-revision-history + (or (magit-local-branch-at-point) + secondary-default + (magit-get-current-branch)))) + +(defun magit-read-local-branch-or-commit (prompt) + (let ((branches (magit-list-local-branch-names)) + (commit (magit-commit-at-point))) + (or (magit-completing-read prompt + (if commit (cons commit branches) branches) + nil nil nil 'magit-revision-history + (or (magit-local-branch-at-point) commit)) + (user-error "Nothing selected")))) + +(defun magit-read-local-branch-or-ref (prompt &optional secondary-default) + (magit-completing-read prompt (nconc (magit-list-local-branch-names) + (magit-list-refs "refs/")) + nil t nil 'magit-revision-history + (or (magit-local-branch-at-point) + secondary-default + (magit-get-current-branch)))) + +(defun magit-read-other-branch (prompt &optional exclude secondary-default) + (let* ((current (magit-get-current-branch)) + (atpoint (magit-branch-at-point)) + (exclude (or exclude current)) + (default (or (and (not (equal atpoint exclude)) atpoint) + (and (not (equal current exclude)) current) + secondary-default (magit-get-previous-branch)))) + (magit-completing-read prompt (delete exclude (magit-list-branch-names)) + nil t nil 'magit-revision-history default))) + +(defun magit-read-other-branch-or-commit + (prompt &optional exclude secondary-default) + (let* ((current (magit-get-current-branch)) + (atpoint (magit-branch-or-commit-at-point)) + (exclude (or exclude current)) + (default (or (and (not (equal atpoint exclude)) atpoint) + (and (not (equal current exclude)) current) + secondary-default (magit-get-previous-branch)))) + (or (magit-completing-read prompt (delete exclude (magit-list-refnames)) + nil nil nil 'magit-revision-history default) + (user-error "Nothing selected")))) + +(defun magit-read-tag (prompt &optional require-match) + (magit-completing-read prompt (magit-list-tags) nil + require-match nil 'magit-revision-history + (magit-tag-at-point))) + +(defun magit-read-stash (prompt &optional use-at-point) + (let ((atpoint (magit-stash-at-point))) + (or (and use-at-point atpoint) + (let ((stashes (magit-git-lines "stash" "list" "--format=%gd"))) + (magit-completing-read prompt stashes nil t nil nil + (or atpoint (car stashes))))))) + +(defun magit-read-remote (prompt &optional default use-only) + (let ((remotes (magit-list-remotes))) + (if (and use-only (= (length remotes) 1)) + (car remotes) + (magit-completing-read prompt remotes + nil t nil nil + (or default + (magit-remote-at-point) + (magit-get-remote)))))) + +;;; Variables + +(defun magit-get (&rest keys) + "Return the value of Git config entry specified by KEYS." + (magit-git-str "config" (mapconcat 'identity keys "."))) + +(defun magit-get-all (&rest keys) + "Return all values of the Git config entry specified by KEYS." + (let ((magit-git-debug nil)) + (magit-git-lines "config" "--get-all" (mapconcat 'identity keys ".")))) + +(defun magit-get-boolean (&rest keys) + "Return the boolean value of Git config entry specified by KEYS." + (magit-git-true "config" "--bool" (mapconcat 'identity keys "."))) + +(defun magit-set (val &rest keys) + "Set Git config settings specified by KEYS to VAL." + (if val + (magit-git-string "config" (mapconcat 'identity keys ".") val) + (magit-git-string "config" "--unset" (mapconcat 'identity keys ".")))) + +;;; magit-git.el ends soon + +(define-obsolete-function-alias 'magit-get-tracked-ref + 'magit-get-upstream-ref "Magit 2.4.0") +(define-obsolete-function-alias 'magit-get-tracked-branch + 'magit-get-upstream-branch "Magit 2.4.0") +(define-obsolete-function-alias 'magit-get-tracked-remote + 'magit-get-upstream-remote "Magit 2.4.0") + +(provide 'magit-git) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-git.el ends here diff --git a/elpa/magit-20151223.1425/magit-log.el b/elpa/magit-20151223.1425/magit-log.el new file mode 100644 index 00000000..72397c68 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-log.el @@ -0,0 +1,1490 @@ +;;; magit-log.el --- inspect Git history -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library implements support for looking at Git logs, including +;; special logs like reflogs and cherry-logs, as well as for selecting +;; a commit from a log. + +;;; Code: + +(require 'magit-core) +(require 'magit-diff) + +(declare-function magit-blame-chunk-get 'magit-blame) +(declare-function magit-blob-visit 'magit) +(declare-function magit-find-file-noselect 'magit) +(declare-function magit-insert-head-branch-header 'magit) +(declare-function magit-insert-upstream-branch-header 'magit) +(declare-function magit-read-file-from-rev 'magit) +(declare-function magit-show-commit 'magit) +(defvar magit-refs-indent-cherry-lines) +(defvar magit-refs-show-commit-count) + +(require 'ansi-color) +(require 'crm) + +;;; Options +;;;; Log Mode + +(defgroup magit-log nil + "Inspect and manipulate Git history." + :group 'magit-modes) + +(defcustom magit-log-mode-hook nil + "Hook run after entering Magit-Log mode." + :group 'magit-log + :type 'hook) + +(defcustom magit-log-arguments '("-n256" "--graph" "--decorate") + "The log arguments used in `magit-log-mode' buffers." + :package-version '(magit . "2.3.0") + :group 'magit-log + :group 'magit-commands + :type '(repeat (string :tag "Argument"))) + +(defcustom magit-log-remove-graph-args '("--follow" "--grep" "-G" "-S" "-L") + "The log arguments that cause the `--graph' argument to be dropped." + :package-version '(magit . "2.3.0") + :group 'magit-log + :type '(repeat (string :tag "Argument")) + :options '("--follow" "--grep" "-G" "-S" "-L")) + +(defcustom magit-log-revision-headers-format "\ +%+b +Author: %aN <%aE> +Committer: %cN <%cE>" + "Additional format string used with the `++header' argument." + :package-version '(magit . "2.3.0") + :group 'magit-log + :type 'string) + +(defcustom magit-log-auto-more nil + "Insert more log entries automatically when moving past the last entry. +Only considered when moving past the last entry with +`magit-goto-*-section' commands." + :group 'magit-log + :type 'boolean) + +(defcustom magit-log-show-margin t + "Whether to initially show the margin in log buffers. + +When non-nil the author name and date are initially displayed in +the margin of log buffers. The margin can be shown or hidden in +the current buffer using the command `magit-toggle-margin'. In +status buffers this option is ignored but it is possible to show +the margin using the mentioned command." + :package-version '(magit . "2.1.0") + :group 'magit-log + :type 'boolean) + +(defcustom magit-duration-spec + `((?Y "year" "years" ,(round (* 60 60 24 365.2425))) + (?M "month" "months" ,(round (* 60 60 24 30.436875))) + (?w "week" "weeks" ,(* 60 60 24 7)) + (?d "day" "days" ,(* 60 60 24)) + (?h "hour" "hours" ,(* 60 60)) + (?m "minute" "minutes" 60) + (?s "second" "seconds" 1)) + "Units used to display durations in a human format. +The value is a list of time units, beginning with the longest. +Each element has the form (CHAR UNIT UNITS SECONDS). UNIT is the +time unit, UNITS is the plural of that unit. CHAR is a character +abbreviation. And SECONDS is the number of seconds in one UNIT. +Also see option `magit-log-margin-spec'." + :package-version '(magit . "2.1.0") + :group 'magit-log + :type '(repeat (list (character :tag "Unit character") + (string :tag "Unit singular string") + (string :tag "Unit plural string") + (integer :tag "Seconds in unit")))) + +(defcustom magit-log-margin-spec '(28 7 magit-duration-spec) + "How to format the log margin. + +The log margin is used to display each commit's author followed +by the commit's age. This option controls the total width of the +margin and how time units are formatted, the value has the form: + + (WIDTH UNIT-WIDTH DURATION-SPEC) + +WIDTH specifies the total width of the log margin. UNIT-WIDTH is +either the integer 1, in which case time units are displayed as a +single characters, leaving more room for author names; or it has +to be the width of the longest time unit string in DURATION-SPEC. +DURATION-SPEC has to be a variable, its value controls which time +units, in what language, are being used." + :package-version '(magit . "2.1.0") + :group 'magit-log + :set-after '(magit-duration-spec) + :type '(list (integer :tag "Margin width") + (choice :tag "Time unit style" + (const :format "%t\n" + :tag "abbreviate to single character" 1) + (integer :format "%t\n" + :tag "show full name" 7)) + (variable :tag "Duration spec variable"))) + +(defcustom magit-log-show-refname-after-summary nil + "Whether to show refnames after commit summaries. +This is useful if you use really long branch names." + :package-version '(magit . "2.2.0") + :group 'magit-log + :type 'boolean) + +(defface magit-log-graph + '((((class color) (background light)) :foreground "grey30") + (((class color) (background dark)) :foreground "grey80")) + "Face for the graph part of the log output." + :group 'magit-faces) + +(defface magit-log-author + '((((class color) (background light)) :foreground "firebrick") + (((class color) (background dark)) :foreground "tomato")) + "Face for the author part of the log output." + :group 'magit-faces) + +(defface magit-log-date + '((((class color) (background light)) :foreground "grey30") + (((class color) (background dark)) :foreground "grey80")) + "Face for the date part of the log output." + :group 'magit-faces) + +;;;; Select Mode + +(defcustom magit-log-select-arguments '("-n256" "--decorate") + "The log arguments used in `magit-log-select-mode' buffers." + :package-version '(magit . "2.3.0") + :group 'magit-log + :type '(repeat (string :tag "Argument"))) + +(defcustom magit-log-select-show-usage 'both + "Whether to show usage information when selecting a commit from a log. +The message can be shown in the `echo-area' or the `header-line', or in +`both' places. If the value isn't one of these symbols, then it should +be nil, in which case no usage information is shown." + :package-version '(magit . "2.1.0") + :group 'magit-log + :type '(choice (const :tag "in echo-area" echo-area) + (const :tag "in header-line" header-line) + (const :tag "in both places" both) + (const :tag "nowhere"))) + +;;;; Cherry Mode + +(defcustom magit-cherry-sections-hook + '(magit-insert-cherry-headers + magit-insert-cherry-commits) + "Hook run to insert sections into the cherry buffer." + :package-version '(magit . "2.1.0") + :group 'magit-log + :type 'hook) + +;;;; Reflog Mode + +(defcustom magit-reflog-arguments '("-n256") + "The log arguments used in `magit-reflog-mode' buffers." + :package-version '(magit . "2.3.0") + :group 'magit-log + :group 'magit-commands + :type '(repeat (string :tag "Argument"))) + +(defcustom magit-reflog-show-margin t + "Whether to initially show the margin in reflog buffers. + +When non-nil the author name and date are initially displayed in +the margin of reflog buffers. The margin can be shown or hidden +in the current buffer using the command `magit-toggle-margin'." + :package-version '(magit . "2.1.0") + :group 'magit-log + :type 'boolean) + +(defface magit-reflog-commit '((t :foreground "green")) + "Face for commit commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-amend '((t :foreground "magenta")) + "Face for amend commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-merge '((t :foreground "green")) + "Face for merge, checkout and branch commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-checkout '((t :foreground "blue")) + "Face for checkout commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-reset '((t :foreground "red")) + "Face for reset commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-rebase '((t :foreground "magenta")) + "Face for rebase commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-cherry-pick '((t :foreground "green")) + "Face for cherry-pick commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-remote '((t :foreground "cyan")) + "Face for pull and clone commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-other '((t :foreground "cyan")) + "Face for other commands in reflogs." + :group 'magit-faces) + +;;;; Log Sections + +(defcustom magit-log-section-commit-count 10 + "How many recent commits to show in certain log sections. +How many recent commits `magit-insert-recent-commits' and +`magit-insert-unpulled-or-recent-commits' (provided there +are no unpulled commits) show." + :package-version '(magit . "2.1.0") + :group 'magit-status + :type 'number) + +(defcustom magit-log-section-arguments '("--decorate") + "The log arguments used in buffers that show other things besides logs." + :package-version '(magit . "2.2.0") + :group 'magit-log + :group 'magit-status + :type '(repeat (string :tag "Argument"))) + +(define-obsolete-variable-alias 'magit-log-section-args + 'magit-log-section-arguments "2.2.0") + +;;; Commands + +(defvar magit-log-popup + '(:variable magit-log-arguments + :man-page "git-log" + :switches ((?g "Show graph" "--graph") + (?c "Show graph in color" "--color") + (?d "Show refnames" "--decorate") + (?S "Show signatures" "--show-signature") + (?u "Show diffs" "--patch") + (?s "Show diffstats" "--stat") + (?h "Show header" "++header") + (?D "Simplify by decoration" "--simplify-by-decoration") + (?f "Follow renames when showing single-file log" "--follow")) + :options ((?n "Limit number of commits" "-n") + (?f "Limit to files" "-- " magit-read-files) + (?a "Limit to author" "--author=") + (?g "Search messages" "--grep=") + (?G "Search changes" "-G") + (?S "Search occurences" "-S") + (?L "Trace line evolution" "-L" magit-read-file-trace)) + :actions ((?l "Log current" magit-log-current) + (?L "Log local branches" magit-log-branches) + (?r "Reflog current" magit-reflog-current) + (?o "Log other" magit-log) + (?b "Log all branches" magit-log-all-branches) + (?O "Reflog other" magit-reflog) + (?h "Log HEAD" magit-log-head) + (?a "Log all references" magit-log-all) + (?H "Reflog HEAD" magit-reflog-head)) + :default-action magit-log-current + :max-action-columns 3)) + +(defvar magit-log-mode-refresh-popup + '(:variable magit-log-arguments + :man-page "git-log" + :switches ((?g "Show graph" "--graph") + (?c "Show graph in color" "--color") + (?d "Show refnames" "--decorate") + (?S "Show signatures" "--show-signature") + (?u "Show diffs" "--patch") + (?s "Show diffstats" "--stat") + (?D "Simplify by decoration" "--simplify-by-decoration") + (?f "Follow renames when showing single-file log" "--follow")) + :options ((?n "Limit number of commits" "-n") + (?f "Limit to files" "-- " magit-read-files) + (?a "Limit to author" "--author=") + (?g "Search messages" "--grep=") + (?G "Search changes" "-G") + (?S "Search occurences" "-S") + (?L "Trace line evolution" "-L" magit-read-file-trace)) + :actions ((?g "Refresh" magit-log-refresh) + (?t "Toggle margin" magit-toggle-margin) + (?s "Set defaults" magit-log-set-default-arguments) nil + (?w "Save defaults" magit-log-save-default-arguments)) + :max-action-columns 2)) + +(defvar magit-reflog-mode-refresh-popup + '(:variable magit-reflog-arguments + :man-page "git-reflog" + :options ((?n "Limit number of commits" "-n")))) + +(defvar magit-log-refresh-popup + '(:variable magit-log-arguments + :man-page "git-log" + :switches ((?g "Show graph" "--graph") + (?c "Show graph in color" "--color") + (?d "Show refnames" "--decorate")) + :actions ((?g "Refresh" magit-log-refresh) + (?t "Toggle margin" magit-toggle-margin) + (?s "Set defaults" magit-log-set-default-arguments) nil + (?w "Save defaults" magit-log-save-default-arguments)) + :max-action-columns 2)) + +(magit-define-popup-keys-deferred 'magit-log-popup) +(magit-define-popup-keys-deferred 'magit-log-mode-refresh-popup) +(magit-define-popup-keys-deferred 'magit-log-refresh-popup) + +(defun magit-read-file-trace (&rest ignored) + (let ((file (magit-read-file-from-rev "HEAD" "File")) + (trace (magit-read-string "Trace"))) + (if (string-match + "^\\(/.+/\\|:[^:]+\\|[0-9]+,[-+]?[0-9]+\\)\\(:\\)?$" trace) + (concat trace (or (match-string 2 trace) ":") file) + (user-error "Trace is invalid, see man git-log")))) + +(defun magit-log-arguments (&optional refresh) + (cond ((memq magit-current-popup + '(magit-log-popup magit-log-refresh-popup)) + (magit-popup-export-file-args magit-current-popup-args)) + ((derived-mode-p 'magit-log-mode) + (list (nth 1 magit-refresh-args) + (nth 2 magit-refresh-args))) + (refresh + (list magit-log-section-arguments nil)) + (t + (-if-let (buffer (magit-mode-get-buffer 'magit-log-mode)) + (with-current-buffer buffer + (list (nth 1 magit-refresh-args) + (nth 2 magit-refresh-args))) + (list (default-value 'magit-log-arguments) nil))))) + +(defun magit-log-popup (arg) + "Popup console for log commands." + (interactive "P") + (let ((magit-log-refresh-popup + (pcase major-mode + (`magit-log-mode magit-log-mode-refresh-popup) + (_ magit-log-refresh-popup))) + (magit-log-arguments + (-if-let (buffer (magit-mode-get-buffer 'magit-log-mode)) + (with-current-buffer buffer + (magit-popup-import-file-args (nth 1 magit-refresh-args) + (nth 2 magit-refresh-args))) + (default-value 'magit-log-arguments)))) + (magit-invoke-popup 'magit-log-popup nil arg))) + +(defun magit-log-refresh-popup (arg) + "Popup console for changing log arguments in the current buffer." + (interactive "P") + (magit-log-refresh-assert) + (let ((magit-log-refresh-popup + (cond ((derived-mode-p 'magit-log-select-mode) + magit-log-refresh-popup) + ((derived-mode-p 'magit-log-mode) + (let ((def (copy-sequence magit-log-refresh-popup))) + (plist-put def :switches (plist-get magit-log-popup :switches)) + (plist-put def :options (plist-get magit-log-popup :options)) + def)) + (t + magit-log-refresh-popup))) + (magit-log-arguments + (cond ((derived-mode-p 'magit-log-select-mode) + (cadr magit-refresh-args)) + ((derived-mode-p 'magit-log-mode) + (magit-popup-import-file-args (nth 1 magit-refresh-args) + (nth 2 magit-refresh-args))) + (t + magit-log-section-arguments)))) + (magit-invoke-popup 'magit-log-refresh-popup nil arg))) + +(defun magit-log-refresh (args files) + "Set the local log arguments for the current buffer." + (interactive (magit-log-arguments t)) + (magit-log-refresh-assert) + (cond ((derived-mode-p 'magit-log-select-mode) + (setcar (cdr magit-refresh-args) args)) + ((derived-mode-p 'magit-log-mode) + (setcdr magit-refresh-args (list args files))) + (t + (setq-local magit-log-section-arguments args))) + (magit-refresh)) + +(defun magit-log-set-default-arguments (args files) + "Set the global log arguments for the current buffer." + (interactive (magit-log-arguments t)) + (magit-log-refresh-assert) + (cond ((derived-mode-p 'magit-log-select-mode) + (customize-set-variable 'magit-log-select-arguments args) + (setcar (cdr magit-refresh-args) args)) + ((derived-mode-p 'magit-log-mode) + (customize-set-variable 'magit-log-arguments args) + (setcdr magit-refresh-args (list args files))) + (t + (customize-set-variable 'magit-log-section-arguments args) + (kill-local-variable 'magit-log-section-arguments))) + (magit-refresh)) + +(defun magit-log-save-default-arguments (args files) + "Set and save the global log arguments for the current buffer." + (interactive (magit-log-arguments t)) + (magit-log-refresh-assert) + (cond ((derived-mode-p 'magit-log-select-mode) + (customize-save-variable 'magit-log-select-arguments args) + (setcar (cdr magit-refresh-args) args)) + ((derived-mode-p 'magit-log-mode) + (customize-save-variable 'magit-log-arguments args) + (setcdr magit-refresh-args (list args files))) + (t + (customize-save-variable 'magit-log-section-arguments args) + (kill-local-variable 'magit-log-section-arguments))) + (magit-refresh)) + +(defun magit-log-refresh-assert () + (cond ((derived-mode-p 'magit-reflog-mode) + (user-error "Cannot change log arguments in reflog buffers")) + ((derived-mode-p 'magit-cherry-mode) + (user-error "Cannot change log arguments in cherry buffers")))) + +(defvar magit-log-read-revs-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map crm-local-completion-map) + (define-key map "\s" 'self-insert-command) + map)) + +(defun magit-log-read-revs (&optional use-current) + (or (and use-current (--when-let (magit-get-current-branch) (list it))) + (let* ((choose-completion-string-functions + '(crm--choose-completion-string)) + (minibuffer-completion-table #'crm--collection-fn) + (minibuffer-completion-confirm t) + (crm-completion-table + `(,@(and (file-exists-p (magit-git-dir "FETCH_HEAD")) + (list "FETCH_HEAD")) + ,@(magit-list-branch-names))) + (crm-separator "\\(\\.\\.\\.?\\|[, ]\\)") + (default (or (magit-branch-or-commit-at-point) + (unless use-current + (magit-get-previous-branch)))) + (input (read-from-minibuffer + (format "Log rev,s%s: " + (if default (format " (%s)" default) "")) + nil magit-log-read-revs-map + nil 'magit-revision-history default))) + (when (string-equal input "") + (or (setq input default) + (user-error "Nothing selected"))) + (split-string input "[, ]" t)))) + +;;;###autoload +(defun magit-log-current (revs &optional args files) + "Show log for the current branch. +When `HEAD' is detached or with a prefix argument show log for +one or more revs read from the minibuffer." + (interactive (cons (magit-log-read-revs t) + (magit-log-arguments))) + (magit-log revs args files)) + +;;;###autoload +(defun magit-log (revs &optional args files) + "Show log for one or more revs read from the minibuffer. +The user can input any revision or revisions separated by a +space, or even ranges, but only branches and tags, and a +representation of the commit at point, are available as +completion candidates." + (interactive (cons (magit-log-read-revs) + (magit-log-arguments))) + (magit-mode-setup #'magit-log-mode revs args files) + (magit-log-goto-same-commit)) + +;;;###autoload +(defun magit-log-head (&optional args files) + "Show log for `HEAD'." + (interactive (magit-log-arguments)) + (magit-log (list "HEAD") args files)) + +;;;###autoload +(defun magit-log-branches (&optional args files) + "Show log for all local branches and `HEAD'." + (interactive (magit-log-arguments)) + (magit-log (if (magit-get-current-branch) + (list "--branches") + (list "HEAD" "--branches")) + args files)) + +;;;###autoload +(defun magit-log-all-branches (&optional args files) + "Show log for all local and remote branches and `HEAD'." + (interactive (magit-log-arguments)) + (magit-log (if (magit-get-current-branch) + (list "--branches" "--remotes") + (list "HEAD" "--branches" "--remotes")) + args files)) + +;;;###autoload +(defun magit-log-all (&optional args files) + "Show log for all references and `HEAD'." + (interactive (magit-log-arguments)) + (magit-log (if (magit-get-current-branch) + (list "--all") + (list "HEAD" "--all")) + args files)) + +;;;###autoload +(defun magit-log-buffer-file (&optional follow beg end) + "Show log for the blob or file visited in the current buffer. +With a prefix argument or when `--follow' is part of +`magit-log-arguments', then follow renames." + (interactive (if (region-active-p) + (list current-prefix-arg + (1- (line-number-at-pos (region-beginning))) + (1- (line-number-at-pos (region-end)))) + (list current-prefix-arg))) + (-if-let (file (magit-file-relative-name)) + (magit-mode-setup #'magit-log-mode + (list (or magit-buffer-refname + (magit-get-current-branch) "HEAD")) + (let ((args (car (magit-log-arguments)))) + (when (and follow (not (member "--follow" args))) + (push "--follow" args)) + (when (and beg end) + (setq args (cons (format "-L%s,%s:%s" beg end file) + (cl-delete "-L" args :test + 'string-prefix-p))) + (setq file nil)) + args) + (and file (list file))) + (user-error "Buffer isn't visiting a file")) + (magit-log-goto-same-commit)) + +;;;###autoload +(defun magit-reflog-current () + "Display the reflog of the current branch." + (interactive) + (magit-reflog (magit-get-current-branch))) + +;;;###autoload +(defun magit-reflog (ref) + "Display the reflog of a branch." + (interactive (list (magit-read-local-branch-or-ref "Show reflog for"))) + (magit-mode-setup #'magit-reflog-mode ref magit-reflog-arguments)) + +;;;###autoload +(defun magit-reflog-head () + "Display the `HEAD' reflog." + (interactive) + (magit-reflog "HEAD")) + +(defun magit-log-toggle-commit-limit () + "Toggle the number of commits the current log buffer is limited to. +If the number of commits is currently limited, then remove that +limit. Otherwise set it to 256." + (interactive) + (magit-log-set-commit-limit (lambda (&rest _) nil))) + +(defun magit-log-double-commit-limit () + "Double the number of commits the current log buffer is limited to." + (interactive) + (magit-log-set-commit-limit '*)) + +(defun magit-log-half-commit-limit () + "Half the number of commits the current log buffer is limited to." + (interactive) + (magit-log-set-commit-limit '/)) + +(defun magit-log-set-commit-limit (fn) + (let* ((val (car (magit-log-arguments t))) + (arg (--first (string-match "^-n\\([0-9]+\\)?$" it) val)) + (num (and arg (string-to-number (match-string 1 arg)))) + (num (if num (funcall fn num 2) 256))) + (setq val (delete arg val)) + (setcar (cdr magit-refresh-args) + (if (and num (> num 0)) + (cons (format "-n%i" num) val) + val))) + (magit-refresh)) + +(defun magit-log-get-commit-limit () + (--when-let (--first (string-match "^-n\\([0-9]+\\)?$" it) + (car (magit-log-arguments t))) + (string-to-number (match-string 1 it)))) + +(defun magit-log-bury-buffer (&optional arg) + "Bury the current buffer or the revision buffer in the same frame. +Like `magit-mode-bury-buffer' (which see) but with a negative +prefix argument instead bury the revision buffer, provided it +is displayed in the current frame." + (interactive "p") + (if (< arg 0) + (let* ((buf (magit-mode-get-buffer 'magit-revision-mode)) + (win (and buf (get-buffer-window buf (selected-frame))))) + (if win + (with-selected-window win + (with-current-buffer buf + (magit-mode-bury-buffer (> (abs arg) 1)))) + (user-error "No revision buffer in this frame"))) + (magit-mode-bury-buffer (> arg 1)))) + +;;; Log Mode + +(defvar magit-log-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + (define-key map "\C-c\C-b" 'magit-go-backward) + (define-key map "\C-c\C-f" 'magit-go-forward) + (define-key map "=" 'magit-log-toggle-commit-limit) + (define-key map "+" 'magit-log-double-commit-limit) + (define-key map "-" 'magit-log-half-commit-limit) + (define-key map "q" 'magit-log-bury-buffer) + map) + "Keymap for `magit-log-mode'.") + +(define-derived-mode magit-log-mode magit-mode "Magit Log" + "Mode for looking at Git log. + +This mode is documented in info node `(magit)Log Buffer'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ +to visit the commit at point. + +Type \\[magit-branch-popup] to see available branch commands. +Type \\[magit-merge-popup] to merge the branch or commit at point. +Type \\[magit-cherry-pick-popup] to apply the commit at point. +Type \\[magit-reset] to reset HEAD to the commit at point. + +\\{magit-log-mode-map}" + :group 'magit-log + (hack-dir-local-variables-non-file-buffer)) + +(defvar magit-log-disable-graph-hack-args + '("-G" "--grep" "--author") + "Arguments which disable the graph speedup hack.") + +(defun magit-log-refresh-buffer (revs args files) + (setq header-line-format + (propertize + (concat " Commits in " (mapconcat 'identity revs " ") + (and files (concat " touching " + (mapconcat 'identity files " ")))) + 'face 'magit-header-line)) + (unless (= (length files) 1) + (setq args (remove "--follow" args))) + (when (--any-p (string-match-p + (concat "^" (regexp-opt magit-log-remove-graph-args)) it) + args) + (setq args (remove "--graph" args))) + (unless (member "--graph" args) + (setq args (remove "--color" args))) + (-when-let* ((limit (magit-log-get-commit-limit)) + (limit (* 2 limit)) ; increase odds for complete graph + (count (and (= (length revs) 1) + (> limit 1024) ; otherwise it's fast enough + (setq revs (car revs)) + (not (string-match-p "\\.\\." revs)) + (not (member revs '("--all" "--branches"))) + (-none-p (lambda (arg) + (--any-p (string-prefix-p it arg) + magit-log-disable-graph-hack-args)) + args) + (magit-git-string "rev-list" "--count" + "--first-parent" args revs)))) + (setq revs (if (< (string-to-number count) limit) + revs + (format "%s~%s..%s" revs limit revs)))) + (magit-insert-section (logbuf) + (magit-insert-log revs args files))) + +(defun magit-insert-log (revs &optional args files) + "Insert a log section. +Do not add this to a hook variable." + (magit-git-wash (apply-partially #'magit-log-wash-log 'log) + "log" + (format "--format=%%h%s %s[%%aN][%%at]%%s%s" + (if (member "--decorate" args) "%d" "") + (if (member "--show-signature" args) + (progn (setq args (remove "--show-signature" args)) "%G?") + "") + (if (member "++header" args) + (if (member "--graph" (setq args (delete "++header" args))) + (concat "\n" magit-log-revision-headers-format "\n") + (concat "\n" magit-log-revision-headers-format "\n")) + "")) + (if (member "--decorate" args) + (cons "--decorate=full" (remove "--decorate" args)) + args) + "--use-mailmap" "--no-prefix" revs "--" files)) + +(defvar magit-commit-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-show-commit) + (define-key map "a" 'magit-cherry-apply) + map) + "Keymap for `commit' sections.") + +(defvar magit-module-commit-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-show-commit) + map) + "Keymap for `module-commit' sections.") + +(defconst magit-log-heading-re + (concat "^" + "\\(?4:[-_/|\\*o. ]*\\)" ; graph + "\\(?1:[0-9a-fA-F]+\\) " ; sha1 + "\\(?:\\(?3:([^()]+)\\) \\)?" ; refs + "\\(?7:[BGUN]\\)?" ; gpg + "\\[\\(?5:[^]]*\\)\\]" ; author + "\\[\\(?6:[^]]*\\)\\]" ; date + "\\(?2:.*\\)$")) ; msg + +(defconst magit-log-cherry-re + (concat "^" + "\\(?8:[-+]\\) " ; cherry + "\\(?1:[0-9a-fA-F]+\\) " ; sha1 + "\\(?2:.*\\)$")) ; msg + +(defconst magit-log-module-re + (concat "^" + "\\(?:\\(?11:[<>]\\) \\)?" ; side + "\\(?1:[0-9a-fA-F]+\\) " ; sha1 + "\\(?2:.*\\)$")) ; msg + +(defconst magit-log-bisect-vis-re + (concat "^" + "\\(?1:[0-9a-fA-F]+\\) " ; sha1 + "\\(?:\\(?3:([^()]+)\\) \\)?" ; refs + "\\(?2:.*\\)$")) ; msg + +(defconst magit-log-bisect-log-re + (concat "^# " + "\\(?3:bad:\\|skip:\\|good:\\) " ; "refs" + "\\[\\(?1:[^]]+\\)\\] " ; sha1 + "\\(?2:.*\\)$")) ; msg + +(defconst magit-log-reflog-re + (concat "^" + "\\(?1:[^ ]+\\) " ; sha1 + "\\(?:\\(?:[^@]+@{\\(?6:[^}]+\\)} " ; date + "\\(?10:merge \\|autosave \\|restart \\|[^:]+: \\)?" ; refsub + "\\(?2:.*\\)?\\)\\| \\)$")) ; msg + +(defconst magit-reflog-subject-re + (concat "\\(?1:[^ ]+\\) ?" ; command + "\\(?2:\\(?: ?-[^ ]+\\)+\\)?" ; option + "\\(?: ?(\\(?3:[^)]+\\))\\)?")) ; type + +(defconst magit-log-stash-re + (concat "^" + "\\(?1:[^ ]+\\)" ; "sha1" + "\\(?5: \\)" ; "author" + "\\(?6:[^ ]+\\) " ; date + "\\(?2:.*\\)$")) ; msg + +(defvar magit-log-count nil) + +(defun magit-log-wash-log (style args) + (setq args (-flatten args)) + (when (and (member "--graph" args) + (member "--color" args)) + (let ((ansi-color-apply-face-function + (lambda (beg end face) + (put-text-property beg end 'font-lock-face + (or face 'magit-log-graph))))) + (ansi-color-apply-on-region (point-min) (point-max)))) + (when (eq style 'cherry) + (reverse-region (point-min) (point-max))) + (let ((magit-log-count 0) + (abbrev (magit-abbrev-length))) + (magit-wash-sequence (apply-partially 'magit-log-wash-rev style abbrev)) + (if (derived-mode-p 'magit-log-mode) + (when (eq magit-log-count (magit-log-get-commit-limit)) + (magit-insert-section (longer) + (insert-text-button + (substitute-command-keys + (format "Type \\<%s>\\[%s] to show more history" + 'magit-log-mode-map + 'magit-log-double-commit-limit)) + 'action (lambda (_button) + (magit-log-double-commit-limit)) + 'follow-link t + 'mouse-face 'magit-section-highlight))) + (unless (equal (car args) "cherry") + (insert ?\n))))) + +(defun magit-log-wash-rev (style abbrev) + (when (derived-mode-p 'magit-log-mode) + (cl-incf magit-log-count)) + (looking-at (pcase style + (`log magit-log-heading-re) + (`cherry magit-log-cherry-re) + (`module magit-log-module-re) + (`reflog magit-log-reflog-re) + (`stash magit-log-stash-re) + (`bisect-vis magit-log-bisect-vis-re) + (`bisect-log magit-log-bisect-log-re))) + (magit-bind-match-strings + (hash msg refs graph author date gpg cherry _ refsub side) nil + (let ((align (not (member "--stat" (cadr magit-refresh-args))))) + (magit-delete-line) + (magit-insert-section section (commit hash) + (pcase style + (`stash (setf (magit-section-type section) 'stash)) + (`module (setf (magit-section-type section) 'module-commit)) + (`bisect-log (setq hash (magit-rev-parse "--short" hash)))) + (when cherry + (when (and (derived-mode-p 'magit-refs-mode) + magit-refs-show-commit-count) + (insert (make-string magit-refs-indent-cherry-lines ?\s))) + (insert (propertize cherry 'face (if (string= cherry "-") + 'magit-cherry-equivalent + 'magit-cherry-unmatched))) + (insert ?\s)) + (when side + (insert (propertize side 'face (if (string= side "<") + 'magit-diff-removed + 'magit-diff-added))) + (insert ?\s)) + (when align + (insert (propertize hash 'face 'magit-hash) ?\s)) + (when graph + (insert graph)) + (unless align + (insert (propertize hash 'face 'magit-hash) ?\s)) + (when (and refs (not magit-log-show-refname-after-summary)) + (insert (magit-format-ref-labels refs) ?\s)) + (when refsub + (insert (format "%-2s " (1- magit-log-count))) + (insert (magit-reflog-format-subject + (substring refsub 0 (if (string-match-p ":" refsub) -2 -1))))) + (when msg + (insert (propertize msg 'face + (pcase (and gpg (aref gpg 0)) + (?G 'magit-signature-good) + (?B 'magit-signature-bad) + (?U 'magit-signature-untrusted))))) + (when (and refs magit-log-show-refname-after-summary) + (insert ?\s) + (insert (magit-format-ref-labels refs))) + (insert ?\n) + (when (memq style '(log reflog stash)) + (goto-char (line-beginning-position)) + (when (and refsub + (string-match "\\`\\([^ ]\\) \\+\\(..\\)\\(..\\)" date)) + (setq date (+ (string-to-number (match-string 1 date)) + (* (string-to-number (match-string 2 date)) 60 60) + (* (string-to-number (match-string 3 date)) 60)))) + (save-excursion + (backward-char) + (magit-format-log-margin author date))) + (when (and (eq style 'log) + (not (or (eobp) (looking-at magit-log-heading-re)))) + (when (looking-at "") + (magit-insert-heading) + (delete-char 1) + (magit-insert-section (commit-header) + (forward-line) + (magit-insert-heading) + (re-search-forward "") + (backward-delete-char 1) + (forward-char) + (insert ?\n)) + (delete-char 1)) + (if (looking-at "^\\(---\\|\n\s\\|\ndiff\\)") + (let ((limit (save-excursion + (and (re-search-forward magit-log-heading-re nil t) + (match-beginning 0))))) + (unless (magit-section-content magit-insert-section--current) + (magit-insert-heading)) + (delete-char (if (looking-at "\n") 1 4)) + (magit-diff-wash-diffs (list "--stat") limit)) + (when align + (setq align (make-string (1+ abbrev) ? ))) + (when (and (not (eobp)) (not (looking-at magit-log-heading-re))) + (when align + (setq align (make-string (1+ abbrev) ? ))) + (while (and (not (eobp)) (not (looking-at magit-log-heading-re))) + (when align + (save-excursion (insert align))) + (magit-format-log-margin) + (forward-line)) + ;; When `--format' is used and its value isn't one of the + ;; predefined formats, then `git-log' does not insert a + ;; separator line. + (save-excursion + (forward-line -1) + (looking-at "[-_/|\\*o. ]*")) + (setq graph (match-string 0)) + (unless (string-match-p "[/\\]" graph) + (insert graph ?\n)))))))) + t) + +(defun magit-format-log-margin (&optional author date) + (-let [(width unit-width duration-spec) magit-log-margin-spec] + (when (and date (not author)) + (setq width (+ (if (= unit-width 1) 1 (1+ unit-width)) + (if (derived-mode-p 'magit-log-mode) 1 0)))) + (if date + (magit-make-margin-overlay + (and author + (concat (propertize (truncate-string-to-width + (or author "") + (- width 1 3 ; gap, digits + (if (= unit-width 1) 1 (1+ unit-width)) + (if (derived-mode-p 'magit-log-mode) 1 0)) + nil ?\s (make-string 1 magit-ellipsis)) + 'face 'magit-log-author) + " ")) + (propertize (magit-format-duration + (abs (truncate (- (float-time) + (string-to-number date)))) + (symbol-value duration-spec) + unit-width) + 'face 'magit-log-date) + (and (derived-mode-p 'magit-log-mode) + (propertize " " 'face 'fringe))) + (magit-make-margin-overlay + (propertize (make-string (1- width) ?\s) 'face 'default) + (propertize " " 'face 'fringe))))) + +(defun magit-format-duration (duration spec &optional width) + (-let [(char unit units weight) (car spec)] + (let ((cnt (round (/ duration weight 1.0)))) + (if (or (not (cdr spec)) + (>= (/ duration weight) 1)) + (if (eq width 1) + (format "%3i%c" cnt char) + (format (if width (format "%%3i %%-%is" width) "%i %s") + cnt (if (= cnt 1) unit units))) + (magit-format-duration duration (cdr spec) width))))) + +(defun magit-log-maybe-show-more-commits (section) + "Automatically insert more commit sections in a log. +Only do so if `point' is on the \"show more\" section, +and `magit-log-auto-more' is non-nil." + (when (and (eq (magit-section-type section) 'longer) + magit-log-auto-more) + (magit-log-double-commit-limit) + (forward-line -1) + (magit-section-forward))) + +(defvar magit--update-revision-buffer nil) + +(defun magit-log-maybe-update-revision-buffer (&optional _) + "When moving in the log buffer, update the revision buffer. +If there is no revision buffer in the same frame, then do nothing." + (when (derived-mode-p 'magit-log-mode) + (magit-log-maybe-update-revision-buffer-1))) + +(defun magit-log-maybe-update-revision-buffer-1 () + (unless magit--update-revision-buffer + (-when-let* ((commit (magit-section-when 'commit)) + (buffer (magit-mode-get-buffer 'magit-revision-mode nil t))) + (setq magit--update-revision-buffer (list commit buffer)) + (run-with-idle-timer + magit-update-other-window-delay nil + (lambda () + (-let [(rev buf) magit--update-revision-buffer] + (setq magit--update-revision-buffer nil) + (when (buffer-live-p buf) + (let ((magit-display-buffer-noselect t)) + (apply #'magit-show-commit rev (magit-diff-arguments))))) + (setq magit--update-revision-buffer nil)))))) + +(defvar magit--update-blob-buffer nil) + +(defun magit-log-maybe-update-blob-buffer (&optional _) + "When moving in the log buffer, update the blob buffer. +If there is no blob buffer in the same frame, then do nothing." + (when (derived-mode-p 'magit-log-mode) + (magit-log-maybe-update-blob-buffer-1))) + +(defun magit-log-maybe-update-blob-buffer-1 () + (unless magit--update-revision-buffer + (-when-let* ((commit (magit-section-when 'commit)) + (buffer (--first (with-current-buffer it magit-buffer-revision) + (-map #'window-buffer (window-list))))) + (setq magit--update-blob-buffer (list commit buffer)) + (run-with-idle-timer + magit-update-other-window-delay nil + (lambda () + (-let [(rev buf) magit--update-blob-buffer] + (setq magit--update-blob-buffer nil) + (when (buffer-live-p buf) + (save-excursion + (with-selected-window (get-buffer-window buf) + (with-current-buffer buf + (magit-blob-visit (list (magit-rev-parse rev) + (magit-file-relative-name + magit-buffer-file-name)) + (line-number-at-pos)))))))))))) + +(defun magit-log-goto-same-commit () + (-when-let* ((prev magit-previous-section) + (rev (cond ((magit-section-match 'commit prev) + (magit-section-value prev)) + ((magit-section-match 'branch prev) + (magit-rev-format + "%h" (magit-section-value prev))))) + (same (--first (equal (magit-section-value it) rev) + (magit-section-children magit-root-section)))) + (goto-char (magit-section-start same)))) + +;;; Select Mode + +(defvar magit-log-select-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-log-mode-map) + (define-key map "\C-c\C-b" 'undefined) + (define-key map "\C-c\C-f" 'undefined) + (define-key map "." 'magit-log-select-pick) + (define-key map "e" 'magit-log-select-pick) + (define-key map "\C-c\C-c" 'magit-log-select-pick) + (define-key map "q" 'magit-log-select-quit) + (define-key map "\C-c\C-k" 'magit-log-select-quit) + map) + "Keymap for `magit-log-select-mode'.") + +(put 'magit-log-select-pick :advertised-binding [?\C-c ?\C-c]) +(put 'magit-log-select-quit :advertised-binding [?\C-c ?\C-k]) + +(define-derived-mode magit-log-select-mode magit-log-mode "Magit Select" + "Mode for selecting a commit from history. + +This mode is documented in info node `(magit)Select from log'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ +to visit the commit at point. + +\\\ +Type \\[magit-log-select-pick] to select the commit at point. +Type \\[magit-log-select-quit] to abort without selecting a commit." + :group 'magit-log + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-log-select-refresh-buffer (rev args) + (magit-insert-section (logbuf) + (magit-insert-log rev args))) + +(defvar-local magit-log-select-pick-function nil) +(defvar-local magit-log-select-quit-function nil) + +(defun magit-log-select (pick &optional msg quit branch) + (declare (indent defun)) + (magit-mode-setup #'magit-log-select-mode + (or branch (magit-get-current-branch) "HEAD") + magit-log-select-arguments) + (magit-log-goto-same-commit) + (setq magit-log-select-pick-function pick) + (setq magit-log-select-quit-function quit) + (when magit-log-select-show-usage + (setq msg (substitute-command-keys + (format-spec + (if msg + (if (string-suffix-p "," msg) + (concat msg " or %q to abort") + msg) + "Type %p to select commit at point, or %q to abort") + '((?p . "\\[magit-log-select-pick]") + (?q . "\\[magit-log-select-quit]"))))) + (when (memq magit-log-select-show-usage '(both header-line)) + (setq header-line-format (propertize (concat " " msg) 'face 'bold))) + (when (memq magit-log-select-show-usage '(both echo-area)) + (message "%s" msg)))) + +(defun magit-log-select-pick () + "Select the commit at point and act on it. +Call `magit-log-select-pick-function' with the selected +commit as argument." + (interactive) + (let ((fun magit-log-select-pick-function) + (rev (magit-commit-at-point))) + (kill-buffer (current-buffer)) + (funcall fun rev))) + +(defun magit-log-select-quit () + "Abort selecting a commit, don't act on any commit." + (interactive) + (kill-buffer (current-buffer)) + (when magit-log-select-quit-function + (funcall magit-log-select-quit-function))) + +;;; Cherry Mode + +(defvar magit-cherry-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + (define-key map "q" 'magit-log-bury-buffer) + (define-key map "L" 'magit-toggle-margin) + map) + "Keymap for `magit-cherry-mode'.") + +(define-derived-mode magit-cherry-mode magit-mode "Magit Cherry" + "Mode for looking at commits not merged upstream. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ +to visit the commit at point. + +Type \\[magit-cherry-pick-popup] to apply the commit at point. + +\\{magit-cherry-mode-map}" + :group 'magit-log + (hack-dir-local-variables-non-file-buffer)) + +;;;###autoload +(defun magit-cherry (head upstream) + "Show commits in a branch that are not merged in the upstream branch." + (interactive + (let ((head (magit-read-branch "Cherry head"))) + (list head (magit-read-other-branch "Cherry upstream" head + (magit-get-upstream-branch head))))) + (magit-mode-setup #'magit-cherry-mode upstream head)) + +(defun magit-cherry-refresh-buffer (_upstream _head) + (magit-insert-section (cherry) + (run-hooks 'magit-cherry-sections-hook))) + +(defun magit-insert-cherry-headers () + "Insert headers appropriate for `magit-cherry-mode' buffers." + (magit-insert-head-branch-header (nth 1 magit-refresh-args)) + (magit-insert-upstream-branch-header (nth 1 magit-refresh-args) + (nth 0 magit-refresh-args) + "Upstream: ") + (insert ?\n)) + +(defun magit-insert-cherry-commits () + "Insert commit sections into a `magit-cherry-mode' buffer." + (magit-insert-section (cherries) + (magit-insert-heading "Cherry commits:") + (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) + "cherry" "-v" "--abbrev" magit-refresh-args))) + +;;; Reflog Mode + +(defvar magit-reflog-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-log-mode-map) + (define-key map "L" 'magit-toggle-margin) + map) + "Keymap for `magit-reflog-mode'.") + +(define-derived-mode magit-reflog-mode magit-log-mode "Magit Reflog" + "Mode for looking at Git reflog. + +This mode is documented in info node `(magit)Reflog'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ +to visit the commit at point. + +Type \\[magit-cherry-pick-popup] to apply the commit at point. +Type \\[magit-reset] to reset HEAD to the commit at point. + +\\{magit-reflog-mode-map}" + :group 'magit-log + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-reflog-refresh-buffer (ref args) + (setq header-line-format + (propertize (concat " Reflog for " ref) 'face 'magit-header-line)) + (magit-insert-section (reflogbuf) + (magit-git-wash (apply-partially 'magit-log-wash-log 'reflog) + "reflog" "show" "--format=%h %gd %gs" "--date=raw" args ref))) + +(defvar magit-reflog-labels + '(("commit" . magit-reflog-commit) + ("amend" . magit-reflog-amend) + ("merge" . magit-reflog-merge) + ("checkout" . magit-reflog-checkout) + ("branch" . magit-reflog-checkout) + ("reset" . magit-reflog-reset) + ("rebase" . magit-reflog-rebase) + ("cherry-pick" . magit-reflog-cherry-pick) + ("initial" . magit-reflog-commit) + ("pull" . magit-reflog-remote) + ("clone" . magit-reflog-remote) + ("autosave" . magit-reflog-commit) + ("restart" . magit-reflog-reset))) + +(defun magit-reflog-format-subject (subject) + (let* ((match (string-match magit-reflog-subject-re subject)) + (command (and match (match-string 1 subject))) + (option (and match (match-string 2 subject))) + (type (and match (match-string 3 subject))) + (label (if (string= command "commit") + (or type command) + command)) + (text (if (string= command "commit") + label + (mapconcat #'identity + (delq nil (list command option type)) + " ")))) + (format "%-16s " + (propertize text 'face + (or (cdr (assoc label magit-reflog-labels)) + 'magit-reflog-other))))) + +;;; Log Sections +;;;; Standard Log Sections + +(defvar magit-unpulled-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-diff-dwim) + map) + "Keymap for `unpulled' sections.") + +(magit-define-section-jumper magit-jump-to-unpulled-from-upstream + "Unpulled from @{upstream}" unpulled "..@{upstream}") + +(defun magit-insert-unpulled-from-upstream () + "Insert commits that haven't been pulled from the upstream yet." + (when (magit-git-success "rev-parse" "@{upstream}") + (magit-insert-section (unpulled "..@{upstream}") + (magit-insert-heading + (format (propertize "Unpulled from %s:" 'face 'magit-section-heading) + (magit-get-upstream-branch))) + (magit-insert-log "..@{upstream}" magit-log-section-arguments) + (magit-section-cache-visibility)))) + +(magit-define-section-jumper magit-jump-to-unpulled-from-pushremote + "Unpulled from " unpulled + (concat ".." (magit-get-push-branch))) + +(defun magit-insert-unpulled-from-pushremote () + "Insert commits that haven't been pulled from the push-remote yet." + (--when-let (magit-get-push-branch) + (unless (equal (magit-rev-name it) + (magit-rev-name "@{upstream}")) + (magit-insert-section (unpulled (concat ".." it)) + (magit-insert-heading + (format (propertize "Unpulled from %s:" 'face 'magit-section-heading) + (propertize it 'face 'magit-branch-remote))) + (magit-insert-log (concat ".." it) magit-log-section-arguments) + (magit-section-cache-visibility))))) + +(defvar magit-unpushed-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-diff-dwim) + map) + "Keymap for `unpushed' sections.") + +(magit-define-section-jumper magit-jump-to-unpushed-to-upstream + "Unpushed to @{upstream}" unpushed "@{upstream}..") + +(defun magit-insert-unpushed-to-upstream () + "Insert commits that haven't been pushed to the upstream yet." + (when (magit-git-success "rev-parse" "@{upstream}") + (magit-insert-section (unpushed "@{upstream}..") + (magit-insert-heading + (format (propertize "Unpushed to %s:" 'face 'magit-section-heading) + (magit-get-upstream-branch))) + (magit-insert-log "@{upstream}.." magit-log-section-arguments) + (magit-section-cache-visibility)))) + +(magit-define-section-jumper magit-jump-to-unpushed-to-pushremote + "Unpushed to " unpushed + (concat (magit-get-push-branch) "..")) + +(defun magit-insert-unpushed-to-pushremote () + "Insert commits that haven't been pushed to the push-remote yet." + (--when-let (magit-get-push-branch) + (unless (equal (magit-rev-name it) + (magit-rev-name "@{upstream}")) + (magit-insert-section (unpushed (concat it "..")) + (magit-insert-heading + (format (propertize "Unpushed to %s:" 'face 'magit-section-heading) + (propertize it 'face 'magit-branch-remote))) + (magit-insert-log (concat it "..") magit-log-section-arguments) + (magit-section-cache-visibility))))) + +;;;; Auxiliary Log Sections + +(defun magit-insert-recent-commits (&optional collapse) + "Insert section showing recent commits. +Show the last `magit-log-section-commit-count' commits." + (let* ((start (format "HEAD~%s" magit-log-section-commit-count)) + (range (and (magit-rev-verify start) + (concat start "..HEAD")))) + (magit-insert-section (recent range collapse) + (magit-insert-heading "Recent commits:") + (magit-insert-log range + (cons (format "-%d" magit-log-section-commit-count) + magit-log-section-arguments))))) + +(defun magit-insert-unpulled-or-recent-commits () + "Insert section showing unpulled or recent commits. +If an upstream is configured for the current branch and it is +ahead of the current branch, then show the missing commits, +otherwise show the last `magit-log-section-commit-count' +commits." + (if (equal (magit-rev-parse "HEAD") + (magit-rev-parse "@{upstream}")) + (magit-insert-recent-commits t) + (magit-insert-unpulled-from-pushremote))) + +(defun magit-insert-unpulled-cherries () + "Insert section showing unpulled commits. +Like `magit-insert-unpulled-to-upstream' but prefix each commit +which has not been applied yet (i.e. a commit with a patch-id +not shared with any local commit) with \"+\", and all others with +\"-\"." + (when (magit-git-success "rev-parse" "@{upstream}") + (magit-insert-section (unpulled "..@{upstream}") + (magit-insert-heading "Unpulled commits:") + (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) + "cherry" "-v" (magit-abbrev-arg) + (magit-get-current-branch) "@{upstream}")))) + +(defun magit-insert-unpushed-cherries () + "Insert section showing unpushed commits. +Like `magit-insert-unpushed-to-upstream' but prefix each commit +which has not been applied to upstream yet (i.e. a commit with +a patch-id not shared with any upstream commit) with \"+\", and +all others with \"-\"." + (when (magit-git-success "rev-parse" "@{upstream}") + (magit-insert-section (unpushed "@{upstream}..") + (magit-insert-heading "Unpushed commits:") + (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) + "cherry" "-v" (magit-abbrev-arg) "@{upstream}")))) + +;;;; Submodule Sections + +(defun magit-insert-submodule-commits (section range) + "For internal use, don't add to a hook." + (if (magit-section-hidden section) + (setf (magit-section-washer section) + (apply-partially #'magit-insert-submodule-commits section range)) + (magit-git-wash (apply-partially 'magit-log-wash-log 'module) + "log" "--oneline" range) + (when (> (point) (magit-section-content section)) + (delete-char -1)))) + +(defun magit-insert-unpulled-module-commits () + "Insert sections for all submodules with unpulled commits. +These sections can be expanded to show the respective commits." + (-when-let (modules (magit-get-submodules)) + (magit-insert-section section (unpulled-modules) + (magit-insert-heading "Unpulled modules:") + (magit-with-toplevel + (dolist (module modules) + (let ((default-directory + (expand-file-name (file-name-as-directory module)))) + (-when-let (tracked (magit-get-upstream-ref)) + (magit-insert-section sec (file module t) + (magit-insert-heading + (concat (propertize module 'face 'magit-diff-file-heading) ":")) + (magit-insert-submodule-commits + section (concat "HEAD.." tracked))))))) + (if (> (point) (magit-section-content section)) + (insert ?\n) + (magit-cancel-section))))) + +(defun magit-insert-unpushed-module-commits () + "Insert sections for all submodules with unpushed commits. +These sections can be expanded to show the respective commits." + (-when-let (modules (magit-get-submodules)) + (magit-insert-section section (unpushed-modules) + (magit-insert-heading "Unpushed modules:") + (magit-with-toplevel + (dolist (module modules) + (let ((default-directory + (expand-file-name (file-name-as-directory module)))) + (-when-let (tracked (magit-get-upstream-ref)) + (magit-insert-section sec (file module t) + (magit-insert-heading + (concat (propertize module 'face 'magit-diff-file-heading) ":")) + (magit-insert-submodule-commits + section (concat tracked "..HEAD"))))))) + (if (> (point) (magit-section-content section)) + (insert ?\n) + (magit-cancel-section))))) + +;;; Buffer Margins + +(defvar-local magit-set-buffer-margin-refresh nil) + +(defvar-local magit-show-margin nil) +(put 'magit-show-margin 'permanent-local t) + +(defun magit-toggle-margin () + "Show or hide the Magit margin." + (interactive) + (unless (derived-mode-p 'magit-log-mode 'magit-status-mode 'magit-refs-mode) + (user-error "Buffer doesn't contain any logs")) + (magit-set-buffer-margin (not (cdr (window-margins))))) + +(defun magit-maybe-show-margin () + "Maybe show the margin, depending on the major-mode and an option. +Supported modes are `magit-log-mode' and `magit-reflog-mode', +and the respective options are `magit-log-show-margin' and +`magit-reflog-show-margin'." + (pcase major-mode + (`magit-log-mode (magit-set-buffer-margin magit-log-show-margin)) + (`magit-reflog-mode (magit-set-buffer-margin magit-reflog-show-margin)))) + +(defun magit-set-buffer-margin (enable) + (let ((width (cond ((not enable) nil) + ((derived-mode-p 'magit-reflog-mode) + (+ (cadr magit-log-margin-spec) 5)) + (t (car magit-log-margin-spec))))) + (setq magit-show-margin width) + (when (and enable magit-set-buffer-margin-refresh) + (magit-refresh)) + (-when-let (window (get-buffer-window)) + (with-selected-window window + (set-window-margins nil (car (window-margins)) width) + (if enable + (add-hook 'window-configuration-change-hook + 'magit-set-buffer-margin-1 nil t) + (remove-hook 'window-configuration-change-hook + 'magit-set-buffer-margin-1 t)))))) + +(defun magit-set-buffer-margin-1 () + (-when-let (window (get-buffer-window)) + (with-selected-window window + (set-window-margins nil (car (window-margins)) magit-show-margin)))) + +(defun magit-make-margin-overlay (&rest strings) + ;; Don't put the overlay on the complete line to work around #1880. + (let ((o (make-overlay (1+ (line-beginning-position)) + (line-end-position) + nil t))) + (overlay-put o 'evaporate t) + (overlay-put o 'before-string + (propertize "o" 'display + (list '(margin right-margin) + (apply #'concat strings)))))) + +;;; magit-log.el ends soon +(provide 'magit-log) +;; Local Variables: +;; coding: utf-8 +;; indent-tabs-mode: nil +;; End: +;;; magit-log.el ends here diff --git a/elpa/magit-20151223.1425/magit-mode.el b/elpa/magit-20151223.1425/magit-mode.el new file mode 100644 index 00000000..158e953f --- /dev/null +++ b/elpa/magit-20151223.1425/magit-mode.el @@ -0,0 +1,1102 @@ +;;; magit-mode.el --- create and refresh Magit buffers -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library implements the abstract major-mode `magit-mode' from +;; which almost all other Magit major-modes derive. The code in here +;; is mostly concerned with creating and refreshing Magit buffers. + +;;; Code: + +(require 'cl-lib) +(require 'dash) + +(require 'magit-section) +(require 'magit-git) + +;; For `magit-xref-insert-buttons' from `magit' +(defvar magit-diff-show-xref-buttons) +(defvar magit-revision-show-xref-buttons) +;; For `magit-revert-buffers' +(declare-function magit-blame-mode 'magit-blame) +(defvar magit-blame-mode) + +(require 'format-spec) +(require 'help-mode) + +;;; Options + +(defcustom magit-mode-hook + '(magit-load-config-extensions + magit-xref-setup) + "Hook run when entering a mode derived from Magit mode." + :group 'magit-modes + :type 'hook + :options '(magit-load-config-extensions + magit-xref-setup + bug-reference-mode)) + +(defcustom magit-mode-setup-hook + '(magit-maybe-save-repository-buffers + magit-maybe-show-margin) + "Hook run by `magit-mode-setup'." + :package-version '(magit . "2.3.0") + :group 'magit-modes + :type 'hook + :options '(magit-maybe-save-repository-buffers + magit-maybe-show-margin)) + +(defcustom magit-display-buffer-function 'magit-display-buffer-traditional + "The function used display a Magit buffer. + +All Magit buffers (buffers whose major-modes derive from +`magit-mode') are displayed using `magit-display-buffer', +which in turn uses the function specified here." + :package-version '(magit . "2.3.0") + :group 'magit-modes + :type '(radio (function-item magit-display-buffer-traditional) + (function-item display-buffer) + (function :tag "Function"))) + +(unless (find-lisp-object-file-name 'magit-pre-display-buffer-hook 'defvar) + (add-hook 'magit-pre-display-buffer-hook 'magit-save-window-configuration)) +(defcustom magit-pre-display-buffer-hook '(magit-save-window-configuration) + "Hook run by `magit-display-buffer' before displaying the buffer." + :package-version '(magit . "2.3.0") + :group 'magit-modes + :type 'hook + :options '(magit-save-window-configuration)) + +(unless (find-lisp-object-file-name 'magit-post-display-buffer-hook 'defvar) + (add-hook 'magit-post-display-buffer-hook 'magit-maybe-set-dedicated)) +(defcustom magit-post-display-buffer-hook '(magit-maybe-set-dedicated) + "Hook run by `magit-display-buffer' after displaying the buffer." + :package-version '(magit . "2.3.0") + :group 'magit-modes + :type 'hook + :options '(magit-maybe-set-dedicated)) + +(defcustom magit-generate-buffer-name-function + 'magit-generate-buffer-name-default-function + "The function used to generate the name for a Magit buffer." + :package-version '(magit . "2.3.0") + :group 'magit-modes + :type '(radio (function-item magit-generate-buffer-name-default-function) + (function :tag "Function"))) + +(defcustom magit-buffer-name-format "*%M%v: %t" + "The format string used to name Magit buffers. + +The following %-sequences are supported: + +`%m' The name of the major-mode, but with the `-mode' suffix + removed. + +`%M' Like \"%m\" but abbreviate `magit-status-mode' as `magit'. + +`%v' The value the buffer is locked to, in parentheses, or an empty + string if the buffer is not locked to a value. + +`%V' Like \"%v\", but the string is prefixed with a space, unless it + is an empty string. + +`%t' The top-level directory of the working tree of the + repository, or if `magit-uniquify-buffer-names' is non-nil + an abbreviation of that. + +The value should always contain either \"%m\" or \"%M\" as well as +\"%t\". If `magit-uniquify-buffer-names' is non-nil, then the +value must end with \"%t\". + +This is used by `magit-generate-buffer-name-default-function'. +If another `magit-generate-buffer-name-function' is used, then +it may not respect this option, or on the contrary it may +support additional %-sequences." + :package-version '(magit . "2.3.0") + :group 'magit-modes + :type 'string) + +(defcustom magit-uniquify-buffer-names t + "Whether to uniquify the names of Magit buffers." + :package-version '(magit . "2.3.0") + :group 'magit-modes + :type 'boolean) + +(defcustom magit-bury-buffer-function 'magit-restore-window-configuration + "The function used to bury or kill the current Magit buffer." + :package-version '(magit . "2.3.0") + :group 'magit-modes + :type '(radio (function-item quit-window) + (function-item magit-mode-quit-window) + (function-item magit-restore-window-configuration) + (function :tag "Function"))) + +(defcustom magit-region-highlight-hook + '(magit-section-update-region magit-diff-update-hunk-region) + "Functions used to highlight the region. +Each function is run with the current section as only argument +until one of them returns non-nil. When multiple sections are +selected, then this hook does not run and the region is not +displayed. Otherwise fall back to regular region highlighting." + :package-version '(magit . "2.1.0") + :group 'magit-modes + :type 'hook + :options '(magit-section-update-region magit-diff-update-hunk-region)) + +(defcustom magit-refresh-verbose nil + "Whether to revert Magit buffers verbosely." + :package-version '(magit . "2.1.0") + :group 'magit-modes + :type 'boolean) + +(defcustom magit-refresh-buffer-hook nil + "Normal hook for `magit-refresh-buffer' to run after refreshing." + :package-version '(magit . "2.1.0") + :group 'magit-modes + :type 'hook) + +(defvar magit-revert-buffers-timer nil) + +(defun magit-revert-buffers-set-timer () + (when (timerp magit-revert-buffers-timer) + (cancel-timer magit-revert-buffers-timer)) + (setq magit-revert-buffers-timer + (and (boundp 'magit-revert-buffers) + (numberp magit-revert-buffers) + (run-with-timer 0 (abs magit-revert-buffers) + 'magit-revert-buffers-async)))) + +(defcustom magit-revert-buffers 'usage + "How file-visiting buffers in the current repository are reverted. + +After running certain commands, after refreshing the current +Magit buffer, unmodified buffers visiting files belonging to +the current repository may optionally be reverted. + +`nil' Don't revert any buffers. + +`ask' List the buffers which might potentially have to be + reverted and ask the user whether she wants to revert + them. If so, then do it synchronously. + +`t' Revert the buffers synchronously, mentioning each one + as it is being reverted and then also show a summary. + +`usage' Like `t' but include usage information in the summary. + This is the default so that users come here and pick + what is right for them. + +`silent' Revert the buffers synchronously and be quiet about it. + This (or a negative number) is the recommended setting, + because for the other values the revert messages might + prevent you from seeing other, more important, messages + in the echo area. + +NUMBER An integer or float. Revert the buffers asynchronously. + If NUMBER is positive, then mention each buffer as it is + being reverted. If it is negative, then be quiet about + it. If user input arrives, then stop reverting. After + (the absolute value of) NUMBER seconds resume reverting." + :package-version '(magit . "2.1.0") + :group 'magit + :type '(choice + (const :tag "Don't revert" nil) + (const :tag "Ask whether to revert" ask) + (const :tag "Revert synchronously" t) + (const :tag "Revert synchronously but in silence" silent) + (const :tag "Revert synchronously with usage information" usage) + (integer :tag "Revert asynchronously (interval in seconds)")) + :set (lambda (var val) + (set-default var val) + (magit-revert-buffers-set-timer))) + +(defcustom magit-after-revert-hook '(magit-refresh-vc-mode-line) + "Normal hook for `magit-revert-buffer' to run after reverting. + +This hook is only run for buffers that were actually reverted. +For other buffers `magit-not-reverted-hook' is run instead." + :package-version '(magit . "2.1.0") + :group 'magit-modes + :type 'hook + :options '(magit-refresh-vc-mode-line)) + +(defcustom magit-not-reverted-hook '(magit-refresh-vc-mode-line) + "Normal hook for `magit-revert-buffer' to run instead of reverting. + +This hook is only run for buffers which might have been reverted +but were not actually reverted, because that was not necessary. +For other buffers `magit-after-revert-hook' is run instead." + :package-version '(magit . "2.1.0") + :group 'magit-modes + :type 'hook + :options '(magit-refresh-vc-mode-line)) + +(defcustom magit-save-repository-buffers t + "Whether to save file-visiting buffers when appropriate. + +If this is non-nil then all modified file-visiting buffers +belonging to the current repository may be saved before running +commands, before creating new Magit buffers, and before +explicitly refreshing such buffers. If this is `dontask' then +this is done without user intervention, if it is t then the user +has to confirm each save. `dontask' is the recommended setting." + :group 'magit + :type '(choice (const :tag "Never" nil) + (const :tag "Ask" t) + (const :tag "Save without asking" dontask))) + +(defcustom magit-keep-region-overlay nil + "Whether to keep the region overlay when there is a valid selection. + +By default Magit removes the regular region overlay if, and only +if, that region constitutes a valid selection as understood by +Magit commands. Otherwise it does not remove that overlay, and +the region looks like it would in other buffers. + +There are two types of such valid selections: hunk-internal +regions and regions that select two or more sibling sections. +In such cases Magit removes the region overlay and instead +highlights a slightly larger range. All text (for hunk-internal +regions) or the headings of all sections (for sibling selections) +that are inside that range (not just inside the region) are acted +on by commands such as the staging command. This buffer range +begins at the beginning of the line on which the region begins +and ends at the end of the line on which the region ends. + +Because Magit acts on this larger range and not the region, it is +actually quite important to visualize that larger range. If we +don't do that, then one might think that these commands act on +the region instead. If you want to *also* visualize the region, +then set this option to t. But please note that when the region +does *not* constitute a valid selection, then the region is +*always* visualized as usual, and that it is usually under such +circumstances that you want to use a non-magit command to act on +the region. + +Besides keeping the region overlay, setting this option to t also +causes all face properties, except for `:foreground', to be +ignored for the faces used to highlight headings of selected +sections. This avoids the worst conflicts that result from +displaying the region and the selection overlays at the same +time. We are not interested in dealing with other conflicts. +In fact we *already* provide a way to avoid all of these +conflicts: *not* changing the value of this option. + +It should be clear by now that we consider it a mistake to set +this to display the region when the Magit selection is also +visualized, but since it has been requested a few times and +because it doesn't cost much to offer this option we do so. +However that might change. If the existence of this option +starts complicating other things, then it will be removed." + :package-version '(magit . "2.3.0") + :group 'magit-modes + :type 'boolean) + +;;; Magit Mode + +(defvar magit-mode-map + (let ((map (make-keymap))) + (suppress-keymap map t) + (define-key map "\t" 'magit-section-toggle) + (define-key map [C-tab] 'magit-section-cycle) + (define-key map [M-tab] 'magit-section-cycle-diffs) + (define-key map [s-tab] 'magit-section-cycle-global) + (define-key map [backtab] 'magit-section-cycle-global) + (define-key map "^" 'magit-section-up) + (define-key map "n" 'magit-section-forward) + (define-key map "p" 'magit-section-backward) + (define-key map "\M-n" 'magit-section-forward-sibling) + (define-key map "\M-p" 'magit-section-backward-sibling) + (define-key map "+" 'magit-diff-more-context) + (define-key map "-" 'magit-diff-less-context) + (define-key map "0" 'magit-diff-default-context) + (define-key map "1" 'magit-section-show-level-1) + (define-key map "2" 'magit-section-show-level-2) + (define-key map "3" 'magit-section-show-level-3) + (define-key map "4" 'magit-section-show-level-4) + (define-key map "\M-1" 'magit-section-show-level-1-all) + (define-key map "\M-2" 'magit-section-show-level-2-all) + (define-key map "\M-3" 'magit-section-show-level-3-all) + (define-key map "\M-4" 'magit-section-show-level-4-all) + (define-key map "g" 'magit-refresh) + (define-key map "G" 'magit-refresh-all) + (define-key map "q" 'magit-mode-bury-buffer) + (define-key map "$" 'magit-process-buffer) + (define-key map "a" 'magit-cherry-apply) + (define-key map "A" 'magit-cherry-pick-popup) + (define-key map "b" 'magit-branch-popup) + (define-key map "B" 'magit-bisect-popup) + (define-key map "c" 'magit-commit-popup) + (define-key map "d" 'magit-diff-popup) + (define-key map "D" 'magit-diff-refresh-popup) + (define-key map "h" 'magit-dispatch-popup) + (define-key map "?" 'magit-dispatch-popup) + (define-key map "\C-c\C-c" 'magit-dispatch-popup) + (define-key map "\C-c\C-e" 'magit-dispatch-popup) + (define-key map "e" 'magit-ediff-dwim) + (define-key map "E" 'magit-ediff-popup) + (define-key map "f" 'magit-fetch-popup) + (define-key map "F" 'magit-pull-popup) + (define-key map "i" 'magit-gitignore) + (define-key map "I" 'magit-gitignore-locally) + (define-key map "k" 'magit-delete-thing) + (define-key map "K" 'magit-file-untrack) + (define-key map "l" 'magit-log-popup) + (define-key map "L" 'magit-log-refresh-popup) + (define-key map "m" 'magit-merge-popup) + (define-key map "M" 'magit-remote-popup) + (define-key map "o" 'magit-submodule-popup) + (define-key map "P" 'magit-push-popup) + (define-key map "r" 'magit-rebase-popup) + (define-key map "R" 'magit-file-rename) + (define-key map "t" 'magit-tag-popup) + (define-key map "T" 'magit-notes-popup) + (define-key map "\r" 'magit-visit-thing) + (define-key map [C-return] 'magit-visit-thing) + (define-key map [M-return] 'magit-dired-jump) + (define-key map "\s" 'magit-diff-show-or-scroll-up) + (define-key map "\d" 'magit-diff-show-or-scroll-down) + (define-key map "s" 'magit-stage-file) + (define-key map "S" 'magit-stage-modified) + (define-key map "u" 'magit-unstage-file) + (define-key map "U" 'magit-unstage-all) + (define-key map "v" 'magit-revert-no-commit) + (define-key map "V" 'magit-revert-popup) + (define-key map "w" 'magit-am-popup) + (define-key map "W" 'magit-patch-popup) + (define-key map "x" 'magit-reset) + (define-key map "y" 'magit-show-refs-popup) + (define-key map "Y" 'magit-cherry) + (define-key map "z" 'magit-stash-popup) + (define-key map "Z" 'magit-stash-popup) + (define-key map ":" 'magit-git-command) + (define-key map "!" 'magit-run-popup) + (define-key map "\C-xa" 'magit-add-change-log-entry) + (define-key map "\C-x4a" 'magit-add-change-log-entry-other-window) + (define-key map "\C-w" 'magit-copy-section-value) + (define-key map "\M-w" 'magit-copy-buffer-revision) + (define-key map [remap evil-previous-line] 'evil-previous-visual-line) + (define-key map [remap evil-next-line] 'evil-next-visual-line) + map) + "Parent keymap for all keymaps of modes derived from `magit-mode'.") + +(defun magit-delete-thing () + "This is a placeholder command. +Where applicable, section-specific keymaps bind another command +which deletes the thing at point." + (interactive) + (user-error "There is no thing at point that could be deleted")) + +(defun magit-visit-thing () + "This is a placeholder command. +Where applicable, section-specific keymaps bind another command +which visits the thing at point." + (interactive) + (user-error "There is no thing at point that could be visited")) + +(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 t] + ["Stage modified" magit-stage-modified t] + ["Unstage" magit-unstage t] + ["Reset index" magit-reset-index t] + ["Commit" magit-commit-popup t] + ["Add log entry" magit-commit-add-log t] + ["Tag" magit-tag t] + "---" + ["Diff working tree" magit-diff-working-tree t] + ["Diff" magit-diff t] + ("Log" + ["Log" magit-log t] + ["Reflog" magit-reflog t] + ["Extended..." magit-log-popup t]) + "---" + ["Cherry pick" magit-cherry-pick t] + ["Revert commit" magit-revert-popup t] + "---" + ["Ignore" magit-gitignore t] + ["Ignore locally" magit-gitignore-locally t] + ["Discard" magit-discard t] + ["Reset head" magit-reset-head t] + ["Stash" magit-stash t] + ["Snapshot" magit-snapshot t] + "---" + ["Branch..." magit-checkout t] + ["Merge" magit-merge t] + ["Ediff resolve" magit-ediff-resolve t] + ["Rebase..." magit-rebase-popup t] + "---" + ["Push" magit-push t] + ["Pull" magit-pull t] + ["Remote update" magit-fetch-all t] + ("Submodule" + ["Submodule update" magit-submodule-update t] + ["Submodule update and init" magit-submodule-setup t] + ["Submodule init" magit-submodule-init t] + ["Submodule sync" magit-submodule-sync t]) + "---" + ("Extensions") + "---" + ["Display Git output" magit-process-buffer t] + ["Quit Magit" magit-mode-bury-buffer t])) + +(defun magit-load-config-extensions () + "Load Magit extensions that are defined at the Git config layer." + (dolist (ext (magit-get-all "magit.extension")) + (let ((sym (intern (format "magit-%s-mode" ext)))) + (when (fboundp sym) + (funcall sym 1))))) + +(define-derived-mode magit-mode special-mode "Magit" + "Parent major mode from which Magit major modes inherit. + +Magit is documented in info node `(magit)'." + :group 'magit-modes + (buffer-disable-undo) + (setq truncate-lines t) + (setq buffer-read-only t) + (setq-local line-move-visual t) ; see #1771 + (setq show-trailing-whitespace nil) + (setq list-buffers-directory default-directory) + (hack-dir-local-variables-non-file-buffer) + (make-local-variable 'text-property-default-nonsticky) + (push (cons 'keymap t) text-property-default-nonsticky) + (add-hook 'post-command-hook #'magit-section-update-highlight t t) + (setq-local redisplay-highlight-region-function 'magit-highlight-region) + (setq-local redisplay-unhighlight-region-function 'magit-unhighlight-region) + (when (fboundp 'linum-mode) + (linum-mode -1))) + +(defvar-local magit-region-overlays nil) + +(defun magit-highlight-region (start end window rol) + (mapc #'delete-overlay magit-region-overlays) + (if (and (run-hook-with-args-until-success 'magit-region-highlight-hook + (magit-current-section)) + (not magit-keep-region-overlay)) + (funcall (default-value 'redisplay-unhighlight-region-function) rol) + (funcall (default-value 'redisplay-highlight-region-function) + start end window rol))) + +(defun magit-unhighlight-region (rol) + (setq magit-section-highlighted-section nil) + (mapc #'delete-overlay magit-region-overlays) + (funcall (default-value 'redisplay-unhighlight-region-function) rol)) + +(defvar-local magit-refresh-args nil + "The arguments used to refresh the current buffer.") +(put 'magit-refresh-args 'permanent-local t) + +(defvar-local magit-previous-section nil) +(put 'magit-previous-section 'permanent-local t) + +(defun magit-mode-setup (mode &rest args) + "Setup up a MODE buffer using ARGS to generate its content." + (let ((buffer (magit-mode-get-buffer mode t)) + (section (magit-current-section))) + (with-current-buffer buffer + (setq magit-previous-section section) + (setq magit-refresh-args args) + (funcall mode)) + (magit-display-buffer buffer) + (with-current-buffer buffer + (run-hooks 'magit-mode-setup-hook) + (magit-refresh-buffer)))) + +(defvar magit-display-buffer-noselect nil + "If non-nil, then `magit-display-buffer' doesn't call `select-window'.") + +(defun magit-display-buffer (buffer) + "Display BUFFER in some window and maybe select it. + +Display the buffer using `magit-display-buffer-function' and +then, unless `magit-display-buffer-noselect' is non-nil, select +the window which was used to display the buffer. + +Also run the hooks `magit-pre-display-buffer-hook' +and `magit-post-display-buffer-hook'." + (with-current-buffer buffer + (run-hooks 'magit-pre-display-buffer-hook)) + (let ((window (funcall magit-display-buffer-function buffer))) + (unless magit-display-buffer-noselect + (select-window window))) + (with-current-buffer buffer + (run-hooks 'magit-post-display-buffer-hook))) + +(defun magit-display-buffer-traditional (buffer) + "Display BUFFER the way this has traditionally been done." + (display-buffer + buffer (if (and (derived-mode-p 'magit-mode) + (not (memq (with-current-buffer buffer major-mode) + '(magit-process-mode + magit-revision-mode + magit-diff-mode + magit-stash-mode + magit-status-mode)))) + '(display-buffer-same-window) + nil))) ; display in another window + +(defun magit-maybe-set-dedicated () + "Mark the selected window as dedicated if appropriate. + +If a new window was created to display the buffer, then remember +that fact. That information is used by `magit-mode-quit-window', +to determine whether the window should be deleted when its last +Magit buffer is buried." + (let ((window (get-buffer-window (current-buffer)))) + (when (and (window-live-p window) + (not (window-prev-buffers window))) + (set-window-parameter window 'magit-dedicated t)))) + +(defvar-local magit--default-directory nil + "Value of `default-directory' when buffer is generated. +This exists to prevent a let-bound `default-directory' from +tricking `magit-mode-get-buffer' or `magit-mode-get-buffers' into +thinking a buffer belongs to a repo that it doesn't.") +(put 'magit--default-directory 'permanent-local t) + +(defun magit-mode-get-buffers () + (let ((topdir (magit-toplevel))) + (--filter (with-current-buffer it + (and (derived-mode-p 'magit-mode) + (equal magit--default-directory topdir))) + (buffer-list)))) + +(defvar-local magit-buffer-locked-p nil) +(put 'magit-buffer-locked-p 'permanent-local t) + +(defun magit-mode-get-buffer (mode &optional create frame) + (-if-let (topdir (magit-toplevel)) + (or (--first (with-current-buffer it + (and (eq major-mode mode) + (equal magit--default-directory topdir) + (not magit-buffer-locked-p))) + (if frame + (-map #'window-buffer + (window-list (unless (eq frame t) frame))) + (buffer-list))) + (and create + (let ((default-directory topdir)) + (magit-generate-new-buffer mode)))) + (user-error "Not inside a Git repository"))) + +(defun magit-generate-new-buffer (mode) + (let* ((name (funcall magit-generate-buffer-name-function mode)) + (buffer (generate-new-buffer name))) + (with-current-buffer buffer + (setq magit--default-directory default-directory)) + (when magit-uniquify-buffer-names + (add-to-list 'uniquify-list-buffers-directory-modes mode) + (with-current-buffer buffer + (setq list-buffers-directory default-directory)) + (let ((uniquify-buffer-name-style + (if (eq uniquify-buffer-name-style 'forward) + 'post-forward-angle-brackets + uniquify-buffer-name-style))) + (uniquify-rationalize-file-buffer-names + name (file-name-directory (directory-file-name default-directory)) + buffer))) + buffer)) + +(defun magit-generate-buffer-name-default-function (mode &optional value) + (let ((m (substring (symbol-name mode) 0 -5)) + (v (and value (format "%s" (if (listp value) value (list value)))))) + (format-spec + magit-buffer-name-format + `((?m . ,m) + (?M . ,(if (eq mode 'magit-status-mode) "magit" m)) + (?v . ,(or v "")) + (?V . ,(if v (concat " " v) "")) + (?t . ,(if magit-uniquify-buffer-names + (file-name-nondirectory + (directory-file-name default-directory)) + default-directory)))))) + +(defun magit-toggle-buffer-lock () + "Lock the current buffer to its value or unlock it. + +Locking a buffer to its value, prevents it from being reused to +display another value. The name of a locked buffer contains its +value, which allows telling it apart from other locked buffers +and the unlocked buffer. + +Not all Magit buffers can be locked to their values, for example +it wouldn't make sense to lock a status buffer. + +There can only be a single unlocked buffer using a certain +major-mode per repository. So when a buffer is being unlocked +and another unlocked buffer already exists for that mode and +repository, then the former buffer is instead deleted and the +latter is displayed in its place." + (interactive) + (if magit-buffer-locked-p + (-if-let (unlocked (magit-mode-get-buffer major-mode)) + (let ((locked (current-buffer))) + (set-buffer unlocked) + (kill-buffer locked)) + (setq magit-buffer-locked-p nil) + (rename-buffer (funcall magit-generate-buffer-name-function + major-mode))) + (setq magit-buffer-locked-p + (cond ((memq major-mode '(magit-cherry-mode + magit-log-mode + magit-reflog-mode + magit-refs-mode + magit-revision-mode + magit-stash-mode + magit-stashes-mode)) + (car magit-refresh-args)) + ((eq major-mode 'magit-diff-mode) + (let ((rev (nth 0 magit-refresh-args)) + (args (nth 1 magit-refresh-args))) + (cond + ((member "--no-index" args) + (nth 3 magit-refresh-args)) + (rev (if args (cons rev args) rev)) + (t (if (member "--cached" args) "staged" "unstaged"))))))) + (if magit-buffer-locked-p + (rename-buffer (funcall magit-generate-buffer-name-function + major-mode magit-buffer-locked-p)) + (user-error "Buffer has no value it could be locked to")))) + +(defun magit-mode-bury-buffer (&optional kill-buffer) + "Bury the current buffer. +With a prefix argument, kill the buffer instead. +This is done using `magit-bury-buffer-function'." + (interactive "P") + (funcall magit-bury-buffer-function kill-buffer)) + +(defun magit-mode-quit-window (kill-buffer) + "Quit the selected window and bury its buffer. + +This behaves similar to `quit-window', but when the window +was originally created to display a Magit buffer and the +current buffer is the last remaining Magit buffer that was +ever displayed in the selected window, then delete that +window." + (if (or (one-window-p) + (--first (let ((buffer (car it))) + (and (not (eq buffer (current-buffer))) + (buffer-live-p buffer) + (or (not (window-parameter nil 'magit-dedicated)) + (with-current-buffer buffer + (derived-mode-p 'magit-mode + 'magit-process-mode))))) + (window-prev-buffers))) + (quit-window kill-buffer) + (let ((window (selected-window))) + (quit-window kill-buffer) + (when (window-live-p window) + (delete-window window))))) + +;;; Refresh Machinery + +(defvar inhibit-magit-refresh nil) + +(defvar magit-pre-refresh-hook nil) + +(defun magit-refresh () + "Refresh some buffers belonging to the current repository. + +Refresh the current buffer if its major mode derives from +`magit-mode', and refresh the corresponding status buffer. + +If option `magit-revert-buffers' call for it, then also revert +all unmodified buffers that visit files being tracked in the +current repository." + (interactive) + (unless inhibit-magit-refresh + (run-hooks 'magit-pre-refresh-hook) + (unless (when (derived-mode-p 'magit-mode) + (magit-refresh-buffer) + (derived-mode-p 'magit-status-mode)) + (--when-let (magit-mode-get-buffer 'magit-status-mode) + (with-current-buffer it + (magit-refresh-buffer)))) + (magit-revert-buffers))) + +(defun magit-refresh-all () + "Refresh all buffers belonging to the current repository. + +Refresh all Magit buffers belonging to the current repository. + +Also always revert all unmodified buffers that visit files being +tracked in the current repository." + (interactive) + (dolist (buffer (magit-mode-get-buffers)) + (with-current-buffer buffer (magit-refresh-buffer))) + (magit-revert-buffers t)) + +(defvar-local magit-refresh-start-time nil) + +(defun magit-refresh-buffer () + "Refresh the current Magit buffer." + (setq magit-refresh-start-time (current-time)) + (let ((refresh (intern (format "%s-refresh-buffer" + (substring (symbol-name major-mode) 0 -5))))) + (when (functionp refresh) + (when magit-refresh-verbose + (message "Refreshing buffer `%s'..." (buffer-name))) + (let* ((buffer (current-buffer)) + (windows + (--mapcat (with-selected-window it + (with-current-buffer buffer + (-when-let (section (magit-current-section)) + (list + (nconc (list it section) + (magit-refresh-get-relative-position)))))) + (or (get-buffer-window-list buffer nil t) + (list (selected-window)))))) + (deactivate-mark) + (setq magit-section-highlight-overlays nil + magit-section-highlighted-section nil + magit-section-highlighted-sections nil + magit-section-unhighlight-sections nil) + (let ((inhibit-read-only t)) + (erase-buffer) + (save-excursion + (apply refresh magit-refresh-args))) + (dolist (window windows) + (with-selected-window (car window) + (with-current-buffer buffer + (apply #'magit-section-goto-successor (cdr window))))) + (run-hooks 'magit-refresh-buffer-hook) + (magit-section-update-highlight) + (set-buffer-modified-p nil)) + (when magit-refresh-verbose + (message "Refreshing buffer `%s'...done (%.3fs)" (buffer-name) + (float-time (time-subtract (current-time) + magit-refresh-start-time))))))) + +(defun magit-refresh-get-relative-position () + (-when-let (section (magit-current-section)) + (let ((start (magit-section-start section))) + (list (count-lines start (point)) + (- (point) (line-beginning-position)) + (and (eq (magit-section-type section) 'hunk) + (region-active-p) + (progn (goto-char (line-beginning-position)) + (when (looking-at "^[-+]") (forward-line)) + (while (looking-at "^[ @]") (forward-line)) + (let ((beg (point))) + (cond ((looking-at "^[-+]") + (forward-line) + (while (looking-at "^[-+]") (forward-line)) + (while (looking-at "^ ") (forward-line)) + (forward-line -1) + (regexp-quote (buffer-substring-no-properties + beg (line-end-position)))) + (t t))))))))) + + +(defvar inhibit-magit-revert nil) +(defvar magit-revert-buffers-backlog nil) + +(defun magit-revert-buffers (&optional force) + "Revert unmodified file-visiting buffers of the current repository. + +If either `magit-revert-buffers' is non-nil and `inhibit-magit-revert' +is nil, or if optional FORCE is non-nil; then revert all unmodified +buffers that visit files being tracked in the current repository. + +When called interactively then the revert is forced." + (interactive (list t)) + (when (or force (and magit-revert-buffers (not inhibit-magit-revert))) + (-when-let (topdir (magit-toplevel)) + (let* ((tracked (magit-revision-files "HEAD")) + (buffers + (if (> (length tracked) + (length (buffer-list))) + (--filter + (let ((file (buffer-file-name it))) + (and file + (equal (file-remote-p file) + (file-remote-p topdir)) + (file-in-directory-p file topdir) + (member (file-relative-name file topdir) tracked))) + (buffer-list)) + (--mapcat + (--when-let (find-buffer-visiting (expand-file-name it topdir)) + (list it)) + tracked)))) + (when (and buffers + (or force + (not (eq magit-revert-buffers 'ask)) + (magit-confirm 'revert-buffer + "Revert %s from visited file" + "Revert %i buffers from visited files" + (mapcar #'buffer-name buffers)))) + (cond + ((numberp magit-revert-buffers) + (magit-revert-buffers-async buffers)) + ((eq magit-revert-buffers 'silent) + (mapc #'magit-revert-buffer buffers)) + (t + (let ((cnt (length buffers))) + (when (> cnt 0) + (message "Reverting (up to) %s file-visiting buffer(s)..." cnt) + (setq cnt (length (-non-nil (mapcar #'magit-revert-buffer + buffers)))) + (if (> cnt 0) + (pcase magit-revert-buffers + (`t + (message "Reverting %s file-visiting buffer(s)...done" cnt)) + (`usage + (message + "Reverting %s file-visiting buffer(s)...done%s%s%s" cnt + (substitute-command-keys + "\n This can be undone using `\\[undo]' in the ") + "affected buffers\n Customize behavior using `M-x " + "customize-option RET magit-revert-buffers RET'")) + ((or `nil `ask) + (message "Reverting %s file-visiting buffer(s)...done%s" + cnt (if force " (forced)" "")))) + (message "(No buffers need to be reverted)"))))))))))) + +(defun magit-revert-buffers-async (&optional buffers) + (setq buffers (nconc buffers (--filter (not (memq it buffers)) + magit-revert-buffers-backlog))) + (while (and buffers (not (input-pending-p))) + (let ((buf (pop buffers))) + (when (buffer-live-p buf) + (with-current-buffer buf + (magit-revert-buffer buf))))) + (setq magit-revert-buffers-backlog buffers)) + +(defun magit-revert-buffer (&optional buffer) + "Revert the current file-visiting buffer." + (let (ret) + (with-current-buffer (or buffer (current-buffer)) + (if (and (file-readable-p buffer-file-name) + (not (verify-visited-file-modtime (current-buffer)))) + (if magit-blame-mode + (progn (message "Reverting %s inhibited due to magit-blame-mode" + buffer-file-name) + (run-hooks 'magit-not-reverted-hook)) + (if (or (eq magit-revert-buffers 'silent) + (and (numberp magit-revert-buffers) + (< magit-revert-buffers 0))) + (revert-buffer 'ignore-auto t t) + (message "Reverting buffer `%s'..." (buffer-name)) + (revert-buffer 'ignore-auto t t) + (message "Reverting buffer `%s'...done" (buffer-name))) + (run-hooks 'magit-after-revert-hook) + (setq ret t)) + (run-hooks 'magit-not-reverted-hook))) + ret)) + +(add-hook 'git-commit-setup-hook #'magit-revert-buffers) + +(defun magit-refresh-vc-mode-line () + "Update `vc-mode' which is displayed in the mode-line. +Like `vc-mode-line' but simpler, more efficient, and less buggy." + (setq vc-mode + (if vc-display-status + (magit-with-toplevel + (let* ((rev (or (magit-get-current-branch) + (magit-rev-parse "--short" "HEAD"))) + (msg (cl-letf (((symbol-function #'vc-working-revision) + (lambda (&rest _) rev))) + (vc-default-mode-line-string + 'Git buffer-file-name)))) + (propertize + (concat " " msg) + 'mouse-face 'mode-line-highlight + 'help-echo (concat (get-text-property 0 'help-echo msg) + "\nCurrent revision: " rev + "\nmouse-1: Version Control menu") + 'local-map vc-mode-line-map))) + " Git")) + (force-mode-line-update)) + +(defvar disable-magit-save-buffers nil) + +(defun magit-pre-command-hook () + (setq disable-magit-save-buffers nil)) +(add-hook 'pre-command-hook #'magit-pre-command-hook) + +(defvar magit-after-save-refresh-buffers nil) + +(defun magit-after-save-refresh-buffers () + (dolist (buffer magit-after-save-refresh-buffers) + (with-current-buffer buffer + (magit-refresh-buffer))) + (setq magit-after-save-refresh-buffers nil) + (remove-hook 'post-command-hook 'magit-after-save-refresh-buffers)) + +(defun magit-after-save-refresh-status () + "Refresh the status buffer of the current repository. + +This function is intended to be added to `after-save-hook'. + +If the status buffer does not exist or the file being visited in +the current buffer isn't inside a repository, then do nothing. + +Note that refreshing a Magit buffer is done by re-creating its +contents from scratch, which can be slow in large repositories. +If you are not satisfied with Magit's performance, then you +should obviously not add this function to that hook." + (unless disable-magit-save-buffers + (--when-let (ignore-errors (magit-mode-get-buffer 'magit-status-mode)) + (add-to-list 'magit-after-save-refresh-buffers it) + (add-hook 'post-command-hook 'magit-after-save-refresh-buffers)))) + +(defun magit-maybe-save-repository-buffers () + "Maybe save file-visiting buffers belonging to the current repository. +Do so if `magit-save-repository-buffers' is non-nil." + (when (and magit-save-repository-buffers + (not disable-magit-save-buffers)) + (setq disable-magit-save-buffers t) + (let ((msg (current-message))) + (magit-save-repository-buffers + (eq magit-save-repository-buffers 'dontask)) + (when (and msg (not (equal msg (current-message)))) + (message "%s" msg))))) + +(add-hook 'magit-pre-refresh-hook #'magit-maybe-save-repository-buffers) +(add-hook 'magit-pre-call-git-hook #'magit-maybe-save-repository-buffers) +(add-hook 'magit-pre-start-git-hook #'magit-maybe-save-repository-buffers) + +(defun magit-save-repository-buffers (&optional arg) + "Save file-visiting buffers belonging to the current repository. +After any buffer where `buffer-save-without-query' is non-nil +is saved without asking, the user is asked about each modified +buffer which visits a file in the current repository. Optional +argument (the prefix) non-nil means save all with no questions." + (interactive "P") + (-when-let (topdir (magit-rev-parse-safe "--show-toplevel")) + (save-some-buffers + arg (-partial (lambda (topdir) + (and buffer-file-name + ;; Avoid needlessly connecting to unrelated remotes. + (string-prefix-p topdir buffer-file-name) + (equal (magit-rev-parse-safe "--show-toplevel") + topdir))) + topdir)))) + +;;; Restore Window Configuration + +(defvar magit-inhibit-save-previous-winconf nil) + +(defvar-local magit-previous-window-configuration nil) +(put 'magit-previous-window-configuration 'permanent-local t) + +(defun magit-save-window-configuration () + "Save the current window configuration. + +Later, when the buffer is buried, it may be restored by +`magit-restore-window-configuration'." + (if magit-inhibit-save-previous-winconf + (when (eq magit-inhibit-save-previous-winconf 'unset) + (setq magit-previous-window-configuration nil)) + (unless (get-buffer-window (current-buffer) (selected-frame)) + (setq magit-previous-window-configuration + (current-window-configuration))))) + +(defun magit-restore-window-configuration (&optional kill-buffer) + "Bury or kill the current buffer and restore previous window configuration." + (let ((winconf magit-previous-window-configuration) + (buffer (current-buffer)) + (frame (selected-frame))) + (quit-window kill-buffer (selected-window)) + (when (and winconf (equal frame (window-configuration-frame winconf))) + (set-window-configuration winconf) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (setq magit-previous-window-configuration nil)))))) + +;;; Buffer History + +(defun magit-go-backward () + "Move backward in current buffer's history." + (interactive) + (if help-xref-stack + (help-xref-go-back (current-buffer)) + (user-error "No previous entry in buffer's history"))) + +(defun magit-go-forward () + "Move forward in current buffer's history." + (interactive) + (if help-xref-forward-stack + (help-xref-go-forward (current-buffer)) + (user-error "No next entry in buffer's history"))) + +(defun magit-insert-xref-buttons (&optional _) + "Insert xref buttons." + (when (or help-xref-stack help-xref-forward-stack) + (when help-xref-stack + (magit-xref-insert-button help-back-label 'magit-xref-backward)) + (when help-xref-forward-stack + (when help-xref-stack + (insert " ")) + (magit-xref-insert-button help-forward-label 'magit-xref-forward)))) + +(defun magit-xref-insert-button (label type) + (magit-insert-section (button label) + (insert-text-button label 'type type + 'help-args (list (current-buffer))))) + +(define-button-type 'magit-xref-backward + :supertype 'help-back + 'mouse-face 'magit-section-highlight + 'help-echo (purecopy "mouse-2, RET: go back to previous history entry")) + +(define-button-type 'magit-xref-forward + :supertype 'help-forward + 'mouse-face 'magit-section-highlight + 'help-echo (purecopy "mouse-2, RET: go back to next history entry")) + +(defun magit-xref-setup () + "Insert backward/forward buttons if the major-mode supports it. +Currently `magit-log-mode', `magit-reflog-mode', +`magit-diff-mode', and `magit-revision-mode' support it" + (when (memq major-mode '(magit-log-mode + magit-reflog-mode + magit-diff-mode + magit-revision-mode)) + (when help-xref-stack-item + (push (cons (point) help-xref-stack-item) help-xref-stack) + (setq help-xref-forward-stack nil)) + (when (called-interactively-p 'interactive) + (--when-let (nthcdr 10 help-xref-stack) + (setcdr it nil))) + (setq help-xref-stack-item + `(magit-xref-restore ,default-directory ,@magit-refresh-args)))) + +(defun magit-xref-restore (&rest args) + (magit-xref-setup) + (setq default-directory (car args)) + (setq magit-refresh-args (cdr args)) + (magit-refresh-buffer)) + +;;; magit-mode.el ends soon +(provide 'magit-mode) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-mode.el ends here diff --git a/elpa/magit-20151223.1425/magit-pkg.el b/elpa/magit-20151223.1425/magit-pkg.el new file mode 100644 index 00000000..0c7e4c8e --- /dev/null +++ b/elpa/magit-20151223.1425/magit-pkg.el @@ -0,0 +1,12 @@ +(define-package "magit" "20151223.1425" "A Git porcelain inside Emacs" + '((emacs "24.4") + (async "20150909.2257") + (dash "20151021.113") + (with-editor "20151111") + (git-commit "20151111") + (magit-popup "20151221")) + :url "https://github.com/magit/magit" :keywords + '("git" "tools" "vc")) +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/magit-20151223.1425/magit-process.el b/elpa/magit-20151223.1425/magit-process.el new file mode 100644 index 00000000..fddb3bf9 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-process.el @@ -0,0 +1,891 @@ +;;; magit-process.el --- process functionality -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library implements the tools used to run Git for side-effects. + +;; Note that the functions used to run Git and then consume its +;; output, are defined in `magit-git.el'. There's a bit of overlap +;; though. + +;;; Code: + +(require 'cl-lib) +(require 'dash) + +(require 'with-editor) +(require 'magit-utils) +(require 'magit-section) +(require 'magit-git) +(require 'magit-mode) + +(eval-when-compile (require 'dired)) +(declare-function dired-uncache 'dired) + +;;; Options + +(defcustom magit-process-connection-type (not (eq system-type 'cygwin)) + "Connection type used for the Git process. + +If nil, use pipes: this is usually more efficient, and works on Cygwin. +If t, use ptys: this enables Magit to prompt for passphrases when needed." + :group 'magit-process + :type '(choice (const :tag "pipe" nil) + (const :tag "pty" t))) + +(defcustom magit-need-cygwin-noglob + (equal "x0\n" (with-temp-buffer + (process-file magit-git-executable + nil (current-buffer) nil + "-c" "alias.echo=!echo" "echo" "x{0}") + (buffer-string))) + "Whether to use a workaround for Cygwin's globbing behavior. + +If non-nil, add environment variables to `process-environment' to +prevent the git.exe distributed by Cygwin and MSYS2 from +attempting to perform glob expansion when called from a native +Windows build of Emacs. See #2246." + :package-version '(magit . "2.3.0") + :group 'magit-process + :type '(choice (const :tag "Yes" t) + (const :tag "No" nil))) + +(defcustom magit-process-popup-time -1 + "Popup the process buffer if a command takes longer than this many seconds." + :group 'magit-process + :type '(choice (const :tag "Never" -1) + (const :tag "Immediately" 0) + (integer :tag "After this many seconds"))) + +(defcustom magit-process-log-max 32 + "Maximum number of sections to keep in a process log buffer. +When adding a new section would go beyond the limit set here, +then the older half of the sections are remove. Sections that +belong to processes that are still running are never removed. +When this is nil, no sections are ever removed." + :package-version '(magit . "2.1.0") + :group 'magit-process + :type '(choice (const :tag "Never remove old sections" nil) integer)) + +(defcustom magit-credential-cache-daemon-socket + (--some (-let [(prog . args) (split-string it)] + (if (string-match-p + "\\`\\(?:\\(?:/.*/\\)?git-credential-\\)?cache\\'" prog) + (or (cl-loop for (opt val) on args + if (string= opt "--socket") + return val) + (expand-file-name "~/.git-credential-cache/socket")))) + ;; Note: `magit-process-file' is not yet defined when + ;; evaluating this form, so we use `process-lines'. + (ignore-errors + (process-lines magit-git-executable + "config" "--get-all" "credential.helper"))) + "If non-nil, start a credential cache daemon using this socket. + +When using Git's cache credential helper in the normal way, Emacs +sends a SIGHUP to the credential daemon after the git subprocess +has exited, causing the daemon to also quit. This can be avoided +by starting the `git-credential-cache--daemon' process directly +from Emacs. + +The function `magit-maybe-start-credential-cache-daemon' takes +care of starting the daemon if necessary, using the value of this +option as the socket. If this option is nil, then it does not +start any daemon. Likewise if another daemon is already running, +then it starts no new daemon. This function has to be a member +of the hook variable `magit-credential-hook' for this to work. +If an error occurs while starting the daemon, most likely because +the necessary executable is missing, then the function removes +itself from the hook, to avoid further futile attempts." + :package-version '(magit . "2.3.0") + :group 'magit-process + :type '(choice (file :tag "Socket") + (const :tag "Don't start a cache daemon" nil))) + +(defcustom magit-process-yes-or-no-prompt-regexp + " [\[(]\\([Yy]\\(?:es\\)?\\)[/|]\\([Nn]o?\\)[\])] ?[?:] ?$" + "Regexp matching Yes-or-No prompts of Git and its subprocesses." + :package-version '(magit . "2.1.0") + :group 'magit-process + :type 'regexp) + +(defcustom magit-process-password-prompt-regexps + '("^\\(Enter \\)?[Pp]assphrase\\( for \\(RSA \\)?key '.*'\\)?: ?$" + ;; match-group 99 is used to identify a host + "^\\(Enter \\)?[Pp]assword\\( for '\\(?99:.*\\)'\\)?: ?$" + "^.*'s password: ?$" + "^Yubikey for .*: ?$") + "List of regexps matching password prompts of Git and its subprocesses. +Also see `magit-process-find-password-functions'." + :package-version '(magit . "2.1.0") + :group 'magit-process + :type '(repeat (regexp))) + +(defcustom magit-process-find-password-functions nil + "List of functions to try in sequence to get a password. + +These functions may be called when git asks for a password, which +is detected using `magit-process-password-prompt-regexps'. They +are called if and only if matching the prompt resulted in the +value of the 99th submatch to be non-nil. Therefore users can +control for which prompts these functions should be called by +putting the host name in the 99th submatch, or not. + +If the functions are called, then they are called in the order +given, with the host name as only argument, until one of them +returns non-nil. If they are not called or none of them returns +non-nil, then the password is read from the user instead." + :package-version '(magit . "2.3.0") + :group 'magit-process + :type 'hook + :options '(magit-process-password-auth-source)) + +(defcustom magit-process-username-prompt-regexps + '("^Username for '.*': ?$") + "List of regexps matching username prompts of Git and its subprocesses." + :package-version '(magit . "2.1.0") + :group 'magit-process + :type '(repeat (regexp))) + +(defface magit-process-ok + '((t :inherit magit-section-heading :foreground "green")) + "Face for zero exit-status." + :group 'magit-faces) + +(defface magit-process-ng + '((t :inherit magit-section-heading :foreground "red")) + "Face for non-zero exit-status." + :group 'magit-faces) + +;;; Process Mode + +(defvar magit-process-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + map) + "Keymap for `magit-process-mode'.") + +(define-derived-mode magit-process-mode magit-mode "Magit Process" + "Mode for looking at Git process output." + :group 'magit-process + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-process-buffer (&optional nodisplay) + "Display the current repository's process buffer. + +If that buffer doesn't exist yet, then create it. +Non-interactively return the buffer and unless +optional NODISPLAY is non-nil also display it." + (interactive) + (let ((topdir (magit-toplevel))) + (unless topdir + (magit--with-safe-default-directory nil + (setq topdir default-directory) + (let (prev) + (while (not (equal topdir prev)) + (setq prev topdir) + (setq topdir (file-name-directory (directory-file-name topdir))))))) + (let ((buffer (or (--first (with-current-buffer it + (and (eq major-mode 'magit-process-mode) + (equal default-directory topdir))) + (buffer-list)) + (let ((default-directory topdir)) + (magit-generate-new-buffer 'magit-process-mode))))) + (with-current-buffer buffer + (if magit-root-section + (when magit-process-log-max + (magit-process-truncate-log)) + (magit-process-mode) + (let ((inhibit-read-only t)) + (make-local-variable 'text-property-default-nonsticky) + (magit-insert-section (processbuf) + (insert "\n"))))) + (unless nodisplay + (magit-display-buffer buffer)) + buffer))) + +(defun magit-process-kill () + "Kill the process at point." + (interactive) + (magit-section-when process + (let ((process (magit-section-value it))) + (if (eq (process-status process) 'run) + (when (magit-confirm 'kill-process) + (kill-process process)) + (user-error "Process isn't running"))))) + +;;; Synchronous Processes + +(defvar magit-process-raise-error nil) + +(defun magit-git (&rest args) + "Call Git synchronously in a separate process, for side-effects. + +Option `magit-git-executable' specifies the Git executable. +The arguments ARGS specify arguments to Git, they are flattened +before use. + +Process output goes into a new section in the buffer returned by +`magit-process-buffer'. If Git exits with a non-zero status, +then raise an error." + (let ((magit-process-raise-error t)) + (magit-call-git args))) + +(defun magit-run-git (&rest args) + "Call Git synchronously in a separate process, and refresh. + +Option `magit-git-executable' specifies the Git executable and +option `magit-git-global-arguments' specifies constant arguments. +The arguments ARGS specify arguments to Git, they are flattened +before use. + +After Git returns, the current buffer (if it is a Magit buffer) +as well as the current repository's status buffer are refreshed. +Unmodified buffers visiting files that are tracked in the current +repository are reverted if `magit-revert-buffers' is non-nil. + +Process output goes into a new section in the buffer returned by +`magit-process-buffer'." + (magit-call-git args) + (magit-refresh)) + +(defun magit-run-git-no-revert (&rest args) + "Call Git synchronously in a separate process, and refresh. + +Option `magit-git-executable' specifies the Git executable and +option `magit-git-global-arguments' specifies constant arguments. +The arguments ARGS specify arguments to Git, they are flattened +before use. + +After Git returns, the current buffer (if it is a Magit buffer) +as well as the current repository's status buffer are refreshed. + +Process output goes into a new section in the buffer returned by +`magit-process-buffer'." + (let ((inhibit-magit-revert t)) + (magit-run-git args))) + +(defvar magit-pre-call-git-hook nil) + +(defun magit-call-git (&rest args) + "Call Git synchronously in a separate process. + +Option `magit-git-executable' specifies the Git executable and +option `magit-git-global-arguments' specifies constant arguments. +The arguments ARGS specify arguments to Git, they are flattened +before use. + +Process output goes into a new section in the buffer returned by +`magit-process-buffer'." + (run-hooks 'magit-pre-call-git-hook) + (apply #'magit-call-process magit-git-executable + (magit-process-git-arguments args))) + +(defun magit-call-process (program &rest args) + "Call PROGRAM synchronously in a separate process. +Process output goes into a new section in the buffer returned by +`magit-process-buffer'." + (-let [(process-buf . section) (magit-process-setup program args)] + (magit-process-finish + (let ((inhibit-read-only t)) + (apply #'magit-process-file program nil process-buf nil args)) + process-buf (current-buffer) default-directory section))) + +(defun magit-process-file (&rest args) + "Process files synchronously in a separate process. +Identical to `process-file' but temporarily enable Cygwin's +\"noglob\" option during the call." + (let ((process-environment (append (magit-cygwin-env-vars) + process-environment))) + (apply #'process-file args))) + +(defun magit-cygwin-env-vars () + (append magit-git-environment + (when magit-need-cygwin-noglob + (mapcar (lambda (var) + (concat var "=" (--if-let (getenv var) + (concat it " noglob") + "noglob"))) + '("CYGWIN" "MSYS"))))) + +(defun magit-run-git-with-input (input &rest args) + "Call Git in a separate process. +ARGS is flattened and then used as arguments to Git. + +The first argument, INPUT, should be a buffer or the name of +an existing buffer. The content of that buffer is used as the +process' standard input. It may also be nil in which case the +current buffer is used. + +Option `magit-git-executable' specifies the Git executable and +option `magit-git-global-arguments' specifies constant arguments. +The remaining arguments ARGS specify arguments to Git, they are +flattened before use. + +After Git returns, the current buffer (if it is a Magit buffer) +as well as the current repository's status buffer are refreshed. +Unmodified buffers visiting files that are tracked in the current +repository are reverted if `magit-revert-buffers' is non-nil. +When INPUT is nil then do not refresh any buffers. + +This function actually starts a asynchronous process, but it then +waits for that process to return." + (declare (indent 1)) + (magit-start-git (or input (current-buffer)) args) + (magit-process-wait) + (when input (magit-refresh))) + +(defvar magit-this-process nil) + +(defun magit-run-git-with-logfile (file &rest args) + "Call Git in a separate process and log its output to FILE. +See `magit-run-git' for more information. +This function might have a short halflive." + (magit-start-git nil args) + (process-put magit-this-process 'logfile file) + (set-process-filter magit-this-process 'magit-process-logfile-filter) + (magit-process-wait) + (magit-refresh)) + +;;; Asynchronous Processes + +(defun magit-run-git-async (&rest args) + "Start Git, prepare for refresh, and return the process object. +ARGS is flattened and then used as arguments to Git. + +Display the command line arguments in the echo area. + +After Git returns some buffers are refreshed: the buffer that was +current when this function was called (if it is a Magit buffer +and still alive), as well as the respective Magit status buffer. +Unmodified buffers visiting files that are tracked in the current +repository are reverted if `magit-revert-buffers' is non-nil. + +See `magit-start-process' for more information." + (message "Running %s %s" magit-git-executable + (let ((m (mapconcat #'identity (-flatten args) " "))) + (remove-list-of-text-properties 0 (length m) '(face) m) + m)) + (magit-start-git nil args)) + +(defun magit-run-git-async-no-revert (&rest args) + "Start Git, prepare for refresh, and return the process object. +ARGS is flattened and then used as arguments to Git. + +Display the command line arguments in the echo area. + +After Git returns some buffers are refreshed: the buffer that was +current when this function was called (if it is a Magit buffer +and still alive), as well as the respective Magit status buffer. + +See `magit-start-process' for more information." + (let ((inhibit-magit-revert t)) + (magit-run-git-async args))) + +(defun magit-run-git-with-editor (&rest args) + "Export GIT_EDITOR and start Git. +Also prepare for refresh and return the process object. +ARGS is flattened and then used as arguments to Git. + +Display the command line arguments in the echo area. + +After Git returns some buffers are refreshed: the buffer that was +current when this function was called (if it is a Magit buffer +and still alive), as well as the respective Magit status buffer. + +See `magit-start-process' and `with-editor' for more information." + (with-editor "GIT_EDITOR" + (let ((magit-process-popup-time -1) + (inhibit-magit-revert nil)) + (magit-run-git-async args)))) + +(defun magit-run-git-sequencer (&rest args) + "Export GIT_EDITOR and start Git. +Also prepare for refresh and return the process object. +ARGS is flattened and then used as arguments to Git. + +Display the command line arguments in the echo area. + +After Git returns some buffers are refreshed: the buffer that was +current when this function was called (if it is a Magit buffer +and still alive), as well as the respective Magit status buffer. +If the sequence stops at a commit, make the section representing +that commit the current section by moving `point' there. + +Unmodified buffers visiting files that are tracked in the current +repository are reverted if `magit-revert-buffers' is non-nil. + +See `magit-start-process' and `with-editor' for more information." + (with-editor "GIT_EDITOR" + (let ((magit-process-popup-time -1)) + (magit-run-git-async args))) + (set-process-sentinel magit-this-process #'magit-sequencer-process-sentinel) + magit-this-process) + +(defvar magit-pre-start-git-hook nil) + +(defun magit-start-git (input &rest args) + "Start Git, prepare for refresh, and return the process object. + +If INPUT is non-nil, it has to be a buffer or the name of an +existing buffer. The buffer content becomes the processes +standard input. + +Option `magit-git-executable' specifies the Git executable and +option `magit-git-global-arguments' specifies constant arguments. +The remaining arguments ARGS specify arguments to Git, they are +flattened before use. + +After Git returns some buffers are refreshed: the buffer that was +current when this function was called (if it is a Magit buffer +and still alive), as well as the respective Magit status buffer. +Unmodified buffers visiting files that are tracked in the current +repository are reverted if `magit-revert-buffers' is non-nil. + +See `magit-start-process' for more information." + (run-hooks 'magit-pre-start-git-hook) + (apply #'magit-start-process magit-git-executable input + (magit-process-git-arguments args))) + +(defun magit-start-process (program &optional input &rest args) + "Start PROGRAM, prepare for refresh, and return the process object. + +If optional argument INPUT is non-nil, it has to be a buffer or +the name of an existing buffer. The buffer content becomes the +processes standard input. + +The process is started using `start-file-process' and then setup +to use the sentinel `magit-process-sentinel' and the filter +`magit-process-filter'. Information required by these functions +is stored in the process object. When this function returns the +process has not started to run yet so it is possible to override +the sentinel and filter. + +After the process returns, `magit-process-sentinel' refreshes the +buffer that was current when `magit-start-process' was called (if +it is a Magit buffer and still alive), as well as the respective +Magit status buffer. Unmodified buffers visiting files that are +tracked in the current repository are reverted if +`magit-revert-buffers' is non-nil." + (-let* (((process-buf . section) + (magit-process-setup program args)) + (process + (let ((process-connection-type + ;; Don't use a pty, because it would set icrnl + ;; which would modify the input (issue #20). + (and (not input) magit-process-connection-type)) + (process-environment (append (magit-cygwin-env-vars) + process-environment))) + (apply #'start-file-process + (file-name-nondirectory program) + process-buf program args)))) + (with-editor-set-process-filter process #'magit-process-filter) + (set-process-sentinel process #'magit-process-sentinel) + (set-process-buffer process process-buf) + (process-put process 'section section) + (process-put process 'command-buf (current-buffer)) + (process-put process 'default-dir default-directory) + (when inhibit-magit-refresh + (process-put process 'inhibit-refresh t)) + (when inhibit-magit-revert + (process-put process 'inhibit-revert t)) + (setf (magit-section-process section) process) + (with-current-buffer process-buf + (set-marker (process-mark process) (point))) + (when input + (with-current-buffer input + (process-send-region process (point-min) (point-max)) + (process-send-eof process))) + (setq magit-this-process process) + (setf (magit-section-value section) process) + (magit-process-display-buffer process) + process)) + +;;; Process Internals + +(defun magit-process-setup (program args) + (magit-process-set-mode-line program args) + (let ((pwd default-directory) + (buf (magit-process-buffer t))) + (cons buf (with-current-buffer buf + (prog1 (magit-process-insert-section pwd program args nil nil) + (backward-char 1)))))) + +(defun magit-process-insert-section (pwd program args &optional errcode errlog) + (let ((inhibit-read-only t) + (magit-insert-section--parent magit-root-section)) + (goto-char (1- (point-max))) + (magit-insert-section (process) + (insert (if errcode + (format "%3s " (propertize (number-to-string errcode) + 'face 'magit-process-ng)) + "run ")) + (unless (equal (expand-file-name pwd) + (expand-file-name default-directory)) + (insert (file-relative-name pwd default-directory) ?\s)) + (insert (propertize program 'face 'magit-section-heading)) + (insert " ") + (when (and args (equal program magit-git-executable)) + (setq args (-split-at (length magit-git-global-arguments) args)) + (insert (propertize (char-to-string magit-ellipsis) + 'face 'magit-section-heading + 'help-echo (mapconcat #'identity (car args) " "))) + (insert " ") + (setq args (cadr args))) + (insert (propertize (mapconcat #'identity args " ") + 'face 'magit-section-heading)) + (magit-insert-heading) + (when errlog + (insert-file-contents errlog) + (goto-char (1- (point-max)))) + (insert "\n")))) + +(defun magit-process-truncate-log () + (let* ((head nil) + (tail (magit-section-children magit-root-section)) + (count (length tail))) + (when (> (1+ count) magit-process-log-max) + (while (and (cdr tail) + (> count (/ magit-process-log-max 2))) + (let* ((inhibit-read-only t) + (section (car tail)) + (process (magit-section-process section))) + (cond ((not process)) + ((memq (process-status process) '(exit signal)) + (delete-region (magit-section-start section) + (1+ (magit-section-end section))) + (cl-decf count)) + (t + (push section head)))) + (pop tail)) + (setf (magit-section-children magit-root-section) + (nconc (reverse head) tail))))) + +(defun magit-process-sentinel (process event) + "Default sentinel used by `magit-start-process'." + (when (memq (process-status process) '(exit signal)) + (setq event (substring event 0 -1)) + (when (string-match "^finished" event) + (message (concat (capitalize (process-name process)) " finished"))) + (magit-process-finish process) + (when (eq process magit-this-process) + (setq magit-this-process nil)) + (unless (process-get process 'inhibit-refresh) + (let ((inhibit-magit-revert (process-get process 'inhibit-revert)) + (command-buf (process-get process 'command-buf))) + (if (buffer-live-p command-buf) + (with-current-buffer command-buf + (magit-refresh)) + (with-temp-buffer + (setq default-directory (process-get process 'default-dir)) + (magit-refresh))))))) + +(defun magit-sequencer-process-sentinel (process event) + "Special sentinel used by `magit-run-git-sequencer'." + (when (memq (process-status process) '(exit signal)) + (magit-process-sentinel process event) + (--when-let (magit-mode-get-buffer 'magit-status-mode) + (with-current-buffer it + (--when-let + (magit-get-section + `((commit . ,(magit-rev-parse "HEAD")) + (,(pcase (car (cadr (-split-at + (1+ (length magit-git-global-arguments)) + (process-command process)))) + ((or "rebase" "am") 'rebase-sequence) + ((or "cherry-pick" "revert") 'sequence))) + (status))) + (goto-char (magit-section-start it)) + (magit-section-update-highlight)))))) + +(defun magit-process-filter (proc string) + "Default filter used by `magit-start-process'." + (with-current-buffer (process-buffer proc) + (let ((inhibit-read-only t)) + (magit-process-yes-or-no-prompt proc string) + (magit-process-username-prompt proc string) + (magit-process-password-prompt proc string) + (goto-char (process-mark proc)) + (setq string (propertize string 'magit-section + (process-get proc 'section))) + ;; Find last ^M in string. If one was found, ignore + ;; everything before it and delete the current line. + (let ((ret-pos (length string))) + (while (and (>= (cl-decf ret-pos) 0) + (/= ?\r (aref string ret-pos)))) + (if (< ret-pos 0) + (insert string) + (delete-region (line-beginning-position) (point)) + (insert (substring string (1+ ret-pos))))) + (set-marker (process-mark proc) (point))))) + +(defun magit-process-logfile-filter (process string) + "Special filter used by `magit-run-git-with-logfile'." + (magit-process-filter process string) + (let ((file (process-get process 'logfile))) + (with-temp-file file + (when (file-exists-p file) + (insert-file-contents file) + (goto-char (point-max))) + (insert string) + (write-region (point-min) (point-max) file)))) + +(defmacro magit-process-kill-on-abort (proc &rest body) + (declare (indent 1) (debug (form body))) + (let ((map (cl-gensym))) + `(let ((,map (make-sparse-keymap))) + (set-keymap-parent ,map minibuffer-local-map) + (define-key ,map "\C-g" + (lambda () + (interactive) + (ignore-errors (kill-process ,proc)) + (abort-recursive-edit))) + (let ((minibuffer-local-map ,map)) + ,@body)))) + +(defun magit-process-yes-or-no-prompt (process string) + "Forward Yes-or-No prompts to the user." + (-when-let (beg (string-match magit-process-yes-or-no-prompt-regexp string)) + (let ((max-mini-window-height 30)) + (process-send-string + process + (downcase + (concat + (match-string + (if (save-match-data + (magit-process-kill-on-abort process + (yes-or-no-p (substring string 0 beg)))) 1 2) + string) + "\n")))))) + +(defun magit-process-password-auth-source (key) + "Use `auth-source-search' to get a password. +If found, return the password. Otherwise, return nil." + (require 'auth-source) + (let ((secret (plist-get (car (auth-source-search :max 1 :host key + :require '(:host))) + :secret))) + (if (functionp secret) + (funcall secret) + secret))) + +(defun magit-process-password-prompt (process string) + "Find a password based on prompt STRING and send it to git. +First try the functions in `magit-process-find-password-functions'. +If none of them returns a password, then read it from the user +instead." + (--when-let (magit-process-match-prompt + magit-process-password-prompt-regexps string) + (process-send-string + process (magit-process-kill-on-abort process + (concat (or (--when-let (match-string 99 string) + (run-hook-with-args-until-success + 'magit-process-find-password-functions it)) + (read-passwd it)) + "\n"))))) + +(defun magit-process-username-prompt (process string) + "Forward username prompts to the user." + (--when-let (magit-process-match-prompt + magit-process-username-prompt-regexps string) + (process-send-string + process (magit-process-kill-on-abort process + (concat (read-string it nil nil (user-login-name)) "\n"))))) + +(defun magit-process-match-prompt (prompts string) + "Match STRING against PROMPTS and set match data. +Return the matched string suffixed with \": \", if needed." + (when (--any? (string-match it string) prompts) + (let ((prompt (match-string 0 string))) + (cond ((string-suffix-p ": " prompt) prompt) + ((string-suffix-p ":" prompt) (concat prompt " ")) + (t (concat prompt ": ")))))) + +(defvar magit-credential-hook nil + "Hook run before Git needs credentials.") + +(defvar magit-credential-cache-daemon-process nil) + +(defun magit-maybe-start-credential-cache-daemon () + "Maybe start a `git-credential-cache--daemon' process. + +If such a process is already running or if the value of option +`magit-credential-cache-daemon-socket' is nil, then do nothing. +Otherwise start the process passing the value of that options +as argument." + (unless (or (not magit-credential-cache-daemon-socket) + (process-live-p magit-credential-cache-daemon-process) + (memq magit-credential-cache-daemon-process + (list-system-processes))) + (setq magit-credential-cache-daemon-process + (or (--first (-let (((&alist 'comm comm 'user user) + (process-attributes it))) + (and (string= comm "git-credential-cache--daemon") + (string= user user-login-name))) + (list-system-processes)) + (condition-case nil + (start-process "git-credential-cache--daemon" + " *git-credential-cache--daemon*" + magit-git-executable + "credential-cache--daemon" + magit-credential-cache-daemon-socket) + ;; Some Git implementations (e.g. Windows) won't have + ;; this program; if we fail the first time, stop trying. + ((debug error) + (remove-hook 'magit-credential-hook + #'magit-maybe-start-credential-cache-daemon))))))) + +(add-hook 'magit-credential-hook #'magit-maybe-start-credential-cache-daemon) + +(defun magit-process-wait () + (while (and magit-this-process + (eq (process-status magit-this-process) 'run)) + (sit-for 0.1 t))) + +(defun tramp-sh-handle-start-file-process--magit-tramp-process-environment + (fn name buffer program &rest args) + (if magit-tramp-process-environment + (apply fn name buffer + (car magit-tramp-process-environment) + (append (cdr magit-tramp-process-environment) + (cons program args))) + (apply fn name buffer program args))) + +(advice-add 'tramp-sh-handle-start-file-process :around + 'tramp-sh-handle-start-file-process--magit-tramp-process-environment) + +(defun tramp-sh-handle-process-file--magit-tramp-process-environment + (fn program &optional infile destination display &rest args) + (if magit-tramp-process-environment + (apply fn "env" infile destination display + (append magit-tramp-process-environment + (cons program args))) + (apply fn program infile destination display args))) + +(advice-add 'tramp-sh-handle-process-file :around + 'tramp-sh-handle-process-file--magit-tramp-process-environment) + +(defun magit-process-set-mode-line (program args) + (when (equal program magit-git-executable) + (setq args (nthcdr (length magit-git-global-arguments) args))) + (let ((str (concat " " program (and args (concat " " (car args)))))) + (dolist (buf (magit-mode-get-buffers)) + (with-current-buffer buf (setq mode-line-process str))))) + +(defun magit-process-unset-mode-line () + (dolist (buf (magit-mode-get-buffers)) + (with-current-buffer buf (setq mode-line-process nil)))) + +(defvar magit-process-error-message-re + (concat "^\\(?:error\\|fatal\\|git\\): \\(.*\\)" paragraph-separate)) + +(define-error 'magit-git-error "Git error") + +(defvar-local magit-this-error nil) + +(defun magit-process-finish (arg &optional process-buf command-buf + default-dir section) + (unless (integerp arg) + (setq process-buf (process-buffer arg) + command-buf (process-get arg 'command-buf) + default-dir (process-get arg 'default-dir) + section (process-get arg 'section) + arg (process-exit-status arg))) + (magit-process-unset-mode-line) + (when (featurep 'dired) + (dired-uncache default-dir)) + (when (buffer-live-p process-buf) + (with-current-buffer process-buf + (let ((inhibit-read-only t) + (marker (magit-section-start section))) + (goto-char marker) + (save-excursion + (delete-char 3) + (set-marker-insertion-type marker nil) + (insert (propertize (format "%3s" arg) + 'magit-section section + 'face (if (= arg 0) + 'magit-process-ok + 'magit-process-ng))) + (set-marker-insertion-type marker t)) + (if (= (magit-section-end section) + (+ (line-end-position) 2)) + (save-excursion + (goto-char (1+ (line-end-position))) + (delete-char -1) + (setf (magit-section-content section) nil)) + (let ((buf (magit-process-buffer t))) + (when (and (= arg 0) + (not (--any-p (eq (window-buffer it) buf) + (window-list)))) + (magit-section-hide section))))))) + (unless (= arg 0) + (let ((msg (or (and (buffer-live-p process-buf) + (with-current-buffer process-buf + (save-excursion + (goto-char (magit-section-end section)) + (--when-let (magit-section-content section) + (when (re-search-backward + magit-process-error-message-re it t) + (match-string 1)))))) + "Git failed"))) + (if magit-process-raise-error + (signal 'magit-git-error msg) + (--when-let (magit-mode-get-buffer 'magit-status-mode) + (setq magit-this-error msg)) + (message "%s ... [%s buffer %s for details]" msg + (-if-let (key (and (buffer-live-p command-buf) + (with-current-buffer command-buf + (car (where-is-internal + 'magit-process-buffer))))) + (format "Hit %s to see" (key-description key)) + "See") + (buffer-name process-buf))))) + arg) + +(defun magit-process-display-buffer (process) + (when (process-live-p process) + (let ((buf (process-buffer process))) + (cond ((not (buffer-live-p buf))) + ((= magit-process-popup-time 0) + (if (minibufferp) + (switch-to-buffer-other-window buf) + (pop-to-buffer buf))) + ((> magit-process-popup-time 0) + (run-with-timer magit-process-popup-time nil + (lambda (p) + (when (eq (process-status p) 'run) + (let ((buf (process-buffer p))) + (when (buffer-live-p buf) + (if (minibufferp) + (switch-to-buffer-other-window buf) + (pop-to-buffer buf)))))) + process)))))) + +;;; magit-process.el ends soon +(provide 'magit-process) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-process.el ends here diff --git a/elpa/magit-20151223.1425/magit-remote.el b/elpa/magit-20151223.1425/magit-remote.el new file mode 100644 index 00000000..cbca5b52 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-remote.el @@ -0,0 +1,668 @@ +;;; magit-remote.el --- transfer Git commits -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library implements support for interacting with remote +;; repositories. Commands for cloning, fetching, pulling, and +;; pushing are defined here. + +;;; Code: + +(require 'magit) + +;;; Clone + +(defcustom magit-clone-set-branch.pushDefault 'ask + "Whether to set the value of `branch.pushDefault' after cloning. + +If t, then set without asking. If nil, then don't set. If +`ask', then ask." + :package-version '(magit . "2.4.0") + :group 'magit-commands + :type '(choice (const "set" t) + (const "ask" ask) + (const "don't set" nil))) + +;;;###autoload +(defun magit-clone (repository directory) + "Clone the REPOSITORY to DIRECTORY. +Then show the status buffer for the new repository." + (interactive + (let ((url (magit-read-string-ns "Clone repository"))) + (list url (read-directory-name + "Clone to: " nil nil nil + (and (string-match "\\([^./]+\\)\\(\\.git\\)?$" url) + (match-string 1 url)))))) + (setq directory (file-name-as-directory (expand-file-name directory))) + (message "Cloning %s..." repository) + (when (= (magit-call-git "clone" repository + ;; Stop cygwin git making a "c:" directory. + (magit-convert-git-filename directory)) + 0) + (when (or (eq magit-clone-set-branch.pushDefault t) + (and magit-clone-set-branch.pushDefault + (y-or-n-p "Set `branch.pushDefault' to \"origin\"? "))) + (magit-call-git "config" "branch.pushDefault" "origin")) + (message "Cloning %s...done" repository) + (magit-status-internal directory))) + +;;; Setup + +(defcustom magit-remote-add-set-branch.pushDefault 'ask-if-unset + "Whether to set the value of `branch.pushDefault' after adding a remote. + +If `ask', then always ask. If `ask-if-unset', then ask, but only +if the variable isn't set already. If nil, then don't ever set. +If the value is a string, then set without asking, provided the +name of the name of the added remote is equal to that string and +the variable isn't already set." + :package-version '(magit . "2.4.0") + :group 'magit-commands + :type '(choice (const "ask if unset" ask-if-unset) + (const "always ask" ask) + (string "set if named") + (const "don't set"))) + +;;;###autoload (autoload 'magit-remote-popup "magit-remote" nil t) +(magit-define-popup magit-remote-popup + "Popup console for remote commands." + 'magit-commands nil nil + :man-page "git-remote" + :actions '((?a "Add" magit-remote-add) + (?r "Rename" magit-remote-rename) + (?k "Remove" magit-remote-remove) + (?u "Set url" magit-remote-set-url))) + +(defun magit-read-url (prompt &optional initial-input) + (let ((url (magit-read-string-ns prompt initial-input))) + (if (string-prefix-p "~" url) + (expand-file-name url) + url))) + +;;;###autoload +(defun magit-remote-add (remote url) + "Add a remote named REMOTE and fetch it." + (interactive (list (magit-read-string-ns "Remote name") + (magit-read-url "Remote url"))) + (if (pcase (list magit-remote-add-set-branch.pushDefault + (magit-get "branch.defaultPush")) + (`(,(pred stringp) ,_) t) + ((or `(ask ,_) `(ask-if-unset nil)) + (y-or-n-p (format "Set `branch.pushDefault' to \"%s\"? " remote)))) + (progn (magit-call-git "remote" "add" "-f" remote url) + (magit-call-git "config" "branch.pushDefault" remote) + (magit-refresh)) + (magit-run-git-async "remote" "add" "-f" remote url))) + +;;;###autoload +(defun magit-remote-rename (old new) + "Rename the remote named OLD to NEW." + (interactive + (let ((remote (magit-read-remote "Rename remote"))) + (list remote (magit-read-string-ns (format "Rename %s to" remote))))) + (unless (string= old new) + (magit-run-git "remote" "rename" old new))) + +;;;###autoload +(defun magit-remote-set-url (remote url) + "Change the url of the remote named REMOTE to URL." + (interactive + (let ((remote (magit-read-remote "Set url of remote"))) + (list remote (magit-read-url + "Url" (magit-get "remote" remote "url"))))) + (magit-run-git "remote" "set-url" remote url)) + +;;;###autoload +(defun magit-remote-remove (remote) + "Delete the remote named REMOTE." + (interactive (list (magit-read-remote "Delete remote"))) + (magit-run-git "remote" "rm" remote)) + +;;; Fetch + +;;;###autoload (autoload 'magit-fetch-popup "magit-remote" nil t) +(magit-define-popup magit-fetch-popup + "Popup console for fetch commands." + 'magit-commands + :man-page "git-fetch" + :switches '((?p "Prune deleted branches" "--prune")) + :actions '("Fetch from" + (?p magit-get-push-remote magit-fetch-from-pushremote) + (?u magit-get-remote magit-fetch-from-upstream) + (?e "elsewhere" magit-fetch) + (?a "all remotes" magit-fetch-all) + "Fetch" + (?m "submodules" magit-submodule-fetch)) + :default-action 'magit-fetch + :max-action-columns 1) + +(defun magit-git-fetch (remote args) + (run-hooks 'magit-credential-hook) + (magit-run-git-async-no-revert "fetch" remote args)) + +;;;###autoload +(defun magit-fetch-from-pushremote (args) + "Fetch from the push-remote of the current branch." + (interactive (list (magit-fetch-arguments))) + (--if-let (magit-get-push-remote) + (magit-git-fetch it args) + (--if-let (magit-get-current-branch) + (user-error "No push-remote is configured for %s" it) + (user-error "No branch is checked out")))) + +;;;###autoload +(defun magit-fetch-from-upstream (args) + "Fetch from the upstream repository of the current branch." + (interactive (list (magit-fetch-arguments))) + (--if-let (magit-get-remote) + (magit-git-fetch it args) + (--if-let (magit-get-current-branch) + (user-error "No upstream is configured for %s" it) + (user-error "No branch is checked out")))) + +;;;###autoload +(defun magit-fetch (remote args) + "Fetch from another repository." + (interactive (list (magit-read-remote "Fetch remote") + (magit-fetch-arguments))) + (magit-git-fetch remote args)) + +;;;###autoload +(defun magit-fetch-all (args) + "Fetch from all remotes." + (interactive (list (magit-fetch-arguments))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async-no-revert "remote" "update" args)) + +;;;###autoload +(defun magit-fetch-all-prune () + "Fetch from all remotes, and prune. +Prune remote tracking branches for branches that have been +removed on the respective remote." + (interactive) + (run-hooks 'magit-credential-hook) + (magit-run-git-async-no-revert "remote" "update" "--prune")) + +;;;###autoload +(defun magit-fetch-all-no-prune () + "Fetch from all remotes." + (interactive) + (run-hooks 'magit-credential-hook) + (magit-run-git-async-no-revert "remote" "update")) + +;;; Pull + +;;;###autoload (autoload 'magit-pull-popup "magit-remote" nil t) +(magit-define-popup magit-pull-popup + "Popup console for pull commands." + 'magit-commands + :man-page "git-pull" + :variables '("Variables" + (?r "branch.%s.rebase" + magit-cycle-branch*rebase + magit-pull-format-branch*rebase)) + :actions '((lambda () + (--if-let (magit-get-current-branch) + (concat + (propertize "Pull into " 'face 'magit-popup-heading) + (propertize it 'face 'magit-branch-local) + (propertize " from" 'face 'magit-popup-heading)) + (propertize "Pull from" 'face 'magit-popup-heading))) + (?p magit-get-push-branch magit-pull-from-pushremote) + (?u magit-get-upstream-branch magit-pull-from-upstream) + (?e "elsewhere" magit-pull)) + :default-action 'magit-pull + :max-action-columns 1) + +;;;###autoload (autoload 'magit-pull-and-fetch-popup "magit-remote" nil t) +(magit-define-popup magit-pull-and-fetch-popup + "Popup console for pull and fetch commands. + +This popup is intended as a replacement for the separate popups +`magit-pull-popup' and `magit-fetch-popup'. To use it, add this +to your init file: + + (with-eval-after-load \\='magit-remote + (define-key magit-mode-map \"f\" \\='magit-pull-and-fetch-popup) + (define-key magit-mode-map \"F\" nil)) + +The combined popup does not offer all commands and arguments +available from the individual popups. Instead of the argument +`--prune' and the command `magit-fetch-all' it uses two commands +`magit-fetch-prune' and `magit-fetch-no-prune'. And the commands +`magit-fetch-from-pushremote' and `magit-fetch-from-upstream' are +missing. To add them use something like: + + (with-eval-after-load \\='magit-remote + (magit-define-popup-action \\='magit-pull-and-fetch-popup ?U + \\='magit-get-upstream-branch + \\='magit-fetch-from-upstream-remote ?F) + (magit-define-popup-action \\='magit-pull-and-fetch-popup ?P + \\='magit-get-push-branch + \\='magit-fetch-from-push-remote ?F))" + 'magit-commands + :man-page "git-pull" + :variables '("Pull variables" + (?r "branch.%s.rebase" + magit-cycle-branch*rebase + magit-pull-format-branch*rebase)) + :actions '((lambda () + (--if-let (magit-get-current-branch) + (concat + (propertize "Pull into " 'face 'magit-popup-heading) + (propertize it 'face 'magit-branch-local) + (propertize " from" 'face 'magit-popup-heading)) + (propertize "Pull from" 'face 'magit-popup-heading))) + (?p magit-get-push-branch magit-pull-from-pushremote) + (?u magit-get-upstream-branch magit-pull-from-upstream) + (?e "elsewhere" magit-pull) + "Fetch from" + (?f "remotes" magit-fetch-all-no-prune) + (?F "remotes and prune" magit-fetch-all-prune) + "Fetch" + (?m "submodules" magit-submodule-fetch)) + :default-action 'magit-fetch + :max-action-columns 1) + +(defun magit-pull-format-branch*rebase () + (magit-popup-format-variable (format "branch.%s.rebase" + (or (magit-get-current-branch) "")) + '("true" "false") + "false" "pull.rebase")) + +(defun magit-git-pull (source args) + (run-hooks 'magit-credential-hook) + (-let [(remote . branch) + (magit-split-branch-name source)] + (magit-run-git-with-editor "pull" args remote branch))) + +;;;###autoload +(defun magit-pull-from-pushremote (args) + "Pull from the push-remote of the current branch." + (interactive (list (magit-pull-arguments))) + (--if-let (magit-get-push-branch) + (magit-git-pull it args) + (--if-let (magit-get-current-branch) + (user-error "No push-remote is configured for %s" it) + (user-error "No branch is checked out")))) + +;;;###autoload +(defun magit-pull-from-upstream (args) + "Pull from the upstream of the current branch." + (interactive (list (magit-pull-arguments))) + (--if-let (magit-get-upstream-branch) + (magit-git-pull it args) + (--if-let (magit-get-current-branch) + (user-error "No upstream is configured for %s" it) + (user-error "No branch is checked out")))) + +;;;###autoload +(defun magit-pull (source args) + "Pull from a branch read in the minibuffer." + (interactive (list (magit-read-remote-branch "Pull" nil nil nil t) + (magit-pull-arguments))) + (magit-git-pull source args)) + +;;; Push + +(defcustom magit-push-current-set-remote-if-missing t + "Whether to configure missing remotes before pushing. + +When nil, then the command `magit-push-current-to-pushremote' and +`magit-push-current-to-upstream' do not appear in the push popup +if the push-remote resp. upstream is not configured. If the user +invokes one of these commands anyway, then it raises an error. + +When non-nil, then these commands always appear in the push +popup. But if the required configuration is missing, then they +do appear in a way that indicates that this is the case. If the +user invokes one of them, then it asks for the necessary +configuration, stores the configuration, and then uses it to push +a first time. + +This option also affects whether the argument `--set-upstream' is +available in the popup. If the value is t, then that argument is +redundant. But note that changing the value of this option does +not take affect immediately, the argument will only be added or +removed after restarting Emacs." + :package-version '(magit . "2.4.0") + :group 'magit-commands + :type 'boolean) + +;;;###autoload (autoload 'magit-push-popup "magit-remote" nil t) +(magit-define-popup magit-push-popup + "Popup console for push commands." + 'magit-commands + :man-page "git-push" + :switches `((?f "Force" "--force-with-lease") + (?h "Disable hooks" "--no-verify") + (?d "Dry run" "--dry-run") + ,@(and (not magit-push-current-set-remote-if-missing) + '((?u "Set upstream" "--set-upstream")))) + :actions '((lambda () + (--when-let (magit-get-current-branch) + (concat (propertize "Push " 'face 'magit-popup-heading) + (propertize it 'face 'magit-branch-local) + (propertize " to" 'face 'magit-popup-heading)))) + (?p magit--push-current-to-pushremote-desc + magit-push-current-to-pushremote) + (?u magit--push-current-to-upstream-desc + magit-push-current-to-upstream) + (?e "elsewhere\n" magit-push-current) + "Push" + (?o "another branch" magit-push) + (?T "a tag" magit-push-tag) + (?m "matching branches" magit-push-matching) + (?t "all tags" magit-push-tags)) + :max-action-columns 2) + +(defun magit-git-push (branch target args) + (run-hooks 'magit-credential-hook) + (-let [(remote . target) + (magit-split-branch-name target)] + (magit-run-git-async-no-revert "push" "-v" args remote + (format "%s:refs/heads/%s" + branch target)))) + +;;;###autoload +(defun magit-push-current-to-pushremote (args &optional push-remote) + "Push the current branch to `branch..pushRemote'. +If that variable is unset, then push to `remote.pushDefault'. + +When `magit-push-current-set-remote-if-missing' is non-nil and +the push-remote is not configured, then read the push-remote from +the user, set it, and then push to it. With a prefix argument +the push-remote can be changed before pushed to it." + (interactive + (list (magit-push-arguments) + (and (magit--push-current-set-pushremote-p current-prefix-arg) + (magit-read-remote (format "Set push-remote of %s and push there" + (magit-get-current-branch)))))) + (--if-let (magit-get-current-branch) + (progn (when push-remote + (magit-call-git "config" + (format "branch.%s.pushRemote" + (magit-get-current-branch)) + push-remote)) + (-if-let (remote (magit-get-push-remote it)) + (if (member remote (magit-list-remotes)) + (magit-git-push it (concat remote "/" it) args) + (user-error "Remote `%s' doesn't exist" remote)) + (user-error "No push-remote is configured for %s" it))) + (user-error "No branch is checked out"))) + +(defun magit--push-current-set-pushremote-p (&optional change) + (and (or change + (and magit-push-current-set-remote-if-missing + (not (magit-get-push-remote)))) + (magit-get-current-branch))) + +(defun magit--push-current-to-pushremote-desc () + (--if-let (magit-get-push-branch) + (concat (magit-branch-set-face it) "\n") + (and (magit--push-current-set-pushremote-p) + (concat (propertize "pushRemote" 'face 'bold) + ", after setting that\n")))) + +;;;###autoload +(defun magit-push-current-to-upstream (args &optional upstream) + "Push the current branch to its upstream branch. + +When `magit-push-current-set-remote-if-missing' is non-nil and +the upstream is not configured, then read the upstream from the +user, set it, and then push to it. With a prefix argument the +upstream can be changed before pushed to it." + (interactive + (list (magit-push-arguments) + (and (magit--push-current-set-upstream-p current-prefix-arg) + (magit-read-remote-branch + (format "Set upstream of %s and push there" + (magit-get-current-branch)))))) + (--if-let (magit-get-current-branch) + (progn + (when upstream + (-let (((remote . merge) (magit-split-branch-name upstream)) + (branch (magit-get-current-branch))) + (magit-call-git "config" (format "branch.%s.remote" branch) remote) + (magit-call-git "config" (format "branch.%s.merge" branch) + (concat "refs/heads/" merge)))) + (-if-let (target (magit-get-upstream-branch it)) + (magit-git-push it target args) + (user-error "No upstream is configured for %s" it))) + (user-error "No branch is checked out"))) + +(defun magit--push-current-set-upstream-p (&optional change) + (and (or change + (and magit-push-current-set-remote-if-missing + (not (magit-get-upstream-branch)))) + (magit-get-current-branch))) + +(defun magit--push-current-to-upstream-desc () + (--if-let (magit-get-upstream-branch) + (concat (magit-branch-set-face it) "\n") + (and (magit--push-current-set-upstream-p) + (concat (propertize "@{upstream}" 'face 'bold) + ", after setting that\n")))) + +;;;###autoload +(defun magit-push-current (target args) + "Push the current branch to a branch read in the minibuffer." + (interactive + (--if-let (magit-get-current-branch) + (list (magit-read-remote-branch (format "Push %s to" it) + nil nil it 'confirm) + (magit-push-arguments)) + (user-error "No branch is checked out"))) + (magit-git-push (magit-get-current-branch) target args)) + +;;;###autoload +(defun magit-push (source target args) + "Push an arbitrary branch or commit somewhere. +Both the source and the target are read in the minibuffer." + (interactive + (let ((source (magit-read-local-branch-or-commit "Push"))) + (list source + (magit-read-remote-branch (format "Push %s to" source) nil + (magit-get-upstream-branch source) + source 'confirm) + (magit-push-arguments)))) + (magit-git-push source target args)) + +;;;###autoload +(defun magit-push-matching (remote &optional args) + "Push all matching branches to another repository. +If multiple remotes exist, then read one from the user. +If just one exists, use that without requiring confirmation." + (interactive (list (magit-read-remote "Push matching branches to" nil t) + (magit-push-arguments))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async-no-revert "push" "-v" args remote ":")) + +;;;###autoload +(defun magit-push-tags (remote &optional args) + "Push all tags to another repository. +If only one remote exists, then push to that. Otherwise prompt +for a remote, offering the remote configured for the current +branch as default." + (interactive (list (magit-read-remote "Push tags to remote" nil t) + (magit-push-arguments))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async-no-revert "push" remote "--tags" args)) + +;;;###autoload +(defun magit-push-tag (tag remote &optional args) + "Push a tag to another repository." + (interactive + (let ((tag (magit-read-tag "Push tag"))) + (list tag (magit-read-remote (format "Push %s to remote" tag) nil t) + (magit-push-arguments)))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async-no-revert "push" remote tag args)) + +;;;###autoload +(defun magit-push-implicitly (args) + "Push somewhere without using an explicit refspec. + +This command simply runs \"git push -v [ARGS]\". ARGS are the +arguments specified in the popup buffer. No explicit refspec +arguments are used. Instead the behavior depends on at least +these Git variables: `push.default', `branch.pushDefault', +`branch..pushRemote', `branch..remote', +`branch..merge', and `remote..push'. + +To add this command to the push popup add this to your init file: + + (with-eval-after-load \\='magit-remote + (magit-define-popup-action \\='magit-push-popup ?P + 'magit-push-implicitly--desc + 'magit-push-implicitly ?p t)) + +The function `magit-push-implicitly--desc' attempts to predict +what this command will do, the value it returns is displayed in +the popup buffer." + (interactive (list (magit-push-arguments))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async-no-revert "push" "-v" args)) + +(defun magit-push-implicitly--desc () + (let ((default (magit-get "push.default"))) + (unless (equal default "nothing") + (or (-when-let* ((remote (or (magit-get-remote) + (magit-remote-p "origin"))) + (refspec (magit-get "remote" remote "push"))) + (format "%s using %s" + (propertize remote 'face 'magit-branch-remote) + (propertize refspec 'face 'bold))) + (--when-let (and (not (magit-get-push-branch)) + (magit-get-upstream-branch)) + (format "%s aka %s\n" + (magit-branch-set-face it) + (propertize "@{upstream}" 'face 'bold))) + (--when-let (magit-get-push-branch) + (format "%s aka %s\n" + (magit-branch-set-face it) + (propertize "pushRemote" 'face 'bold))) + (--when-let (magit-get-@{push}-branch) + (format "%s aka %s\n" + (magit-branch-set-face it) + (propertize "@{push}" 'face 'bold))) + (format "using %s (%s is %s)\n" + (propertize "git push" 'face 'bold) + (propertize "push.default" 'face 'bold) + (propertize default 'face 'bold)))))) + +;;;###autoload +(defun magit-push-to-remote (remote args) + "Push to REMOTE without using an explicit refspec. +The REMOTE is read in the minibuffer. + +This command simply runs \"git push -v [ARGS] REMOTE\". ARGS +are the arguments specified in the popup buffer. No refspec +arguments are used. Instead the behavior depends on at least +these Git variables: `push.default', `branch.pushDefault', +`branch..pushRemote', `branch..remote', +`branch..merge', and `remote..push'. + +To add this command to the push popup add this to your init file: + + (with-eval-after-load \\='magit-remote + (magit-define-popup-action \\='magit-push-popup ?r + 'magit-push-to-remote--desc + 'magit-push-to-remote ?p t))" + (interactive (list (magit-read-remote "Push to remote") + (magit-push-arguments))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async-no-revert "push" "-v" args remote)) + +(defun magit-push-to-remote--desc () + (format "using %s\n" (propertize "git push " 'face 'bold))) + +;;; Email + +;;;###autoload (autoload 'magit-patch-popup "magit-remote" nil t) +(magit-define-popup magit-patch-popup + "Popup console for patch commands." + 'magit-commands + :man-page "git-format-patch" + :options '("Options for formatting patches" + (?f "From" "--from=") + (?t "To" "--to=") + (?c "CC" "--cc=") + (?r "In reply to" "--in-reply-to=") + (?v "Reroll count" "--reroll-count=") + (?s "Thread style" "--thread=") + (?U "Context lines" "-U") + (?M "Detect renames" "-M") + (?C "Detect copies" "-C") + (?A "Diff algorithm" "--diff-algorithm=" + magit-diff-select-algorithm) + (?o "Output directory" "--output-directory=")) + :actions '((?p "Format patches" magit-format-patch) + (?r "Request pull" magit-request-pull)) + :default-action 'magit-format-patch) + +;;;###autoload +(defun magit-format-patch (range args) + "Create patches for the commits in RANGE. +When a single commit is given for RANGE, create a patch for the +changes introduced by that commit (unlike 'git format-patch' +which creates patches for all commits that are reachable from +HEAD but not from the specified commit)." + (interactive + (list (-if-let (revs (magit-region-values 'commit)) + (concat (car (last revs)) "^.." (car revs)) + (let ((range (magit-read-range-or-commit "Format range or commit"))) + (if (string-match-p "\\.\\." range) + range + (format "%s~..%s" range range)))) + (magit-patch-arguments))) + (magit-run-git-no-revert "format-patch" range args)) + +;;;###autoload +(defun magit-request-pull (url start end) + "Request upstream to pull from you public repository. + +URL is the url of your publically accessible repository. +START is a commit that already is in the upstream repository. +END is the last commit, usually a branch name, which upstream +is asked to pull. START has to be reachable from that commit." + (interactive + (list (magit-get "remote" (magit-read-remote "Remote") "url") + (magit-read-branch-or-commit "Start" (magit-get-upstream-branch)) + (magit-read-branch-or-commit "End"))) + (let ((dir default-directory)) + ;; mu4e changes default-directory + (compose-mail) + (setq default-directory dir)) + (message-goto-body) + (let ((inhibit-magit-revert t)) + (magit-git-insert "request-pull" start url end)) + (set-buffer-modified-p nil)) + +;;; magit-remote.el ends soon +(provide 'magit-remote) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-remote.el ends here diff --git a/elpa/magit-20151223.1425/magit-section.el b/elpa/magit-20151223.1425/magit-section.el new file mode 100644 index 00000000..bb894f99 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-section.el @@ -0,0 +1,1134 @@ +;;; magit-section.el --- section functionality -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library implements "sections" as used in all Magit buffers. +;; If you have used Magit before then you probably know what that +;; means, otherwise think "read-only Org-Mode for Git", kinda. + +;;; Code: + +(require 'cl-lib) +(require 'dash) + +(require 'magit-utils) + +(defvar magit-keep-region-overlay) + +;;; Options + +(defgroup magit-section nil + "Expandable sections." + :group 'magit) + +(defcustom magit-section-show-child-count t + "Whether to append the number of children to section headings." + :package-version '(magit . "2.1.0") + :group 'magit-section + :type 'boolean) + +(defcustom magit-section-movement-hook + '(magit-hunk-set-window-start + magit-log-maybe-update-revision-buffer + magit-log-maybe-show-more-commits) + "Hook run by `magit-section-goto'. +That function in turn is used by all section movement commands." + :package-version '(magit . "2.3.0") + :group 'magit-section + :type 'hook + :options '(magit-hunk-set-window-start + magit-status-maybe-update-revision-buffer + magit-status-maybe-update-blob-buffer + magit-log-maybe-update-revision-buffer + magit-log-maybe-update-blob-buffer + magit-log-maybe-show-more-commits)) + +(defcustom magit-section-highlight-hook + '(magit-diff-highlight + magit-section-highlight + magit-section-highlight-selection) + "Functions used to highlight the current section. +Each function is run with the current section as only argument +until one of them returns non-nil." + :package-version '(magit . "2.1.0") + :group 'magit-section + :type 'hook + :options '(magit-diff-highlight + magit-section-highlight + magit-section-highlight-selection)) + +(defcustom magit-section-unhighlight-hook + '(magit-diff-unhighlight) + "Functions used to unhighlight the previously current section. +Each function is run with the current section as only argument +until one of them returns non-nil. Most sections are properly +unhighlighted without requiring a specialized unhighlighter, +diff-related sections being the only exception." + :package-version '(magit . "2.1.0") + :group 'magit-section + :type 'hook + :options '(magit-diff-unhighlight)) + +(defcustom magit-section-set-visibility-hook + '(magit-diff-expansion-threshold + magit-section-set-visibility-from-cache) + "Hook used to set the initial visibility of a section. +Stop at the first function that returns non-nil. The value +should be `show' or `hide'. If no function returns non-nil +determine the visibility as usual, i.e. use the hardcoded +section specific default (see `magit-insert-section')." + :package-version '(magit . "2.4.0") + :group 'magit-section + :type 'hook + :options '(magit-diff-expansion-threshold + magit-section-set-visibility-from-cache)) + +(defface magit-section-highlight + '((((class color) (background light)) :background "grey95") + (((class color) (background dark)) :background "grey20")) + "Face for highlighting the current section." + :group 'magit-faces) + +(defface magit-section-heading + '((((class color) (background light)) :foreground "DarkGoldenrod4" :weight bold) + (((class color) (background dark)) :foreground "LightGoldenrod2" :weight bold)) + "Face for section headings." + :group 'magit-faces) + +(defface magit-section-secondary-heading '((t :weight bold)) + "Face for section headings of some secondary headings." + :group 'magit-faces) + +(defface magit-section-heading-selection + '((((class color) (background light)) :foreground "salmon4") + (((class color) (background dark)) :foreground "LightSalmon3")) + "Face for selected section headings." + :group 'magit-faces) + +;;; Core + +(cl-defstruct magit-section + type value start content end hidden washer refined + source diff-header process parent children) + +(defvar-local magit-root-section nil + "The root section in the current buffer. +All other sections are descendants of this section. The value +of this variable is set by `magit-insert-section' and you should +never modify it.") +(put 'magit-root-section 'permanent-local t) + +(defun magit-current-section () + "Return the section at point." + (or (get-text-property (point) 'magit-section) magit-root-section)) + +(defun magit-section-ident (section) + "Return an unique identifier for SECTION. +The return value has the form ((TYPE . VALUE)...)." + (cons (cons (magit-section-type section) + (magit-section-value section)) + (--when-let (magit-section-parent section) + (magit-section-ident it)))) + +(defun magit-get-section (ident &optional root) + "Return the section identified by IDENT. +IDENT has to be a list as returned by `magit-section-ident'." + (setq ident (reverse ident)) + (let ((section (or root magit-root-section))) + (when (eq (car (pop ident)) (magit-section-type section)) + (while (and ident + (setq section + (--first + (and (eq (caar ident) (magit-section-type it)) + (equal (cdar ident) (magit-section-value it))) + (magit-section-children section)))) + (pop ident)) + section))) + +(defvar magit-insert-section--current nil "For internal use only.") +(defvar magit-insert-section--parent nil "For internal use only.") +(defvar magit-insert-section--oldroot nil "For internal use only.") + +;;; Commands +;;;; Movement + +(defun magit-section-forward () + "Move to the beginning of the next visible section." + (interactive) + (if (eobp) + (user-error "No next section") + (let ((section (magit-current-section))) + (if (magit-section-parent section) + (let ((next (and (not (magit-section-hidden section)) + (not (= (magit-section-end section) (1+ (point)))) + (car (magit-section-children section))))) + (while (and section (not next)) + (unless (setq next (car (magit-section-siblings section 'next))) + (setq section (magit-section-parent section)))) + (if next + (magit-section-goto next) + (user-error "No next section"))) + (magit-section-goto 1))))) + +(defun magit-section-backward () + "Move to the beginning of the current or the previous visible section. +When point is at the beginning of a section then move to the +beginning of the previous visible section. Otherwise move to +the beginning of the current section." + (interactive) + (if (bobp) + (user-error "No previous section") + (let ((section (magit-current-section)) children) + (cond + ((and (= (point) (1- (magit-section-end section))) + (setq children (magit-section-children section))) + (magit-section-goto (car (last children)))) + ((and (magit-section-parent section) + (not (= (point) (magit-section-start section)))) + (magit-section-goto section)) + (t + (let ((prev (car (magit-section-siblings section 'prev)))) + (if prev + (while (and (not (magit-section-hidden prev)) + (setq children (magit-section-children prev))) + (setq prev (car (last children)))) + (setq prev (magit-section-parent section))) + (cond (prev + (magit-section-goto prev)) + ((magit-section-parent section) + (user-error "No previous section")) + ;; Eob special cases. + ((not (get-text-property (1- (point)) 'invisible)) + (magit-section-goto -1)) + (t + (goto-char (previous-single-property-change + (1- (point)) 'invisible)) + (forward-line -1) + (magit-section-goto (magit-current-section)))))))))) + +(defun magit-section-up () + "Move to the beginning of the parent section." + (interactive) + (--if-let (magit-section-parent (magit-current-section)) + (magit-section-goto it) + (user-error "No parent section"))) + +(defun magit-section-forward-sibling () + "Move to the beginning of the next sibling section. +If there is no next sibling section, then move to the parent." + (interactive) + (let ((current (magit-current-section))) + (if (magit-section-parent current) + (--if-let (car (magit-section-siblings current 'next)) + (magit-section-goto it) + (magit-section-forward)) + (magit-section-goto 1)))) + +(defun magit-section-backward-sibling () + "Move to the beginning of the previous sibling section. +If there is no previous sibling section, then move to the parent." + (interactive) + (let ((current (magit-current-section))) + (if (magit-section-parent current) + (--if-let (car (magit-section-siblings current 'prev)) + (magit-section-goto it) + (magit-section-backward)) + (magit-section-goto -1)))) + +(defun magit-section-goto (arg) + (if (integerp arg) + (progn (forward-line arg) + (setq arg (magit-current-section))) + (goto-char (magit-section-start arg))) + (run-hook-with-args 'magit-section-movement-hook arg)) + +(defun magit-section-set-window-start (section) + "Ensure the beginning of SECTION is visible." + (unless (pos-visible-in-window-p (magit-section-end section)) + (set-window-start (selected-window) (magit-section-start section)))) + +(defun magit-hunk-set-window-start (section) + "Ensure the beginning of the `hunk' SECTION is visible. +It the SECTION has a different type, then do nothing." + (when (eq (magit-section-type section) 'hunk) + (magit-section-set-window-start section))) + +(defmacro magit-define-section-jumper (name heading type &optional value) + "Define an interactive function to go some section. +Together TYPE and VALUE identify the section. +HEADING is the displayed heading of the section." + (declare (indent defun)) + `(defun ,name (&optional expand) ,(format "\ +Jump to the section \"%s\". +With a prefix argument also expand it." heading) + (interactive "P") + (--if-let (magit-get-section + (cons (cons ',type ,value) + (magit-section-ident magit-root-section))) + (progn (goto-char (magit-section-start it)) + (when expand + (with-local-quit (magit-section-show it)) + (recenter 0))) + (message ,(format "Section \"%s\" wasn't found" heading))))) + +;;;; Visibility + +(defun magit-section-show (section) + "Show the body of the current section." + (interactive (list (magit-current-section))) + (setf (magit-section-hidden section) nil) + (-when-let (washer (magit-section-washer section)) + (setf (magit-section-washer section) nil) + (let ((inhibit-read-only t) + (magit-insert-section--parent section) + (content (magit-section-content section))) + (save-excursion + (if (and content (< content (magit-section-end section))) + (funcall washer section) ; already partially washed (hunk) + (goto-char (magit-section-end section)) + (setf (magit-section-content section) (point-marker)) + (funcall washer) + (setf (magit-section-end section) (point-marker))))) + (magit-section-update-highlight)) + (-when-let (beg (magit-section-content section)) + (remove-overlays beg (magit-section-end section) 'invisible t)) + (magit-section-update-visibility-cache section) + (dolist (child (magit-section-children section)) + (if (magit-section-hidden child) + (magit-section-hide child) + (magit-section-show child)))) + +(defun magit-section-hide (section) + "Hide the body of the current section." + (interactive (list (magit-current-section))) + (if (eq section magit-root-section) + (user-error "Cannot hide root section") + (setf (magit-section-hidden section) t) + (-when-let (beg (magit-section-content section)) + (let ((end (magit-section-end section))) + (remove-overlays beg end 'invisible t) + (let ((o (make-overlay beg end))) + (overlay-put o 'evaporate t) + (overlay-put o 'invisible t)))))) + +(defun magit-section-toggle (section) + "Toggle visibility of the body of the current section." + (interactive (list (magit-current-section))) + (if (eq section magit-root-section) + (user-error "Cannot hide root section") + (goto-char (magit-section-start section)) + (if (magit-section-hidden section) + (magit-section-show section) + (magit-section-hide section)))) + +(defun magit-section-toggle-children (section) + "Toggle visibility of bodies of children of the current section." + (interactive (list (magit-current-section))) + (goto-char (magit-section-start section)) + (let* ((children (magit-section-children section)) + (show (-any? 'magit-section-hidden children))) + (dolist (c children) + (setf (magit-section-hidden c) show))) + (magit-section-show section)) + +(defun magit-section-show-children (section &optional depth) + "Recursively show the bodies of children of the current section. +With a prefix argument show children that deep and hide deeper +children." + (interactive (list (magit-current-section))) + (magit-section-show-children-1 section depth) + (magit-section-show section)) + +(defun magit-section-show-children-1 (section &optional depth) + (dolist (s (magit-section-children section)) + (setf (magit-section-hidden s) nil) + (if depth + (if (> depth 0) + (magit-section-show-children-1 s (1- depth)) + (magit-section-hide s)) + (magit-section-show-children-1 s)))) + +(defun magit-section-hide-children (section) + "Recursively hide the bodies of children of the current section." + (interactive (list (magit-current-section))) + (mapc 'magit-section-hide (magit-section-children section))) + +(defun magit-section-show-headings (section) + "Recursively show headings of children of the current section. +Only show the headings, previously shown text-only bodies are +hidden." + (interactive (list (magit-current-section))) + (magit-section-show-headings-1 section) + (magit-section-show section)) + +(defun magit-section-show-headings-1 (section) + (dolist (s (magit-section-children section)) + (setf (magit-section-hidden s) nil) + (when (or (magit-section-children s) + (not (magit-section-content s))) + (magit-section-show-headings-1 s)))) + +(defun magit-section-cycle (section) + "Cycle visibility of current section and its children." + (interactive (list (magit-current-section))) + (goto-char (magit-section-start section)) + (if (magit-section-hidden section) + (progn (magit-section-show section) + (magit-section-hide-children section)) + (let ((children (magit-section-children section))) + (cond ((and (-any? 'magit-section-hidden children) + (-any? 'magit-section-children children)) + (magit-section-show-headings section)) + ((-any? 'magit-section-hidden-body children) + (magit-section-show-children section)) + (t + (magit-section-hide section)))))) + +(defun magit-section-cycle-global () + "Cycle visibility of all sections in the current buffer." + (interactive) + (let ((children (magit-section-children magit-root-section))) + (cond ((and (-any? 'magit-section-hidden children) + (-any? 'magit-section-children children)) + (magit-section-show-headings magit-root-section)) + ((-any? 'magit-section-hidden-body children) + (magit-section-show-children magit-root-section)) + (t + (mapc 'magit-section-hide children))))) + +(defun magit-section-cycle-diffs () + "Cycle visibility of diff-related sections in the current buffer." + (interactive) + (-when-let (sections + (cond ((derived-mode-p 'magit-status-mode) + (--mapcat + (when it + (when (magit-section-hidden it) + (magit-section-show it)) + (magit-section-children it)) + (list (magit-get-section '((staged) (status))) + (magit-get-section '((unstaged) (status)))))) + ((derived-mode-p 'magit-diff-mode) + (--filter (eq (magit-section-type it) 'file) + (magit-section-children magit-root-section))))) + (if (-any? 'magit-section-hidden sections) + (dolist (s sections) + (magit-section-show s) + (magit-section-hide-children s)) + (let ((children (cl-mapcan 'magit-section-children sections))) + (cond ((and (-any? 'magit-section-hidden children) + (-any? 'magit-section-children children)) + (mapc 'magit-section-show-headings sections)) + ((-any? 'magit-section-hidden-body children) + (mapc 'magit-section-show-children sections)) + (t + (mapc 'magit-section-hide sections))))))) + +(defun magit-section-hidden-body (section &optional pred) + (--if-let (magit-section-children section) + (funcall (or pred '-any?) 'magit-section-hidden-body it) + (and (magit-section-content section) + (magit-section-hidden section)))) + +(defun magit-section-invisible-p (section) + "Return t if the SECTION's body is invisible. +When the body of an ancestor of SECTION is collapsed then +SECTION's body (and heading) obviously cannot be visible." + (or (magit-section-hidden section) + (--when-let (magit-section-parent section) + (magit-section-invisible-p it)))) + +(defun magit-section-show-level (level) + "Show surrounding sections up to LEVEL. +If LEVEL is negative show up to the absolute value. +Sections at higher levels are hidden." + (if (< level 0) + (let ((s (magit-current-section))) + (setq level (- level)) + (while (> (1- (length (magit-section-ident s))) level) + (setq s (magit-section-parent s)) + (goto-char (magit-section-start s))) + (magit-section-show-children magit-root-section (1- level))) + (cl-do* ((s (magit-current-section) (magit-section-parent s)) + (i (1- (length (magit-section-ident s))) (cl-decf i))) + ((cond ((< i level) (magit-section-show-children s (- level i 1)) t) + ((= i level) (magit-section-hide s) t)) + (magit-section-goto s))))) + +(defun magit-section-show-level-1 () + "Show surrounding sections on first level." + (interactive) + (magit-section-show-level 1)) + +(defun magit-section-show-level-1-all () + "Show all sections on first level." + (interactive) + (magit-section-show-level -1)) + +(defun magit-section-show-level-2 () + "Show surrounding sections up to second level." + (interactive) + (magit-section-show-level 2)) + +(defun magit-section-show-level-2-all () + "Show all sections up to second level." + (interactive) + (magit-section-show-level -2)) + +(defun magit-section-show-level-3 () + "Show surrounding sections up to third level." + (interactive) + (magit-section-show-level 3)) + +(defun magit-section-show-level-3-all () + "Show all sections up to third level." + (interactive) + (magit-section-show-level -3)) + +(defun magit-section-show-level-4 () + "Show surrounding sections up to fourth level." + (interactive) + (magit-section-show-level 4)) + +(defun magit-section-show-level-4-all () + "Show all sections up to fourth level." + (interactive) + (magit-section-show-level -4)) + +;;;; Auxiliary + +(defun magit-describe-section () + "Show information about the section at point. +This command is intended for debugging purposes." + (interactive) + (let ((section (magit-current-section))) + (message "%S %S %s-%s" + (magit-section-value section) + (apply 'vector (mapcar 'car (magit-section-ident section))) + (marker-position (magit-section-start section)) + (marker-position (magit-section-end section))))) + +;;; Match + +(defun magit-section-match (condition &optional section) + "Return t if SECTION matches CONDITION. +SECTION defaults to the section at point. + +Conditions can take the following forms: + (CONDITION...) matches if any of the CONDITIONs matches. + [TYPE...] matches if the first TYPE matches the type + of the section at point, the second matches + that of its parent, and so on. + [* TYPE...] matches sections that match [TYPE...] and + also recursively all their child sections. + TYPE matches TYPE regardless of its parents. + +Each TYPE is a symbol. Note that is not necessary to specify all +TYPEs up to the root section as printed by `magit-describe-type', +unless of course your want to be that precise." + ;; When recursing SECTION actually is a type list. Matching + ;; macros also pass such a list instead of a section struct. + (let ((types (if (magit-section-p section) + (mapcar 'car (magit-section-ident section)) + section))) + (when (or types section (magit-current-section)) + (if (listp condition) + (--first (magit-section-match it types) condition) + (magit-section-match-1 (if (symbolp condition) + (list condition) + (append condition nil)) + types))))) + +(defun magit-section-match-1 (l1 l2) + (or (null l1) + (if (eq (car l1) '*) + (or (magit-section-match-1 (cdr l1) l2) + (and l2 + (magit-section-match-1 l1 (cdr l2)))) + (and l2 + (equal (car l1) (car l2)) + (magit-section-match-1 (cdr l1) (cdr l2)))))) + +(defmacro magit-section-when (condition &rest body) + "If the section at point matches CONDITION evaluate BODY. + +If the section matches evaluate BODY forms sequentially and +return the value of the last one, or if there are no BODY forms +return the value of the section. If the section does not match +return nil. + +See `magit-section-match' for the forms CONDITION can take." + (declare (indent 1) + (debug (sexp body))) + `(--when-let (magit-current-section) + (when (magit-section-match ',condition + (mapcar 'car (magit-section-ident it))) + ,@(or body '((magit-section-value it)))))) + +(defmacro magit-section-case (&rest clauses) + "Choose among clauses on the type of the section at point. + +Each clause looks like (CONDITION BODY...). The type of the +section is compared against each CONDITION; the BODY forms of the +first match are evaluated sequentially and the value of the last +form is returned. Inside BODY the symbol `it' is bound to the +section at point. If no clause succeeds or if there is no +section at point return nil. + +See `magit-section-match' for the forms CONDITION can take. +Additionally a CONDITION of t is allowed in the final clause, and +matches if no other CONDITION match, even if there is no section +at point." + (declare (indent 0) + (debug (&rest (sexp body)))) + (let ((ident (cl-gensym "id"))) + `(let* ((it (magit-current-section)) + (,ident (and it (mapcar 'car (magit-section-ident it))))) + (cond ,@(mapcar (lambda (clause) + `(,(or (eq (car clause) t) + `(and it (magit-section-match + ',(car clause) ,ident))) + ,@(cdr clause))) + clauses))))) +;;; Create + +(defvar magit-insert-section-hook nil + "Hook run after `magit-insert-section's BODY. +Avoid using this hook and only ever do so if you know +what you are doing and are sure there is no other way.") + +(defmacro magit-insert-section (&rest args) + "Insert a section at point. + +TYPE is the section type, a symbol. Many commands that act on +the current section behave differently depending on that type. +Also if a variable `magit-TYPE-section-map' exists, then use +that as the text-property `keymap' of all text belonging to the +section (but this may be overwritten in subsections). + +Optional VALUE is the value of the section, usually a string +that is required when acting on the section. + +When optional HIDE is non-nil collapse the section body by +default, i.e. when first creating the section, but not when +refreshing the buffer. Else expand it by default. This can be +overwritten using `magit-section-set-visibility-hook'. When a +section is recreated during a refresh, then the visibility of +predecessor is inherited and HIDE is ignored (but the hook is +still honored). + +BODY is any number of forms that actually insert the section's +heading and body. Optional NAME, if specified, has to be a +symbol, which is then bound to the struct of the section being +inserted. + +Before BODY is evaluated the `start' of the section object is set +to the value of `point' and after BODY was evaluated its `end' is +set to the new value of `point'; BODY is responsible for moving +`point' forward. + +If it turns out inside BODY that the section is empty, then +`magit-cancel-section' can be used to abort and remove all traces +of the partially inserted section. This can happen when creating +a section by washing Git's output and Git didn't actually output +anything this time around. + +\(fn [NAME] (TYPE &optional VALUE HIDE) &rest BODY)" + (declare (indent defun) + (debug ([&optional symbolp] (symbolp &optional form form) body))) + (let ((s (if (symbolp (car args)) + (pop args) + (cl-gensym "section")))) + `(let* ((,s (make-magit-section + :type ',(nth 0 (car args)) + :value ,(nth 1 (car args)) + :start (point-marker) + :parent magit-insert-section--parent))) + (setf (magit-section-hidden ,s) + (-if-let (value (run-hook-with-args-until-success + 'magit-section-set-visibility-hook ,s)) + (eq value 'hide) + (--if-let (and magit-insert-section--oldroot + (magit-get-section + (magit-section-ident ,s) + magit-insert-section--oldroot)) + (magit-section-hidden it) + ,(nth 2 (car args))))) + (let ((magit-insert-section--current ,s) + (magit-insert-section--parent ,s) + (magit-insert-section--oldroot + (or magit-insert-section--oldroot + (unless magit-insert-section--parent + (prog1 magit-root-section + (setq magit-root-section ,s)))))) + (catch 'cancel-section + ,@(cdr args) + (run-hooks 'magit-insert-section-hook) + (magit-insert-child-count ,s) + (set-marker-insertion-type (magit-section-start ,s) t) + (let* ((end (setf (magit-section-end ,s) (point-marker))) + (map (intern (format "magit-%s-section-map" + (magit-section-type ,s)))) + (map (and (boundp map) (symbol-value map)))) + (save-excursion + (goto-char (magit-section-start ,s)) + (while (< (point) end) + (let ((next (or (next-single-property-change + (point) 'magit-section) + end))) + (unless (get-text-property (point) 'magit-section) + (put-text-property (point) next 'magit-section ,s) + (when map + (put-text-property (point) next 'keymap map))) + (goto-char next))))) + (if (eq ,s magit-root-section) + (magit-section-show ,s) + (setf (magit-section-children (magit-section-parent ,s)) + (nconc (magit-section-children (magit-section-parent ,s)) + (list ,s))))) + ,s)))) + +(defun magit-cancel-section () + (when magit-insert-section--current + (if (not (magit-section-parent magit-insert-section--current)) + (insert "(empty)\n") + (delete-region (magit-section-start magit-insert-section--current) + (point)) + (setq magit-insert-section--current nil) + (throw 'cancel-section nil)))) + +(defun magit-insert-heading (&rest args) + "Insert the heading for the section currently being inserted. + +This function should only be used inside `magit-insert-section'. + +When called without any arguments, then just set the `content' +slot of the object representing the section being inserted to +a marker at `point'. The section should only contain a single +line when this function is used like this. + +When called with arguments ARGS, which have to be strings, then +insert those strings at point. The section should not contain +any text before this happens and afterwards it should again only +contain a single line. If the `face' property is set anywhere +inside any of these strings, then insert all of them unchanged. +Otherwise use the `magit-section-heading' face for all inserted +text. + +The `content' property of the section struct is the end of the +heading (which lasts from `start' to `content') and the beginning +of the the body (which lasts from `content' to `end'). If the +value of `content' is nil, then the section has no heading and +its body cannot be collapsed. If a section does have a heading +then its height must be exactly one line, including a trailing +newline character. This isn't enforced, you are responsible for +getting it right. The only exception is that this function does +insert a newline character if necessary." + (declare (indent defun)) + (when args + (let ((heading (apply #'concat args))) + (insert (if (next-single-property-change 0 'face (concat "0" heading)) + heading + (propertize heading 'face 'magit-section-heading))))) + (unless (bolp) + (insert ?\n)) + (setf (magit-section-content magit-insert-section--current) (point-marker))) + +(defvar magit-insert-headers-hook nil "For internal use only.") + +(defun magit-insert-headers (hooks) + (let ((magit-insert-section-hook + (cons 'magit-insert-remaining-headers + (if (listp magit-insert-section-hook) + magit-insert-section-hook + (list magit-insert-section-hook)))) + (magit-insert-headers-hook hooks) + wrapper) + (while (and (setq wrapper (pop magit-insert-headers-hook)) + (= (point) (point-min))) + (funcall wrapper)))) + +(defun magit-insert-remaining-headers () + (if (= (point) (point-min)) + (magit-cancel-section) + (magit-insert-heading) + (remove-hook 'magit-insert-section-hook 'magit-insert-remaining-headers) + (mapc #'funcall magit-insert-headers-hook) + (insert "\n"))) + +(defun magit-insert-child-count (section) + "Modify SECTION's heading to contain number of child sections. + +If `magit-section-show-child-count' is non-nil and the SECTION +has children and its heading ends with \":\", then replace that +with \" (N)\", where N is the number of child sections. + +This function is called by `magit-insert-section' after that has +evaluated its BODY. Admittedly that's a bit of a hack." + ;; This has to be fast, not pretty! + (let (content count) + (when (and magit-section-show-child-count + (setq count (length (magit-section-children section))) + (> count 0) + (setq content (magit-section-content section)) + (eq (char-before (1- content)) ?:)) + (save-excursion + (goto-char (- content 2)) + (insert (format " (%s)" count)) + (delete-char 1))))) + +;;; Update + +(defvar-local magit-section-highlight-overlays nil) +(defvar-local magit-section-highlighted-section nil) +(defvar-local magit-section-highlighted-sections nil) +(defvar-local magit-section-unhighlight-sections nil) + +(defun magit-section-update-region (_) + ;; Don't show complete region. Highlighting emphasizes headings. + (magit-region-sections)) + +(defun magit-section-update-highlight () + (let ((section (magit-current-section))) + (unless (eq section magit-section-highlighted-section) + (let ((inhibit-read-only t) + (deactivate-mark nil) + (selection (magit-region-sections))) + (mapc #'delete-overlay magit-section-highlight-overlays) + (setq magit-section-unhighlight-sections + magit-section-highlighted-sections + magit-section-highlighted-sections nil) + (unless (eq section magit-root-section) + (run-hook-with-args-until-success + 'magit-section-highlight-hook section selection)) + (--each magit-section-unhighlight-sections + (run-hook-with-args-until-success + 'magit-section-unhighlight-hook it selection)) + (restore-buffer-modified-p nil) + (unless (eq magit-section-highlighted-section section) + (setq magit-section-highlighted-section + (unless (magit-section-hidden section) section)))) + (setq deactivate-mark nil)))) + +(defun magit-section-highlight (section selection) + "Highlight SECTION and if non-nil all SELECTION. +This function works for any section but produces undesirable +effects for diff related sections, which by default are +highlighted using `magit-diff-highlight'. Return t." + (cond (selection + (magit-section-make-overlay (magit-section-start (car selection)) + (magit-section-end (car (last selection))) + 'magit-section-highlight) + (magit-section-highlight-selection nil selection)) + (t + (magit-section-make-overlay (magit-section-start section) + (magit-section-end section) + 'magit-section-highlight))) + t) + +(defun magit-section-highlight-selection (_ selection) + "Highlight the section selection region. +If SELECTION is non-nil then it is a list of sections selected by +the region. The headings of these sections are then highlighted. + +This is a fallback for people who don't want to highlight the +current section and therefore removed `magit-section-highlight' +from `magit-section-highlight-hook'. + +This function is necessary to ensure that a representation of +such a region is visible. If neither of these functions were +part of the hook variable, then such a region would be +invisible." + (when selection + (--each selection + (magit-section-make-overlay (magit-section-start it) + (or (magit-section-content it) + (magit-section-end it)) + 'magit-section-heading-selection)) + t)) + +(defun magit-section-make-overlay (start end face) + ;; Yes, this doesn't belong here. But the alternative of + ;; spreading this hack across the code base is even worse. + (when (and magit-keep-region-overlay + (memq face '(magit-section-heading-selection + magit-diff-file-heading-selection + magit-diff-hunk-heading-selection))) + (setq face (list :foreground (face-foreground face)))) + (let ((ov (make-overlay start end nil t))) + (overlay-put ov 'face face) + (overlay-put ov 'evaporate t) + (push ov magit-section-highlight-overlays) + ov)) + +(defun magit-section-goto-successor (section line char arg) + (let ((ident (magit-section-ident section))) + (--if-let (magit-get-section ident) + (let ((start (magit-section-start it))) + (goto-char start) + (unless (eq it magit-root-section) + (ignore-errors + (forward-line line) + (forward-char char)) + (unless (eq (magit-current-section) it) + (goto-char start)))) + (or (and (eq (magit-section-type section) 'hunk) + (-when-let (parent (magit-get-section + (magit-section-ident + (magit-section-parent section)))) + (let* ((children (magit-section-children parent)) + (siblings (magit-section-siblings section 'prev)) + (previous (nth (length siblings) children))) + (if (not arg) + (--when-let (or previous (car (last children))) + (goto-char (magit-section-start it))) + (when previous + (goto-char (magit-section-start previous))) + (if (and (stringp arg) + (re-search-forward + arg (magit-section-end parent) t)) + (goto-char (match-beginning 0)) + (goto-char (magit-section-end (car (last children)))) + (forward-line -1) + (while (looking-at "^ ") (forward-line -1)) + (while (looking-at "^[-+]") (forward-line -1)) + (forward-line)))))) + (goto-char (--if-let (magit-section-goto-successor-1 section) + (if (eq (magit-section-type it) 'button) + (point-min) + (magit-section-start it)) + (point-min))))))) + +(defun magit-section-goto-successor-1 (section) + (or (--when-let (pcase (magit-section-type section) + (`staged 'unstaged) + (`unstaged 'staged) + (`unpushed 'unpulled) + (`unpulled 'unpushed)) + (magit-get-section `((,it) (status)))) + (--when-let (car (magit-section-siblings section 'next)) + (magit-get-section (magit-section-ident it))) + (--when-let (car (magit-section-siblings section 'prev)) + (magit-get-section (magit-section-ident it))) + (--when-let (magit-section-parent section) + (or (magit-get-section (magit-section-ident it)) + (magit-section-goto-successor-1 it))))) + +;;; Visibility + +(defvar-local magit-section-visibility-cache nil) +(put 'magit-section-visibility-cache 'permanent-local t) + +(defun magit-section-set-visibility-from-cache (section) + (and (member (magit-section-visibility-ident section) + magit-section-visibility-cache) + 'hide)) + +(cl-defun magit-section-cache-visibility + (&optional (section magit-insert-section--current)) + (let ((ident (magit-section-visibility-ident section))) + (if (magit-section-hidden section) + (cl-pushnew ident magit-section-visibility-cache :test #'equal) + (setq magit-section-visibility-cache + (delete ident magit-section-visibility-cache))))) + +(defun magit-section-update-visibility-cache (section) + (setq magit-section-visibility-cache + (delete (magit-section-visibility-ident section) + magit-section-visibility-cache))) + +(defun magit-section-visibility-ident (section) + (let ((type (magit-section-type section)) + (value (magit-section-value section))) + (cons type + (cond ((not (memq type '(unpulled unpushed))) value) + ((string-match-p "@{upstream}" value) value) + ;; Unfortunately Git chokes on "@{push}" when the + ;; value of `push.default' does not allow a 1:1 + ;; mapping. But collapsed logs of unpushed and + ;; unpulled commits in the status buffer should + ;; remain invisible after changing branches. + ;; So we have to pretend the value is constant. + ((string-match-p "\\`\\.\\." value) "..@{push}") + (t "@{push}.."))))) + +;;; Utilities + +(cl-defun magit-section-selected-p (section &optional (selection nil sselection)) + (and (not (eq section magit-root-section)) + (or (eq section (magit-current-section)) + (memq section (if sselection + selection + (setq selection (magit-region-sections)))) + (--when-let (magit-section-parent section) + (magit-section-selected-p it selection))))) + +(defun magit-section-parent-value (section) + (setq section (magit-section-parent section)) + (when section (magit-section-value section))) + +(defun magit-section-siblings (section &optional direction) + "Return a list of the sibling sections of SECTION. + +If optional DIRECTION is `prev' then return siblings that come +before SECTION, if it is `next' then return siblings that come +after SECTION. For all other values return all siblings +excluding SECTION itself." + (-when-let (parent (magit-section-parent section)) + (let ((siblings (magit-section-children parent))) + (pcase direction + (`prev (cdr (member section (reverse siblings)))) + (`next (cdr (member section siblings))) + (_ (remq section siblings)))))) + +(defun magit-region-values (&rest types) + "Return a list of the values of the selected sections. + +Also see `magit-region-sections' whose doc-string explains when a +region is a valid section selection. If the region is not active +or is not a valid section selection, then return nil. If optional +TYPES is non-nil then the selection not only has to be valid; the +types of all selected sections additionally have to match one of +TYPES, or nil is returned." + (mapcar 'magit-section-value (apply 'magit-region-sections types))) + +(defun magit-region-sections (&rest types) + "Return a list of the selected sections. + +When the region is active and constitutes a valid section +selection, then return a list of all selected sections. This is +the case when the region begins in the heading of a section and +ends in the heading of a sibling of that first section. When +the selection is not valid then return nil. Most commands that +can act on the selected sections, then instead just act on the +current section, the one point is in. + +When the region looks like it would in any other buffer then +the selection is invalid. When the selection is valid then the +region uses the `magit-section-highlight'. This does not apply +to diffs were things get a bit more complicated, but even here +if the region looks like it usually does, then that's not a +valid selection as far as this function is concerned. + +If optional TYPES is non-nil then the selection not only has to +be valid; the types of all selected sections additionally have to +match one of TYPES, or nil is returned." + (when (use-region-p) + (let* ((rbeg (region-beginning)) + (rend (region-end)) + (sbeg (get-text-property rbeg 'magit-section)) + (send (get-text-property rend 'magit-section))) + (unless (memq send (list sbeg magit-root-section nil)) + (let ((siblings (magit-section-siblings sbeg 'next)) sections) + (when (and (memq send siblings) + (magit-section-position-in-heading-p sbeg rbeg) + (magit-section-position-in-heading-p send rend)) + (while siblings + (push (car siblings) sections) + (when (eq (pop siblings) send) + (setq siblings nil))) + (setq sections (cons sbeg (nreverse sections))) + (when (or (not types) + (--all-p (memq (magit-section-type it) types) sections)) + sections))))))) + +(defun magit-section-position-in-heading-p (section pos) + "Return t if POSITION is inside the heading of SECTION." + (and (>= pos (magit-section-start section)) + (< pos (or (magit-section-content section) + (magit-section-end section))) + t)) + +(defun magit-section-internal-region-p (&optional section) + "Return t if the region is active and inside SECTION's body. +If optional SECTION is nil, use the current section." + (and (region-active-p) + (or section (setq section (magit-current-section))) + (let ((beg (get-text-property (region-beginning) 'magit-section))) + (and (eq beg (get-text-property (region-end) 'magit-section)) + (eq beg section))) + (not (or (magit-section-position-in-heading-p section (region-beginning)) + (magit-section-position-in-heading-p section (region-end)))) + t)) + +(defun magit-wash-sequence (function) + "Repeatedly call FUNCTION until it returns nil or eob is reached. +FUNCTION has to move point forward or return nil." + (while (and (not (eobp)) (funcall function)))) + +(defun magit-add-section-hook (hook function &optional at append local) + "Add to the value of section hook HOOK the function FUNCTION. + +Add FUNCTION at the beginning of the hook list unless optional +APPEND is non-nil, in which case FUNCTION is added at the end. +If FUNCTION already is a member then move it to the new location. + +If optional AT is non-nil and a member of the hook list, then add +FUNCTION next to that instead. Add before or after AT depending +on APPEND. If only FUNCTION is a member of the list, then leave +it where ever it already is. + +If optional LOCAL is non-nil, then modify the hook's buffer-local +value rather than its global value. This makes the hook local by +copying the default value. That copy is then modified. + +HOOK should be a symbol. If HOOK is void, it is first set to nil. +HOOK's value must not be a single hook function. FUNCTION should +be a function that takes no arguments and inserts one or multiple +sections at point, moving point forward. FUNCTION may choose not +to insert its section(s), when doing so would not make sense. It +should not be abused for other side-effects. To remove FUNCTION +again use `remove-hook'." + (unless (boundp hook) + (error "Cannot add function to undefined hook variable %s" hook)) + (or (default-boundp hook) (set-default hook nil)) + (let ((value (if local + (if (local-variable-p hook) + (symbol-value hook) + (unless (local-variable-if-set-p hook) + (make-local-variable hook)) + (copy-sequence (default-value hook))) + (default-value hook)))) + (if at + (when (setq at (member at value)) + (setq value (delq function value)) + (if append + (push function (cdr at)) + (push (car at) (cdr at)) + (setcar at function))) + (setq value (delq function value))) + (unless (member function value) + (setq value (if append + (append value (list function)) + (cons function value)))) + (if local + (set hook value) + (set-default hook value)))) + +;;; magit-section.el ends soon +(provide 'magit-section) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-section.el ends here diff --git a/elpa/magit-20151223.1425/magit-sequence.el b/elpa/magit-20151223.1425/magit-sequence.el new file mode 100644 index 00000000..14e56893 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-sequence.el @@ -0,0 +1,651 @@ +;;; magit-sequence.el --- history manipulation in Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2011-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; Support for Git commands that replay commits and help the user make +;; changes along the way. Supports `cherry-pick', `revert', `rebase', +;; `rebase--interactive' and `am'. + +;;; Code: + +(require 'magit) + +;;; Options +;;;; Faces + +(defface magit-sequence-pick + '((t :inherit default)) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-stop + '((((class color) (background light)) :foreground "DarkOliveGreen4") + (((class color) (background dark)) :foreground "DarkSeaGreen2")) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-part + '((((class color) (background light)) :foreground "Goldenrod4") + (((class color) (background dark)) :foreground "LightGoldenrod2")) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-head + '((((class color) (background light)) :foreground "SkyBlue4") + (((class color) (background dark)) :foreground "LightSkyBlue1")) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-drop + '((((class color) (background light)) :foreground "IndianRed") + (((class color) (background dark)) :foreground "IndianRed")) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-done + '((t :inherit magit-hash)) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-onto + '((t :inherit magit-sequence-done)) + "Face used in sequence sections." + :group 'magit-faces) + +;;; Common + +;;;###autoload +(defun magit-sequencer-continue () + "Resume the current cherry-pick or revert sequence." + (interactive) + (if (magit-sequencer-in-progress-p) + (if (magit-anything-unstaged-p t) + (user-error "Cannot continue due to unstaged changes") + (magit-run-git-sequencer + (if (magit-revert-in-progress-p) "revert" "cherry-pick") "--continue")) + (user-error "No cherry-pick or revert in progress"))) + +;;;###autoload +(defun magit-sequencer-skip () + "Skip the stopped at commit during a cherry-pick or revert sequence." + (interactive) + (if (magit-sequencer-in-progress-p) + (progn (magit-call-git "reset" "--hard") + (magit-sequencer-continue)) + (user-error "No cherry-pick or revert in progress"))) + +;;;###autoload +(defun magit-sequencer-abort () + "Abort the current cherry-pick or revert sequence. +This discards all changes made since the sequence started." + (interactive) + (if (magit-sequencer-in-progress-p) + (magit-run-git-sequencer + (if (magit-revert-in-progress-p) "revert" "cherry-pick") "--abort") + (user-error "No cherry-pick or revert in progress"))) + +(defun magit-sequencer-in-progress-p () + (or (magit-cherry-pick-in-progress-p) + (magit-revert-in-progress-p))) + +;;; Cherry-Pick + +;;;###autoload (autoload 'magit-cherry-pick-popup "magit-sequence" nil t) +(magit-define-popup magit-cherry-pick-popup + "Popup console for cherry-pick commands." + 'magit-commands + :man-page "git-cherry-pick" + :switches '((?s "Add Signed-off-by lines" "--signoff") + (?e "Edit commit messages" "--edit") + (?x "Reference cherry in commit message" "-x") + (?F "Attempt fast-forward" "--ff") + (?m "Reply merge relative to parent" "--mainline=")) + :options '((?s "Strategy" "--strategy=")) + :actions '((?A "Cherry Pick" magit-cherry-pick) + (?a "Cherry Apply" magit-cherry-apply)) + :sequence-actions '((?A "Continue" magit-sequencer-continue) + (?s "Skip" magit-sequencer-skip) + (?a "Abort" magit-sequencer-abort)) + :sequence-predicate 'magit-sequencer-in-progress-p + :default-arguments '("--ff")) + +(defun magit-cherry-pick-read-args (prompt) + (list (or (nreverse (magit-region-values 'commit)) + (magit-read-other-branch-or-commit prompt)) + (magit-cherry-pick-arguments))) + +;;;###autoload +(defun magit-cherry-pick (commit &optional args) + "Cherry-pick COMMIT. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then pick all of them, +without prompting." + (interactive (magit-cherry-pick-read-args "Cherry-pick")) + (magit-assert-one-parent (car (if (listp commit) + commit + (split-string commit "\\.\\."))) + "cherry-pick") + (magit-run-git-sequencer "cherry-pick" args commit)) + +;;;###autoload +(defun magit-cherry-apply (commit &optional args) + "Apply the changes in COMMIT but do not commit them. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then apply all of them, +without prompting." + (interactive (magit-cherry-pick-read-args "Apply changes from commit")) + (magit-assert-one-parent commit "cherry-pick") + (magit-run-git-sequencer "cherry-pick" "--no-commit" + (remove "--ff" args) commit)) + +(defun magit-cherry-pick-in-progress-p () + ;; .git/sequencer/todo does not exist when there is only one commit left. + (file-exists-p (magit-git-dir "CHERRY_PICK_HEAD"))) + +;;; Revert + +;;;###autoload (autoload 'magit-revert-popup "magit-sequence" nil t) +(magit-define-popup magit-revert-popup + "Popup console for revert commands." + 'magit-commands + :man-page "git-revert" + :switches '((?s "Add Signed-off-by lines" "--signoff")) + :options '((?s "Strategy" "--strategy=")) + :actions '((?V "Revert commit(s)" magit-revert) + (?v "Revert changes" magit-revert-no-commit)) + :sequence-actions '((?V "Continue" magit-sequencer-continue) + (?s "Skip" magit-sequencer-skip) + (?a "Abort" magit-sequencer-abort)) + :sequence-predicate 'magit-sequencer-in-progress-p) + +(defun magit-revert-read-args (prompt) + (list (or (magit-region-values 'commit) + (magit-read-branch-or-commit prompt)) + (magit-revert-arguments))) + +;;;###autoload +(defun magit-revert (commit &optional args) + "Revert COMMIT by creating a new commit. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then revert all of them, +without prompting." + (interactive (magit-revert-read-args "Revert commit")) + (magit-assert-one-parent commit "revert") + (magit-run-git-sequencer "revert" args commit)) + +;;;###autoload +(defun magit-revert-no-commit (commit &optional args) + "Revert COMMIT by applying it in reverse to the worktree. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then revert all of them, +without prompting." + (interactive (magit-revert-read-args "Revert changes")) + (magit-assert-one-parent commit "revert") + (magit-run-git-sequencer "revert" "--no-commit" args commit)) + +(defun magit-revert-in-progress-p () + ;; .git/sequencer/todo does not exist when there is only one commit left. + (file-exists-p (magit-git-dir "REVERT_HEAD"))) + +;;; Patch + +;;;###autoload (autoload 'magit-am-popup "magit-sequence" nil t) +(magit-define-popup magit-am-popup + "Popup console for mailbox commands." + 'magit-commands + :man-page "git-am" + :switches '((?3 "Fall back on 3way merge" "--3way") + (?s "Add Signed-off-by lines" "--signoff") + (?c "Remove text before scissors line" "--scissors") + (?k "Inhibit removal of email cruft" "--keep") + (?b "Limit removal of email cruft" "--keep-non-patch") + (?d "Use author date as committer date" + "--committer-date-is-author-date") + (?D "Use committer date as author date" "--ignore-date")) + :options '((?p "Remove leading slashes from paths" "-p" + magit-popup-read-number)) + :actions '((?w "Apply patches" magit-am-apply-patches) + (?m "Apply maildir" magit-am-apply-maildir)) + :default-arguments '("--3way") + :default-actions 'magit-am-apply-patches + :sequence-actions '((?w "Continue" magit-am-continue) + (?s "Skip" magit-am-skip) + (?a "Abort" magit-am-abort)) + :sequence-predicate 'magit-am-in-progress-p) + +;;;###autoload +(defun magit-am-apply-patches (&optional files args) + "Apply the patches FILES." + (interactive (list (or (magit-region-values 'file) + (list (let ((default (magit-file-at-point))) + (read-file-name + (if default + (format "Apply patch (%s): " default) + "Apply patch: ") + nil default)))) + (magit-am-arguments))) + (magit-run-git-sequencer "am" args "--" (mapcar 'expand-file-name files))) + +;;;###autoload +(defun magit-am-apply-maildir (&optional maildir args) + "Apply the patches from MAILDIR." + (interactive (list (read-file-name "Apply mbox or Maildir: ") + (magit-am-arguments))) + (magit-run-git-sequencer "am" args (expand-file-name maildir))) + +;;;###autoload +(defun magit-am-continue () + "Resume the current patch applying sequence." + (interactive) + (if (magit-am-in-progress-p) + (if (magit-anything-unstaged-p t) + (error "Cannot continue due to unstaged changes") + (magit-run-git-sequencer "am" "--continue")) + (user-error "Not applying any patches"))) + +;;;###autoload +(defun magit-am-skip () + "Skip the stopped at patch during a patch applying sequence." + (interactive) + (if (magit-am-in-progress-p) + (magit-run-git-sequencer "am" "--skip") + (user-error "Not applying any patches"))) + +;;;###autoload +(defun magit-am-abort () + "Abort the current patch applying sequence. +This discards all changes made since the sequence started." + (interactive) + (if (magit-am-in-progress-p) + (magit-run-git "am" "--abort") + (user-error "Not applying any patches"))) + +(defun magit-am-in-progress-p () + (file-exists-p (magit-git-dir "rebase-apply/applying"))) + +;;; Rebase + +;;;###autoload (autoload 'magit-rebase-popup "magit-sequence" nil t) +(magit-define-popup magit-rebase-popup + "Key menu for rebasing." + 'magit-commands + :man-page "git-rebase" + :switches '((?k "Keep empty commits" "--keep-empty") + (?p "Preserve merges" "--preserve-merges") + (?c "Lie about author date" "--committer-date-is-author-date") + (?a "Autosquash" "--autosquash") + (?A "Autostash" "--autostash") + (?i "Interactive" "--interactive")) + :actions '((lambda () + (concat (propertize "Rebase " 'face 'magit-popup-heading) + (propertize (or (magit-get-current-branch) "HEAD") + 'face 'magit-branch-local) + (propertize " onto" 'face 'magit-popup-heading))) + (?p (lambda () + (--when-let (magit-get-push-branch) (concat it "\n"))) + magit-rebase-onto-pushremote) + (?u (lambda () + (--when-let (magit-get-upstream-branch) (concat it "\n"))) + magit-rebase-onto-upstream) + (?e "elsewhere" magit-rebase) + "Rebase" + (?i "interactively" magit-rebase-interactive) + (?m "to edit a commit" magit-rebase-edit-commit) + (?s "subset" magit-rebase-subset) + (?w "to reword a commit" magit-rebase-reword-commit) nil + (?f "to autosquash" magit-rebase-autosquash)) + :sequence-actions '((?r "Continue" magit-rebase-continue) + (?s "Skip" magit-rebase-skip) + (?e "Edit" magit-rebase-edit) + (?a "Abort" magit-rebase-abort)) + :sequence-predicate 'magit-rebase-in-progress-p + :max-action-columns 2) + +(defun magit-git-rebase (target args) + (magit-run-git-sequencer "rebase" target args)) + +;;;###autoload +(defun magit-rebase-onto-pushremote (args) + "Rebase the current branch onto `branch..pushRemote'. +If that variable is unset, then rebase onto `remote.pushDefault'." + (interactive (list (magit-rebase-arguments))) + (--if-let (magit-get-current-branch) + (-if-let (remote (magit-get-push-remote it)) + (if (member remote (magit-list-remotes)) + (magit-git-rebase (concat remote "/" it) args) + (user-error "Remote `%s' doesn't exist" remote)) + (user-error "No push-remote is configured for %s" it)) + (user-error "No branch is checked out"))) + +;;;###autoload +(defun magit-rebase-onto-upstream (args) + "Rebase the current branch onto its upstream branch." + (interactive (list (magit-rebase-arguments))) + (--if-let (magit-get-current-branch) + (-if-let (target (magit-get-upstream-branch it)) + (magit-git-rebase target args) + (user-error "No upstream is configured for %s" it)) + (user-error "No branch is checked out"))) + +;;;###autoload +(defun magit-rebase (target args) + "Rebase the current branch onto a branch read in the minibuffer. +All commits that are reachable from head but not from the +selected branch TARGET are being rebased." + (interactive (list (magit-read-other-branch-or-commit "Rebase onto") + (magit-rebase-arguments))) + (message "Rebasing...") + (magit-git-rebase target args) + (message "Rebasing...done")) + +;;;###autoload +(defun magit-rebase-subset (newbase start args) + "Rebase a subset of the current branches history onto a new base. +Rebase commits from START to `HEAD' onto NEWBASE. +START has to be selected from a list of recent commits." + (interactive (list (magit-read-other-branch-or-commit + "Rebase subset onto" nil + (magit-get-upstream-branch)) + nil + (magit-rebase-arguments))) + (if start + (progn (message "Rebasing...") + (magit-run-git-sequencer "rebase" "--onto" newbase start args) + (message "Rebasing...done")) + (magit-log-select + `(lambda (commit) + (magit-rebase-subset ,newbase (concat commit "^") (list ,@args))) + (concat "Type %p on a commit to rebase it " + "and commits above it onto " newbase ",")))) + +(defun magit-rebase-interactive-1 (commit args message &optional editor) + (declare (indent 2)) + (when commit + (if (eq commit :merge-base) + (setq commit (--if-let (magit-get-upstream-branch) + (magit-git-string "merge-base" it "HEAD") + nil)) + (when (magit-git-failure "merge-base" "--is-ancestor" commit "HEAD") + (user-error "%s isn't an ancestor of HEAD" commit)) + (if (magit-commit-parents commit) + (setq commit (concat commit "^")) + (setq args (cons "--root" args))))) + (when (and commit + (magit-git-lines "rev-list" "--merges" (concat commit "..HEAD"))) + (magit-read-char-case "Proceed despite merge in rebase range? " nil + (?c "[c]ontinue") + (?s "[s]elect other" (setq commit nil)) + (?a "[a]bort" (user-error "Quit")))) + (if commit + (let ((process-environment process-environment)) + (when editor + (setenv "GIT_SEQUENCE_EDITOR" editor)) + (magit-run-git-sequencer "rebase" "-i" args + (unless (member "--root" args) commit))) + (magit-log-select + `(lambda (commit) + (magit-rebase-interactive-1 commit (list ,@args) ,message ,editor)) + message))) + +;;;###autoload +(defun magit-rebase-interactive (commit args) + "Start an interactive rebase sequence." + (interactive (list (magit-commit-at-point) + (magit-rebase-arguments))) + (magit-rebase-interactive-1 commit args + "Type %p on a commit to rebase it and all commits above it,")) + +;;;###autoload +(defun magit-rebase-autosquash (args) + "Combine squash and fixup commits with their intended targets." + (interactive (list (magit-rebase-arguments))) + (magit-rebase-interactive-1 :merge-base (cons "--autosquash" args) + "Type %p on a commit to squash into it and then rebase as necessary," + "true")) + +;;;###autoload +(defun magit-rebase-edit-commit (commit args) + "Edit a single older commit using rebase." + (interactive (list (magit-commit-at-point) + (magit-rebase-arguments))) + (magit-rebase-interactive-1 commit args + "Type %p on a commit to edit it," + "perl -i -p -e '++$x if not $x and s/^pick/edit/'")) + +;;;###autoload +(defun magit-rebase-reword-commit (commit args) + "Reword a single older commit using rebase." + (interactive (list (magit-commit-at-point) + (magit-rebase-arguments))) + (magit-rebase-interactive-1 commit args + "Type %p on a commit to reword its message," + "perl -i -p -e '++$x if not $x and s/^pick/reword/'")) + +;;;###autoload +(defun magit-rebase-continue () + "Restart the current rebasing operation." + (interactive) + (if (magit-rebase-in-progress-p) + (if (magit-anything-unstaged-p t) + (user-error "Cannot continue rebase with unstaged changes") + (magit-run-git-sequencer "rebase" "--continue")) + (user-error "No rebase in progress"))) + +;;;###autoload +(defun magit-rebase-skip () + "Skip the current commit and restart the current rebase operation." + (interactive) + (if (magit-rebase-in-progress-p) + (magit-run-git-sequencer "rebase" "--skip") + (user-error "No rebase in progress"))) + +;;;###autoload +(defun magit-rebase-edit () + "Edit the todo list of the current rebase operation." + (interactive) + (if (magit-rebase-in-progress-p) + (magit-run-git-sequencer "rebase" "--edit-todo") + (user-error "No rebase in progress"))) + +;;;###autoload +(defun magit-rebase-abort () + "Abort the current rebase operation, restoring the original branch." + (interactive) + (if (magit-rebase-in-progress-p) + (magit-run-git "rebase" "--abort") + (user-error "No rebase in progress"))) + +(defun magit-rebase-in-progress-p () + "Return t if a rebase is in progress." + (or (file-exists-p (magit-git-dir "rebase-merge")) + (file-exists-p (magit-git-dir "rebase-apply/onto")))) + +;;; Sections + +(defun magit-insert-sequencer-sequence () + "Insert section for the on-going cherry-pick or revert sequence. +If no such sequence is in progress, do nothing." + (let ((picking (magit-cherry-pick-in-progress-p))) + (when (or picking (magit-revert-in-progress-p)) + (magit-insert-section (sequence) + (magit-insert-heading (if picking "Cherry Picking" "Reverting")) + (-when-let (lines (cdr (magit-file-lines (magit-git-dir "sequencer/todo")))) + (dolist (line (nreverse lines)) + (when (string-match "^\\(pick\\|revert\\) \\([^ ]+\\) \\(.*\\)$" line) + (magit-bind-match-strings (cmd hash msg) line + (magit-insert-section (commit hash) + (insert (propertize cmd 'face 'magit-sequence-pick) + " " (propertize hash 'face 'magit-hash) + " " msg "\n")))))) + (magit-sequence-insert-sequence + (magit-file-line (magit-git-dir (if picking + "CHERRY_PICK_HEAD" + "REVERT_HEAD"))) + (magit-file-line (magit-git-dir "sequencer/head"))) + (insert "\n"))))) + +(defun magit-insert-am-sequence () + "Insert section for the on-going patch applying sequence. +If no such sequence is in progress, do nothing." + (when (magit-am-in-progress-p) + (magit-insert-section (rebase-sequence) + (magit-insert-heading "Applying patches") + (let ((patches (nreverse (magit-rebase-patches))) + patch commit) + (while patches + (setq patch (pop patches) + commit (magit-rev-verify-commit + (cadr (split-string (magit-file-line patch))))) + (cond ((and commit patches) + (magit-sequence-insert-commit + "pick" commit 'magit-sequence-pick)) + (patches + (magit-sequence-insert-am-patch + "pick" patch 'magit-sequence-pick)) + (commit + (magit-sequence-insert-sequence commit "ORIG_HEAD")) + (t + (magit-sequence-insert-am-patch + "stop" patch 'magit-sequence-stop) + (magit-sequence-insert-sequence nil "ORIG_HEAD"))))) + (insert ?\n)))) + +(defun magit-sequence-insert-am-patch (type patch face) + (magit-insert-section (file patch) + (insert (propertize type 'face face) + ?\s (propertize (file-name-nondirectory patch) 'face 'magit-hash) + ?\n))) + +(defun magit-insert-rebase-sequence () + "Insert section for the on-going rebase sequence. +If no such sequence is in progress, do nothing." + (when (magit-rebase-in-progress-p) + (let* ((interactive (file-directory-p (magit-git-dir "rebase-merge"))) + (dir (if interactive "rebase-merge/" "rebase-apply/")) + (name (-> (concat dir "head-name") magit-git-dir magit-file-line)) + (onto (-> (concat dir "onto") magit-git-dir magit-file-line)) + (onto (or (magit-rev-name onto name) + (magit-rev-name onto "refs/heads/*") onto)) + (name (or (magit-rev-name name "refs/heads/*") name))) + (magit-insert-section (rebase-sequence) + (magit-insert-heading (format "Rebasing %s onto %s" name onto)) + (if interactive + (magit-rebase-insert-merge-sequence) + (magit-rebase-insert-apply-sequence)) + (magit-sequence-insert-sequence + (magit-file-line + (magit-git-dir + (concat dir (if interactive "stopped-sha" "original-commit")))) + onto (--map (cadr (split-string it)) + (magit-file-lines (magit-git-dir "rebase-merge/done")))) + (insert ?\n))))) + +(defun magit-rebase-insert-merge-sequence () + (dolist (line (nreverse + (magit-file-lines + (magit-git-dir "rebase-merge/git-rebase-todo")))) + (when (string-match "^\\([^# ]+\\) \\([^ ]+\\) .*$" line) + (magit-bind-match-strings (action hash) line + (magit-sequence-insert-commit action hash 'magit-sequence-pick))))) + +(defun magit-rebase-insert-apply-sequence () + (dolist (patch (nreverse (cdr (magit-rebase-patches)))) + (magit-sequence-insert-commit + "pick" (cadr (split-string (magit-file-line patch))) 'magit-sequence-pick))) + +(defun magit-rebase-patches () + (directory-files (magit-git-dir "rebase-apply") t "^[0-9]\\{4\\}$")) + +(defun magit-sequence-insert-sequence (stop onto &optional orig) + (let ((head (magit-rev-parse "HEAD")) done) + (setq onto (if onto (magit-rev-parse onto) head)) + (setq done (magit-git-lines "log" "--format=%H" (concat onto "..HEAD"))) + (when (and stop (not (member stop done))) + (let ((id (magit-patch-id stop))) + (--if-let (--first (equal (magit-patch-id it) id) done) + (setq stop it) + (cond + ((--first (magit-rev-equal it stop) done) + ;; The commit's testament has been executed. + (magit-sequence-insert-commit "void" stop 'magit-sequence-drop)) + ;; The faith of the commit is still undecided... + ((magit-anything-unmerged-p) + ;; ...and time travel isn't for the faint of heart. + (magit-sequence-insert-commit "join" stop 'magit-sequence-part)) + ((magit-anything-modified-p t) + ;; ...and the dust hasn't settled yet... + (magit-sequence-insert-commit + (let ((staged (magit-commit-tree "oO" nil "HEAD")) + (unstaged (magit-commit-worktree "oO" "--reset"))) + (cond + ;; ...but we could end up at the same tree just by committing. + ((or (magit-rev-equal staged stop) + (magit-rev-equal unstaged stop)) "goal") + ;; ...but the changes are still there, untainted. + ((or (equal (magit-patch-id staged) id) + (equal (magit-patch-id unstaged) id)) "same") + ;; ...and some changes are gone and/or others were added. + (t "work"))) + stop 'magit-sequence-part)) + ;; The commit is definitely gone... + ((--first (magit-rev-equal it stop) done) + ;; ...but all of its changes are still in effect. + (magit-sequence-insert-commit "poof" stop 'magit-sequence-drop)) + (t + ;; ...and some changes are gone and/or other changes were added. + (magit-sequence-insert-commit "gone" stop 'magit-sequence-drop))) + (setq stop nil)))) + (dolist (rev done) + (apply 'magit-sequence-insert-commit + (cond ((equal rev stop) + ;; ...but its reincarnation lives on. + ;; Or it didn't die in the first place. + (list (if (and (equal rev head) + (equal (magit-patch-id (concat stop "^")) + (magit-patch-id (car (last orig 2))))) + "stop" ; We haven't done anything yet. + "same") ; There are new commits. + rev (if (equal rev head) + 'magit-sequence-head + 'magit-sequence-stop))) + ((equal rev head) + (list "done" rev 'magit-sequence-head)) + (t + (list "done" rev 'magit-sequence-done))))) + (magit-sequence-insert-commit "onto" onto + (if (equal onto head) + 'magit-sequence-head + 'magit-sequence-onto)))) + +(defun magit-sequence-insert-commit (type hash face) + (magit-insert-section (commit hash) + (insert (propertize type 'face face) ?\s + (magit-format-rev-summary hash) ?\n))) + +;;; magit-sequence.el ends soon +(provide 'magit-sequence) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-sequence.el ends here diff --git a/elpa/magit-20151223.1425/magit-stash.el b/elpa/magit-20151223.1425/magit-stash.el new file mode 100644 index 00000000..c46679b7 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-stash.el @@ -0,0 +1,403 @@ +;;; magit-stash.el --- stash support for Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; Support for Git stashes. + +;;; Code: + +(require 'magit) + +;;; Commands + +;;;###autoload (autoload 'magit-stash-popup "magit-stash" nil t) +(magit-define-popup magit-stash-popup + "Popup console for stash commands." + 'magit-commands + :man-page "git-stash" + :switches '((?u "Also save untracked files" "--include-untracked") + (?a "Also save untracked and ignored files" "--all")) + :actions '((?z "Save" magit-stash) + (?Z "Snapshot" magit-snapshot) + (?p "Pop" magit-stash-pop) + (?i "Save index" magit-stash-index) + (?I "Snapshot index" magit-snapshot-index) + (?a "Apply" magit-stash-apply) + (?w "Save worktree" magit-stash-worktree) + (?W "Snapshot worktree" magit-snapshot-worktree) + (?l "List" magit-stash-list) + (?x "Save keeping index" magit-stash-keep-index) + (?r "Snapshot to wipref" magit-wip-commit) + (?v "Show" magit-stash-show) + (?b "Branch" magit-stash-branch) + (?k "Drop" magit-stash-drop) nil + (?f "Format patch" magit-stash-format-patch)) + :default-action 'magit-stash + :max-action-columns 3) + +;;;###autoload +(defun magit-stash (message &optional include-untracked) + "Create a stash of the index and working tree. +Untracked files are included according to popup arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'." + (interactive (magit-stash-read-args)) + (magit-stash-save message t t include-untracked t)) + +;;;###autoload +(defun magit-stash-index (message) + "Create a stash of the index only. +Unstaged and untracked changes are not stashed. The stashed +changes are applied in reverse to both the index and the +worktree. This command can fail when the worktree is not clean. +Applying the resulting stash has the inverse effect." + (interactive (list (magit-stash-read-message))) + (magit-stash-save message t nil nil t 'worktree)) + +;;;###autoload +(defun magit-stash-worktree (message &optional include-untracked) + "Create a stash of the working tree only. +Untracked files are included according to popup arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'." + (interactive (magit-stash-read-args)) + (magit-stash-save message nil t include-untracked t 'index)) + +;;;###autoload +(defun magit-stash-keep-index (message &optional include-untracked) + "Create a stash of the index and working tree, keeping index intact. +Untracked files are included according to popup arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'." + (interactive (magit-stash-read-args)) + (magit-stash-save message t t include-untracked t 'index)) + +(defun magit-stash-read-args () + (list (magit-stash-read-message) + (magit-stash-read-untracked))) + +(defun magit-stash-read-untracked () + (let ((prefix (prefix-numeric-value current-prefix-arg)) + (args (magit-stash-arguments))) + (cond ((or (= prefix 16) (member "--all" args)) 'all) + ((or (= prefix 4) (member "--include-untracked" args)) t)))) + +(defun magit-stash-read-message () + (let* ((default (format "On %s: " + (or (magit-get-current-branch) "(no branch)"))) + (input (magit-read-string "Stash message" default))) + (if (equal input default) + (concat default (magit-rev-format "%h %s")) + input))) + +;;;###autoload +(defun magit-snapshot (&optional include-untracked) + "Create a snapshot of the index and working tree. +Untracked files are included according to popup arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'." + (interactive (magit-snapshot-read-args)) + (magit-snapshot-save t t include-untracked t)) + +;;;###autoload +(defun magit-snapshot-index () + "Create a snapshot of the index only. +Unstaged and untracked changes are not stashed." + (interactive) + (magit-snapshot-save t nil nil t)) + +;;;###autoload +(defun magit-snapshot-worktree (&optional include-untracked) + "Create a snapshot of the working tree only. +Untracked files are included according to popup arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'." + (interactive (magit-snapshot-read-args)) + (magit-snapshot-save nil t include-untracked t)) + +(defun magit-snapshot-read-args () + (list (magit-stash-read-untracked))) + +(defun magit-snapshot-save (index worktree untracked &optional refresh) + (magit-stash-save (concat "WIP on " (magit-stash-summary)) + index worktree untracked refresh t)) + +;;;###autoload +(defun magit-stash-apply (stash) + "Apply a stash to the working tree. +Try to preserve the stash index. If that fails because there +are staged changes, apply without preserving the stash index." + (interactive (list (magit-read-stash "Apply stash" t))) + (if (= (magit-call-git "stash" "apply" "--index" stash) 0) + (magit-refresh) + (magit-run-git "stash" "apply" stash))) + +(defun magit-stash-pop (stash) + "Apply a stash to the working tree and remove it from stash list. +Try to preserve the stash index. If that fails because there +are staged changes, apply without preserving the stash index +and forgo removing the stash." + (interactive (list (magit-read-stash "Apply pop" t))) + (if (= (magit-call-git "stash" "apply" "--index" stash) 0) + (magit-stash-drop stash) + (magit-run-git "stash" "apply" stash))) + +;;;###autoload +(defun magit-stash-drop (stash) + "Remove a stash from the stash list. +When the region is active offer to drop all contained stashes." + (interactive (list (--if-let (magit-region-values 'stash) + (magit-confirm t nil "Drop %i stashes" it) + (magit-read-stash "Drop stash")))) + (dolist (stash (if (listp stash) + (nreverse (prog1 stash (setq stash (car stash)))) + (list stash))) + (message "Deleted refs/%s (was %s)" stash + (magit-rev-parse "--short" stash)) + (magit-call-git "reflog" "delete" "--updateref" "--rewrite" stash)) + (-when-let (ref (and (string-match "\\(.+\\)@{[0-9]+}$" stash) + (match-string 1 stash))) + (unless (string-match "^refs/" ref) + (setq ref (concat "refs/" ref))) + (unless (magit-rev-verify (concat ref "@{0}")) + (magit-run-git "update-ref" "-d" ref))) + (magit-refresh)) + +;;;###autoload +(defun magit-stash-clear (ref) + "Remove all stashes saved in REF's reflog by deleting REF." + (interactive + (let ((ref (or (magit-section-when 'stashes) "refs/stash"))) + (if (magit-confirm t (format "Drop all stashes in %s" ref)) + (list ref) + (user-error "Abort")))) + (magit-run-git "update-ref" "-d" ref)) + +;;;###autoload +(defun magit-stash-branch (stash branch) + "Create and checkout a new BRANCH from STASH." + (interactive (list (magit-read-stash "Branch stash" t) + (magit-read-string-ns "Branch name"))) + (magit-run-git "stash" "branch" branch stash)) + +;;;###autoload +(defun magit-stash-format-patch (stash) + "Create a patch from STASH" + (interactive (list (magit-read-stash "Create patch from stash" t))) + (with-temp-file (magit-rev-format "0001-%f.patch" stash) + (magit-git-insert "stash" "show" "-p" stash)) + (magit-refresh)) + +;;; Plumbing + +(defun magit-stash-save (message index worktree untracked + &optional refresh keep noerror ref) + (if (or (and index (magit-staged-files t)) + (and worktree (magit-modified-files t)) + (and untracked (magit-untracked-files (eq untracked 'all)))) + (magit-with-toplevel + (magit-stash-store message (or ref "refs/stash") + (magit-stash-create message index worktree untracked)) + (if (eq keep 'worktree) + (with-temp-buffer + (magit-git-insert "diff" "--cached") + (magit-run-git-with-input nil + "apply" "--reverse" "--cached" "--ignore-space-change" "-") + (magit-run-git-with-input nil + "apply" "--reverse" "--ignore-space-change" "-")) + (unless (eq keep t) + (if (eq keep 'index) + (magit-call-git "checkout" "--" ".") + (magit-call-git "reset" "--hard" "HEAD")) + (when untracked + (magit-call-git "clean" "-f" (and (eq untracked 'all) "-x"))))) + (when refresh + (magit-refresh))) + (unless noerror + (user-error "No %s changes to save" (cond ((not index) "unstaged") + ((not worktree) "staged") + (t "local")))))) + +(defun magit-stash-store (message ref commit) + (magit-reflog-enable ref t) + (unless (magit-git-success "update-ref" "-m" message ref commit + (or (magit-rev-verify ref) "")) + (error "Cannot update %s with %s" ref commit))) + +(defun magit-stash-create (message index worktree untracked) + (unless (magit-rev-parse "--verify" "HEAD") + (error "You do not have the initial commit yet")) + (let ((magit-git-global-arguments (nconc (list "-c" "commit.gpgsign=false") + magit-git-global-arguments)) + (default-directory (magit-toplevel)) + (summary (magit-stash-summary)) + (head "HEAD")) + (when (and worktree (not index)) + (setq head (magit-commit-tree "pre-stash index" nil "HEAD"))) + (or (setq index (magit-commit-tree (concat "index on " summary) nil head)) + (error "Cannot save the current index state")) + (and untracked + (setq untracked (magit-untracked-files (eq untracked 'all))) + (setq untracked (magit-with-temp-index nil nil + (or (and (magit-update-files untracked) + (magit-commit-tree + (concat "untracked files on " summary))) + (error "Cannot save the untracked files"))))) + (magit-with-temp-index index "-m" + (when worktree + (or (magit-update-files (magit-git-items "diff" "-z" "--name-only" head)) + (error "Cannot save the current worktree state"))) + (or (magit-commit-tree message nil head index untracked) + (error "Cannot save the current worktree state"))))) + +(defun magit-stash-summary () + (concat (or (magit-get-current-branch) "(no branch)") + ": " (magit-rev-format "%h %s"))) + +;;; Sections + +(defvar magit-stashes-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-delete-thing] 'magit-stash-clear) + map) + "Keymap for `stashes' section.") + +(defvar magit-stash-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-stash-show) + (define-key map [remap magit-delete-thing] 'magit-stash-drop) + (define-key map "a" 'magit-stash-apply) + (define-key map "A" 'magit-stash-pop) + map) + "Keymap for `stash' sections.") + +(magit-define-section-jumper magit-jump-to-stashes + "Stashes" stashes "refs/stash") + +(cl-defun magit-insert-stashes (&optional (ref "refs/stash") + (heading "Stashes:")) + "Insert `stashes' section showing reflog for \"refs/stash\". +If optional REF is non-nil show reflog for that instead. +If optional HEADING is non-nil use that as section heading +instead of \"Stashes:\"." + (when (magit-rev-verify ref) + (magit-insert-section (stashes ref (not magit-status-expand-stashes)) + (magit-insert-heading heading) + (magit-git-wash (apply-partially 'magit-log-wash-log 'stash) + "reflog" "--format=%gd %at %gs" ref)))) + +;;; List Stashes + +;;;###autoload +(defun magit-stash-list () + "List all stashes in a buffer." + (interactive) + (magit-mode-setup #'magit-stashes-mode "refs/stash")) + +(define-derived-mode magit-stashes-mode magit-reflog-mode "Magit Stashes" + "Mode for looking at lists of stashes." + :group 'magit-log + (hack-dir-local-variables-non-file-buffer)) + +(cl-defun magit-stashes-refresh-buffer (ref) + (magit-insert-section (stashesbuf) + (magit-insert-heading (if (equal ref "refs/stash") + "Stashes:" + (format "Stashes [%s]:" ref))) + (magit-git-wash (apply-partially 'magit-log-wash-log 'stash) + "reflog" "--format=%gd %at %gs" ref))) + +;;; Show Stash + +(defcustom magit-stash-sections-hook + '(magit-insert-stash-worktree + magit-insert-stash-index + magit-insert-stash-untracked) + "Hook run to insert sections into stash buffers." + :package-version '(magit . "2.1.0") + :group 'magit-log + :type 'hook) + +;;;###autoload +(defun magit-stash-show (stash &optional args files) + "Show all diffs of a stash in a buffer." + (interactive (cons (or (and (not current-prefix-arg) + (magit-stash-at-point)) + (magit-read-stash "Show stash")) + (-let [(args files) (magit-diff-arguments)] + (list (delete "--stat" args) files)))) + (magit-mode-setup #'magit-stash-mode stash nil args files)) + +(define-derived-mode magit-stash-mode magit-diff-mode "Magit Stash" + "Mode for looking at individual stashes." + :group 'magit-diff + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-stash-refresh-buffer (stash _const _args _files) + (setq header-line-format + (concat + "\s" (propertize (capitalize stash) 'face 'magit-section-heading) + "\s" (magit-rev-format "%s" stash))) + (magit-insert-section (stash) + (run-hooks 'magit-stash-sections-hook))) + +(defun magit-stash-insert-section (commit range message &optional files) + (magit-insert-section (commit commit) + (magit-insert-heading message) + (magit-git-wash #'magit-diff-wash-diffs + "diff" range "-p" "--no-prefix" + (nth 2 magit-refresh-args) + "--" (or files (nth 3 magit-refresh-args))))) + +(defun magit-insert-stash-index () + "Insert section showing the index commit of the stash." + (let ((stash (car magit-refresh-args))) + (magit-stash-insert-section (format "%s^2" stash) + (format "%s^..%s^2" stash stash) + "Index"))) + +(defun magit-insert-stash-worktree () + "Insert section showing the worktree commit of the stash." + (let ((stash (car magit-refresh-args))) + (magit-stash-insert-section stash + (format "%s^2..%s" stash stash) + "Working tree"))) + +(defun magit-insert-stash-untracked () + "Insert section showing the untracked files commit of the stash." + (let ((stash (car magit-refresh-args)) + (rev (concat (car magit-refresh-args) "^3"))) + (when (magit-rev-verify rev) + (magit-stash-insert-section (format "%s^3" stash) + (format "%s^..%s^3" stash stash) + "Untracked files" + (magit-git-items "ls-tree" "-z" "--name-only" + "--full-tree" rev))))) + +;;; magit-stash.el ends soon +(provide 'magit-stash) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-stash.el ends here diff --git a/elpa/magit-20151223.1425/magit-utils.el b/elpa/magit-20151223.1425/magit-utils.el new file mode 100644 index 00000000..8b2b535e --- /dev/null +++ b/elpa/magit-20151223.1425/magit-utils.el @@ -0,0 +1,408 @@ +;;; magit-utils.el --- various utilities -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Contains code from GNU Emacs https://www.gnu.org/software/emacs, +;; released under the GNU General Public License version 3 or later. + +;; 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: + +;; This library defines several utility functions used by several +;; other libraries which cannot depend on one another (because +;; circular dependencies are not good). Luckily most (all) of these +;; functions have very little (nothing) to do with Git, so we not only +;; have to do this, it even makes sense. + +;; Unfortunately there are also some options which are used by several +;; libraries which cannot depend on one another, they are defined here +;; too. + +;;; Code: + +(require 'cl-lib) +(require 'dash) + +(eval-when-compile (require 'ido)) +(declare-function ido-completing-read+ 'ido-completing-read+) + +(defvar magit-wip-before-change-mode) + +;;; Options + +(defcustom magit-completing-read-function 'magit-builtin-completing-read + "Function to be called when requesting input from the user." + :group 'magit + :type '(radio (function-item magit-builtin-completing-read) + (function-item magit-ido-completing-read) + (function-item helm-completing-read-with-cands-in-buffer) + (function :tag "Other"))) + +(defcustom magit-no-confirm nil + "A list of symbols for actions Magit should not confirm, or t. + +Many potentially dangerous commands by default ask the user for +confirmation. Each of the below symbols stands for an action +which, when invoked unintentionally or without being fully aware +of the consequences, could lead to tears. In many cases there +are several commands that perform variations of a certain action, +so we don't use the command names but more generic symbols. + +Applying changes: + + `discard' Discarding one or more changes (i.e. hunks or the + complete diff for a file) loses that change, obviously. + + `reverse' Reverting one or more changes can usually be undone + by reverting the reversion. + + `stage-all-changes', `unstage-all-changes' When there are both + staged and unstaged changes, then un-/staging everything would + destroy that distinction. Of course that also applies when + un-/staging a single change, but then less is lost and one does + that so often that having to confirm every time would be + unacceptable. + +Files: + + `delete' When a file that isn't yet tracked by Git is deleted + then it is completely lost, not just the last changes. Very + dangerous. + + `trash' Instead of deleting a file it can also be move to the + system trash. Obviously much less dangerous than deleting it. + + Also see option `magit-delete-by-moving-to-trash'. + + `resurrect' A deleted file can easily be resurrected by + \"deleting\" the deletion, which is done using the same command + that was used to delete the same file in the first place. + + `rename' Renaming a file can easily be undone. + +Sequences: + + `reset-bisect' Aborting (known to Git as \"resetting\") a + bisect operation loses all information collected so far. + + `abort-merge' Aborting a merge throws away all conflict + resolutions which has already been carried out by the user. + + `merge-dirty' Merging with a dirty worktree can make it hard to + go back to the state before the merge was initiated. + +References: + + `delete-unmerged-branch' Once a branch has been deleted it can + only be restored using low-level recovery tools provided by + Git. And even then the reflog is gone. The user always has + to confirm the deletion of a branch by accepting the default + choice (or selecting another branch), but when a branch has + not been merged yet, also make sure the user is aware of that. + + `drop-stashes' Dropping a stash is dangerous because Git stores + stashes in the reflog. Once a stash is removed, there is no + going back without using low-level recovery tools provided by + Git. When a single stash is dropped, then the user always has + to confirm by accepting the default (or selecting another). + This action only concerns the deletion of multiple stashes at + once. + +Various: + + `kill-process' There seldom is a reason to kill a process. + +Global settings: + + Instead of adding all of the above symbols to the value of this + option you can also set it to the atom `t', which has the same + effect as adding all of the above symbols. Doing that most + certainly is a bad idea, especially because other symbols might + be added in the future. So even if you don't want to be asked + for confirmation for any of these actions, you are still better + of adding all of the respective symbols individually. + + When `magit-wip-before-change-mode' is enabled then these actions + can fairly easily be undone: `discard', `reverse', + `stage-all-changes', and `unstage-all-changes'. If and only if + this mode is enabled then `safe-with-wip' has the same effect + as adding all of these symbols individually." + :package-version '(magit . "2.1.0") + :group 'magit + :type '(choice (const :tag "No confirmation needed" t) + (set (const reverse) (const discard) + (const rename) (const resurrect) + (const trash) (const delete) + (const abort-merge) (const merge-dirty) + (const drop-stashes) (const resect-bisect) + (const kill-process) (const delete-unmerged-branch) + (const stage-all-changes) (const unstage-all-changes) + (const safe-with-wip)))) + +(defcustom magit-ellipsis ?… + "Character used to abbreviate text." + :package-version '(magit . "2.1.0") + :group 'magit-modes + :type 'character) + +(defcustom magit-update-other-window-delay 0.2 + "Delay before automatically updating the other window. + +When moving around in certain buffers certain other buffers, +which are being displayed in another window, may optionally be +updated to display information about the section at point. + +When holding down a key to move by more than just one section, +then that would update that buffer for each section on the way. +To prevent that, updating the revision buffer is delayed, and +this option controls for how long. For optimal experience you +might have to adjust this delay and/or the keyboard repeat rate +and delay of your graphical environment or operating system." + :package-version '(magit . "2.3.0") + :group 'magit-modes + :type 'number) + +;;; User Input + +(defun magit-completing-read + (prompt collection &optional predicate require-match initial-input hist def) + "Magit wrapper around `completing-read' or an alternative function. + +Option `magit-completing-read-function' can be used to wrap +around another `completing-read'-like function. Unless it +doesn't have the exact same signature, an additional wrapper is +required. Even if it has the same signature it might be a good +idea to wrap it, so that `magit-prompt-with-default' can be used. + +See `completing-read' for the meanings of the arguments, but note +that this wrapper makes the following changes: + +- If REQUIRE-MATCH is nil and the user exits without a choice, + then return nil instead of an empty string. + +- If REQUIRE-MATCH is non-nil and the users exits without a + choice, then raise an user-error. + +- \": \" is appended to PROMPT. + +- If a `magit-completing-read-function' is used which in turn + uses `magit-prompt-with-completion' and DEF is non-nil, then + PROMPT is modified to end with \" (default DEF): \". + +The use of another completing function and/or wrapper obviously +results in additional differences." + (let ((reply (funcall magit-completing-read-function + (concat prompt ": ") collection predicate + require-match initial-input hist def))) + (if (string= reply "") + (if require-match + (user-error "Nothing selected") + nil) + reply))) + +(defun magit-builtin-completing-read + (prompt choices &optional predicate require-match initial-input hist def) + "Magit wrapper for standard `completing-read' function." + (completing-read (magit-prompt-with-default prompt def) + choices predicate require-match + initial-input hist def)) + +(defun magit-ido-completing-read + (prompt choices &optional predicate require-match initial-input hist def) + "Ido-based `completing-read' almost-replacement. + +Unfortunately `ido-completing-read' is not suitable as a +drop-in replacement for `completing-read', instead we use +`ido-completing-read+' from the third-party package by the +same name." + (if (require 'ido-completing-read+ nil t) + (ido-completing-read+ prompt choices predicate require-match + initial-input hist def) + (display-warning 'magit "ido-completing-read+ is not installed + +To use Ido completion with Magit you need to install the +third-party `ido-completing-read+' packages. Falling +back to built-in `completing-read' for now." :error) + (magit-builtin-completing-read prompt choices predicate require-match + initial-input hist def))) + +(defun magit-prompt-with-default (prompt def) + (if (and def (> (length prompt) 2) + (string-equal ": " (substring prompt -2))) + (format "%s (default %s): " (substring prompt 0 -2) def) + prompt)) + +(defvar magit-minibuffer-local-ns-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map minibuffer-local-map) + (define-key map "\s" 'magit-whitespace-disallowed) + (define-key map "\t" 'magit-whitespace-disallowed) + map)) + +(defun magit-whitespace-disallowed () + "Beep to tell the user that whitespace is not allowed." + (interactive) + (ding) + (message "Whitespace isn't allowed here") + (setq defining-kbd-macro nil) + (force-mode-line-update)) + +(defun magit-read-string (prompt &optional initial-input history default-value + inherit-input-method no-whitespace) + "Read a string from the minibuffer, prompting with string PROMPT. + +This is similar to `read-string', but +* empty input is only allowed if DEFAULT-VALUE is non-nil in + which case that is returned, +* whitespace is not allowed if NO-WHITESPACE is non-nil, +* \": \" is appended to PROMPT, and +* an invalid DEFAULT-VALUE is silently ignored." + (when default-value + (when (consp default-value) + (setq default-value (car default-value))) + (unless (stringp default-value) + (setq default-value nil))) + (let* ((minibuffer-completion-table nil) + (val (read-from-minibuffer + (magit-prompt-with-default (concat prompt ": ") default-value) + initial-input (and no-whitespace magit-minibuffer-local-ns-map) + nil history default-value inherit-input-method))) + (when (and (string= val "") default-value) + (setq val default-value)) + (cond ((string= val "") + (user-error "Need non-empty input")) + ((and no-whitespace (string-match-p "[\s\t\n]" val)) + (user-error "Input contains whitespace")) + (t val)))) + +(defun magit-read-string-ns (prompt &optional initial-input history + default-value inherit-input-method) + "Call `magit-read-string' with non-nil NO-WHITESPACE." + (magit-read-string prompt initial-input history default-value + inherit-input-method t)) + +(defmacro magit-read-char-case (prompt verbose &rest clauses) + (declare (indent 2) + (debug (form form &rest (characterp form body)))) + `(pcase (read-char-choice + (concat ,prompt + ,(concat (mapconcat 'cadr clauses ", ") + (and verbose ", or [C-g] to abort") " ")) + ',(mapcar 'car clauses)) + ,@(--map `(,(car it) ,@(cddr it)) clauses))) + +(cl-defun magit-confirm (action &optional prompt prompt-n (items nil sitems)) + (declare (indent defun)) + (setq prompt-n (format (concat (or prompt-n prompt) "? ") (length items)) + prompt (format (concat (or prompt (magit-confirm-make-prompt action)) + "? ") + (car items))) + (cond ((and (not (eq action t)) + (or (eq magit-no-confirm t) + (memq action + `(,@magit-no-confirm + ,@(and magit-wip-before-change-mode + (memq 'safe-with-wip magit-no-confirm) + `(discard reverse + stage-all-changes + unstage-all-changes)))))) + (or (not sitems) items)) + ((not sitems) + (y-or-n-p prompt)) + ((= (length items) 1) + (and (y-or-n-p prompt) items)) + ((> (length items) 1) + (let ((buffer (get-buffer-create " *Magit Confirm*"))) + (with-current-buffer buffer + (with-current-buffer-window + buffer (cons 'display-buffer-below-selected + '((window-height . fit-window-to-buffer))) + (lambda (window _value) + (with-selected-window window + (unwind-protect (and (y-or-n-p prompt-n) items) + (when (window-live-p window) + (quit-restore-window window 'kill))))) + (dolist (item items) + (insert item "\n")))))))) + +(defun magit-confirm-files (action files &optional prompt) + (when files + (unless prompt + (setq prompt (magit-confirm-make-prompt action))) + (magit-confirm action + (concat prompt " %s") + (concat prompt " %i files") + files))) + +(defun magit-confirm-make-prompt (action) + (let ((prompt (symbol-name action))) + (replace-regexp-in-string + "-" " " (concat (upcase (substring prompt 0 1)) (substring prompt 1))))) + +;;; Text Utilities + +(defmacro magit-bind-match-strings (varlist string &rest body) + "Bind variables to submatches according to VARLIST then evaluate BODY. +Bind the symbols in VARLIST to submatches of the current match +data, starting with 1 and incrementing by 1 for each symbol. If +the last match was against a string then that has to be provided +as STRING." + (declare (indent 2) (debug (listp form body))) + (let ((s (cl-gensym "string")) + (i 0)) + `(let ((,s ,string)) + (let ,(save-match-data + (--map (list it (list 'match-string (cl-incf i) s)) varlist)) + ,@body)))) + +(defun magit-delete-line () + "Delete the rest of the current line." + (delete-region (point) (1+ (line-end-position)))) + +(defun magit-delete-match (&optional num) + "Delete text matched by last search. +If optional NUM is specified only delete that subexpression." + (delete-region (match-beginning (or num 0)) + (match-end (or num 0)))) + +(defun magit-file-line (file) + "Return the first line of FILE as a string." + (when (file-regular-p file) + (with-temp-buffer + (insert-file-contents file) + (buffer-substring-no-properties (point-min) + (line-end-position))))) + +(defun magit-file-lines (file &optional keep-empty-lines) + "Return a list of strings containing one element per line in FILE. +Unless optional argument KEEP-EMPTY-LINES is t, trim all empty lines." + (when (file-regular-p file) + (with-temp-buffer + (insert-file-contents file) + (split-string (buffer-string) "\n" (not keep-empty-lines))))) + +;;; magit-utils.el ends soon +(provide 'magit-utils) +;; Local Variables: +;; coding: utf-8 +;; indent-tabs-mode: nil +;; End: +;;; magit-utils.el ends here diff --git a/elpa/magit-20151223.1425/magit-wip.el b/elpa/magit-20151223.1425/magit-wip.el new file mode 100644 index 00000000..9255dce2 --- /dev/null +++ b/elpa/magit-20151223.1425/magit-wip.el @@ -0,0 +1,289 @@ +;;; magit-wip.el --- commit snapshots to work-in-progress refs -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; 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: + +;; This library defines tree global modes which automatically commit +;; snapshots to branch specific work-in-progress refs before and after +;; making changes, and two commands which can be used to do so on +;; demand. + +;;; Code: + +(require 'magit-core) +(require 'magit-log) + +;;; Options + +(defgroup magit-wip nil + "Automatically commit to work-in-progress refs." + :group 'magit-extensions) + +(defcustom magit-wip-after-save-local-mode-lighter " sWip" + "Lighter for Magit-Wip-After-Save-Local mode." + :package-version '(magit . "2.1.0") + :group 'magit-wip + :type 'string) + +(defcustom magit-wip-after-apply-mode-lighter " aWip" + "Lighter for Magit-Wip-After-Apply mode." + :package-version '(magit . "2.1.0") + :group 'magit-wip + :type 'string) + +(defcustom magit-wip-before-change-mode-lighter " cWip" + "Lighter for Magit-Wip-Before-Change mode." + :package-version '(magit . "2.1.0") + :group 'magit-wip + :type 'string) + +(defcustom magit-wip-namespace "refs/wip/" + "Namespace used for work-in-progress refs. +The wip refs are named \"index/\" +and \"wtree/\". When snapshots +are created while the `HEAD' is detached then \"HEAD\" +is used as `branch-ref'." + :package-version '(magit . "2.1.0") + :group 'magit-wip + :type 'string) + +;;; Modes + +(define-minor-mode magit-wip-after-save-local-mode + "After saving, also commit to a worktree work-in-progress ref. + +After saving the current file-visiting buffer this mode also +commits the changes to the worktree work-in-progress ref for +the current branch. + +This mode should be enabled globally by turning on the globalized +variant `magit-wip-after-save-mode'." + :package-version '(magit . "2.1.0") + :lighter magit-wip-after-save-local-mode-lighter + (if magit-wip-after-save-local-mode + (if (and buffer-file-name (magit-inside-worktree-p)) + (add-hook 'after-save-hook 'magit-wip-commit-buffer-file t t) + (setq magit-wip-after-save-local-mode nil) + (user-error "Need a worktree and a file")) + (remove-hook 'after-save-hook 'magit-wip-commit-buffer-file t))) + +(defun magit-wip-after-save-local-mode-turn-on () + (and buffer-file-name + (ignore-errors (magit-inside-worktree-p)) + (magit-file-tracked-p buffer-file-name) + (magit-wip-after-save-local-mode))) + +;;;###autoload +(define-globalized-minor-mode magit-wip-after-save-mode + magit-wip-after-save-local-mode magit-wip-after-save-local-mode-turn-on + :package-version '(magit . "2.1.0") + :group 'magit-wip) + +(defun magit-wip-commit-buffer-file () + "Commit visited file to a worktree work-in-progress ref. + +Also see `magit-wip-after-save-mode' which calls this function +automatically whenever a buffer visiting a tracked file is saved." + (interactive) + (--when-let (magit-wip-get-ref) + (magit-with-toplevel + (let ((file (file-relative-name buffer-file-name))) + (magit-wip-commit-worktree + it (list file) (if (called-interactively-p 'any) + (format "wip-save %s after save" file) + (format "autosave %s after save" file))))))) + +;;;###autoload +(define-minor-mode magit-wip-after-apply-mode + "Commit to work-in-progress refs. + +After applying a change using any \"apply variant\" +command (apply, stage, unstage, discard, and reverse) commit the +affected files to the current wip refs. For each branch there +may be two wip refs; one contains snapshots of the files as found +in the worktree and the other contains snapshots of the entries +in the index." + :package-version '(magit . "2.1.0") + :group 'magit-wip + :lighter magit-wip-after-change-mode-lighter + :global t) + +(defun magit-wip-commit-after-apply (&optional files msg) + (when magit-wip-after-apply-mode + (magit-wip-commit files msg))) + +;;;###autoload +(define-minor-mode magit-wip-before-change-mode + "Commit to work-in-progress refs before certain destructive changes. + +Before invoking a revert command or an \"apply variant\" +command (apply, stage, unstage, discard, and reverse) commit the +affected tracked files to the current wip refs. For each branch +there may be two wip refs; one contains snapshots of the files +as found in the worktree and the other contains snapshots of the +entries in the index. + +Only changes to files which could potentially be affected by the +command which is about to be called are committed." + :package-version '(magit . "2.1.0") + :group 'magit-wip + :lighter magit-wip-before-change-mode-lighter + :global t) + +(defun magit-wip-commit-before-change (&optional files msg) + (when magit-wip-before-change-mode + (magit-with-toplevel + (magit-wip-commit files msg)))) + +;;; Core + +(defun magit-wip-commit (&optional files msg) + "Commit all tracked files to the work-in-progress refs. + +Interactively, commit all changes to all tracked files using +a generic commit message. With a prefix-argument the commit +message is read in the minibuffer. + +Non-interactively, only commit changes to FILES using MSG as +commit message." + (interactive (list nil (if current-prefix-arg + (magit-read-string "Wip commit message") + "wip-save tracked files"))) + (--when-let (magit-wip-get-ref) + (magit-wip-commit-index it files msg) + (magit-wip-commit-worktree it files msg))) + +(defun magit-wip-commit-index (ref files msg &optional cached-only) + (let* ((wipref (concat magit-wip-namespace "index/" ref)) + (parent (magit-wip-get-parent ref wipref))) + (when (magit-git-failure "diff-index" "--quiet" + (and cached-only "--cached") + parent "--" files) + (magit-wip-update-wipref wipref (magit-git-string "write-tree") + parent files msg "index")))) + +(defun magit-wip-commit-worktree (ref files msg) + (let* ((wipref (concat magit-wip-namespace "wtree/" ref)) + (parent (magit-wip-get-parent ref wipref)) + (tree (magit-with-temp-index parent "--reset" + (if files + (magit-call-git "add" "--" files) + (magit-with-toplevel + (magit-call-git "add" "-u" "."))) + (magit-git-string "write-tree")))) + (when (magit-git-failure "diff-tree" "--quiet" parent tree "--" files) + (magit-wip-update-wipref wipref tree parent files msg "worktree")))) + +(defun magit-wip-update-wipref (wipref tree parent files msg start-msg) + (let ((len (length files))) + (unless (and msg (not (= (aref msg 0) ?\s))) + (setq msg (concat + (cond ((= len 0) "autosave tracked files") + ((> len 1) (format "autosave %s files" len)) + (t (concat "autosave " + (file-relative-name (car files) + (magit-toplevel))))) + msg))) + (magit-reflog-enable wipref) + (unless (equal parent wipref) + (setq start-msg (concat "restart autosaving " start-msg)) + (magit-call-git "update-ref" wipref "-m" start-msg + (magit-git-string "commit-tree" "-p" parent + "-m" start-msg + (concat parent "^{tree}"))) + (setq parent wipref)) + (magit-call-git "update-ref" wipref "-m" msg + (magit-git-string "commit-tree" tree + "-p" parent "-m" msg)))) + +(defun magit-wip-get-ref () + (let ((ref (or (magit-git-string "symbolic-ref" "HEAD") "HEAD"))) + (when (magit-rev-verify ref) + ref))) + +(defun magit-wip-get-parent (ref wipref) + (if (and (magit-rev-verify wipref) + (equal (magit-git-string "merge-base" wipref ref) + (magit-rev-verify ref))) + wipref + ref)) + +;;; Log + +(defun magit-wip-log-current (branch args files count) + "Show log for the current branch and its wip refs. +With a negative prefix argument only show the worktree wip ref. +The absolute numeric value of the prefix argument controls how +many \"branches\" of each wip ref are shown." + (interactive + (nconc (list (or (magit-get-current-branch) "HEAD")) + (magit-log-arguments) + (list (prefix-numeric-value current-prefix-arg)))) + (magit-wip-log branch args files count)) + +(defun magit-wip-log (branch args files count) + "Show log for a branch and its wip refs. +With a negative prefix argument only show the worktree wip ref. +The absolute numeric value of the prefix argument controls how +many \"branches\" of each wip ref are shown." + (interactive + (nconc (list (magit-completing-read + "Log branch and its wip refs" + (-snoc (magit-list-local-branch-names) "HEAD") + nil t nil 'magit-revision-history + (or (magit-branch-at-point) + (magit-get-current-branch) + "HEAD"))) + (magit-log-arguments) + (list (prefix-numeric-value current-prefix-arg)))) + (unless (equal branch "HEAD") + (setq branch (concat "refs/heads/" branch))) + (magit-log (nconc (list branch) + (magit-wip-log-get-tips + (concat magit-wip-namespace "wtree/" branch) + (abs count)) + (and (>= count 0) + (magit-wip-log-get-tips + (concat magit-wip-namespace "index/" branch) + (abs count)))) + args files)) + +(defun magit-wip-log-get-tips (wipref count) + (-when-let (reflog (magit-git-lines "reflog" wipref)) + (let (tips) + (while (and reflog (> count 1)) + (setq reflog (cl-member "^[^ ]+ [^:]+: restart autosaving" + reflog :test #'string-match-p)) + (when (and (cadr reflog) + (string-match "^[^ ]+ \\([^:]+\\)" (cadr reflog))) + (push (match-string 1 (cadr reflog)) tips)) + (setq reflog (cddr reflog)) + (cl-decf count)) + (cons wipref (nreverse tips))))) + +;;; magit-wip.el ends soon +(provide 'magit-wip) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-wip.el ends here diff --git a/elpa/magit-20151223.1425/magit.el b/elpa/magit-20151223.1425/magit.el new file mode 100644 index 00000000..da157fe8 --- /dev/null +++ b/elpa/magit-20151223.1425/magit.el @@ -0,0 +1,3033 @@ +;;; magit.el --- A Git porcelain inside Emacs -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Marius Vollmer +;; Maintainer: Jonas Bernoulli +;; Kyle Meyer +;; Noam Postavsky +;; Former-Maintainers: +;; Nicolas Dudebout +;; Peter J. Weisberg +;; Phil Jackson +;; Rémi Vanicat +;; Yann Hodique + +;; Package-Requires: ((emacs "24.4") (async "20150909.2257") (dash "20151021.113") (with-editor "20151111") (git-commit "20151111") (magit-popup "20151221")) +;; Keywords: git tools vc +;; Homepage: https://github.com/magit/magit + +;; Magit requires at least GNU Emacs 24.4 and Git 1.9.4. + +;; 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: + +;; Magit is an interface to the version control system Git, +;; implemented as an Emacs package. Magit aspires to be a complete +;; Git porcelain. While we cannot (yet) claim, that Magit wraps and +;; improves upon each and every Git command, it is complete enough to +;; allow even experienced Git users to perform almost all of their +;; daily version control tasks directly from within Emacs. While many +;; fine Git clients exist, only Magit and Git itself deserve to be +;; called porcelains. + +;;; Code: + +(require 'cl-lib) +(require 'dash) + +(require 'with-editor) +(require 'git-commit) +(require 'magit-core) +(require 'magit-diff) +(require 'magit-apply) +(require 'magit-log) + +(require 'format-spec) +(require 'package nil t) ; used in `magit-version' + +(eval-when-compile (require 'dired-x)) +(declare-function dired-jump 'dired-x) +(eval-when-compile (require 'eshell)) +(declare-function eshell-parse-arguments 'eshell) +(eval-when-compile (require 'message)) +(declare-function message-goto-body 'message) + +(defconst magit--minimal-git "1.9.4") +(defconst magit--minimal-emacs "24.4") + +;;; Options +;;;; Status Mode + +(defgroup magit-status nil + "Inspect and manipulate Git repositories." + :group 'magit-modes) + +(defcustom magit-status-mode-hook nil + "Hook run after entering Magit-Status mode." + :group 'magit-status + :type 'hook) + +(defcustom magit-status-headers-hook + '(magit-insert-error-header + magit-insert-diff-filter-header + magit-insert-head-branch-header + magit-insert-upstream-branch-header + magit-insert-push-branch-header + magit-insert-tags-header) + "Hook run to insert headers into the status buffer. + +This hook is run by `magit-insert-status-headers', which in turn +has to be a member of `magit-insert-status-sections' to be used +at all." + :package-version '(magit . "2.1.0") + :group 'magit-status + :type 'hook + :options '(magit-insert-error-header + magit-insert-diff-filter-header + magit-insert-repo-header + magit-insert-remote-header + magit-insert-head-branch-header + magit-insert-upstream-branch-header + magit-insert-push-branch-header + magit-insert-tags-header)) + +(defcustom magit-status-sections-hook + '(magit-insert-status-headers + magit-insert-merge-log + magit-insert-rebase-sequence + magit-insert-am-sequence + magit-insert-sequencer-sequence + magit-insert-bisect-output + magit-insert-bisect-rest + magit-insert-bisect-log + magit-insert-untracked-files + magit-insert-unstaged-changes + magit-insert-staged-changes + magit-insert-stashes + magit-insert-unpulled-from-upstream + magit-insert-unpulled-from-pushremote + magit-insert-unpushed-to-upstream + magit-insert-unpushed-to-pushremote) + "Hook run to insert sections into a status buffer." + :package-version '(magit . "2.4.0") + :group 'magit-status + :type 'hook) + +(defcustom magit-status-refresh-hook nil + "Hook run after a status buffer has been refreshed." + :package-version '(magit . "2.1.0") + :group 'magit-status + :type 'hook) + +(defcustom magit-status-expand-stashes t + "Whether the list of stashes is expanded initially." + :package-version '(magit . "2.3.0") + :group 'magit-status + :type 'boolean) + +;;;; Refs Mode + +(defgroup magit-refs nil + "Inspect and manipulate Git branches and tags." + :group 'magit-modes) + +(defcustom magit-refs-mode-hook nil + "Hook run after entering Magit-Refs mode." + :package-version '(magit . "2.1.0") + :group 'magit-refs + :type 'hook) + +(defcustom magit-refs-sections-hook + '(magit-insert-error-header + magit-insert-branch-description + magit-insert-local-branches + magit-insert-remote-branches + magit-insert-tags) + "Hook run to insert sections into a references buffer." + :package-version '(magit . "2.1.0") + :group 'magit-refs + :type 'hook) + +(defcustom magit-refs-show-commit-count nil + "Whether to show commit counts in Magit-Refs mode buffers. + +all Show counts for branches and tags. +branch Show counts for branches only. +nil Never show counts." + :package-version '(magit . "2.1.0") + :group 'magit-refs + :safe (lambda (val) (memq val '(all branch nil))) + :type '(choice (const all :tag "For branches and tags") + (const branch :tag "For branches only") + (const nil :tag "Never"))) +(put 'magit-refs-show-commit-count 'safe-local-variable 'symbolp) +(put 'magit-refs-show-commit-count 'permanent-local t) + +(defcustom magit-refs-show-margin 'branch + "Whether to initially show the margin in refs buffers. + +When non-nil the committer name and date are initially displayed +in the margin of refs buffers. The margin can be shown or hidden +in the current buffer using the command `magit-toggle-margin'." + :package-version '(magit . "2.1.0") + :group 'magit-refs + :safe (lambda (val) (memq val '(all branch nil))) + :type '(choice (const all :tag "For branches and tags") + (const branch :tag "For branches only") + (const nil :tag "Never"))) + +(defcustom magit-visit-ref-create nil + "Whether `magit-visit-ref' may create new branches. + +When this is non-nil, then \"visiting\" a remote branch in a +refs buffer works by creating a new local branch which tracks +the remote branch and then checking out the new local branch." + :package-version '(magit . "2.1.0") + :group 'magit-refs + :group 'magit-commands + :type 'boolean) + +;;;; Miscellaneous + +(defcustom magit-branch-read-upstream-first t + "When creating a branch, read upstream before name of new branch." + :package-version '(magit . "2.2.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-branch-prefer-remote-upstream nil + "Whether to favor remote upstreams when creating new branches. + +When a new branch is created, Magit offers the branch, commit, or +stash as the default starting point of the new branch. If there +is no such thing at point, then it falls back to offer the +current branch as starting-point. The user may then accept that +default or pick something else. + +If the chosen starting-point is a branch, then it may also be set +as the upstream of the new branch, depending on the value of the +Git variable `branch.autoSetupMerge'. By default this is done +for remote branches, but not for local branches. + +You might prefer to always use some remote branch as upstream. +If the chosen starting-point is (1) a local branch, (2) whose +name is a member of the value of this option, (3) the upstream of +that local branch is a remote branch with the same name, and (4) +that remote branch can be fast-forwarded to the local branch, +then the chosen branch is used as starting-point, but its own +upstream is used as the upstream of the new branch. + +Assuming the chosen branch matches these conditions you would end +up with with e.g.: + + feature --upstream--> origin/master + +instead of + + feature --upstream--> master --upstream--> origin/master + +Which you prefer is a matter of personal preference. If you do +prefer the former, then you should add branches such as \"master\", +\"next\", and \"maint\" to the value of this options." + :package-version '(magit . "2.4.0") + :group 'magit-commands + :type '(repeat string)) + +(defcustom magit-repository-directories nil + "Directories containing Git repositories. +Magit checks these directories for Git repositories and offers +them as choices when `magit-status' is used with a prefix +argument." + :group 'magit + :type '(repeat string)) + +(defcustom magit-repository-directories-depth 3 + "The maximum depth to look for Git repositories. +When looking for a Git repository below the directories in +`magit-repository-directories', only descend this many levels +deep." + :group 'magit + :type 'integer) + +;;;; Faces + +(defface magit-header-line + '((t :inherit magit-section-heading)) + "Face for the `header-line'." + :group 'magit-faces) + +(defface magit-dimmed + '((((class color) (background light)) :foreground "grey50") + (((class color) (background dark)) :foreground "grey50")) + "Face for text that shouldn't stand out." + :group 'magit-faces) + +(defface magit-hash + '((((class color) (background light)) :foreground "grey60") + (((class color) (background dark)) :foreground "grey40")) + "Face for the sha1 part of the log output." + :group 'magit-faces) + +(defface magit-tag + '((((class color) (background light)) :foreground "Goldenrod4") + (((class color) (background dark)) :foreground "LightGoldenrod2")) + "Face for tag labels shown in log buffer." + :group 'magit-faces) + +(defface magit-branch-remote + '((((class color) (background light)) :foreground "DarkOliveGreen4") + (((class color) (background dark)) :foreground "DarkSeaGreen2")) + "Face for remote branch head labels shown in log buffer." + :group 'magit-faces) + +(defface magit-branch-local + '((((class color) (background light)) :foreground "SkyBlue4") + (((class color) (background dark)) :foreground "LightSkyBlue1")) + "Face for local branches." + :group 'magit-faces) + +(defface magit-branch-current + '((((class color) (background light)) :inherit magit-branch-local :box t) + (((class color) (background dark)) :inherit magit-branch-local :box t)) + "Face for current branch." + :group 'magit-faces) + +(defface magit-head + '((((class color) (background light)) :inherit magit-branch-local) + (((class color) (background dark)) :inherit magit-branch-local)) + "Face for the symbolic ref \"HEAD\"." + :group 'magit-faces) + +(defface magit-refname + '((((class color) (background light)) :foreground "grey30") + (((class color) (background dark)) :foreground "grey80")) + "Face for refnames without a dedicated face." + :group 'magit-faces) + +(defface magit-refname-stash + '((t :inherit magit-refname)) + "Face for wip refnames." + :group 'magit-faces) + +(defface magit-refname-wip + '((t :inherit magit-refname)) + "Face for wip refnames." + :group 'magit-faces) + +(defface magit-signature-good + '((t :foreground "green")) + "Face for good signatures." + :group 'magit-faces) + +(defface magit-signature-bad + '((t :foreground "red")) + "Face for bad signatures." + :group 'magit-faces) + +(defface magit-signature-untrusted + '((t :foreground "cyan")) + "Face for good untrusted signatures." + :group 'magit-faces) + +(defface magit-cherry-unmatched + '((t :foreground "cyan")) + "Face for unmatched cherry commits." + :group 'magit-faces) + +(defface magit-cherry-equivalent + '((t :foreground "magenta")) + "Face for equivalent cherry commits." + :group 'magit-faces) + +(defface magit-filename + '((t :weight normal)) + "Face for filenames." + :group 'magit-faces) + +;;; Inspect +;;;; Status Mode +;;;;; Status Core + +(defvar magit-status-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + (define-key map "jz" 'magit-jump-to-stashes) + (define-key map "jt" 'magit-jump-to-tracked) + (define-key map "jn" 'magit-jump-to-untracked) + (define-key map "ju" 'magit-jump-to-unstaged) + (define-key map "js" 'magit-jump-to-staged) + (define-key map "jfu" 'magit-jump-to-unpulled-from-upstream) + (define-key map "jfp" 'magit-jump-to-unpulled-from-pushremote) + (define-key map "jpu" 'magit-jump-to-unpushed-to-upstream) + (define-key map "jpp" 'magit-jump-to-unpushed-to-pushremote) + map) + "Keymap for `magit-status-mode'.") + +(eval-after-load 'dired-x + '(define-key magit-status-mode-map [remap dired-jump] 'magit-dired-jump)) + +(define-derived-mode magit-status-mode magit-mode "Magit" + "Mode for looking at Git status. + +This mode is documented in info node `(magit)Status buffer'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-section-toggle] to expand or hide the section at point. +Type \\[magit-visit-thing] to visit the change or commit at point. + +Type \\[magit-dispatch-popup] to see available prefix popups. + +Staging and applying changes is documented in info node +`(magit)Staging and unstaging' and info node `(magit)Applying'. + +\\Type \ +\\[magit-apply] to apply the change at point, \ +\\[magit-stage] to stage, +\\[magit-unstage] to unstage, \ +\\[magit-discard] to discard, or \ +\\[magit-reverse] to reverse it. + +\\\ +Type \\[magit-commit-popup] to create a commit. + +\\{magit-status-mode-map}" + :group 'magit-status + (hack-dir-local-variables-non-file-buffer)) + +;;;###autoload +(defun magit-status (&optional directory) + "Show the status of the current Git repository in a buffer. +With a prefix argument prompt for a repository to be shown. +With two prefix arguments prompt for an arbitrary directory. +If that directory isn't the root of an existing repository +then offer to initialize it as a new repository." + (interactive + (list (and (or current-prefix-arg (not (magit-toplevel))) + (magit-read-repository + (>= (prefix-numeric-value current-prefix-arg) 16))))) + (if directory + (let ((toplevel (magit-toplevel directory))) + (setq directory (file-name-as-directory (expand-file-name directory))) + (if (and toplevel (string-equal directory toplevel)) + (magit-status-internal directory) + (when (y-or-n-p + (if toplevel + (format "%s is a repository. Create another in %s? " + toplevel directory) + (format "Create repository in %s? " directory))) + (magit-init directory)))) + (magit-status-internal default-directory))) + +(put 'magit-status 'interactive-only 'magit-status-internal) + +;;;###autoload +(defun magit-status-internal (directory) + (magit-tramp-asserts directory) + (let ((default-directory directory)) + (magit-mode-setup #'magit-status-mode))) + +;;;;; Standard Status Sections + +(defvar magit-status-sections-hook-1 nil) + +(defun magit-status-refresh-buffer () + (magit-git-exit-code "update-index" "--refresh") + (magit-insert-section (status) + (if (-all-p #'functionp magit-status-sections-hook) + (run-hooks 'magit-status-sections-hook) + (message "`magit-status-sections-hook' contains entries that are \ +no longer valid.\nUsing standard value instead. Please re-configure") + (sit-for 5) + (let ((magit-status-sections-hook-1 + (eval (car (get 'magit-status-sections-hook 'standard-value))))) + (run-hooks 'magit-status-sections-hook-1)))) + (run-hooks 'magit-status-refresh-hook)) + +(defun magit-insert-status-headers () + "Insert header sections appropriate for `magit-status-mode' buffers. +The sections are inserted by running the functions on the hook +`magit-status-headers-hook'." + (if (magit-rev-verify "HEAD") + (magit-insert-headers magit-status-headers-hook) + (insert "In the beginning there was darkness\n\n"))) + +(defun magit-insert-error-header () + "Insert the message about the Git error that just occured. + +This function is only aware of the last error that occur when Git +was run for side-effects. If, for example, an error occurs while +generating a diff, then that error won't be inserted. Refreshing +the status buffer causes this section to disappear again." + (when magit-this-error + (magit-insert-section (error 'git) + (insert (propertize (format "%-10s" "GitError! ") + 'face 'magit-section-heading)) + (insert (propertize magit-this-error 'face 'font-lock-warning-face)) + (-when-let (key (car (where-is-internal 'magit-process-buffer))) + (insert (format " [Type `%s' for details]" (key-description key)))) + (insert ?\n)) + (setq magit-this-error nil))) + +(cl-defun magit-insert-head-branch-header + (&optional (branch (magit-get-current-branch))) + "Insert a header line about BRANCH. +When BRANCH is nil, use the current branch or, if none, the +detached `HEAD'." + (let ((output (magit-rev-format "%h %s" (or branch "HEAD")))) + (string-match "^\\([^ ]+\\) \\(.*\\)" output) + (magit-bind-match-strings (commit summary) output + (if branch + (magit-insert-section (branch branch) + (insert (format "%-10s" "Head: ")) + (insert (propertize branch 'face 'magit-branch-local)) + (insert ?\s summary ?\n)) + (magit-insert-section (commit commit) + (insert (format "%-10s" "Head: ")) + (insert (propertize commit 'face 'magit-hash)) + (insert ?\s summary ?\n)))))) + +(cl-defun magit-insert-upstream-branch-header + (&optional (branch (magit-get-current-branch)) + (pull (magit-get-upstream-branch branch)) + keyword) + "Insert a header line about branch usually pulled into current branch." + (when pull + (magit-insert-section (branch pull) + (insert (format "%-10s" + (or keyword + (if (magit-get-boolean "branch" branch "rebase") + "Rebase: " + "Merge: ")))) + (insert (propertize pull 'face + (if (string= (magit-get "branch" branch "remote") ".") + 'magit-branch-local + 'magit-branch-remote))) + (insert ?\s) + (if (magit-rev-verify pull) + (insert (or (magit-rev-format "%s" pull) "")) + (insert (propertize "is missing" 'face 'font-lock-warning-face))) + (insert ?\n)))) + +(cl-defun magit-insert-push-branch-header + (&optional (branch (magit-get-current-branch)) + (push (magit-get-push-branch branch))) + "Insert a header line about the branch the current branch is pushed to." + (when push + (magit-insert-section (branch push) + (insert (format "%-10s" "Push: ")) + (insert (propertize push 'face 'magit-branch-remote) ?\s) + (if (magit-rev-verify push) + (insert (or (magit-rev-format "%s" push) "")) + (insert (propertize "is missing" 'face 'font-lock-warning-face))) + (insert ?\n)))) + +(defun magit-insert-tags-header () + "Insert a header line about the current and/or next tag." + (let* ((this-tag (magit-get-current-tag nil t)) + (next-tag (magit-get-next-tag nil t)) + (this-cnt (cadr this-tag)) + (next-cnt (cadr next-tag)) + (this-tag (car this-tag)) + (next-tag (car next-tag)) + (both-tags (and this-tag next-tag t))) + (when (or this-tag next-tag) + (magit-insert-section (tag (or this-tag next-tag)) + (insert (format "%-10s" (if both-tags "Tags: " "Tag: "))) + (when this-tag + (insert (magit-format-status-tag-sentence this-tag this-cnt nil))) + (when both-tags + (insert ", ")) + (when next-tag + (insert (magit-format-status-tag-sentence next-tag next-cnt t))) + (insert ?\n))))) + +(defun magit-format-status-tag-sentence (tag count next) + (concat (propertize tag 'face 'magit-tag) + (and (> count 0) + (format " (%s)" + (propertize (format "%s" count) 'face + (if next 'magit-tag 'magit-branch-local)))))) + +(defun magit-insert-diff-filter-header () + "Insert a header line showing the effective diff filters." + (when magit-diff-section-file-args + (magit-insert-section (filter 'diff) + (insert (propertize (format "%-10s" "Filter! ") + 'face 'magit-section-heading)) + (insert (mapconcat #'identity magit-diff-section-file-args " ")) + (insert ?\n)))) + +(magit-define-section-jumper magit-jump-to-untracked "Untracked files" untracked) + +(defvar magit-untracked-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-delete-thing] 'magit-discard) + (define-key map "s" 'magit-stage) + map) + "Keymap for the `untracked' section.") + +(defun magit-insert-untracked-files () + "Maybe insert a list or tree of untracked files. +Do so depending on the value of `status.showUntrackedFiles'." + (let ((show (or (magit-get "status.showUntrackedFiles") "normal"))) + (unless (equal show "no") + (if (equal show "all") + (-when-let (files (magit-untracked-files)) + (magit-insert-section (untracked) + (magit-insert-heading "Untracked files:") + (magit-insert-un/tracked-files-1 files nil) + (insert ?\n))) + (-when-let + (files (--mapcat (and (eq (aref it 0) ??) + (list (substring it 3))) + (magit-git-items "status" "-z" "--porcelain"))) + (magit-insert-section (untracked) + (magit-insert-heading "Untracked files:") + (dolist (file files) + (magit-insert-section (file file) + (insert (propertize file 'face 'magit-filename) ?\n)))) + (insert ?\n)))))) + +(defun magit-insert-un/tracked-files-1 (files directory) + (while (and files (string-prefix-p (or directory "") (car files))) + (let ((dir (file-name-directory (car files)))) + (if (equal dir directory) + (let ((file (pop files))) + (magit-insert-section (file file) + (insert (propertize file 'face 'magit-filename) ?\n))) + (magit-insert-section (file dir t) + (insert (propertize dir 'file 'magit-filename) ?\n) + (magit-insert-heading) + (setq files (magit-insert-un/tracked-files-1 files dir)))))) + files) + +;;;;; Auxiliary Status Sections + +(magit-define-section-jumper magit-jump-to-tracked "Tracked files" tracked) + +(defun magit-insert-tracked-files () + "Insert a tree of tracked files." + (-when-let (files (magit-list-files)) + (magit-insert-section (tracked nil t) + (magit-insert-heading "Tracked files:") + (magit-insert-un/tracked-files-1 files nil) + (insert ?\n)))) + +(defun magit-insert-user-header () + "Insert a header line about the current user." + (let ((name (magit-get "user.name")) + (email (magit-get "user.email"))) + (when (and name email) + (magit-insert-section (user name) + (insert (format "%-10s" "User: ")) + (insert (propertize name 'face 'magit-log-author)) + (insert " <" email ">\n"))))) + +(defun magit-insert-repo-header () + "Insert a header line showing the path to the repository top-level." + (let ((topdir (magit-toplevel))) + (magit-insert-section (repo topdir) + (insert (format "%-10s%s\n" "Repo: " (abbreviate-file-name topdir)))))) + +(defun magit-insert-remote-header () + "Insert a header line about the remote of the current branch. + +If no remote is configured for the current branch, then fall back +showing the \"origin\" remote, or if that does not exist the first +remote in alphabetic order." + (--when-let (or (magit-get-remote) + (let ((remotes (magit-list-remotes))) + (or (car (member "origin" remotes)) + (car remotes)))) + (magit-insert-section (remote it) + (insert (format "%-10s" "Remote: ")) + (insert (propertize it 'face 'magit-branch-remote) ?\s) + (insert (magit-get "remote" it "url") ?\n)))) + +;;;;; Status Miscellaneous + +(defun ido-enter-magit-status () + "Drop into `magit-status' from file switching. + +To make this command available use something like: + + (add-hook \\='ido-setup-hook + (lambda () + (define-key ido-completion-map + (kbd \"C-x g\") \\='ido-enter-magit-status))) + +Starting with Emacs 25.1 the Ido keymaps are defined just once +instead of every time Ido is invoked, so now you can modify it +like pretty much every other keymap: + + (define-key ido-common-completion-map + (kbd \"C-x g\") 'ido-enter-magit-status)" + (interactive) + (with-no-warnings ; FIXME these are internal variables + (setq ido-exit 'fallback fallback 'magit-status)) + (exit-minibuffer)) + +(defun magit-status-maybe-update-revision-buffer (&optional _) + "When moving in the status buffer, update the revision buffer. +If there is no revision buffer in the same frame, then do nothing." + (when (derived-mode-p 'magit-status-mode) + (magit-log-maybe-update-revision-buffer-1))) + +(defun magit-status-maybe-update-blob-buffer (&optional _) + "When moving in the status buffer, update the blob buffer. +If there is no blob buffer in the same frame, then do nothing." + (when (derived-mode-p 'magit-status-mode) + (magit-log-maybe-update-blob-buffer-1))) + +;;;; Refs Mode + +(defvar magit-refs-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + (define-key map "\C-y" 'magit-refs-set-show-commit-count) + map) + "Keymap for `magit-refs-mode'.") + +(define-derived-mode magit-refs-mode magit-mode "Magit Refs" + "Mode which lists and compares references. + +This mode is documented in info node `(magit)References buffer'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-section-toggle] to expand or hide the section at point. +Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ +to visit the commit or branch at point. + +Type \\[magit-branch-popup] to see available branch commands. +Type \\[magit-merge-popup] to merge the branch or commit at point. +Type \\[magit-cherry-pick-popup] to apply the commit at point. +Type \\[magit-reset] to reset HEAD to the commit at point. + +\\{magit-refs-mode-map}" + :group 'magit-refs + (hack-dir-local-variables-non-file-buffer)) + +;;;###autoload (autoload 'magit-show-refs-popup "magit" nil t) +(magit-define-popup magit-show-refs-popup + "Popup console for `magit-show-refs'." + 'magit-refs + :man-page "git-branch" + :switches '((?m "Merged to HEAD" "--merged") + (?M "Merged to master" "--merged=master") + (?n "Not merged to HEAD" "--no-merged") + (?N "Not merged to master" "--no-merged=master")) + :options '((?c "Contains" "--contains=" magit-read-branch-or-commit) + (?m "Merged" "--merged=" magit-read-branch-or-commit) + (?n "Not merged" "--no-merged=" magit-read-branch-or-commit)) + :actions '((?y "Show refs, comparing them with HEAD" + magit-show-refs-head) + (?c "Show refs, comparing them with current branch" + magit-show-refs-current) + (?o "Show refs, comparing them with other branch" + magit-show-refs)) + :default-action 'magit-show-refs-head + :use-prefix 'popup) + +;;;###autoload +(defun magit-show-refs-head (&optional args) + "List and compare references in a dedicated buffer. +Refs are compared with `HEAD'." + (interactive (list (magit-show-refs-arguments))) + (magit-show-refs nil args)) + +;;;###autoload +(defun magit-show-refs-current (&optional args) + "List and compare references in a dedicated buffer. +Refs are compared with the current branch or `HEAD' if +it is detached." + (interactive (list (magit-show-refs-arguments))) + (magit-show-refs (magit-get-current-branch) args)) + +;;;###autoload +(defun magit-show-refs (&optional ref args) + "List and compare references in a dedicated buffer. +Refs are compared with a branch read form the user." + (interactive (list (magit-read-other-branch "Compare with") + (magit-show-refs-arguments))) + (magit-mode-setup #'magit-refs-mode ref args)) + +(defun magit-refs-refresh-buffer (&rest _ignore) + (setq magit-set-buffer-margin-refresh (not magit-show-margin)) + (unless (magit-rev-verify (or (car magit-refresh-args) "HEAD")) + (setq magit-refs-show-commit-count nil)) + (magit-insert-section (branchbuf) + (run-hooks 'magit-refs-sections-hook))) + +(defun magit-insert-branch-description () + "Insert header containing the description of the current branch. +Insert a header line with the name and description of the +current branch. The description is taken from the Git variable +`branch..description'; if that is undefined then no header +line is inserted at all." + (let ((branch (magit-get-current-branch))) + (--when-let (magit-git-lines + "config" (format "branch.%s.description" branch)) + (magit-insert-section (branchdesc branch t) + (magit-insert-heading branch ": " (car it)) + (insert (mapconcat 'identity (cdr it) "\n")) + (insert "\n\n"))))) + +(defconst magit-refs-branch-line-re + (concat "^" + "\\(?:[ \\*]\\) " + "\\(?1:([^)]+)\\|[^ ]+?\\)" ; branch + "\\(?: +\\)" + "\\(?2:[0-9a-fA-F]+\\) " ; sha1 + "\\(?:\\[" + "\\(?4:[^:]+\\)" ; upstream + "\\(?:: \\(?:" + "\\(?7:gone\\)\\|" ; gone + "\\(?:ahead \\(?5:[0-9]+\\)\\)?" ; ahead + "\\(?:, \\)?" + "\\(?:behind \\(?6:[0-9]+\\)\\)?" ; behind + "\\)\\)?" + "\\] \\)?" + "\\(?3:.*\\)")) ; message + +(defvar magit-refs-local-branch-format "%4c %-25n %U%m\n" + "Format used for local branches in refs buffers.") +(defvar magit-refs-remote-branch-format "%4c %-25n %m\n" + "Format used for remote branches in refs buffers.") +(defvar magit-refs-tags-format "%4c %-25n %m\n" + "Format used for tags in refs buffers.") +(defvar magit-refs-indent-cherry-lines 3 + "Indentation of cherries in refs buffers.") + +(defvar magit-branch-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-visit-ref) + (define-key map [remap magit-delete-thing] 'magit-branch-delete) + (define-key map "R" 'magit-branch-rename) + map) + "Keymap for `branch' sections.") + +(defvar magit-remote-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-delete-thing] 'magit-remote-remove) + (define-key map "R" 'magit-remote-rename) + map) + "Keymap for `remote' sections.") + +(defun magit-refs-set-show-commit-count () + "Change for which refs the commit count is shown." + (interactive) + (setq-local magit-refs-show-commit-count + (magit-read-char-case "Show commit counts for " nil + (?a "[a]ll refs" 'all) + (?b "[b]ranches only" t) + (?n "[n]othing" nil))) + (magit-refresh)) + +(defun magit-visit-ref () + "Visit the reference or revision at point. + +In most places use `magit-show-commit' to visit the reference or +revision at point. + +In `magit-refs-mode', when there is a reference at point, instead +checkout that reference. When option `magit-visit-ref-create' is +non-nil and point is on remote branch, then create a local branch +with the same name and check it out. + +With a prefix argument only focus on the reference at point, i.e. +the commit counts and cherries are updated to be relative to that +reference, but it is not checked out." + (interactive) + (if (derived-mode-p 'magit-refs-mode) + (magit-section-case + (([branch * branchbuf] + [tag * branchbuf]) + (let ((ref (magit-section-value (magit-current-section)))) + (if current-prefix-arg + (magit-show-refs ref) + (if (magit-section-when [branch remote]) + (let ((start ref) + (arg "-b")) + (string-match "^[^/]+/\\(.+\\)" ref) + (setq ref (match-string 1 ref)) + (when (magit-branch-p ref) + (if (yes-or-no-p + (format "Branch %s already exists. Recreate it?" ref)) + (setq arg "-B") + (user-error "Abort"))) + (magit-run-git "checkout" arg ref start)) + (magit-run-git "checkout" ref)) + (setcar magit-refresh-args ref) + (magit-refresh)))) + ([commit * branchbuf] + (call-interactively #'magit-show-commit))) + (call-interactively #'magit-show-commit))) + +(defun magit-insert-local-branches () + "Insert sections showing all local branches." + (magit-insert-section (local nil) + (magit-insert-heading "Branches:") + (let ((current (magit-get-current-branch)) + (branches (magit-list-local-branch-names))) + (dolist (line (magit-git-lines "branch" "-vv" + (cadr magit-refresh-args))) + (string-match magit-refs-branch-line-re line) + (magit-bind-match-strings + (branch hash message upstream ahead behind gone) line + (when (string-match-p "(HEAD detached" branch) + (setq branch nil)) + (magit-insert-branch + branch magit-refs-local-branch-format current branches + 'magit-branch-local hash message upstream ahead behind gone)))) + (insert ?\n))) + +(defun magit-insert-remote-branches () + "Insert sections showing all remote-tracking branches." + (dolist (remote (magit-list-remotes)) + (magit-insert-section (remote remote) + (magit-insert-heading + (let ((pull (magit-get "remote" remote "url")) + (push (magit-get "remote" remote "pushurl"))) + (format "%s (%s):" (capitalize remote) + (concat pull (and pull push ", ") push)))) + (let ((current (magit-get-current-branch)) + (branches (magit-list-local-branch-names))) + (dolist (line (magit-git-lines "branch" "-vvr" + (cadr magit-refresh-args))) + (when (string-match magit-refs-branch-line-re line) + (magit-bind-match-strings (branch hash message) line + (when (string-match-p (format "^%s/" remote) branch) + (magit-insert-branch + branch magit-refs-remote-branch-format current branches + 'magit-branch-remote hash message)))))) + (insert ?\n)))) + +(defun magit-insert-branch (branch format &rest args) + "For internal use, don't add to a hook." + (unless magit-refs-show-commit-count + (setq format (replace-regexp-in-string "%[0-9]\\([cC]\\)" "%1\\1" format t))) + (if (equal branch "HEAD") + (magit-insert-section it (commit (magit-rev-parse "HEAD") t) + (apply #'magit-insert-branch-1 it nil format args)) + (magit-insert-section it (branch branch t) + (apply #'magit-insert-branch-1 it branch format args)))) + +(defun magit-insert-branch-1 + (section branch format current branches face + &optional hash message upstream ahead behind gone) + "For internal use, don't add to a hook." + (let* ((head (or (car magit-refresh-args) current "HEAD")) + (count (and branch + (magit-refs-format-commit-count branch head format))) + (mark (cond ((or (equal branch head) + (and (not branch) (equal head "HEAD"))) + (if (equal branch current) + (propertize "@" 'face 'magit-head) + (propertize "#" 'face 'magit-tag))) + ((equal branch current) + (propertize "." 'face 'magit-head))))) + (when upstream + (setq upstream (propertize upstream 'face + (if (member upstream branches) + 'magit-branch-local + 'magit-branch-remote)))) + (magit-insert-heading + (format-spec + format + `((?a . ,(or ahead "")) + (?b . ,(or behind "")) + (?c . ,(or mark count "")) + (?C . ,(or mark " ")) + (?h . ,(or (propertize hash 'face 'magit-hash) "")) + (?m . ,(or message "")) + (?n . ,(propertize (or branch "(detached)") 'face face)) + (?u . ,(or upstream "")) + (?U . ,(if upstream + (format (propertize "[%s%s] " 'face 'magit-dimmed) + upstream + (cond + (gone + (concat ": " (propertize gone 'face 'error))) + ((or ahead behind) + (concat ": " + (and ahead (format "ahead %s" ahead)) + (and ahead behind ", ") + (and behind (format "behind %s" behind)))) + (t ""))) + ""))))) + (when magit-show-margin + (magit-refs-format-margin branch)) + (magit-refs-insert-cherry-commits head branch section))) + +(defvar magit-tag-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-visit-ref) + (define-key map [remap magit-delete-thing] 'magit-tag-delete) + map) + "Keymap for `tag' sections.") + +(defun magit-insert-tags () + "Insert sections showing all tags." + (-when-let (tags (magit-git-lines "tag" "-l" "-n")) + (magit-insert-section (tags) + (magit-insert-heading "Tags:") + (let ((head (or (car magit-refresh-args) + (magit-get-current-branch) + "HEAD")) + (format (if magit-refs-show-commit-count + magit-refs-tags-format + (replace-regexp-in-string + "%[0-9]\\([cC]\\)" "%1\\1" magit-refs-tags-format t)))) + (dolist (tag (nreverse tags)) + (string-match "^\\([^ \t]+\\)[ \t]+\\([^ \t\n].*\\)?" tag) + (let* ((message (match-string 2 tag)) + (tag (match-string 1 tag)) + (count (magit-refs-format-commit-count tag head format t)) + (mark (and (equal tag head) + (propertize "#" 'face 'magit-tag)))) + (magit-insert-section section (tag tag t) + (magit-insert-heading + (format-spec format + `((?n . ,(propertize tag 'face 'magit-tag)) + (?c . ,(or mark count "")) + (?m . ,(or message ""))))) + (when (and magit-show-margin + (eq magit-refs-show-margin 'all)) + (magit-refs-format-margin (concat tag "^{commit}"))) + (magit-refs-insert-cherry-commits head tag section))))) + (insert ?\n)))) + +(defun magit-refs-insert-cherry-commits (head ref section) + (if (magit-section-hidden section) + (setf (magit-section-washer section) + (apply-partially #'magit-refs-insert-cherry-commits-1 + head ref section)) + (magit-refs-insert-cherry-commits-1 head ref section))) + +(defun magit-refs-insert-cherry-commits-1 (head ref section) + (let ((start (point))) + (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) + "cherry" "-v" "--abbrev" head ref magit-refresh-args) + (unless (= (point) start) + (insert (propertize "\n" 'magit-section section))))) + +(defun magit-refs-format-commit-count (ref head format &optional tag-p) + (and (string-match-p "%-?[0-9]+c" format) + (if tag-p + (eq magit-refs-show-commit-count 'all) + magit-refs-show-commit-count) + (let ((count (cadr (magit-rev-diff-count head ref)))) + (and (> count 0) + (propertize (number-to-string count) 'face 'magit-dimmed))))) + +(defun magit-refs-format-margin (commit) + (save-excursion + (goto-char (line-beginning-position 0)) + (let ((line (magit-rev-format "%ct%cN" commit))) + (magit-format-log-margin (substring line 10) + (substring line 0 10))))) + +;;;; Files + +;;;###autoload +(defun magit-find-file (rev file) + "View FILE from REV. +Switch to a buffer visiting blob REV:FILE, +creating one if none already exists." + (interactive (magit-find-file-read-args "Find file")) + (switch-to-buffer (magit-find-file-noselect rev file))) + +;;;###autoload +(defun magit-find-file-other-window (rev file) + "View FILE from REV, in another window. +Like `magit-find-file', but create a new window or reuse an +existing one." + (interactive (magit-find-file-read-args "Find file in other window")) + (switch-to-buffer-other-window (magit-find-file-noselect rev file))) + +(defun magit-find-file-read-args (prompt) + (let ((rev (magit-read-branch-or-commit "Find file from revision"))) + (list rev (magit-read-file-from-rev rev prompt)))) + +(defvar magit-read-file-hist nil) + +(defun magit-read-file-from-rev (rev prompt &optional default) + (let ((files (magit-revision-files rev))) + (magit-completing-read + prompt files nil t nil 'magit-read-file-hist + (car (member (or default (magit-current-file)) files))))) + +(defun magit-read-changed-file (rev-or-range prompt &optional default) + (magit-read-file-choice + prompt + (magit-changed-files rev-or-range) + default + (concat "No file changed in " rev-or-range))) + +(defun magit-get-revision-buffer (rev file &optional create) + (funcall (if create 'get-buffer-create 'get-buffer) + (format "%s.~%s~" file (subst-char-in-string ?/ ?_ rev)))) + +(defun magit-get-revision-buffer-create (rev file) + (magit-get-revision-buffer rev file t)) + +(defvar magit-find-file-hook nil) + +(defun magit-find-file-noselect (rev file) + "Read FILE from REV into a buffer and return the buffer. +FILE must be relative to the top directory of the repository." + (let ((topdir (magit-toplevel))) + (when (file-name-absolute-p file) + (setq file (file-relative-name file topdir))) + (or (magit-get-revision-buffer rev file) + (with-current-buffer (magit-get-revision-buffer-create rev file) + (let ((inhibit-read-only t)) + (erase-buffer) + (magit-git-insert "cat-file" "-p" (concat rev ":" file))) + (setq magit-buffer-revision (magit-rev-format "%H" rev) + magit-buffer-refname rev + magit-buffer-file-name (expand-file-name file topdir)) + (let ((buffer-file-name magit-buffer-file-name)) + (normal-mode t)) + (setq buffer-read-only t) + (set-buffer-modified-p nil) + (goto-char (point-min)) + (magit-blob-mode 1) + (run-hooks 'magit-find-file-hook) + (current-buffer))))) + +(defvar magit-find-index-hook nil) + +(defun magit-find-file-index-noselect (file &optional revert) + "Read FILE from the index into a buffer and return the buffer. +FILE must to be relative to the top directory of the repository." + (let* ((bufname (concat file ".~{index}~")) + (origbuf (get-buffer bufname)) + (default-directory (magit-toplevel))) + (with-current-buffer (get-buffer-create bufname) + (when (or (not origbuf) revert + (y-or-n-p (format "%s already exists; revert it? " bufname))) + (let ((inhibit-read-only t) + (temp (car (split-string + (or (magit-git-string "checkout-index" "--temp" file) + (error "Error making temp file")) + "\t")))) + (erase-buffer) + (insert-file-contents temp nil nil nil t) + (delete-file temp))) + (setq magit-buffer-revision "{index}" + magit-buffer-refname "{index}" + magit-buffer-file-name (expand-file-name file)) + (let ((buffer-file-name magit-buffer-file-name)) + (normal-mode t)) + (setq buffer-read-only t) + (set-buffer-modified-p nil) + (goto-char (point-min)) + (run-hooks 'magit-find-index-hook) + (current-buffer)))) + +(defun magit-update-index () + "Update the index with the contents of the current buffer. +The current buffer has to be visiting a file in the index, which +is done using `magit-find-index-noselect'." + (interactive) + (let ((file (magit-file-relative-name))) + (unless (equal magit-buffer-refname "{index}") + (user-error "%s isn't visiting the index" file)) + (if (y-or-n-p (format "Update index with contents of %s" (buffer-name))) + (let ((index (make-temp-file "index")) + (buffer (current-buffer))) + (when magit-wip-before-change-mode + (magit-wip-commit-before-change (list file) " before un-/stage")) + (with-temp-file index + (insert-buffer-substring buffer)) + (magit-call-git "update-index" "--cacheinfo" + (substring (magit-git-string "ls-files" "-s" file) 0 6) + (magit-git-string "hash-object" "-t" "blob" "-w" + (concat "--path=" file) + "--" index) + file) + (set-buffer-modified-p nil) + (when magit-wip-after-apply-mode + (magit-wip-commit-after-apply (list file) " after un-/stage"))) + (message "Abort"))) + (--when-let (magit-mode-get-buffer 'magit-status-mode) + (with-current-buffer it (magit-refresh))) + t) + +;;;###autoload +(defun magit-dired-jump (&optional other-window) + "Visit file at point using Dired. +With a prefix argument, visit in other window. If there +is no file at point then instead visit `default-directory'." + (interactive "P") + (dired-jump other-window (--if-let (magit-file-at-point) + (expand-file-name it) + default-directory))) + +;;;###autoload +(defun magit-checkout-file (rev file) + "Checkout FILE from REV." + (interactive + (let ((rev (magit-read-branch-or-commit + "Checkout from revision" magit-buffer-revision))) + (list rev (magit-read-file-from-rev rev "Checkout file")))) + (magit-with-toplevel + (magit-run-git "checkout" rev "--" file))) + +;;; Manipulate +;;;; Init + +;;;###autoload +(defun magit-init (directory) + "Initialize a Git repository, then show its status. + +If the directory is below an existing repository, then the user +has to confirm that a new one should be created inside. If the +directory is the root of the existing repository, then the user +has to confirm that it should be reinitialized. + +Non-interactively DIRECTORY is (re-)initialized unconditionally." + (interactive + (let ((directory (file-name-as-directory + (expand-file-name + (read-directory-name "Create repository in: "))))) + (-when-let (toplevel (magit-toplevel directory)) + (setq toplevel (expand-file-name toplevel)) + (unless (y-or-n-p (if (string-equal toplevel directory) + (format "Reinitialize existing repository %s? " + directory) + (format "%s is a repository. Create another in %s? " + toplevel directory))) + (user-error "Abort"))) + (list directory))) + ;; `git init' does not understand the meaning of "~"! + (magit-call-git "init" (magit-convert-git-filename + (expand-file-name directory))) + (magit-status-internal directory)) + +;;;; Branch +;;;;; Branch Popup + +;;;###autoload (autoload 'magit-branch-popup "magit" nil t) +(magit-define-popup magit-branch-popup + "Popup console for branch commands." + 'magit-commands + :man-page "git-branch" + :variables '("Configure existing branches" + (?d "branch.%s.description" + magit-edit-branch*description + magit-format-branch*description) + (?u "branch.%s.merge" + magit-set-branch*merge/remote + magit-format-branch*merge/remote) + (?r "branch.%s.rebase" + magit-cycle-branch*rebase + magit-format-branch*rebase) + (?p "branch.%s.pushRemote" + magit-cycle-branch*pushRemote + magit-format-branch*pushRemote) + "Configure repository defaults" + (?\M-r "pull.rebase" + magit-cycle-pull.rebase + magit-format-pull.rebase) + (?\M-p "remote.pushDefault" + magit-cycle-remote.pushDefault + magit-format-remote.pushDefault) + "Configure branch creation" + (?U "branch.autoSetupMerge" + magit-cycle-branch*autoSetupMerge + magit-format-branch*autoSetupMerge) + (?R "branch.autoSetupRebase" + magit-cycle-branch*autoSetupRebase + magit-format-branch*autoSetupRebase)) + :actions '((?c "Create and checkout" magit-branch-and-checkout) + (?b "Checkout" magit-checkout) + (?n "Create" magit-branch) + (?m "Rename" magit-branch-rename) + (?s "Create spin-off" magit-branch-spinoff) + (?x "Reset" magit-branch-reset) nil + (?k "Delete" magit-branch-delete)) + :default-action 'magit-checkout + :max-action-columns 2 + :setup-function 'magit-branch-popup-setup) + +(defun magit-branch-popup-setup (val def) + (magit-popup-default-setup val def) + (use-local-map (copy-keymap magit-popup-mode-map)) + (dolist (ev (-filter #'magit-popup-event-p (magit-popup-get :variables))) + (local-set-key (vector (magit-popup-event-key ev)) + 'magit-invoke-popup-action))) + +;;;;; Branch Actions + +;;;###autoload +(defun magit-checkout (revision) + "Checkout REVISION, updating the index and the working tree. +If REVISION is a local branch then that becomes the current +branch. If it is something else then `HEAD' becomes detached. +Checkout fails if the working tree or the staging area contain +changes. +\n(git checkout REVISION)." + (interactive (list (magit-read-other-branch-or-commit "Checkout"))) + (magit-run-git "checkout" revision)) + +;;;###autoload +(defun magit-branch (branch start-point &optional args) + "Create BRANCH at branch or revision START-POINT. +\n(git branch [ARGS] BRANCH START-POINT)." + (interactive (magit-branch-read-args "Create branch")) + (magit-call-git "branch" args branch start-point) + (--when-let (and (magit-get-upstream-branch branch) + (magit-get-indirect-upstream-branch start-point)) + (magit-call-git "branch" (concat "--set-upstream-to=" it) branch)) + (magit-refresh)) + +;;;###autoload +(defun magit-branch-and-checkout (branch start-point &optional args) + "Create and checkout BRANCH at branch or revision START-POINT. +\n(git checkout [ARGS] -b BRANCH START-POINT)." + (interactive (magit-branch-read-args "Create and checkout branch")) + (if (string-match-p "^stash@{[0-9]+}$" start-point) + (magit-run-git "stash" "branch" branch start-point) + (magit-call-git "checkout" args "-b" branch start-point) + (--when-let (and (magit-get-upstream-branch branch) + (magit-get-indirect-upstream-branch start-point)) + (magit-call-git "branch" (concat "--set-upstream-to=" it) branch)) + (magit-refresh))) + +(defun magit-branch-read-starting-point (prompt) + (or (magit-completing-read (concat prompt " starting at") + (cons "HEAD" (magit-list-refnames)) + nil nil nil 'magit-revision-history + (or (magit-remote-branch-at-point) + (magit-local-branch-at-point) + (magit-commit-at-point) + (magit-stash-at-point) + (magit-get-current-branch))) + (user-error "Nothing selected"))) + +(defun magit-branch-read-args (prompt) + (let ((args (magit-branch-arguments)) start branch) + (cond (magit-branch-read-upstream-first + (setq start (magit-branch-read-starting-point prompt)) + (setq branch (magit-read-string-ns + "Branch name" + (and (member start (magit-list-remote-branch-names)) + (mapconcat #'identity + (cdr (split-string start "/")) + "/"))))) + (t + (setq branch (magit-read-string-ns "Branch name")) + (setq start (magit-branch-read-starting-point prompt)))) + (list branch start args))) + +;;;###autoload +(defun magit-branch-spinoff (branch &rest args) + "Create new branch from the unpushed commits. + +Create and checkout a new branch starting at and tracking the +current branch. That branch in turn is reset to the last commit +it shares with its upstream. If the current branch has no +upstream or no unpushed commits, then the new branch is created +anyway and the previously current branch is not touched. + +This is useful to create a feature branch after work has already +began on the old branch (likely but not necessarily \"master\"). + +If the current branch is a member of the value of option +`magit-branch-prefer-remote-upstream' (which see), then the +current branch will be used as the starting point as usual, but +the upstream of the starting-point may be used as the upstream +of the new branch, instead of the starting-point itself." + (interactive (list (magit-read-string "Spin off branch") + (magit-branch-arguments))) + (when (magit-branch-p branch) + (user-error "Branch %s already exists" branch)) + (-if-let (current (magit-get-current-branch)) + (let (tracked base) + (magit-call-git "checkout" args "-b" branch current) + (--when-let (magit-get-indirect-upstream-branch current) + (magit-call-git "branch" "--set-upstream-to" it branch)) + (when (and (setq tracked (magit-get-upstream-branch current)) + (setq base (magit-git-string "merge-base" current tracked)) + (not (magit-rev-equal base current))) + (magit-call-git "update-ref" "-m" + (format "reset: moving to %s" base) + (concat "refs/heads/" current) base)) + (magit-refresh)) + (magit-run-git "checkout" "-b" branch))) + +;;;###autoload +(defun magit-branch-reset (branch to &optional args) + "Reset a branch to the tip of another branch or any other commit. + +When resetting to another branch, then also set that branch as +the upstream of the branch being reset. + +When the branch being reset is the current branch, then do a +hard reset. If there are any uncommitted changes, then the user +has to confirming the reset because those changes would be lost. + +This is useful when you have started work on a feature branch but +realize it's all crap and want to start over." + (interactive + (let* ((atpoint (magit-branch-at-point)) + (branch (magit-read-local-branch "Reset branch" atpoint))) + (list branch + (magit-completing-read (format "Reset %s to" branch) + (delete branch (magit-list-branch-names)) + nil nil nil 'magit-revision-history + (or (and (not (equal branch atpoint)) atpoint) + (magit-get-upstream-branch branch))) + (magit-branch-arguments)))) + (unless (member "--force" args) + (setq args (cons "--force" args))) + (if (magit-branch-p to) + (unless (member "--track" args) + (setq args (cons "--track" args))) + (setq args (delete "--track" args))) + (if (equal branch (magit-get-current-branch)) + (if (and (magit-anything-modified-p) + (not (yes-or-no-p "Uncommitted changes will be lost. Proceed?"))) + (user-error "Abort") + (magit-reset-hard to) + (magit-set-branch*merge/remote branch to)) + (magit-branch branch to args))) + +;;;###autoload +(defun magit-branch-delete (branches &optional force) + "Delete one or multiple branches. +If the region marks multiple branches, then offer to delete +those, otherwise prompt for a single branch to be deleted, +defaulting to the branch at point." + (interactive + (let ((branches (magit-region-values 'branch)) + (force current-prefix-arg)) + (if (if (> (length branches) 1) + (magit-confirm t nil "Delete %i branches" branches) + (setq branches + (list (magit-read-branch (if current-prefix-arg + "Force delete branch" + "Delete branch") + (magit-get-previous-branch))))) + (unless force + (--when-let (-intersection + (-union (magit-list-unmerged-branches) + (magit-list-unmerged-to-upstream-branches)) + branches) + (if (magit-confirm 'delete-unmerged-branch + "Delete unmerged branch %s" + "Delete %i unmerged branches" it) + (setq force t) + (or (setq branches (-difference branches it)) + (user-error "Abort"))))) + (user-error "Abort")) + (list branches force))) + (let* ((refs (-map #'magit-ref-fullname branches)) + (ambiguous (--filter (not it) refs))) + (when ambiguous + (user-error + "%s ambiguous. Please cleanup using git directly." + (let ((len (length ambiguous))) + (cond + ((= len 1) + (format "%s is" (--first (not (magit-ref-fullname it)) branches))) + ((= len (length refs)) + (format "These %s names are" len)) + (t + (format "%s of these names are" len)))))) + (cond + ((string-match "^refs/remotes/\\([^/]+\\)" (car refs)) + (let* ((remote (match-string 1 (car refs))) + (offset (1+ (length remote)))) + (magit-run-git-async + "push" remote (--map (concat ":" (substring it offset)) branches)))) + ((> (length branches) 1) + (magit-run-git "branch" (if force "-D" "-d") + (delete (magit-get-current-branch) branches))) + (t ; And now for something completely different. + (let* ((branch (car branches)) + (prompt (format "Branch %s is checked out. " branch))) + (when (equal branch (magit-get-current-branch)) + (pcase (if (or (equal branch "master") + (not (magit-rev-verify "master"))) + (magit-read-char-case prompt nil + (?d "[d]etach HEAD & delete" 'detach) + (?a "[a]bort" 'abort)) + (magit-read-char-case prompt nil + (?d "[d]etach HEAD & delete" 'detach) + (?c "[c]heckout master & delete" 'master) + (?a "[a]bort" 'abort))) + (`detach (magit-call-git "checkout" "--detach")) + (`master (magit-call-git "checkout" "master")) + (`abort (user-error "Abort"))) + (setq force t)) + (magit-run-git "branch" (if force "-D" "-d") branch)))))) + +(put 'magit-branch-delete 'interactive-only t) + +;;;###autoload +(defun magit-branch-rename (old new &optional force) + "Rename branch OLD to NEW. +With prefix, forces the rename even if NEW already exists. +\n(git branch -m|-M OLD NEW)." + (interactive + (let ((branch (magit-read-local-branch "Rename branch"))) + (list branch + (magit-read-string-ns (format "Rename branch '%s' to" branch)) + current-prefix-arg))) + (unless (string= old new) + (magit-run-git-no-revert "branch" (if force "-M" "-m") old new))) + +;;;;; Branch Variables + +;;;###autoload +(defun magit-edit-branch*description (branch) + "Edit the description of the current branch. +With a prefix argument edit the description of another branch. + +The description for the branch named NAME is stored in the Git +variable `branch..description'." + (interactive + (list (or (and (not current-prefix-arg) + (magit-get-current-branch)) + (magit-read-local-branch "Edit branch description")))) + (magit-run-git-with-editor "branch" "--edit-description" branch)) + +(defun magit-edit-branch*description-check-buffers () + (and buffer-file-name + (string-match-p "/BRANCH_DESCRIPTION\\'" buffer-file-name) + (add-hook 'with-editor-post-finish-hook + (lambda () + (when (derived-mode-p 'magit-popup-mode) + (magit-refresh-popup-buffer))) + nil t))) + +(add-hook 'find-file-hook 'magit-edit-branch*description-check-buffers) + +(defun magit-format-branch*description () + (let* ((branch (or (magit-get-current-branch) "")) + (width (+ (length branch) 19)) + (var (format "branch.%s.description" branch))) + (concat var " " (make-string (- width (length var)) ?\s) + (-if-let (value (magit-get var)) + (propertize value 'face 'magit-popup-option-value) + (propertize "unset" 'face 'magit-popup-disabled-argument))))) + +;;;###autoload +(defun magit-set-branch*merge/remote (branch upstream) + "Set or unset the upstream of the current branch. +With a prefix argument do so for another branch. + +When the branch in question already has an upstream then simply +unsets it. Invoke this command again to set another upstream. + +Together the Git variables `branch..remote' and +`branch..merge' define the upstream branch of the local +branch named NAME. The value of `branch..remote' is the +name of the upstream remote. The value of `branch..merge' +is the full reference of the upstream branch, on the remote." + (interactive + (let ((branch (or (and (not current-prefix-arg) + (magit-get-current-branch)) + (magit-read-local-branch "Change upstream of branch")))) + (list branch (and (not (magit-get-upstream-branch branch)) + (magit-completing-read + (format "Change upstream of %s to" branch) + (delete branch (magit-list-branch-names)) + nil nil nil 'magit-revision-history))))) + (if upstream + (magit-run-git-no-revert + "branch" (concat "--set-upstream-to=" upstream) branch) + (magit-run-git-no-revert "branch" "--unset-upstream" branch))) + +(defun magit-format-branch*merge/remote () + (let* ((branch (or (magit-get-current-branch) "")) + (width (+ (length branch) 20)) + (varM (format "branch.%s.merge" branch)) + (varR (format "branch.%s.remote" branch)) + (face (if (equal (magit-get varR) ".") + 'magit-branch-local + 'magit-branch-remote))) + (concat varM (make-string (- width (length varM)) ?\s) + (-if-let (value (magit-get varM)) + (propertize value 'face face) + (propertize "unset" 'face 'magit-popup-disabled-argument)) + "\n " varR (make-string (- width (length varR)) ?\s) + (-if-let (value (magit-get varR)) + (propertize value 'face face) + (propertize "unset" 'face 'magit-popup-disabled-argument))))) + +;;;###autoload +(defun magit-cycle-branch*rebase (branch) + "Cycle the value of `branch..rebase' for the current branch. +With a prefix argument cycle the value for another branch. + +The Git variables `branch..rebase' controls whether pulling +into the branch named NAME is done by rebasing that branch onto +the fetched branch or by merging that branch. + +When `true' then pulling is done by rebasing. +When `false' then pulling is done by merging. + +When that variable is undefined then the value of `pull.rebase' +is used instead. It defaults to `false'." + (interactive + (list (or (and (not current-prefix-arg) + (magit-get-current-branch)) + (magit-read-local-branch "Cycle branch..rebase for")))) + (magit-popup-set-variable (format "branch.%s.rebase" branch) + '("true" "false") + "false" "pull.rebase")) + +(defun magit-format-branch*rebase () + (let ((branch (or (magit-get-current-branch) ""))) + (magit-popup-format-variable (format "branch.%s.rebase" branch) + '("true" "false") + "false" "pull.rebase" + (+ (length branch) 20)))) + +;;;###autoload +(defun magit-cycle-branch*pushRemote (branch) + "Cycle the value of `branch..pushRemote' for the current branch. +With a prefix argument cycle the value for another branch. + +The Git variable `branch..pushRemote' specifies the remote +that the branch named NAME is usually pushed to. The value has +to be the name of an existing remote. + +If that variable is undefined, then the value of the Git variable +`remote.pushDefault' is used instead, provided that it is defined, +which by default it is not." + (interactive + (list (or (and (not current-prefix-arg) + (magit-get-current-branch)) + (magit-read-local-branch "Cycle branch..pushRemote for")))) + (magit-popup-set-variable (format "branch.%s.pushRemote" branch) + (magit-list-remotes) + "remote.pushDefault")) + +(defun magit-format-branch*pushRemote () + (let ((branch (or (magit-get-current-branch) ""))) + (magit-popup-format-variable (format "branch.%s.pushRemote" branch) + (magit-list-remotes) + nil "remote.pushDefault" + (+ (length branch) 20)))) + +;;;###autoload +(defun magit-cycle-pull.rebase () + "Cycle the repository-local value of `pull.rebase'. + +The Git variable `pull.rebase' specifies whether pulling is done +by rebasing or by merging. It can be overwritten using the Git +variable `branch..rebase'. + +When `true' then pulling is done by rebasing. +When `false' (the default) then pulling is done by merging." + (interactive) + (magit-popup-set-variable "pull.rebase" '("true" "false") "false")) + +(defun magit-format-pull.rebase () + (magit-popup-format-variable "pull.rebase" '("true" "false") "false" nil 19)) + +;;;###autoload +(defun magit-cycle-remote.pushDefault () + "Cycle the repository-local value of `remote.pushDefault'. + +The Git variable `remote.pushDefault' specifies the remote that +local branches are usually pushed to. It can be overwritten +using the Git variable `branch..pushRemote'." + (interactive) + (magit-popup-set-variable "remote.pushDefault" (magit-list-remotes))) + +(defun magit-format-remote.pushDefault () + (magit-popup-format-variable "remote.pushDefault" + (magit-list-remotes) nil nil 19)) + +;;;###autoload +(defun magit-cycle-branch*autoSetupMerge () + "Cycle the repository-local value of `branch.autoSetupMerge'. + +The Git variable `branch.autoSetupMerge' under what circumstances +creating a branch (named NAME) should result in the variables +`branch..merge' and `branch..remote' being set +according to the starting point used to create the branch. If +the starting point isn't a branch, then these variables are never +set. + +When `always' then the variables are set regardless of whether +the starting point is a local or a remote branch. + +When `true' (the default) then the variable are set when the +starting point is a remote branch, but not when it is a local +branch. + +When `false' then the variables are never set." + (interactive) + (magit-popup-set-variable "branch.autoSetupMerge" + '("always" "true" "false") "true")) + +(defun magit-format-branch*autoSetupMerge () + (magit-popup-format-variable "branch.autoSetupMerge" + '("always" "true" "false") "true" nil 23)) + +;;;###autoload +(defun magit-cycle-branch*autoSetupRebase () + "Cycle the repository-local value of `branch.autoSetupRebase'. + +The Git variable `branch.autoSetupRebase' specifies whether +creating a branch (named NAME) should result in the variable +`branch..rebase' being set to `true'. + +When `always' then the variable is set regardless of whether the +starting point is a local or a remote branch. + +When `local' then the variable are set when the starting point +is a local branch, but not when it is a remote branch. + +When `remote' then the variable are set when the starting point +is a remote branch, but not when it is a local branch. + +When `never' (the default) then the variable is never set." + (interactive) + (magit-popup-set-variable "branch.autoSetupRebase" + '("always" "local" "remote" "never") "never")) + +(defun magit-format-branch*autoSetupRebase () + (magit-popup-format-variable "branch.autoSetupRebase" + '("always" "local" "remote" "never") + "never" nil 23)) + +;;;; Merge + +;;;###autoload (autoload 'magit-merge-popup "magit" nil t) +(magit-define-popup magit-merge-popup + "Popup console for merge commands." + 'magit-commands + :man-page "git-merge" + :switches '((?f "Fast-forward only" "--ff-only") + (?n "No fast-forward" "--no-ff") + (?s "Squash" "--squash")) + :options '((?s "Strategy" "--strategy=")) + :actions '((?m "Merge" magit-merge) + (?e "Merge and edit message" magit-merge-editmsg) + (?p "Preview merge" magit-merge-preview) + (?n "Merge but don't commit" magit-merge-nocommit)) + :sequence-actions '((?m "Commit merge" magit-commit) + (?a "Abort merge" magit-merge-abort)) + :sequence-predicate 'magit-merge-state + :default-action 'magit-merge + :max-action-columns 2) + +;;;###autoload +(defun magit-merge (rev &optional args nocommit) + "Merge commit REV into the current branch; using default message. + +Unless there are conflicts or a prefix argument is used create a +merge commit using a generic commit message and without letting +the user inspect the result. With a prefix argument pretend the +merge failed to give the user the opportunity to inspect the +merge. + +\(git merge --no-edit|--no-commit [ARGS] REV)" + (interactive (list (magit-read-other-branch-or-commit "Merge") + (magit-merge-arguments) + current-prefix-arg)) + (magit-merge-assert) + (magit-run-git "merge" (if nocommit "--no-commit" "--no-edit") args rev)) + +;;;###autoload +(defun magit-merge-editmsg (rev &optional args) + "Merge commit REV into the current branch; and edit message. +Perform the merge and prepare a commit message but let the user +edit it. +\n(git merge --edit [ARGS] rev)" + (interactive (list (magit-read-other-branch-or-commit "Merge") + (magit-merge-arguments))) + (magit-merge-assert) + (with-editor "GIT_EDITOR" + (let ((magit-process-popup-time -1)) + (magit-run-git-async "merge" "--edit" args rev)))) + +;;;###autoload +(defun magit-merge-nocommit (rev &optional args) + "Merge commit REV into the current branch; pretending it failed. +Pretend the merge failed to give the user the opportunity to +inspect the merge and change the commit message. +\n(git merge --no-commit [ARGS] rev)" + (interactive (list (magit-read-other-branch-or-commit "Merge") + (magit-merge-arguments))) + (magit-merge-assert) + (magit-run-git "merge" "--no-commit" args rev)) + +;;;###autoload +(defun magit-merge-preview (rev) + "Preview result of merging REV into the current branch." + (interactive (list (magit-read-other-branch-or-commit "Preview merge"))) + (magit-mode-setup #'magit-merge-preview-mode rev)) + +(define-derived-mode magit-merge-preview-mode magit-diff-mode "Magit Merge" + "Mode for previewing a merge." + :group 'magit-diff + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-merge-preview-refresh-buffer (rev) + (let* ((branch (magit-get-current-branch)) + (head (or branch (magit-rev-verify "HEAD")))) + (setq header-line-format + (propertize (format "Preview merge of %s into %s" + rev (or branch "HEAD")) + 'face 'magit-header-line)) + (magit-insert-section (diffbuf) + (magit-git-wash #'magit-diff-wash-diffs + "merge-tree" (magit-git-string "merge-base" head rev) head rev)))) + +;;;###autoload +(defun magit-merge-abort () + "Abort the current merge operation. +\n(git merge --abort)" + (interactive) + (if (file-exists-p (magit-git-dir "MERGE_HEAD")) + (when (magit-confirm 'abort-merge) + (magit-run-git-async "merge" "--abort")) + (user-error "No merge in progress"))) + +(defun magit-checkout-stage (file arg) + "During a conflict checkout and stage side, or restore conflict." + (interactive + (let ((file (magit-completing-read "Checkout file" + (magit-tracked-files) nil nil nil + 'magit-read-file-hist + (magit-current-file)))) + (cond ((member file (magit-unmerged-files)) + (list file (magit-checkout-read-stage file))) + ((yes-or-no-p (format "Restore conflicts in %s? " file)) + (list file "--merge")) + (t + (user-error "Quit"))))) + (pcase (cons arg (cddr (car (magit-file-status file)))) + ((or `("--ours" ?D ,_) + `("--theirs" ,_ ?D)) + (magit-run-git "rm" "--" file)) + (_ (if (equal arg "--merge") + ;; This fails if the file was deleted on one + ;; side. And we cannot do anything about it. + (magit-run-git "checkout" "--merge" "--" file) + (magit-call-git "checkout" arg "--" file) + (magit-run-git "add" "-u" "--" file))))) + +(defun magit-merge-state () + (file-exists-p (magit-git-dir "MERGE_HEAD"))) + +(defun magit-merge-assert () + (or (not (magit-anything-modified-p)) + (magit-confirm 'merge-dirty + "Merging with dirty worktree is risky. Continue") + (user-error "Abort"))) + +(defun magit-checkout-read-stage (file) + (magit-read-char-case (format "For %s checkout: " file) t + (?o "[o]ur stage" "--ours") + (?t "[t]heir stage" "--theirs") + (?c "[c]onflict" "--merge"))) + +(defun magit-insert-merge-log () + "Insert section for the on-going merge. +Display the heads that are being merged. +If no merge is in progress, do nothing." + (-when-let (heads (mapcar 'magit-get-shortname + (magit-file-lines (magit-git-dir "MERGE_HEAD")))) + (magit-insert-section (commit (car heads)) + (magit-insert-heading + (format "Merging %s:" (mapconcat 'identity heads ", "))) + (magit-insert-log + (concat (magit-git-string "merge-base" "--octopus" "HEAD" (car heads)) + ".." (car heads)) + (let ((args magit-log-section-arguments)) + (unless (member "--decorate=full" magit-log-section-arguments) + (push "--decorate=full" args)) + args))))) + +;;;; Reset + +;;;###autoload +(defun magit-reset-index (commit) + "Reset the index to COMMIT. +Keep the head and working tree as-is, so if COMMIT refers to the +head this effectively unstages all changes. +\n(git reset COMMIT)" + (interactive (list (magit-read-branch-or-commit "Reset index to"))) + (magit-reset-internal nil commit ".")) + +;;;###autoload +(defun magit-reset (commit &optional hard) + "Reset the head and index to COMMIT, but not the working tree. +With a prefix argument also reset the working tree. +\n(git reset --mixed|--hard COMMIT)" + (interactive (list (magit-read-branch-or-commit + (if current-prefix-arg + "Hard reset to" + "Reset head to")) + current-prefix-arg)) + (magit-reset-internal (if hard "--hard" "--mixed") commit)) + +;;;###autoload +(defun magit-reset-head (commit) + "Reset the head and index to COMMIT, but not the working tree. +\n(git reset --mixed COMMIT)" + (interactive (list (magit-read-branch-or-commit "Reset head to"))) + (magit-reset-internal "--mixed" commit)) + +;;;###autoload +(defun magit-reset-soft (commit) + "Reset the head to COMMIT, but not the index and working tree. +\n(git reset --soft REVISION)" + (interactive (list (magit-read-branch-or-commit "Soft reset to"))) + (magit-reset-internal "--soft" commit)) + +;;;###autoload +(defun magit-reset-hard (commit) + "Reset the head, index, and working tree to COMMIT. +\n(git reset --hard REVISION)" + (interactive (list (magit-read-branch-or-commit "Hard reset to"))) + (magit-reset-internal "--hard" commit)) + +(defun magit-reset-internal (arg commit &optional path) + (when (and (not (member arg '("--hard" nil))) + (equal (magit-rev-parse commit) + (magit-rev-parse "HEAD~"))) + (with-temp-buffer + (magit-git-insert "show" "-s" "--format=%B" "HEAD") + (when git-commit-major-mode + (funcall git-commit-major-mode)) + (git-commit-setup-font-lock) + (git-commit-save-message))) + (let ((cmd (if (and (equal commit "HEAD") (not arg)) "unstage" "reset"))) + (magit-wip-commit-before-change nil (concat " before " cmd)) + (magit-run-git "reset" arg commit "--" path) + (when (equal cmd "unstage") + (magit-wip-commit-after-apply nil " after unstage")))) + +;;;; Files + +(defun magit-file-rename (file newname) + "Rename the FILE to NEWNAME. +If FILE isn't tracked in Git fallback to using `rename-file'." + (interactive + (let* ((file (magit-read-file "Rename file")) + (newname (read-file-name (format "Rename %s to file: " file)))) + (list (expand-file-name file (magit-toplevel)) + (expand-file-name newname)))) + (if (magit-file-tracked-p file) + (let ((oldbuf (get-file-buffer file))) + (when (and oldbuf (buffer-modified-p oldbuf)) + (user-error "Save %s before moving it" file)) + (when (file-exists-p newname) + (user-error "%s already exists" newname)) + (magit-run-git "mv" file newname) + (when oldbuf + (with-current-buffer oldbuf + (let ((buffer-read-only buffer-read-only)) + (set-visited-file-name newname)) + (if (fboundp 'vc-refresh-state) + (vc-refresh-state) + (with-no-warnings + (vc-find-file-hook)))))) + (rename-file file newname current-prefix-arg) + (magit-refresh))) + +(defun magit-file-untrack (file) + "Untrack FILE. +Stop tracking FILE in Git but do not remove it from the working +tree." + (interactive (list (magit-read-tracked-file "Untrack file"))) + (magit-run-git "rm" "--cached" "--" file)) + +(defun magit-file-delete (file &optional force) + "Delete FILE. +With a prefix argument FORCE do so even when FILE has uncommitted +changes. + +If FILE isn't tracked in Git fallback to using `delete-file'." + (interactive (list (magit-read-file "Delete file"))) + (if (magit-file-tracked-p file) + (magit-run-git "rm" (and force "--force") "--" file) + (delete-file (expand-file-name file (magit-toplevel)) t) + (magit-refresh))) + +(defun magit-read-tracked-file (prompt) + (magit-read-file prompt t)) + +(defun magit-read-file (prompt &optional tracked-only) + (let ((choices (nconc (magit-list-files) + (unless tracked-only (magit-untracked-files))))) + (magit-completing-read prompt choices nil t nil nil + (car (member (or (magit-section-when (file)) + (magit-file-relative-name + nil tracked-only)) + choices))))) + +(defun magit-read-files (prompt initial-contents) + (mapconcat 'identity + (completing-read-multiple (or prompt "File,s: ") + (magit-list-files) + nil nil initial-contents) ",")) + +(defun magit-read-file-choice (prompt files &optional error default) + "Read file from FILES. + +If FILES has only one member, return that instead of prompting. +If FILES has no members, give a user error. ERROR can be given +to provide a more informative error. + +If DEFAULT is non-nil, use this as the default value instead of +`magit-current-file'." + (pcase (length files) + (0 (user-error (or error "No file choices"))) + (1 (car files)) + (_ (magit-completing-read + prompt files nil t nil 'magit-read-file-hist + (car (member (or default (magit-current-file)) files)))))) + +;;; Miscellaneous +;;;; Tag + +;;;###autoload (autoload 'magit-tag-popup "magit" nil t) +(magit-define-popup magit-tag-popup + "Popup console for tag commands." + 'magit-commands + :man-page "git-tag" + :switches '((?a "Annotate" "--annotate") + (?s "Sign" "--sign") + (?f "Force" "--force")) + :actions '((?t "Create" magit-tag) + (?k "Delete" magit-tag-delete) + (?p "Prune" magit-tag-prune)) + :default-action 'magit-tag) + +;;;###autoload +(defun magit-tag (name rev &optional args) + "Create a new tag with the given NAME at REV. +With a prefix argument annotate the tag. +\n(git tag [--annotate] NAME REV)" + (interactive (list (magit-read-tag "Tag name") + (magit-read-branch-or-commit "Place tag on") + (let ((args (magit-tag-arguments))) + (when current-prefix-arg + (cl-pushnew "--annotate" args)) + args))) + (magit-run-git-with-editor "tag" args name rev)) + +;;;###autoload +(defun magit-tag-delete (tags) + "Delete one or more tags. +If the region marks multiple tags (and nothing else), then offer +to delete those, otherwise prompt for a single tag to be deleted, +defaulting to the tag at point. +\n(git tag -d TAGS)" + (interactive (list (--if-let (magit-region-values 'tag) + (magit-confirm t nil "Delete %i tags" it) + (magit-read-tag "Delete tag" t)))) + (magit-run-git-no-revert "tag" "-d" tags)) + +(defun magit-tag-prune (tags remote-tags remote) + "Offer to delete tags missing locally from REMOTE, and vice versa." + (interactive + (let* ((remote (magit-read-remote "Prune tags using remote")) + (tags (magit-list-tags)) + (rtags (prog2 (message "Determining remote tags...") + (magit-remote-list-tags remote) + (message "Determining remote tags...done"))) + (ltags (-difference tags rtags)) + (rtags (-difference rtags tags))) + (unless (or ltags rtags) + (message "Same tags exist locally and remotely")) + (unless (magit-confirm t "Delete %s locally" + "Delete %i tags locally" ltags) + (setq ltags nil)) + (unless (magit-confirm t "Delete %s from remote" + "Delete %i tags from remote" rtags) + (setq rtags nil)) + (list ltags rtags remote))) + (when tags + (magit-call-git "tag" "-d" tags)) + (when remote-tags + (magit-run-git-async-no-revert + "push" remote (--map (concat ":" it) remote-tags)))) + +;;;; Notes + +;;;###autoload (autoload 'magit-notes-popup "magit" nil t) +(magit-define-popup magit-notes-popup + "Popup console for notes commands." + 'magit-commands + :man-page "git-tag" + :switches '("Switch for prune" + (?n "Dry run" "--dry-run")) + :options '("Option for edit and remove" + (?r "Manipulate ref" "--ref=" magit-notes-popup-read-ref) + "Option for merge" + (?s "Merge strategy" "--strategy=")) + :actions '((?T "Edit" magit-notes-edit) + (?r "Remove" magit-notes-remove) + (?m "Merge" magit-notes-merge) + (?p "Prune" magit-notes-prune) + (?s "Set ref" magit-notes-set-ref) + (?S "Set display refs" magit-notes-set-display-refs)) + :sequence-actions '((?c "Commit merge" magit-notes-merge-commit) + (?a "Abort merge" magit-notes-merge-abort)) + :sequence-predicate 'magit-notes-merging-p + :default-action 'magit-notes-edit) + +(defun magit-notes-edit (commit &optional ref) + "Edit the note attached to COMMIT. +REF is the notes ref used to store the notes. + +Interactively or when optional REF is nil use the value of Git +variable `core.notesRef' or \"refs/notes/commits\" if that is +undefined." + (interactive (magit-notes-read-args "Edit notes")) + (magit-run-git-with-editor "notes" (and ref (concat "--ref=" ref)) + "edit" commit)) + +(defun magit-notes-remove (commit &optional ref) + "Remove the note attached to COMMIT. +REF is the notes ref from which the note is removed. + +Interactively or when optional REF is nil use the value of Git +variable `core.notesRef' or \"refs/notes/commits\" if that is +undefined." + (interactive (magit-notes-read-args "Remove notes")) + (magit-run-git-with-editor "notes" (and ref (concat "--ref=" ref)) + "remove" commit)) + +(defun magit-notes-merge (ref) + "Merge the notes ref REF into the current notes ref. + +The current notes ref is the value of Git variable +`core.notesRef' or \"refs/notes/commits\" if that is undefined. + +When there are conflict, then they have to resolved in the +temporary worktree \".git/NOTES_MERGE_WORKTREE\". When +done use `magit-notes-merge-commit' to finish. To abort +use `magit-notes-merge-abort'." + (interactive (list (magit-read-string-ns "Merge reference"))) + (magit-run-git-with-editor "notes" "merge" ref)) + +(defun magit-notes-merge-commit () + "Commit the current notes ref merge. +Also see `magit-notes-merge'." + (interactive) + (magit-run-git-with-editor "notes" "merge" "--commit")) + +(defun magit-notes-merge-abort () + "Abort the current notes ref merge. +Also see `magit-notes-merge'." + (interactive) + (magit-run-git-with-editor "notes" "merge" "--abort")) + +(defun magit-notes-prune (&optional dry-run) + "Remove notes about unreachable commits." + (interactive (list (and (member "--dry-run" (magit-notes-arguments)) t))) + (when dry-run + (magit-process-buffer)) + (magit-run-git-with-editor "notes" "prune" (and dry-run "--dry-run"))) + +(defun magit-notes-set-ref (ref &optional global) + "Set the current notes ref to REF. +The ref is made current by setting the value of the Git variable +`core.notesRef'. With a prefix argument GLOBAL change the global +value, else the value in the current repository. When this is +undefined, then \"refs/notes/commit\" is used. + +Other `magit-notes-*' commands, as well as the sub-commands +of Git's `note' command, default to operate on that ref." + (interactive + (list (magit-completing-read "Set notes ref" + (nconc (list "refs/" "refs/notes/") + (magit-list-notes-refnames)) + nil nil + (--when-let (magit-get "core.notesRef") + (if (string-match "^refs/notes/\\(.+\\)" it) + (match-string 1 it) + it))) + current-prefix-arg)) + (if ref + (magit-run-git-no-revert "config" (and global "--global") "core.notesRef" + (if (string-prefix-p "refs/" ref) + ref + (concat "refs/notes/" ref))) + (magit-run-git-no-revert "config" (and global "--global") + "--unset" "core.notesRef"))) + +(defun magit-notes-set-display-refs (refs &optional global) + "Set notes refs to be display in addition to \"core.notesRef\". +REFS is a colon separated list of notes refs. The values are +stored in the Git variable `notes.displayRef'. With a prefix +argument GLOBAL change the global values, else the values in +the current repository." + (interactive + (list (magit-completing-read "Set additional notes ref(s)" + (nconc (list "refs/" "refs/notes/") + (magit-list-notes-refnames)) + nil nil + (mapconcat #'identity + (magit-get-all "notes.displayRef") + ":")) + current-prefix-arg)) + (when (and refs (atom refs)) + (setq refs (split-string refs ":"))) + (when global + (setq global "--global")) + (magit-git-success "config" "--unset-all" global "notes.displayRef") + (dolist (ref refs) + (magit-call-git "config" "--add" global "notes.displayRef" ref)) + (let ((inhibit-magit-revert t)) + (magit-refresh))) + +(defun magit-notes-read-args (prompt) + (list (magit-read-branch-or-commit prompt) + (--when-let (--first (string-match "^--ref=\\(.+\\)" it) + (magit-notes-arguments)) + (match-string 1 it)))) + +(defun magit-notes-popup-read-ref (prompt &optional initial-input) + (magit-completing-read prompt (nconc (list "refs/" "refs/notes/") + (magit-list-notes-refnames)) + nil nil initial-input)) + +(defun magit-notes-merging-p () + (let ((dir (magit-git-dir "NOTES_MERGE_WORKTREE"))) + (and (file-directory-p dir) + (directory-files dir nil "^[^.]")))) + +;;;; Submodules + +;;;###autoload (autoload 'magit-submodule-popup "magit" nil t) +(magit-define-popup magit-submodule-popup + "Popup console for submodule commands." + 'magit-commands nil nil + :man-page "git-submodule" + :actions '((?a "Add" magit-submodule-add) + (?b "Setup" magit-submodule-setup) + (?i "Init" magit-submodule-init) + (?u "Update" magit-submodule-update) + (?s "Sync" magit-submodule-sync) + (?f "Fetch" magit-submodule-fetch) + (?d "Deinit" magit-submodule-deinit))) + +;;;###autoload +(defun magit-submodule-add (url &optional path) + "Add the repository at URL as a submodule. +Optional PATH is the path to the submodule relative to the root +of the superproject. If it is nil then the path is determined +based on URL." + (interactive + (magit-with-toplevel + (let ((path (read-file-name + "Add submodule: " nil nil nil + (magit-section-when [file untracked] + (directory-file-name (magit-section-value it)))))) + (when path + (setq path (file-name-as-directory (expand-file-name path))) + (when (member path (list "" default-directory)) + (setq path nil))) + (list (magit-read-string-ns + "Remote url" + (and path (magit-git-repo-p path t) + (let ((default-directory path)) + (magit-get "remote" (or (magit-get-remote) "origin") + "url")))) + (and path (directory-file-name (file-relative-name path))))))) + (magit-run-git "submodule" "add" url path)) + +;;;###autoload +(defun magit-submodule-setup () + "Clone and register missing submodules and checkout appropriate commits." + (interactive) + (magit-submodule-update t)) + +;;;###autoload +(defun magit-submodule-init () + "Register submodules listed in \".gitmodules\" into \".git/config\"." + (interactive) + (magit-with-toplevel + (magit-run-git-async "submodule" "init"))) + +;;;###autoload +(defun magit-submodule-update (&optional init) + "Clone missing submodules and checkout appropriate commits. +With a prefix argument also register submodules in \".git/config\"." + (interactive "P") + (magit-with-toplevel + (magit-run-git-async "submodule" "update" (and init "--init")))) + +;;;###autoload +(defun magit-submodule-sync () + "Update each submodule's remote URL according to \".gitmodules\"." + (interactive) + (magit-with-toplevel + (magit-run-git-async "submodule" "sync"))) + +;;;###autoload +(defun magit-submodule-fetch (&optional all) + "Fetch all submodules. +With a prefix argument fetch all remotes." + (interactive "P") + (magit-with-toplevel + (magit-run-git-async "submodule" "foreach" + (format "git fetch %s || true" (if all "--all" ""))))) + +;;;###autoload +(defun magit-submodule-deinit (path) + "Unregister the submodule at PATH." + (interactive + (list (magit-completing-read "Deinit module" (magit-get-submodules) + nil t nil nil (magit-section-when module)))) + (magit-with-toplevel + (magit-run-git-async "submodule" "deinit" path))) + +;;;; File Mode + +(defvar magit-file-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\C-xg" 'magit-status) + (define-key map "\C-x\M-g" 'magit-dispatch-popup) + (define-key map "\C-c\M-g" 'magit-file-popup) + map) + "Keymap for `magit-file-mode'.") + +(magit-define-popup magit-file-popup + "Popup console for Magit commands in file-visiting buffers." + :actions '((?s "Stage" magit-stage-file) + (?l "Log" magit-log-buffer-file) + (?c "Commit" magit-commit-popup) + (?u "Unstage" magit-unstage-file) + (?b "Blame" magit-blame-popup) nil nil + (?p "Find blob" magit-blob-previous)) + :max-action-columns 3) + +(defvar magit-file-mode-lighter "") + +(define-minor-mode magit-file-mode + "Enable some Magit features in file-visiting buffers. + +Currently this only adds the following key bindings. +\n\\{magit-file-mode-map}" + :package-version '(magit . "2.2.0") + :lighter magit-file-mode-lighter + :keymap magit-file-mode-map) + +(defun magit-file-mode-turn-on () + (and buffer-file-name + (ignore-errors (magit-inside-worktree-p)) + (magit-file-mode))) + +;;;###autoload +(define-globalized-minor-mode global-magit-file-mode + magit-file-mode magit-file-mode-turn-on + :package-version '(magit . "2.2.0") + :group 'magit-modes) + +;;;; Blob Mode + +(defvar magit-blob-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "n" 'magit-blob-next) + (define-key map "p" 'magit-blob-previous) + (define-key map "q" 'magit-kill-this-buffer) + map) + "Keymap for `magit-blob-mode'.") + +(define-minor-mode magit-blob-mode + "Enable some Magit features in blob-visiting buffers. + +Currently this only adds the following key bindings. +\n\\{magit-blob-mode-map}" + :package-version '(magit . "2.3.0")) + +(defun magit-blob-next () + "Visit the next blob which modified the current file." + (interactive) + (if magit-buffer-file-name + (magit-blob-visit (or (magit-blob-successor magit-buffer-revision + magit-buffer-file-name) + magit-buffer-file-name) + (line-number-at-pos)) + (if (buffer-file-name (buffer-base-buffer)) + (user-error "You have reached the end of time") + (user-error "Buffer isn't visiting a file or blob")))) + +(defun magit-blob-previous () + "Visit the previous blob which modified the current file." + (interactive) + (-if-let (file (or magit-buffer-file-name + (buffer-file-name (buffer-base-buffer)))) + (--if-let (magit-blob-ancestor magit-buffer-revision file) + (magit-blob-visit it (line-number-at-pos)) + (user-error "You have reached the beginning of time")) + (user-error "Buffer isn't visiting a file or blob"))) + +(defun magit-blob-visit (blob-or-file line) + (if (stringp blob-or-file) + (find-file blob-or-file) + (-let [(rev file) blob-or-file] + (magit-find-file rev file) + (let ((str (magit-rev-format "%ct%s" rev))) + (message "%s (%s ago)" (substring str 10) + (magit-format-duration + (abs (truncate (- (float-time) + (string-to-number + (substring str 0 10))))) + magit-duration-spec))))) + (goto-char (point-min)) + (forward-line (1- line))) + +(defun magit-blob-ancestor (rev file) + (let ((lines (magit-with-toplevel + (magit-git-lines "log" "-2" "--format=%H" "--name-only" + "--follow" (or rev "HEAD") "--" file)))) + (if rev (cddr lines) (butlast lines 2)))) + +(defun magit-blob-successor (rev file) + (let ((lines (magit-with-toplevel + (magit-git-lines "log" "--format=%H" "--name-only" "--follow" + "HEAD" "--" file)))) + (catch 'found + (while lines + (if (equal (nth 2 lines) rev) + (throw 'found (list (nth 0 lines) (nth 1 lines))) + (setq lines (nthcdr 2 lines))))))) + +(defun magit-kill-this-buffer () + "Kill the current buffer." + (interactive) + (kill-buffer (current-buffer))) + +;;;; Dispatch Popup + +;;;###autoload (autoload 'magit-dispatch-popup "magit" nil t) +(magit-define-popup magit-dispatch-popup + "Popup console for dispatching other popups." + 'magit-commands nil nil + :actions '("Popup and dwim commands" + (?A "Cherry-picking" magit-cherry-pick-popup) + (?b "Branching" magit-branch-popup) + (?B "Bisecting" magit-bisect-popup) + (?c "Committing" magit-commit-popup) + (?d "Diffing" magit-diff-popup) + (?D "Change diffs" magit-diff-refresh-popup) + (?e "Ediff dwimming" magit-ediff-dwim) + (?E "Ediffing" magit-ediff-popup) + (?f "Fetching" magit-fetch-popup) + (?F "Pulling" magit-pull-popup) + (?l "Logging" magit-log-popup) + (?m "Merging" magit-merge-popup) + (?M "Remoting" magit-remote-popup) + (?o "Submodules" magit-submodule-popup) + (?P "Pushing" magit-push-popup) + (?r "Rebasing" magit-rebase-popup) + (?t "Tagging" magit-tag-popup) + (?T "Notes" magit-notes-popup) + (?V "Reverting" magit-revert-popup) + (?w "Apply patches" magit-am-popup) + (?W "Format patches" magit-patch-popup) + (?y "Show Refs" magit-show-refs-popup) + (?z "Stashing" magit-stash-popup) + (?! "Running" magit-run-popup) + "Applying changes" + (?a "Apply" magit-apply) + (?s "Stage" magit-stage) + (?u "Unstage" magit-unstage) + nil + (?v "Reverse" magit-reverse) + (?S "Stage all" magit-stage-modified) + (?U "Unstage all" magit-unstage-all) + nil + (?k "Discard" magit-discard) + "\ + g refresh current buffer + TAB toggle section at point + RET visit thing at point + + C-h m show all key bindings" nil) + :max-action-columns 4) + +;;;; Git Popup + +(defvar magit-git-command-history nil) + +;;;###autoload (autoload 'magit-run-popup "magit" nil t) +(magit-define-popup magit-run-popup + "Popup console for running raw Git commands." + 'magit-commands nil nil + :actions '((?! "Git Subcommand (in topdir)" magit-git-command-topdir) + (?k "Gitk" magit-run-gitk) + (?p "Git Subcommand (in pwd)" magit-git-command) + (?a "Gitk --all" magit-run-gitk-all) + (?s "Shell command (in topdir)" magit-shell-command-topdir) + (?b "Gitk --branches" magit-run-gitk-branches) + (?S "Shell command (in pwd)" magit-shell-command) + (?g "Git Gui" magit-run-git-gui)) + :default-action 'magit-git-command + :max-action-columns 2) + +;;;###autoload +(defun magit-git-command (args directory) + "Execute a Git subcommand asynchronously, displaying the output. +With a prefix argument run Git in the root of the current +repository, otherwise in `default-directory'." + (interactive (magit-read-shell-command "Git subcommand (pwd: %s)")) + (require 'eshell) + (with-temp-buffer + (insert args) + (setq args (mapcar 'eval (eshell-parse-arguments (point-min) + (point-max)))) + (setq default-directory directory) + (let ((magit-git-global-arguments + ;; A human will want globbing by default. + (remove "--literal-pathspecs" + magit-git-global-arguments))) + (magit-run-git-async args))) + (magit-process-buffer)) + +;;;###autoload +(defun magit-git-command-topdir (args directory) + "Execute a Git subcommand asynchronously, displaying the output. +Run Git in the top-level directory of the current repository. +\n(fn)" ; arguments are for internal use + (interactive (magit-read-shell-command "Git subcommand (pwd: %s)" t)) + (magit-git-command args directory)) + +;;;###autoload +(defun magit-shell-command (args directory) + "Execute a shell command asynchronously, displaying the output. +With a prefix argument run the command in the root of the current +repository, otherwise in `default-directory'." + (interactive (magit-read-shell-command "Shell command (pwd: %s)")) + (require 'eshell) + (with-temp-buffer + (insert args) + (setq args (mapcar 'eval (eshell-parse-arguments (point-min) + (point-max)))) + (setq default-directory directory) + (apply #'magit-start-process (car args) nil (cdr args))) + (magit-process-buffer)) + +;;;###autoload +(defun magit-shell-command-topdir (args directory) + "Execute a shell command asynchronously, displaying the output. +Run the command in the top-level directory of the current repository. +\n(fn)" ; arguments are for internal use + (interactive (magit-read-shell-command "Shell command (pwd: %s)" t)) + (magit-shell-command args directory)) + +(defun magit-read-shell-command (prompt &optional root) + (let ((dir (if (or root current-prefix-arg) + (or (magit-toplevel) + (user-error "Not inside a Git repository")) + default-directory))) + (list (magit-read-string (format prompt (abbreviate-file-name dir)) + nil 'magit-git-command-history) + dir))) + +;;;; Read Repository + +(defun magit-read-repository (&optional read-directory-name) + "Read a Git repository in the minibuffer, with completion. + +The completion choices are the basenames of top-levels of +repositories found in the directories specified by option +`magit-repository-directories'. In case of name conflicts +the basenames are prefixed with the name of the respective +parent directories. The returned value is the actual path +to the selected repository. + +With prefix argument simply read a directory name using +`read-directory-name'." + (if (and (not read-directory-name) magit-repository-directories) + (let* ((repos (magit-list-repos-uniquify + (--map (cons (file-name-nondirectory it) it) + (magit-list-repos)))) + (reply (magit-completing-read "Git repository" repos))) + (file-name-as-directory + (or (cdr (assoc reply repos)) + (if (file-directory-p reply) + (expand-file-name reply) + (user-error "Not a repository or a directory: %s" reply))))) + (file-name-as-directory + (read-directory-name "Git repository: " + (or (magit-toplevel) default-directory))))) + +(defun magit-list-repos () + (--mapcat (magit-list-repos-1 it magit-repository-directories-depth) + magit-repository-directories)) + +(defun magit-list-repos-1 (directory depth) + (cond ((file-readable-p (expand-file-name ".git" directory)) + (list directory)) + ((and (> depth 0) (file-accessible-directory-p directory)) + (--mapcat (when (file-directory-p it) + (magit-list-repos-1 it (1- depth))) + (directory-files directory t "^[^.]" t))))) + +(defun magit-list-repos-uniquify (alist) + (let (result (dict (make-hash-table :test 'equal))) + (dolist (a (delete-dups 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) + (setq result + (append result + (magit-list-repos-uniquify + (--map (cons (concat + key "\\" + (file-name-nondirectory + (directory-file-name + (substring it 0 (- (length key)))))) + it) + value)))))) + dict) + result)) + +;;;; Revision Stack + +(defvar magit-revision-stack nil) + +(defcustom magit-pop-revision-stack-format + '("[%N: %h] " "%N: %H\n %s\n" "\\[\\([0-9]+\\)[]:]") + "Control how `magit-pop-revision-stack' inserts a revision. + +The command `magit-pop-revision-stack' inserts a representation +of the revision last pushed to the `magit-revision-stack' into +the current buffer. It inserts text at point and/or near the end +of the buffer, and removes the consumed revision from the stack. + +The entries on the stack have the format (HASH TOPLEVEL) and this +option has the format (POINT-FORMAT EOB-FORMAT INDEX-REGEXP), all +of which may be nil or a string (though either one of EOB-FORMAT +or POINT-FORMAT should be a string, and if INDEX-REGEXP is +non-nil, then the two formats should be too). + +First INDEX-REGEXP is used to find the previously inserted entry, +by searching backward from point. The first submatch must match +the index number. That number is incremented by one, and becomes +the index number of the entry to be inserted. If you don't want +to number the inserted revisions, then use nil for INDEX-REGEXP. + +If INDEX-REGEXP is non-nil then both POINT-FORMAT and EOB-FORMAT +should contain \"%N\", which is replaced with the number that was +determined in the previous step. + +Both formats, if non-nil and after removing %N, are then expanded +using `git show --format=FORMAT ...' inside TOPLEVEL. + +The expansion of POINT-FORMAT is inserted at point, and the +expansion of EOB-FORMAT is inserted at the end of the buffer (if +the buffer ends with a comment, then it is inserted right before +that)." + :package-version '(magit . "2.3.0") + :group 'magit-status + :type '(list (choice (string :tag "Insert at point format") + (cons (string :tag "Insert at point format") + (repeat (string :tag "Argument to git show"))) + (const :tag "Don't insert at point" nil)) + (choice (string :tag "Insert at eob format") + (cons (string :tag "Insert at eob format") + (repeat (string :tag "Argument to git show"))) + (const :tag "Don't insert at eob" nil)) + (choice (regexp :tag "Find index regexp") + (const :tag "Don't number entries" nil)))) + +(defun magit-pop-revision-stack (rev toplevel) + "Insert a representation of a revision into the current buffer. + +Pop a revision from the `magit-revision-stack' and insert it into +the current buffer according to `magit-pop-revision-stack-format'. +Revisions can be put on the stack using `magit-copy-section-value' +and `magit-copy-buffer-revision'. + +If the stack is empty or with a prefix argument instead read a +revision in the minibuffer. By using the minibuffer history this +allows selecting an item which was popped earlier or to insert an +arbitrary reference or revision without first pushing it onto the +stack. + +When reading the revision from the minibuffer, then it might not +be possible to guess the correct repository. When this command +is called inside a repository (e.g. while composing a commit +message), then that repository is used. Otherwise (e.g. while +composing an email) then the repository recorded for the top +element of the stack is used (even though we insert another +revision). If not called inside a repository and with an empty +stack, or with two prefix arguments, then read the repository in +the minibuffer too." + (interactive + (if (or current-prefix-arg (not magit-revision-stack)) + (let ((default-directory + (or (and (not (= (prefix-numeric-value current-prefix-arg) 16)) + (or (magit-toplevel) + (cadr (car magit-revision-stack)))) + (magit-read-repository)))) + (list (magit-read-branch-or-commit "Insert revision") + default-directory)) + (push (caar magit-revision-stack) magit-revision-history) + (pop magit-revision-stack))) + (if rev + (-let [(pnt-format eob-format idx-format) magit-pop-revision-stack-format] + (let ((default-directory toplevel) + (idx (and idx-format + (save-excursion + (if (re-search-backward idx-format nil t) + (number-to-string + (1+ (string-to-number (match-string 1)))) + "1")))) + pnt-args eob-args) + (when (listp pnt-format) + (setq pnt-args (cdr pnt-format) + pnt-format (car pnt-format))) + (when (listp eob-format) + (setq eob-args (cdr eob-format) + eob-format (car eob-format))) + (when pnt-format + (when idx-format + (setq pnt-format + (replace-regexp-in-string "%N" idx pnt-format t t))) + (magit-rev-insert-format pnt-format rev pnt-args) + (backward-delete-char 1)) + (when eob-format + (when idx-format + (setq eob-format + (replace-regexp-in-string "%N" idx eob-format t t))) + (save-excursion + (goto-char (point-max)) + (skip-syntax-backward ">s-") + (beginning-of-line) + (if (and comment-start (looking-at comment-start)) + (while (looking-at comment-start) + (forward-line -1)) + (forward-line) + (unless (= (current-column) 0) + (insert ?\n))) + (insert ?\n) + (magit-rev-insert-format eob-format rev eob-args) + (backward-delete-char 1))))) + (user-error "Revision stack is empty"))) + +(define-key git-commit-mode-map + (kbd "C-c C-w") 'magit-pop-revision-stack) + +(defun magit-copy-section-value () + "Save the value of the current section for later use. + +Save the section value to the `kill-ring', and, provided that +the current section is a commit, branch, or tag section, push +the (referenced) revision to the `magit-revision-stack' for use +with `magit-pop-revision-stack'. + +When the current section is a branch or a tag, and a prefix +argument is used, then save the revision at its tip to the +`kill-ring' instead of the reference name. + +When the region is active, then save that to the `kill-ring', +like `kill-ring-save' would, instead of behaving as described +above." + (interactive) + (if (region-active-p) + (copy-region-as-kill (mark) (point) 'region) + (-when-let* ((section (magit-current-section)) + (value (magit-section-value section))) + (magit-section-case + ((branch commit module-commit tag) + (let ((default-directory default-directory) ref) + (magit-section-case + ((branch tag) + (setq ref value)) + (module-commit + (setq default-directory + (file-name-as-directory + (expand-file-name (magit-section-parent-value section) + (magit-toplevel)))))) + (setq value (magit-rev-parse value)) + (push (list value default-directory) magit-revision-stack) + (kill-new (message "%s" (or (and current-prefix-arg ref) + value))))) + (t (kill-new (message "%s" value))))))) + +(defun magit-copy-buffer-revision () + "Save the revision of the current buffer for later use. + +Save the revision shown in the current buffer to the `kill-ring' +and push it to the `magit-revision-stack'. + +This command is mainly intended for use in `magit-revision-mode' +buffers, the only buffers where it is always unambiguous exactly +which revision should be saved. + +Most other Magit buffers usually show more than one revision, in +some way or another, so this command has to select one of them, +and that choice might not always be the one you think would have +been the best pick. + +In such buffers it is often more useful to save the value of +the current section instead, using `magit-copy-section-value'. + +When the region is active, then save that to the `kill-ring', +like `kill-ring-save' would, instead of behaving as described +above." + (interactive) + (if (region-active-p) + (copy-region-as-kill (mark) (point) 'region) + (-when-let (rev (cond ((memq major-mode '(magit-cherry-mode + magit-log-select-mode + magit-reflog-mode + magit-refs-mode + magit-revision-mode + magit-stash-mode + magit-stashes-mode)) + (car magit-refresh-args)) + ((memq major-mode '(magit-diff-mode + magit-log-mode)) + (let ((r (caar magit-refresh-args))) + (if (string-match "\\.\\.\\.?\\(.+\\)" r) + (match-string 1 r) + r))) + ((eq major-mode 'magit-status-mode) "HEAD"))) + (when (magit-rev-verify-commit rev) + (setq rev (magit-rev-parse rev)) + (push (list rev default-directory) magit-revision-stack) + (kill-new (message "%s" rev)))))) + +;;; magit.el ends soon + +(defconst magit-font-lock-keywords + (eval-when-compile + `((,(concat "(\\(magit-define-section-jumper\\)\\_>" + "[ \t'\(]*" + "\\(\\(?:\\sw\\|\\s_\\)+\\)?") + (1 'font-lock-keyword-face) + (2 'font-lock-function-name-face nil t)) + (,(concat "(" (regexp-opt '("magit-insert-section" + "magit-section-case" + "magit-section-when" + "magit-bind-match-strings" + "magit-with-temp-index" + "magit-with-blob" + "magit-with-toplevel") t) + "\\_>") + . 1)))) + +(font-lock-add-keywords 'emacs-lisp-mode magit-font-lock-keywords) + +(defvar magit-version 'undefined + "The version of Magit that you're using. +Use the function by the same name instead of this variable.") + +;;;###autoload +(defun magit-version () + "Return the version of Magit currently in use. +When called interactive also show the used versions of Magit, +Git, and Emacs in the echo area." + (interactive) + (let ((magit-git-global-arguments nil) + (toplib (or load-file-name buffer-file-name)) + debug) + (unless (and toplib + (equal (file-name-nondirectory toplib) "magit.el")) + (setq toplib (locate-library "magit.el"))) + (push toplib debug) + (when toplib + (let* ((topdir (file-name-directory toplib)) + (gitdir (expand-file-name + ".git" (file-name-directory + (directory-file-name topdir)))) + (static (expand-file-name "magit-version.el" topdir))) + (or (progn + (push 'repo debug) + (when (and (file-exists-p gitdir) + ;; It is a repo, but is it the Magit repo? + (file-exists-p + (expand-file-name "../lisp/magit.el" gitdir))) + (push t debug) + ;; Inside the repo the version file should only exist + ;; while running make. + (unless noninteractive + (ignore-errors (delete-file static))) + (setq magit-version + (let ((default-directory topdir)) + (magit-git-string "describe" "--tags" "--dirty"))))) + (progn + (push 'static debug) + (when (file-exists-p static) + (push t debug) + (load-file static) + magit-version)) + (when (featurep 'package) + (push 'elpa debug) + (ignore-errors + (--when-let (assq 'magit package-alist) + (push t debug) + (setq magit-version + (and (fboundp 'package-desc-version) + (package-version-join + (package-desc-version (cadr it))))))))))) + (if (stringp magit-version) + (when (called-interactively-p 'any) + (message "Magit %s, Git %s, Emacs %s" + (or magit-version "(unknown)") + (or (magit-git-version) "(unknown)") + emacs-version)) + (setq debug (reverse debug)) + (setq magit-version 'error) + (when magit-version + (push magit-version debug)) + (message "Cannot determine Magit's version %S" debug)) + magit-version)) + +(defun magit-git-version (&optional numeric) + (--when-let (let (magit-git-global-arguments) + (ignore-errors (substring (magit-git-string "version") 12))) + (if numeric + (and (string-match "^\\([0-9]+\\.[0-9]+\\.[0-9]+\\)" it) + (match-string 1 it)) + it))) + +(defun magit-startup-asserts () + (let ((version (magit-git-version t))) + (when (and version + (version< version magit--minimal-git) + (not (equal (getenv "TRAVIS") "true"))) + (display-warning 'magit (format "\ +Magit requires Git >= %s, you are using %s. + +If this comes as a surprise to you, because you do actually have +a newer version installed, then that probably means that the +older version happens to appear earlier on the `$PATH'. If you +always start Emacs from a shell, then that can be fixed in the +shell's init file. If you start Emacs by clicking on an icon, +or using some sort of application launcher, then you probably +have to adjust the environment as seen by graphical interface. +For X11 something like ~/.xinitrc should work. + +If you use Tramp to work inside remote Git repositories, then you +have to make sure a suitable Git is used on the remote machines +too.\n" magit--minimal-git version) :error))) + (when (version< emacs-version magit--minimal-emacs) + (display-warning 'magit (format "\ +Magit requires Emacs >= %s, you are using %s. + +If this comes as a surprise to you, because you do actually have +a newer version installed, then that probably means that the +older version happens to appear earlier on the `$PATH'. If you +always start Emacs from a shell, then that can be fixed in the +shell's init file. If you start Emacs by clicking on an icon, +or using some sort of application launcher, then you probably +have to adjust the environment as seen by graphical interface. +For X11 something like ~/.xinitrc should work.\n" + magit--minimal-emacs emacs-version) + :error)) + (--each '((magit-log-edit . git-commit) + (git-commit-mode . git-commit) + (git-rebase-mode . git-rebase)) + (when (or (featurep (car it)) (locate-library (symbol-name (car it)))) + (display-warning 'magit (format "%s has to be removed + +Magit is no longer compatible with the library `%s', +which was used in earlier releases. Please remove it, so that +Magit can use the successor `%s' without the obsolete +library getting in the way. Then restart Emacs.\n" + (car it) (car it) (cdr it)) :error)))) + +(defvar magit--remotes-using-recent-git nil) + +(defun magit-tramp-asserts (directory) + (-when-let (remote (file-remote-p directory)) + (unless (member remote magit--remotes-using-recent-git) + (-if-let (version (let ((default-directory directory)) + (magit-git-version t))) + (if (version<= magit--minimal-git version) + (push version magit--remotes-using-recent-git) + (display-warning 'magit (format "\ +Magit requires Git >= %s, but on %s the version is %s. + +If multiple Git versions are installed on the host then the +problem might be that TRAMP uses the wrong executable. + +First check the value of `magit-git-executable'. Its value is +used when running git locally as well as when running it on a +remote host. The default value is \"git\", except on Windows +where an absolute path is used for performance reasons. + +If the value already is just \"git\" but TRAMP never-the-less +doesn't use the correct executable, then consult the info node +`(tramp)Remote programs'.\n" magit--minimal-git remote version) :error)) + (display-warning 'magit (format "\ +Magit cannot find Git on %s. + +First check the value of `magit-git-executable'. Its value is +used when running git locally as well as when running it on a +remote host. The default value is \"git\", except on Windows +where an absolute path is used for performance reasons. + +If the value already is just \"git\" but TRAMP never-the-less +doesn't find the executable, then consult the info node +`(tramp)Remote programs'.\n" remote) :error))))) + +(define-obsolete-function-alias 'global-magit-file-buffer-mode + 'global-magit-file-mode "Magit 2.3.0") + +(define-obsolete-function-alias 'magit-insert-head-header + 'magit-insert-head-branch-header "Magit 2.4.0") + +(define-obsolete-function-alias 'magit-insert-upstream-header + 'magit-insert-upstream-branch-header "Magit 2.4.0") + +(define-obsolete-function-alias 'magit-insert-pull-branch-header + 'magit-insert-upstream-branch-header "Magit 2.4.0") + +(provide 'magit) + +(cl-eval-when (load eval) + (require 'magit-sequence) + (require 'magit-commit) + (require 'magit-remote) + (require 'magit-bisect) + (require 'magit-stash) + (require 'magit-blame) + (unless (load "magit-autoloads" t t) + (require 'magit-ediff) + (require 'magit-extras) + (require 'git-rebase))) + +(if after-init-time + (progn (magit-startup-asserts) + (magit-version)) + (add-hook 'after-init-hook #'magit-startup-asserts t) + (add-hook 'after-init-hook #'magit-version t)) + +;; Local Variables: +;; coding: utf-8 +;; indent-tabs-mode: nil +;; End: +;;; magit.el ends here diff --git a/elpa/magit-20151223.1425/magit.info b/elpa/magit-20151223.1425/magit.info new file mode 100644 index 00000000..2f6b7f8c --- /dev/null +++ b/elpa/magit-20151223.1425/magit.info @@ -0,0 +1,158 @@ +This is magit.info, produced by makeinfo version 5.2 from magit.texi. + +Magit is an interface to the version control system Git, implemented as +an Emacs package. Magit aspires to be a complete Git porcelain. While +we cannot (yet) claim that Magit wraps and improves upon each and every +Git command, it is complete enough to allow even experienced Git users +to perform almost all of their daily version control tasks directly from +within Emacs. While many fine Git clients exist, only Magit and Git +itself deserve to be called porcelains. + + Copyright (C) 2015 Jonas Bernoulli + + You can redistribute this document 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 document 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. +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Magit: (magit). Using Git from Emacs with Magit. +END-INFO-DIR-ENTRY + + +Indirect: +magit.info-1: 1217 +magit.info-2: 306253 + +Tag Table: +(Indirect) +Node: Top1217 +Node: Introduction5670 +Node: Installation10363 +Node: Updating from an older release10738 +Node: Installing from an Elpa archive12333 +Node: Installing from the Git repository13891 +Node: Post-installation tasks16128 +Node: Getting started17654 +Node: Interface concepts23389 +Node: Modes and Buffers23715 +Node: Switching Buffers25330 +Node: Naming Buffers28394 +Node: Quitting Windows31229 +Node: Automatic save32815 +Node: Automatic refresh and revert33880 +Node: Sections38680 +Node: Section movement39632 +Node: Section visibility43559 +Node: Section hooks47150 +Node: Section types and values49188 +Node: Section options50458 +Node: Popup buffers and prefix commands50930 +Node: Completion and confirmation52244 +Node: Running Git55150 +Node: Viewing Git output55386 +Node: Running Git manually56386 +Node: Git executable58512 +Node: Global Git arguments60519 +Node: Inspecting61326 +Node: Status buffer62453 +Node: Status sections64976 +Node: Status header sections69723 +Node: Status options72282 +Node: Logging73006 +Node: Refreshing logs75373 +Node: Log Buffer76758 +Node: Select from log79847 +Node: Reflog80787 +Node: Diffing81265 +Node: Refreshing diffs84077 +Node: Diff buffer87058 +Node: Diff options88960 +Node: Revision buffer90592 +Node: Ediffing91547 +Node: References buffer94596 +Node: References sections99306 +Node: Bisecting100181 +Node: Visiting blobs101677 +Node: Blaming102186 +Node: Manipulating105506 +Node: Repository setup105798 +Node: Staging and unstaging106838 +Node: Staging from file-visiting buffers109187 +Node: Applying110355 +Node: Committing111998 +Node: Initiating a commit112581 +Node: Editing commit messages115893 +Node: Branching126289 +Node: Merging138576 +Node: Rebasing140660 +Node: Editing rebase sequences143608 +Node: Rebase sequence log146642 +Node: Cherry picking153386 +Node: Reverting154992 +Node: Resetting156355 +Node: Stashing157865 +Node: Transferring161010 +Node: Remotes161248 +Node: Fetching162534 +Node: Pulling163511 +Node: Pushing164237 +Node: Creating and sending patches168566 +Node: Applying patches169261 +Node: Miscellaneous170259 +Node: Tagging170550 +Node: Notes171335 +Node: Submodules173860 +Node: Common commands175180 +Node: Wip modes176928 +Node: Minor mode for buffers visiting files183664 +Node: Minor mode for buffers visiting blobs185807 +Node: Customizing186612 +Node: Per-repository configuration188284 +Node: Essential settings189918 +Node: Safety190242 +Node: Performance193476 +Node: Plumbing200122 +Node: Calling Git200750 +Node: Getting a value from Git202273 +Node: Calling Git for effect205377 +Node: Section plumbing211881 +Node: Creating sections212109 +Node: Section selection215912 +Node: Matching sections217592 +Node: Refreshing buffers222794 +Node: Conventions225929 +Node: Confirmation and completion226106 +Node: Theming Faces227004 +Node: FAQ235155 +Node: Magit is slow236325 +Node: I changed several thousand files at once and now Magit is unusable236526 +Node: I am having problems committing237242 +Node: I don't like how branching and pushing works237695 +Node: I cannot install the pre-requisites for Magit v2238175 +Node: I am using an Emacs release older than v244238649 +Node: I am using a Git release older than v194240262 +Node: I am using MS Windows and cannot push with Magit241249 +Node: How to install the gitman info manual?241828 +Node: How can I show Git's output?244354 +Node: Expanding a file to show the diff causes it to disappear245166 +Node: Point is wrong in the COMMIT_EDITMSG buffer245692 +Node: Can Magit be used as ediff-version-control-package?246710 +Node: How to show diffs for gpg-encrypted files?248734 +Node: Emacs 245 hangs when loading Magit249325 +Node: Keystroke Index249844 +Node: Command Index277035 +Node: Function Index306253 +Node: Variable Index317867 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/magit-20151223.1425/magit.info-1 b/elpa/magit-20151223.1425/magit.info-1 new file mode 100644 index 00000000..c9e4ab84 --- /dev/null +++ b/elpa/magit-20151223.1425/magit.info-1 @@ -0,0 +1,7293 @@ +This is magit.info, produced by makeinfo version 5.2 from magit.texi. + +Magit is an interface to the version control system Git, implemented as +an Emacs package. Magit aspires to be a complete Git porcelain. While +we cannot (yet) claim that Magit wraps and improves upon each and every +Git command, it is complete enough to allow even experienced Git users +to perform almost all of their daily version control tasks directly from +within Emacs. While many fine Git clients exist, only Magit and Git +itself deserve to be called porcelains. + + Copyright (C) 2015 Jonas Bernoulli + + You can redistribute this document 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 document 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. +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Magit: (magit). Using Git from Emacs with Magit. +END-INFO-DIR-ENTRY + + +File: magit.info, Node: Top, Next: Introduction, Up: (dir) + +Magit User Manual +***************** + +Magit is an interface to the version control system Git, implemented as +an Emacs package. Magit aspires to be a complete Git porcelain. While +we cannot (yet) claim that Magit wraps and improves upon each and every +Git command, it is complete enough to allow even experienced Git users +to perform almost all of their daily version control tasks directly from +within Emacs. While many fine Git clients exist, only Magit and Git +itself deserve to be called porcelains. + + Copyright (C) 2015 Jonas Bernoulli + + You can redistribute this document 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 document 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. + +* Menu: + +* Introduction:: +* Installation:: +* Getting started:: +* Interface concepts:: +* Inspecting:: +* Manipulating:: +* Transferring:: +* Miscellaneous:: +* Customizing:: +* Plumbing:: +* FAQ:: +* Keystroke Index:: +* Command Index:: +* Function Index:: +* Variable Index:: + +— The Detailed Node Listing — + +Installation + +* Updating from an older release:: +* Installing from an Elpa archive:: +* Installing from the Git repository:: +* Post-installation tasks:: + +Interface concepts + +* Modes and Buffers:: +* Automatic save:: +* Automatic refresh and revert:: +* Sections:: +* Popup buffers and prefix commands:: +* Completion and confirmation:: +* Running Git:: + +Modes and Buffers + +* Switching Buffers:: +* Naming Buffers:: +* Quitting Windows:: + +Sections + +* Section movement:: +* Section visibility:: +* Section hooks:: +* Section types and values:: +* Section options:: + +Running Git + +* Viewing Git output:: +* Running Git manually:: +* Git executable:: +* Global Git arguments:: + +Inspecting + +* Status buffer:: +* Logging:: +* Diffing:: +* Ediffing:: +* References buffer:: +* Bisecting:: +* Visiting blobs:: +* Blaming:: + +Status buffer + +* Status sections:: +* Status header sections:: +* Status options:: + +Logging + +* Refreshing logs:: +* Log Buffer:: +* Select from log:: +* Reflog:: + +Diffing + +* Refreshing diffs:: +* Diff buffer:: +* Diff options:: +* Revision buffer:: + +References buffer + +* References sections:: + +Manipulating + +* Repository setup:: +* Staging and unstaging:: +* Applying:: +* Committing:: +* Branching:: +* Merging:: +* Rebasing:: +* Cherry picking:: +* Resetting:: +* Stashing:: + +Staging and unstaging + +* Staging from file-visiting buffers:: + +Committing + +* Initiating a commit:: +* Editing commit messages:: + +Rebasing + +* Editing rebase sequences:: +* Rebase sequence log:: + +Cherry picking + +* Reverting:: + +Transferring + +* Remotes:: +* Fetching:: +* Pulling:: +* Pushing:: +* Creating and sending patches:: +* Applying patches:: + +Miscellaneous + +* Tagging:: +* Notes:: +* Submodules:: +* Common commands:: +* Wip modes:: +* Minor mode for buffers visiting files:: +* Minor mode for buffers visiting blobs:: + +Customizing + +* Per-repository configuration:: +* Essential settings:: + +Essential settings + +* Safety:: +* Performance:: + +Plumbing + +* Calling Git:: +* Section plumbing:: +* Refreshing buffers:: +* Conventions:: + +Calling Git + +* Getting a value from Git:: +* Calling Git for effect:: + +Section plumbing + +* Creating sections:: +* Section selection:: +* Matching sections:: + +Conventions + +* Confirmation and completion:: +* Theming Faces:: + +FAQ + +* Magit is slow:: +* I changed several thousand files at once and now Magit is unusable:: +* I am having problems committing:: +* I don't like how branching and pushing works:: +* I cannot install the pre-requisites for Magit v2:: +* I am using an Emacs release older than v24.4: I am using an Emacs release older than v244. +* I am using a Git release older than v1.9.4: I am using a Git release older than v194. +* I am using MS Windows and cannot push with Magit:: +* How to install the gitman info manual?:: +* How can I show Git's output?:: +* Expanding a file to show the diff causes it to disappear:: +* Point is wrong in the COMMIT_EDITMSG buffer:: +* Can Magit be used as ediff-version-control-package?:: +* How to show diffs for gpg-encrypted files?:: +* Emacs 24.5 hangs when loading Magit: Emacs 245 hangs when loading Magit. + + + +File: magit.info, Node: Introduction, Next: Installation, Prev: Top, Up: Top + +1 Introduction +************** + +Magit is an interface to the version control system Git, implemented as +an Emacs package. Magit aspires to be a complete Git porcelain. While +we cannot (yet) claim that Magit wraps and improves upon each and every +Git command, it is complete enough to allow even experienced Git users +to perform almost all of their daily version control tasks directly from +within Emacs. While many fine Git clients exist, only Magit and Git +itself deserve to be called porcelains. + + Staging and otherwise applying changes is one of the most important +features in a Git porcelain and here Magit outshines anything else, +including Git itself. Git’s own staging interface (‘git add --patch’) +is so cumbersome that many users only use it in exceptional cases. In +Magit staging a hunk or even just part of a hunk is as trivial as +staging all changes made to a file. + + The most visible part of Magit’s interface is the status buffer, +which displays information about the current repository. Its content is +created by running several Git commands and making their output +actionable. Among other things, it displays information about the +current branch, lists unpulled and unpushed changes and contains +sections displaying the staged and unstaged changes. That might sound +noisy, but, since sections are collapsible, it’s not. + + To stage or unstage a change one places the cursor on the change and +then types ‘s’ or ‘u’. The change can be a file or a hunk, or when the +region is active (i.e. when there is a selection) several files or +hunks, or even just part of a hunk. The change or changes that these +commands - and many others - would act on are highlighted. + + Magit also implements several other "apply variants" in addition to +staging and unstaging. One can discard or reverse a change, or apply it +to the working tree. Git’s own porcelain only supports this for staging +and unstaging and you would have to do something like ‘git diff ... | +??? | git apply ...’ to discard, revert, or apply a single hunk on the +command line. In fact that’s exactly what Magit does internally (which +is what lead to the term "apply variants"). + + Magit isn’t just for Git experts, but it does assume some prior +experience with Git as well as Emacs. That being said, many users have +reported that using Magit was what finally taught them what Git is +capable of and how to use it to its fullest. Other users wished they +had switched to Emacs sooner so that they would have gotten their hands +on Magit earlier. + + While one has to know the basic features of Emacs to be able to make +full use of Magit, acquiring just enough Emacs skills doesn’t take long +and is worth it, even for users who prefer other editors. Vim users are +advised to give Evil (https://bitbucket.org/lyro/evil/wiki/Home), the +"Extensible VI Layer for Emacs", and Spacemacs +(https://github.com/syl20bnr/spacemacs), an "Emacs starter-kit focused +on Evil" a try. + + Magit provides a consistent and efficient Git porcelain. After a +short learning period, you will be able to perform most of your daily +version control tasks faster than you would on the command line. You +will likely also start using features that seemed too daunting in the +past. + + Magit fully embraces Git. It exposes many advanced features using a +simple but flexible interface instead of only wrapping the trivial ones +like many GUI clients do. Of course Magit supports logging, cloning, +pushing, and other commands that usually don’t fail in spectacular ways; +but it also supports tasks that often cannot be completed in a single +step. Magit fully supports tasks such as merging, rebasing, +cherry-picking, reverting, and blaming by not only providing a command +to initiate these tasks but also by displaying context sensitive +information along the way and providing commands that are useful for +resolving conflicts and resuming the sequence after doing so. + + Magit wraps and in many cases improves upon at least the following +Git porcelain commands: ‘add’, ‘am’, ‘bisect’, ‘blame’, ‘branch’, +‘checkout’, ‘cherry’, ‘cherry-pick’, ‘clean’, ‘clone’, ‘commit’, +‘config’, ‘describe’, ‘diff’, ‘fetch’, ‘format-patch’, ‘init’, ‘log’, +‘merge’, ‘merge-tree’, ‘mv’, ‘notes’, ‘pull’, ‘rebase’, ‘reflog’, +‘remote’, ‘request-pull’, ‘reset’, ‘revert’, ‘rm’, ‘show’, ‘stash’, +‘submodule’, and ‘tag’. Many more Magit porcelain commands are +implemented on top of Git plumbing commands. + + +File: magit.info, Node: Installation, Next: Getting started, Prev: Introduction, Up: Top + +2 Installation +************** + +Magit can be installed using Emacs’ package manager or manually from its +development repository. + +* Menu: + +* Updating from an older release:: +* Installing from an Elpa archive:: +* Installing from the Git repository:: +* Post-installation tasks:: + + +File: magit.info, Node: Updating from an older release, Next: Installing from an Elpa archive, Up: Installation + +2.1 Updating from an older release +================================== + +When updating from ‘1.2.*’ or ‘1.4.*’, you should first uninstall Magit +and some of its dependencies and restart Emacs before installing the +latest release. + + • The old Magit installation has to be removed because some macros + have changed and using the old definitions when building the new + release would lead to very strange results, including compile + errors. This is due to a limitation in Emacs’ package manager or + rather Emacs itself: it’s not possible to reliably unload a feature + or even all features belonging to a package. + + • Furthermore the old dependencies ‘git-commit-mode’ and + ‘git-rebase-mode’ have to be removed because they are no longer + used by the ‘2.1.0’ release and later, and get in the way of their + successors ‘git-commit’ and ‘git-rebase’. + + So please uninstall the packages ‘magit’, ‘git-commit-mode’, and +‘git-rebase-mode’. Then quit Emacs and start a new instance. Only then +follow the instructions in either one of the next two sections. + + Also note that starting with the ‘2.1.0’ release, Magit requires at +least Emacs ‘24.4’ and Git ‘1.9.4’. You should make sure you have at +least these releases installed before updating Magit. And if you +connect to remote hosts using Tramp, then you should also make sure to +install a recent enough Git version on these hosts. + + +File: magit.info, Node: Installing from an Elpa archive, Next: Installing from the Git repository, Prev: Updating from an older release, Up: Installation + +2.2 Installing from an Elpa archive +=================================== + +If you are updating from a release older than ‘2.1.0’, then you have to +first uninstall the old version. See *note Updating from an older +release: Updating from an older release. + + Magit is available from all three of the popular unofficial Elpa +archives: Melpa, Melpa-Stable, and Marmalade. If you haven’t used +Emacs’ package manager before, then it is high time you familiarize +yourself with it by reading the documentation in the Emacs manual, see +*note (emacs)Packages::. Then add one of the archives to +‘package-archives’: + + • To use Melpa: + + (require 'package) + (add-to-list 'package-archives + '("melpa" . "http://melpa.org/packages/") t) + + • To use Melpa-Stable: + + (require 'package) + (add-to-list 'package-archives + '("melpa-stable" . "http://stable.melpa.org/packages/") t) + + • To use Marmalade: + + (require 'package) + (add-to-list 'package-archives + '("marmalade" . "http://marmalade-repo.org/packages/") t) + + Once you have added your preferred archive, you need to update the +local package list using: + + M-x package-refresh-contents RET + + Once you have done that, you can install Magit and its dependencies +using: + + M-x package-install RET magit RET + + Now see *note Post-installation tasks: Post-installation tasks. + + +File: magit.info, Node: Installing from the Git repository, Next: Post-installation tasks, Prev: Installing from an Elpa archive, Up: Installation + +2.3 Installing from the Git repository +====================================== + +If you are updating from a release older than ‘2.1.0’, then you have to +first uninstall the old version. See *note Updating from an older +release: Updating from an older release. + + Magit depends on the ‘dash’ library, available from all three of the +popular third-party Elpa archives. Install it using ‘M-x +package-install RET dash RET’. Of course you may also install it +manually from its development repository, but I won’t cover that here. + + Then clone the Magit repository: + + $ git clone git://github.com/magit/magit.git ~/.emacs.d/site-lisp/magit + $ cd ~/.emacs.d/site-lisp/magit + + Then compile the libraries and generate the info manuals: + + $ make + + If you haven’t installed ‘dash’ using Elpa or at +‘/path/to/magit/../dash’, then you have to tell ‘make’ where to find it. +To do so create ‘/path/to/magit/config.mk’ with the following content +before running ‘make’: + + LOAD_PATH = -L /path/to/magit/lisp -L /path/to/dash + + Finally add this to your init file: + + (add-to-list 'load-path "~/.emacs.d/site-lisp/magit/lisp") + (require 'magit) + + (with-eval-after-load 'info + (info-initialize) + (add-to-list 'Info-directory-list + "~/.emacs.d/site-lisp/magit/Documentation/")) + + Note that you have to add the ‘lisp/’ subdirectory to the +‘load-path’, not the top-level of the repository. + + Instead of requiring the feature ‘magit’, you could only load the +autoloads, by loading the file ‘magit-autoloads.el’. + + Instead of running Magit directly from the repository by adding that +to the ‘load-path’, you might want to instead install it in some other +directory using ‘sudo make install’ and setting ‘load-path’ accordingly. + + To update Magit use: + + $ git pull + $ make + + At times it might be necessary to run ‘make clean all’ instead. + + To view all available targets use ‘make help’. + + Now see *note Post-installation tasks: Post-installation tasks. + + +File: magit.info, Node: Post-installation tasks, Prev: Installing from the Git repository, Up: Installation + +2.4 Post-installation tasks +=========================== + +After installing Magit you should verify that you are indeed using the +Magit, Git, and Emacs releases you think you are using. It’s best to +restart Emacs before doing so, to make sure you are not using an +outdated value for ‘load-path’. + + M-x magit-version RET + + should display something like + + Magit 2.2.0, Git 2.4.2, Emacs 24.5.1 + + Then you might also want to read about options that many users likely +want to customize. See *note Essential settings: Essential settings. + + To be able to follow cross references to Git manpages found in this +manual, you might also have to manually install the ‘gitman’ info +manual, or advice ‘Info-follow-nearest-node’ to instead open the actual +manpage. See *note How to install the gitman info manual?: How to +install the gitman info manual?. + + If you are completely new to Magit then see *note Getting started: +Getting started. + + If you have used an older Magit release before, then you should have +a look at the release notes + +and + + + And last but not least please consider making a donation, to ensure +that I can keep working on Magit. See +for various donation options. + + +File: magit.info, Node: Getting started, Next: Interface concepts, Prev: Installation, Up: Top + +3 Getting started +***************** + +This section describes the most essential features that many Magitians +use on a daily basis. It only scratches the surface but should be +enough to get you started. + + (You might want to create a repository just for this walk-through, +e.g. by cloning an existing repository. If you don’t use a separate +repository then make sure you create a snapshot as described below). + + To display information about the current Git repository, type ‘M-x +magit-status’. You will be doing that so often that it is best to bind +this command globally: + + (global-set-key (kbd "C-x g") 'magit-status) + + Most Magit commands are commonly invoked from this buffer. It should +be considered the primary interface to interact with Git using Magit. +There are many other Magit buffers, but they are usually created from +this buffer. + + Depending on what state your repository is in, this buffer will +contain sections titled "Staged changes", "Unstaged changes", "Unpulled +commits", "Unpushed commits", and/or some others. + + If some staged and/or unstaged changes exist, you should back them up +now. Type ‘z’ to show the stashing popup buffer featuring various stash +variants and arguments that can be passed to these commands. Do not +worry about those for now, just type ‘Z’ (uppercase) to create a stash +while also keeping the index and work tree intact. The status buffer +should now also contain a section titled "Stashes". + + Otherwise, if there are no uncommitted changes, you should create +some now by editing and saving some of the tracked files. Then go back +to the status buffer, while at the same time refreshing it, by typing +‘C-x g’. (When the status buffer, or any Magit buffer for that matter, +is the current buffer, then you can also use just ‘g’ to refresh it). + + Move between sections using ‘p’ and ‘n’. Note that the bodies of +some sections are hidden. Type ‘TAB’ to expand or collapse the section +at point. You can also use ‘C-tab’ to cycle the visibility of the +current section and its children. Move to a file section inside the +section named "Unstaged changes" and type ‘s’ to stage the changes you +have made to that file. That file now appears under "Staged changes". + + Magit can stage and unstage individual hunks, not just complete +files. Move to the file you have just staged, expand it using ‘TAB’, +move to one of the hunks using ‘n’, and unstage just that by typing ‘u’. +Note how the staging (‘s’) and unstaging (‘u’) commands operate on the +change at point. Many other commands behave the same way. + + You can also un-/stage just part of a hunk. Inside the body of a +hunk section (move there using ‘C-n’), set the mark using ‘C-SPC’ and +move down until some added and removed lines fall inside the region but +not all of them. Again type ‘s’ to stage. + + It’s also possible to un-/stage multiple files at once. Move to a +file section, type ‘C-SPC’, move to the next file using ‘n’, and then +‘s’ to stage both files. Note that both the mark and point have to be +on the headings of sibling sections for this to work. If the region +looks like it does in other buffers, then it doesn’t select Magit +sections that can be acted on as a unit. + + And then of course you want to commit your changes. Type ‘c’. This +shows the committing popup buffer featuring various commit variants and +arguments that can be passed to ‘git commit’. Do not worry about those +for now. We want to create a "normal" commit, which is done by typing +‘c’ again. + + Now two new buffers appear. One is for writing the commit message, +the other shows a diff with the changes that are about to committed. +Write a message and then type ‘C-c C-c’ to actually create the commit. + + You probably don’t want to push the commit you just created because +you just committed some random changes, but if that is not the case you +could push it by typing ‘P’ to bring up the push popup and then ‘P’ +again to push to the configured upstream. (If the upstream is not +configured, then you would be prompted for the push target instead.) + + Instead we are going to undo the changes made so far. Bring up the +log for the current branch by typing ‘l l’, move to the last commit +created before starting with this walk through using ‘n’, and do a hard +reset using ‘C-u x’. *WARNING*: this discards all uncommitted changes. +If you did not follow the advice about using a separate repository for +these experiments and did not create a snapshot of uncommitted changes +before starting to try out Magit, then don’t do this. + + So far we have mentioned the commit, push, and log popups. These are +probably among the popups you will be using the most, but many others +exist. To show a popup with all other popups (as well as the various +apply commands), type ‘h’. Try a few. + + The key bindings in that popup correspond to the bindings in Magit +buffers, including but not limited to the status buffer. So you could +type ‘h d’ to bring up the diff popup, but once you remember that "d" +stands for "diff", you would usually do so by just typing ‘d’. But the +"popup of popups" is useful even once you have memorized all the +bindings, as it can provide easy access to Magit commands from non-Magit +buffers. So you should bind this globally too: + + (global-set-key (kbd "C-x M-g") 'magit-dispatch-popup) + + You might also want to enable ‘global-magit-file-mode’ (see *note +Minor mode for buffers visiting files: Minor mode for buffers visiting +files.). + + +File: magit.info, Node: Interface concepts, Next: Inspecting, Prev: Getting started, Up: Top + +4 Interface concepts +******************** + +* Menu: + +* Modes and Buffers:: +* Automatic save:: +* Automatic refresh and revert:: +* Sections:: +* Popup buffers and prefix commands:: +* Completion and confirmation:: +* Running Git:: + + +File: magit.info, Node: Modes and Buffers, Next: Automatic save, Up: Interface concepts + +4.1 Modes and Buffers +===================== + +Magit provides several major-modes. For each of these modes there +usually exists only one buffer per repository. Separate modes and thus +buffers exist for commits, diffs, logs, and some other things. + + Besides these special purpose buffers, there also exists an overview +buffer, called the *status buffer*. Its usually from this buffer that +the user invokes Git commands, or creates or visits other buffers. + + In this manual we often speak about "Magit buffers". By that we mean +buffers whose major-modes derive from ‘magit-mode’. + +‘M-x magit-toggle-buffer-lock’ (‘magit-toggle-buffer-lock’) + + This command locks the current buffer to its value or if the buffer + is already locked, then it unlocks it. + + Locking a buffer to its value, prevents it from being reused to + display another value. The name of a locked buffer contains its + value, which allows telling it apart from other locked buffers and + the unlocked buffer. + + Not all Magit buffers can be locked to their values, for example it + wouldn’t make sense to lock a status buffer. + + There can only be a single unlocked buffer using a certain + major-mode per repository. So when a buffer is being unlocked and + another unlocked buffer already exists for that mode and + repository, then the former buffer is instead deleted and the + latter is displayed in its place. + +* Menu: + +* Switching Buffers:: +* Naming Buffers:: +* Quitting Windows:: + + +File: magit.info, Node: Switching Buffers, Next: Naming Buffers, Up: Modes and Buffers + +4.1.1 Switching Buffers +----------------------- + + -- Function: magit-display-buffer buffer + + This function is a wrapper around ‘display-buffer’ and is used to + display any Magit buffer. It displays BUFFER in some window and, + unlike ‘display-buffer’, also selects that window, provided + ‘magit-display-buffer-noselect’ is ‘nil’. It also runs the hooks + mentioned below. + + -- Variable: magit-display-buffer-noselect + + When this is non-nil, then ‘magit-display-buffer’ only displays the + buffer but forgoes also selecting the window. This variable should + not be set globally, it is only intended to be let-bound, by code + that automatically updates "the other window". This is used for + example when the revision buffer is updated when you move inside + the log buffer. + + -- User Option: magit-display-buffer-function + + The function specified here is called by ‘magit-display-buffer’ + with one argument, a buffer, to actually display that buffer. This + function should call ‘display-buffer’ with that buffer as first and + a list of display actions as second argument. + + Instead of using a wrapper around ‘display-buffer’, that function + itself can be used here, in which case the display actions have to + be specified by adding them to ‘display-buffer-alist’ instead. + + To learn about display actions, see *note (elisp)Choosing a Window + for Display::. + + -- Function: magit-display-buffer-traditional buffer + + This function is the current default value of the option + ‘magit-display-buffer-function’. Before that option and this + function were added, the behavior was hard-coded in many places all + over the code base but now all the rules are contained in this one + function (except for the "noselect" special case mentioned above). + + If you want to use different rules, then a good way of doing that + is to start with a copy of this function and then adjust it to your + needs. More functions to choose from will be added in the future, + and eventually the default will change. + + -- User Option: magit-pre-display-buffer-hook + + This hook is run by ‘magit-display-buffer’ before displaying the + buffer. + + -- Function: magit-save-window-configuration + + This function saves the current window configuration. Later when + the buffer is buried, it may be restored by + ‘magit-restore-window-configuration’. + + -- User Option: magit-post-display-buffer-hook + + This hook is run by ‘magit-display-buffer’ after displaying the + buffer. + + -- Function: magit-maybe-set-dedicated + + This function remembers if a new window had to be created to + display the buffer, or whether an existing window was reused. This + information is later used by ‘magit-mode-quit-window’, to determine + whether the window should be deleted when its last Magit buffer is + buried. + + +File: magit.info, Node: Naming Buffers, Next: Quitting Windows, Prev: Switching Buffers, Up: Modes and Buffers + +4.1.2 Naming Buffers +-------------------- + + -- User Option: magit-generate-buffer-name-function + + The function used to generate the names of Magit buffers. + + Such a function should take the options + ‘magit-uniquify-buffer-names’ as well as ‘magit-buffer-name-format’ + into account. If it doesn’t, then should be clearly stated in the + doc-string. And if it supports %-sequences beyond those mentioned + in the doc-string of the option ‘magit-buffer-name-format’, then + its own doc-string should describe the additions. + + -- Function: magit-generate-buffer-name-default-function mode + + This function returns a buffer name suitable for a buffer whose + major-mode is MODE and which shows information about the repository + in which ‘default-directory’ is located. + + This function uses ‘magit-buffer-name-format’ and supporting all of + the %-sequences mentioned the documentation of that option. It + also respects the option ‘magit-uniquify-buffer-names’. + + -- User Option: magit-buffer-name-format + + The format string used to name Magit buffers. + + At least the following %-sequences are supported: + + • ‘%m’ + + The name of the major-mode, but with the ‘-mode’ suffix + removed. + + • ‘%M’ + + Like ‘%m’ but abbreviate ‘magit-status-mode’ as ‘magit’. + + • ‘%v’ + + The value the buffer is locked to, in parentheses, or an empty + string if the buffer is not locked to a value. + + • ‘%V’ + + Like ‘%v’, but the string is prefixed with a space, unless it + is an empty string. + + • ‘%t’ + + The top-level directory of the working tree of the repository, + or if ‘magit-uniquify-buffer-names’ is non-nil an abbreviation + of that. + The value should always contain either ‘%m’ or ‘%M’, ‘%v’ or ‘%V’, + and ‘%t’. If ‘magit-uniquify-buffer-names’ is non-nil, then the + value must end with ‘%t’. + + -- User Option: magit-uniquify-buffer-names + + This option controls whether the names of Magit buffers are + uniquified. If the names are not being uniquified, then they + contain the full path of the top-level of the working tree of the + corresponding repository. If they are being uniquified, then they + end with the basename of the top-level, or if that would conflict + with the name used for other buffers, then the names of all these + buffers are adjusted until they no longer conflict. + + This is done using the ‘uniquify’ package; customize its options to + control how buffer names are uniquified. + + +File: magit.info, Node: Quitting Windows, Prev: Naming Buffers, Up: Modes and Buffers + +4.1.3 Quitting Windows +---------------------- + +‘q’ (‘magit-mode-bury-buffer’) + + This command buries the current Magit buffer. With a prefix + argument, it instead kills the buffer. + + -- User Option: magit-bury-buffer-function + + The function used to actually bury or kill the current buffer. + + ‘magit-mode-bury-buffer’ calls this function with one argument. If + the argument is non-nil, then the function has to kill the current + buffer. Otherwise it has to bury it alive. The default value + currently is ‘magit-restore-window-configuration’. + + -- Function: magit-restore-window-configuration kill-buffer + + Bury or kill the current buffer using ‘quit-window’, which is + called with KILL-BUFFER as first and the selected window as second + argument. + + Then restore the window configuration that existed right before the + current buffer was displayed in the selected frame. Unfortunately + that also means that point gets adjusted in all the buffers, which + are being displayed in the selected frame. + + -- Function: magit-mode-quit-window kill-buffer + + Bury or kill the current buffer using ‘quit-window’, which is + called with KILL-BUFFER as first and the selected window as second + argument. + + Then, if the window was originally created to display a Magit + buffer and the buried buffer was the last remaining Magit buffer + that was ever displayed in the window, then that is deleted. + + +File: magit.info, Node: Automatic save, Next: Automatic refresh and revert, Prev: Modes and Buffers, Up: Interface concepts + +4.2 Automatic save +================== + +File-visiting buffers are by default saved at certain points in time. +This doesn’t guarantee that Magit buffers are always up-to-date, but, +provided one only edits files by editing them in Emacs and uses only +Magit to interact with Git, one can be fairly confident. When in doubt +or after outside changes, type ‘g’ (‘magit-refresh’) to save and refresh +explicitly. + + -- User Option: magit-save-repository-buffers + + This option controls whether file-visiting buffers are saved before + certain events. + + If this is non-nil then all modified file-visiting buffers + belonging to the current repository may be saved before running + commands, before creating new Magit buffers, and before explicitly + refreshing such buffers. If this is ‘dontask’ then this is done + without user intervention. If it is ‘t’ then the user has to + confirm each save. + + +File: magit.info, Node: Automatic refresh and revert, Next: Sections, Prev: Automatic save, Up: Interface concepts + +4.3 Automatic refresh and revert +================================ + +After running a command which may change the state of the current +repository, the current Magit buffer and the corresponding status buffer +are refreshed. Status buffer may optionally be automatically refreshed +whenever a buffer is saved to a file inside the respective repository. + + Automatically refreshing Magit buffers ensures that the displayed +information is up-to-date most of the time but can lead to a noticeable +delay in big repositories. Other Magit buffers are not refreshed to +keep the delay to a minimum and also because doing so can sometimes be +undesirable. + + -- User Option: magit-revert-buffers + + This option controls if and how file-visiting buffers in the + current repository are reverted. + + Unmodified buffers visiting files belonging to the current + repository may be reverted after refreshing the current Magit + buffer and after running certain other commands. + + • ‘nil’ + + Don’t revert any buffers. + + • ‘ask’ + + List the buffers which might potentially have to be reverted + and ask the user whether she wants to revert them. If so, + then do it synchronously. + + • ‘t’ + + Revert the buffers synchronously, mentioning each one as it is + being reverted and then also show a summary in the echo area. + + • ‘usage’ + + Like ‘t’ but include usage information in the summary. This + is the default so that users come here and pick what is right + for them. + + • ‘silent’ + + Revert the buffers synchronously and be quiet about it. + + This (or a negative number) is the recommended setting, + because for the other values the revert messages might prevent + you from seeing other, more important, messages in the echo + area. + + • NUMBER + + An integer or float. Revert the buffers asynchronously. If + NUMBER is positive, then mention each buffer as it is being + reverted. If it is negative, then be quiet about it. If user + input arrives, then stop reverting. After (the absolute value + of) NUMBER seconds resume reverting. + + Buffers can also be refreshed explicitly, which is useful in buffers +that weren’t current during the last refresh and after changes were made +to the repository outside of Magit. + +‘g’ (‘magit-refresh’) + + This command refreshes the current buffer if its major mode derives + from ‘magit-mode’ as well as the corresponding status buffer. + + If the option ‘magit-revert-buffers’ calls for it, then it also + reverts all unmodified buffers that visit files being tracked in + the current repository. + +‘G’ (‘magit-refresh-all’) + + This command refreshes all Magit buffers belonging to the current + repository and also reverts all unmodified buffers that visit files + being tracked in the current repository. + + The file-visiting buffers are always reverted, even if + ‘magit-revert-buffers’ is nil. + + -- Function: magit-after-save-refresh-status + + This function is intended to be added to ‘after-save-hook’. After + doing that the corresponding status buffer is refreshed whenever a + buffer is saved to a file inside a repository. + + Note that refreshing a Magit buffer is done by re-creating its + contents from scratch, which can be slow in large repositories. If + you are not satisfied with Magit’s performance, then you should + obviously not add this function to that hook. + + -- User Option: magit-refresh-buffer-hook + + This hook is run in each Magit buffer that was refreshed during the + current refresh - normally the current buffer and the status + buffer. + + -- User Option: magit-after-revert-hook + + This hook is run in each file-visiting buffer belonging to the + current repository that was actually reverted during a refresh. + + Note that adding something here is very expensive. If you + experience performance issues, you might want to check this hook, + as well as ‘magit-not-reverted-hook’ and, if possible, remove some + of the functions added by third-party packages. + + -- User Option: magit-not-reverted-hook + + This hook is run in each file-visiting buffer belonging to the + current repository that was reverted during a refresh. The file + was not reverted because it did not change, and so Magit does not + have to do anything. This hook is intended for third-party + extensions that need to run some functions even on such files. + + +File: magit.info, Node: Sections, Next: Popup buffers and prefix commands, Prev: Automatic refresh and revert, Up: Interface concepts + +4.4 Sections +============ + +Magit buffers are organized into nested sections, which can be collapsed +and expanded, similar to how sections are handled in Org mode. Each +section also has a type, and some sections also have a value. For each +section type there can also be a local keymap, shared by all sections of +that type. + + Taking advantage of the section value and type, many commands operate +on the current section, or when the region is active and selects +sections of the same type, all of the selected sections. Commands that +only make sense for a particular section type (as opposed to just +behaving differently depending on the type) are usually bound in section +type keymaps. + +* Menu: + +* Section movement:: +* Section visibility:: +* Section hooks:: +* Section types and values:: +* Section options:: + + +File: magit.info, Node: Section movement, Next: Section visibility, Up: Sections + +4.4.1 Section movement +---------------------- + +To move within a section use the usual keys (‘C-p’, ‘C-n’, ‘C-b’, ‘C-f’ +etc), whose global bindings are not shadowed. To move to another +section use the following commands. + +‘p’ (‘magit-section-backward’) + + When not at the beginning of a section, then move to the beginning + of the current section. At the beginning of a section, instead + move to the beginning of the previous visible section. + +‘n’ (‘magit-section-forward’) + + Move to the beginning of the next visible section. + +‘M-p’ (‘magit-section-backward-siblings’) + + Move to the beginning of the previous sibling section. If there is + no previous sibling section, then move to the parent section + instead. + +‘M-n’ (‘magit-section-forward-siblings’) + + Move to the beginning of the next sibling section. If there is no + next sibling section, then move to the parent section instead. + +‘^’ (‘magit-section-up’) + + Move to the beginning of the parent of the current section. + + The above commands all call the hook ‘magit-section-movement-hook’. +And, except for the second, the below functions are all members of that +hook’s default value. + + -- Variable: magit-section-movement-hook + + This hook is run by all of the above movement commands, after + arriving at the destination. + + -- Function: magit-hunk-set-window-start + + This hook function ensures that the beginning of the current + section is visible, provided it is a ‘hunk’ section. Otherwise, it + does nothing. + + -- Function: magit-section-set-window-start + + This hook function ensures that the beginning of the current + section is visible, regardless of the section’s type. If you add + this to ‘magit-section-movement-hook’, then you must remove the + hunk-only variant in turn. + + -- Function: magit-log-maybe-show-more-commits + + This hook function only has an effect in log buffers, and ‘point’ + is on the "show more" section. If that is the case, then it + doubles the number of commits that are being shown. + + -- Function: magit-log-maybe-update-revision-buffer + + When moving inside a log buffer, then this function updates the + revision buffer, provided it is already being displayed in another + window of the same frame. + + -- Function: magit-log-maybe-update-blob-buffer + + When moving inside a log buffer and another window of the same + frame displays a blob buffer, then this function instead displays + the blob buffer for the commit at point in that window. + + -- Function: magit-status-maybe-update-revision-buffer + + When moving inside a status buffer, then this function updates the + revision buffer, provided it is already being displayed in another + window of the same frame. + + -- Function: magit-status-maybe-update-blob-buffer + + When moving inside a status buffer and another window of the same + frame displays a blob buffer, then this function instead displays + the blob buffer for the commit at point in that window. + + -- User Option: magit-update-other-window-delay + + Delay before automatically updating the other window. + + When moving around in certain buffers certain other buffers, which + are being displayed in another window, may optionally be updated to + display information about the section at point. + + When holding down a key to move by more than just one section, then + that would update that buffer for each section on the way. To + prevent that, updating the revision buffer is delayed, and this + option controls for how long. For optimal experience you might + have to adjust this delay and/or the keyboard repeat rate and delay + of your graphical environment or operating system. + + +File: magit.info, Node: Section visibility, Next: Section hooks, Prev: Section movement, Up: Sections + +4.4.2 Section visibility +------------------------ + +Magit provides many commands for changing the visibility of sections, +but all you need to get started are the next two. + +‘TAB’ (‘magit-section-toggle’) + + Toggle the visibility of the body of the current section. + +‘C-’ (‘magit-section-cycle’) + + Cycle the visibility of current section and its children. + +‘M-’ (‘magit-section-cycle-diffs’) + + Cycle the visibility of diff-related sections in the current + buffer. + +‘s-’ (‘magit-section-cycle-global’) + + Cycle the visibility of all sections in the current buffer. + + -- Command: magit-section-show-level-1 + -- Command: magit-section-show-level-2 + -- Command: magit-section-show-level-3 + -- Command: magit-section-show-level-4 + + To show sections surrounding the current section, up to level N, + press the respective number key (‘1’, ‘2’, ‘3’, or ‘4’). + + -- Command: magit-section-show-level-1-all + -- Command: magit-section-show-level-2-all + -- Command: magit-section-show-level-3-all + -- Command: magit-section-show-level-4-all + + To show all sections up to level N, press the respective number key + and meta (‘M-1’, ‘M-2’, ‘M-3’, or ‘M-4’). + + Some functions, which are used to implement the above commands, are +also exposed as commands themselves. By default no keys are bound to +these commands, as they are generally perceived to be much less useful. +But your mileage may vary. + + -- Command: magit-section-show + + Show the body of the current section. + + -- Command: magit-section-hide + + Hide the body of the current section. + + -- Command: magit-section-show-headings + + Recursively show headings of children of the current section. Only + show the headings. Previously shown text-only bodies are hidden. + + -- Command: magit-section-show-children + + Recursively show the bodies of children of the current section. + With a prefix argument show children down to the level of the + current section, and hide deeper children. + + -- Command: magit-section-hide-children + + Recursively hide the bodies of children of the current section. + + -- Command: magit-section-toggle-children + + Toggle visibility of bodies of children of the current section. + + When a buffer is first created then some sections are shown expanded +while others are not. This is hard coded. When a buffer is refreshed +then the previous visibility is preserved. The initial visibility of +certain sections can also be overwritten using the hook +‘magit-section-set-visibility-hook’. + + -- Variable: magit-section-set-visibility-hook + + This hook is run when first creating a buffer and also when + refreshing an existing buffer, and is used to determine the + visibility of the section currently being inserted. + + Each function is called with one argument, the section being + inserted. It should return ‘hide’ or ‘show’, or to leave the + visibility undefined ‘nil’. If no function decides on the + visibility and the buffer is being refreshed, then the visibility + is preserved; or if the buffer is being created, then the hard + coded default is used. + + Usually this should only be used to set the initial visibility but + not during refreshes. If ‘magit-insert-section--oldroot’ is + non-nil, then the buffer is being refreshed and these functions + should immediately return ‘nil’. + + +File: magit.info, Node: Section hooks, Next: Section types and values, Prev: Section visibility, Up: Sections + +4.4.3 Section hooks +------------------- + +Which sections are inserted into certain buffers is controlled with +hooks. This includes the status and the refs buffers. For other +buffers, e.g. log, diff, and revision buffers, this is not possible. + + For buffers whose sections can be customized by the user, a hook +variable called ‘magit-TYPE-sections-hook’ exists. This hook should be +changed using ‘magit-add-section-hook’. Avoid using ‘add-hooks’ or the +Custom interface. + + The various available section hook variables are described later in +this manual along with the appropriate "section inserter functions". + + -- Function: magit-add-section-hook hook function &optional at append + local + + Add the function FUNCTION to the value of section hook HOOK. + + Add FUNCTION at the beginning of the hook list unless optional + APPEND is non-nil, in which case FUNCTION is added at the end. If + FUNCTION already is a member then move it to the new location. + + If optional AT is non-nil and a member of the hook list, then add + FUNCTION next to that instead. Add before or after AT depending on + APPEND. If only FUNCTION is a member of the list, then leave it + wherever it already is. + + If optional LOCAL is non-nil, then modify the hook’s buffer-local + value rather than its global value. This makes the hook local by + copying the default value. That copy is then modified. + + HOOK should be a symbol. If HOOK is void, it is first set to nil. + HOOK’s value must not be a single hook function. FUNCTION should + be a function that takes no arguments and inserts one or multiple + sections at point, moving point forward. FUNCTION may choose not + to insert its section(s), when doing so would not make sense. It + should not be abused for other side-effects. + + To remove a function from a section hook, use ‘remove-hook’. + + +File: magit.info, Node: Section types and values, Next: Section options, Prev: Section hooks, Up: Sections + +4.4.4 Section types and values +------------------------------ + +Each section has a type, for example ‘hunk’, ‘file’, and ‘commit’. +Instances of certain section types also have a value. The value of a +section of type ‘file’, for example, is a file name. + + Users usually do not have to worry about a section’s type and value, +but knowing them can be handy at times. + +‘M-x magit-describe-section’ (‘magit-describe-section’) + + Show information about the section at point in the echo area, as + "VALUE [TYPE PARENT-TYPE…] BEGINNING-END". + + Many commands behave differently depending on the type of the section +at point and/or somehow consume the value of that section. But that is +only one of the reasons why the same key may do something different, +depending on what section is current. + + Additionally for each section type a keymap *might* be defined, named +‘magit-TYPE-section-map’. That keymap is used as text property keymap +of all text belonging to any section of the respective type. If such a +map does not exist for a certain type, then you can define it yourself, +and it will automatically be used. + + +File: magit.info, Node: Section options, Prev: Section types and values, Up: Sections + +4.4.5 Section options +--------------------- + +This section describes options that have an effect on more than just a +certain type of sections. As you can see there are not many of those. + + -- User Option: magit-section-show-child-count + + Whether to append the number of children to section headings. This + only affects sections that could benefit from this information. + + +File: magit.info, Node: Popup buffers and prefix commands, Next: Completion and confirmation, Prev: Sections, Up: Interface concepts + +4.5 Popup buffers and prefix commands +===================================== + +Many Magit commands are implemented using *popup buffers*. First the +user invokes a *popup* or *prefix* command, which causes a popup buffer +with the available *infix* arguments and *suffix* commands to be +displayed. The user then optionally toggles/sets some arguments and +finally invokes one of the suffix commands. + + This is implemented in the library ‘magit-popup’. Earlier releases +used the library ‘magit-key-mode’. A future release will switch to a +yet-to-be-written successor, which will likely be named ‘transient’. + + Because ‘magit-popup’ can also be used by other packages without +having to depend on all of Magit, it is documented in its own manual. +See *note (magit-popup)Top::. + +‘C-c C-c’ (‘magit-dispatch-popup’) + + This popup command shows a buffer featuring all other Magit popup + commands as well as some other commands that are not popup commands + themselves. + + This command is also, or especially, useful outside Magit buffers, so +you should setup a global binding: + + (global-set-key (kbd "C-x M-g") 'magit-dispatch-popup) + + +File: magit.info, Node: Completion and confirmation, Next: Running Git, Prev: Popup buffers and prefix commands, Up: Interface concepts + +4.6 Completion and confirmation +=============================== + +Many commands read a value from the user. By default this is done using +the built-in function ‘completing-read’, but Magit can instead use +another completion framework. + + -- User Option: magit-completing-read-function + + The value of this variable is the function used to perform + completion. Because functions _intended_ to replace + ‘completing-read’ often are not fully compatible drop-in + replacements, and also because Magit expects them to add the + default choice to the prompt themselves, such functions should not + be used directly. Instead a wrapper function has to be used. + + Currently only the real ‘completing-read’ and Ido +(http://www.emacswiki.org/emacs/InteractivelyDoThings) are fully +supported. More frameworks will be supported in the future. + + -- Function: magit-builtin-completing-read prompt choices &optional + predicate require-match initial-input hist def + + Perform completion using ‘completion-read’. + + -- Function: magit-ido-completing-read prompt choices &optional + predicate require-match initial-input hist def + + Perform completion using ‘ido-completing-read+’ from the package by + the same name (which you have to explicitly install). Ido itself + comes with a supposed drop-in replacement ‘ido-completing-read’, + but that has too many deficits to serve our needs. + + By default many commands that could potentially lead to data loss +have to be confirmed. This includes many very common commands, so this +can become annoying quickly. Many of these actions can be undone, +provided ‘magit-wip-before-change-mode’ is turned on (which it is not by +default, due to performance concerns). + + -- User Option: magit-no-confirm + + The value of this option is a list of symbols, representing + commands which do not have to be confirmed by the user before being + carried out. + + When the global mode ‘magit-wip-before-change-mode’ is enabled then + many commands can be undone. If that mode is enabled then adding + ‘safe-with-wip’ to this list has the same effect as adding + ‘discard’, ‘reverse’, ‘stage-all-changes’, and + ‘unstage-all-changes’. + + (add-to-list 'magit-no-confirm 'safe-with-wip) + + For a list of all symbols that can be added to the value of this + variable, see the doc-string. + + Note that there are commands that ignore this option and always +require confirmation, or which can be told not to do so using another +dedicated option. Also most commands, when acting on multiple sections +at once always, require confirmation, even when they do respect this +option when acting on a single section. + + +File: magit.info, Node: Running Git, Prev: Completion and confirmation, Up: Interface concepts + +4.7 Running Git +=============== + +* Menu: + +* Viewing Git output:: +* Running Git manually:: +* Git executable:: +* Global Git arguments:: + + +File: magit.info, Node: Viewing Git output, Next: Running Git manually, Up: Running Git + +4.7.1 Viewing Git output +------------------------ + +Magit runs Git either for side-effects (e.g. when pushing) or to get +some value (e.g. the name of the current branch). When Git is run for +side-effects then the output goes into a per-repository log buffer, +which can be consulted when things don’t go as expected. + +‘$’ (‘magit-process’) + + This commands displays the process buffer for the current + repository. + + Inside that buffer, the usual key bindings for navigating and showing +sections are available. There is one additional command. + +‘k’ (‘magit-process-kill’) + + This command kills the process represented by the section at point. + + -- User Option: magit-git-debug + + When this is non-nil then the output of all calls to git are logged + in the process buffer. This is useful when debugging, otherwise it + just negatively affects performance. + + +File: magit.info, Node: Running Git manually, Next: Git executable, Prev: Viewing Git output, Up: Running Git + +4.7.2 Running Git manually +-------------------------- + +While Magit provides many Emacs commands to interact with Git, it does +not cover everything. In those cases your existing Git knowledge will +come in handy. Magit provides some commands for running arbitrary Git +commands by typing them into the minibuffer, instead of having to switch +to a shell. + +‘!’ (‘magit-run-popup’) + + Shows the popup buffer featuring the below suffix commands. + + These suffix commands run a Git subcommand. The user input has to +begin with the subcommand, "git" is assumed. + +‘! !’ (‘magit-git-command-topdir’) + + This command reads a Git subcommand from the user and executes it + in the top-level directory of the current repository. + +‘! p’ (‘magit-git-command’) + + This command reads a Git subcommand from the user and executes it + in ‘default-directory’. With a prefix argument the command is + executed in the top-level directory of the current repository + instead. + + These suffix commands run arbitrary shell commands. + +‘! s’ (‘magit-shell-command-topdir’) + + This command reads a shell command from the user and executes it in + the top-level directory of the current repository. + +‘! S’ (‘magit-shell-command’) + + This command reads a shell command from the user and executes it in + ‘default-directory’. With a prefix argument the command is + executed in the top-level directory of the current repository + instead. + + These suffix commands start external gui tools. + +‘! k’ (‘magit-run-gitk’) + + This command runs ‘gitk’ in the current repository. + +‘! a’ (‘magit-run-gitk-all’) + + This command runs ‘gitk --all’ in the current repository. + +‘! b’ (‘magit-run-gitk-branches’) + + This command runs ‘gitk --branches’ in the current repository. + +‘! g’ (‘magit-run-git-gui’) + + This command runs ‘git gui’ in the current repository. + + +File: magit.info, Node: Git executable, Next: Global Git arguments, Prev: Running Git manually, Up: Running Git + +4.7.3 Git executable +-------------------- + +Except on MS Windows, Magit defaults to running Git without specifying +the path to the git executable. Instead the first executable found by +Emacs on ‘exec-path’ is used (whose value in turn is set based on the +value of the environment variable ‘$PATH’ when Emacs was started). + + This has the advantage that it continues to work even when using +Tramp to connect to a remote machine on which the executable is found in +a different place. The downside is that if you have multiple versions +of Git installed, then you might end up using another version than the +one you think you are using. + +‘M-x magit-version’ (‘magit-version’) + + Shows the currently used versions of Magit, Git, and Emacs in the + echo area. Non-interactively this just returns the Magit version. + + When the ‘system-type’ is ‘windows-nt’, then ‘magit-git-executable’ +is set to an absolute path when Magit is first loaded. This is +necessary because Git on that platform comes with several wrapper +scripts for the actual git binary, which are also placed on ‘$PATH’, and +using one of these wrappers instead of the binary would degrade +performance horribly. + + If Magit doesn’t find the correct executable then you *can* work +around that by setting ‘magit-git-executable’ to an absolute path. But +note that doing so is a kludge. It is better to make sure the order in +the environment variable ‘$PATH’ is correct, and that Emacs is started +with that environment in effect. If you have to connect from Windows to +a non-Windows machine, then you must change the value to "git". + + -- User Option: magit-git-executable + + The git executable used by Magit, either the full path to the + executable or the string "git" to let Emacs find the executable + itself, using the standard mechanism for doing such things. + + +File: magit.info, Node: Global Git arguments, Prev: Git executable, Up: Running Git + +4.7.4 Global Git arguments +-------------------------- + + -- User Option: magit-git-global-arguments + + The arguments set here are used every time the git executable is + run as a subprocess. They are placed right after the executable + itself and before the git command - as in ‘git HERE... COMMAND + REST’. For valid arguments see *note (gitman)git:: . + + Be careful what you add here, especially if you are using Tramp to + connect to servers with ancient Git versions. Never remove + anything that is part of the default value, unless you really know + what you are doing. And think very hard before adding something; + it will be used every time Magit runs Git for any purpose. + + +File: magit.info, Node: Inspecting, Next: Manipulating, Prev: Interface concepts, Up: Top + +5 Inspecting +************ + +The functionality provided by Magit can be roughly divided into three +groups: inspecting existing data, manipulating existing data or adding +new data, and transferring data. Of course that is a rather crude +distinction that often falls short, but it’s more useful than no +distinction at all. This section is concerned with inspecting data, the +next two with manipulating and transferring it. Then follows a section +about miscellaneous functionality, which cannot easily be fit into this +distinction. + + Of course other distinctions make sense too, e.g. Git’s distinction +between porcelain and plumbing commands, which for the most part is +equivalent to Emacs’ distinction between interactive commands and +non-interactive functions. All of the sections mentioned before are +mainly concerned with the porcelain – Magit’s plumbing layer is +described later. + +* Menu: + +* Status buffer:: +* Logging:: +* Diffing:: +* Ediffing:: +* References buffer:: +* Bisecting:: +* Visiting blobs:: +* Blaming:: + + +File: magit.info, Node: Status buffer, Next: Logging, Up: Inspecting + +5.1 Status buffer +================= + +While other Magit buffers contain e.g. one particular diff or one +particular log, the status buffer contains the diffs for staged and +unstaged changes, logs for unpushed and unpulled commits, lists of +stashes and untracked files, and information related to the current +branch. + + During certain incomplete operations – for example when a merge +resulted in a conflict – additional information is displayed that helps +proceeding with or aborting the operation. + + The command ‘magit-status’ displays the status buffer belonging to +the current repository in another window. This command is used so often +that it should be bound globally. We recommend using ‘C-x g’: + + (global-set-key (kbd "C-x g") 'magit-status) + +‘C-x g’ (‘magit-status’) + + Show the status of the current Git repository in a buffer. With a + prefix argument prompt for a repository to be shown. With two + prefix arguments prompt for an arbitrary directory. If that + directory isn’t the root of an existing repository, then offer to + initialize it as a new repository. + + -- User Option: magit-repository-directories + + Directories containing Git repositories. Magit checks these + directories for Git repositories and offers them as choices when + ‘magit-status’ is used with a prefix argument. + + -- User Option: magit-repository-directories-depth + + The maximum depth to look for Git repositories. When looking for a + Git repository below the directories in + ‘magit-repository-directories’, only descend this many levels deep. + + -- Command: ido-enter-magit-status + + From an Ido prompt used to open a file, instead drop into + ‘magit-status’. This is similar to ‘ido-magic-delete-char’, which, + despite its name, usually causes a Dired buffer to be created. + + To make this command available, use something like: + + (add-hook 'ido-setup-hook + (lambda () + (define-key ido-completion-map + (kbd \"C-x g\") 'ido-enter-magit-status))) + + Starting with Emacs 25.1 the Ido keymaps are defined just once + instead of every time Ido is invoked, so now you can modify it like + pretty much every other keymap: + + (define-key ido-common-completion-map + (kbd \"C-x g\") 'ido-enter-magit-status) + +* Menu: + +* Status sections:: +* Status header sections:: +* Status options:: + + +File: magit.info, Node: Status sections, Next: Status header sections, Up: Status buffer + +5.1.1 Status sections +--------------------- + +The contents of status buffers is controlled using the hook +‘magit-status-sections-hook’. See *note Section hooks: Section hooks. +to learn about such hooks and how to customize them. + + -- User Option: magit-status-sections-hook + + Hook run to insert sections into a status buffer. + + The first function on that hook by default is +‘magit-insert-status-headers’; it is described in the next section. By +default the following functions are also members of that hook: + + -- Function: magit-insert-merge-log + + Insert section for the on-going merge. Display the heads that are + being merged. If no merge is in progress, do nothing. + + -- Function: magit-insert-rebase-sequence + + Insert section for the on-going rebase sequence. If no such + sequence is in progress, do nothing. + + -- Function: magit-insert-am-sequence + + Insert section for the on-going patch applying sequence. If no + such sequence is in progress, do nothing. + + -- Function: magit-insert-sequencer-sequence + + Insert section for the on-going cherry-pick or revert sequence. If + no such sequence is in progress, do nothing. + + -- Function: magit-insert-bisect-output + + While bisecting, insert section with output from ‘git bisect’. + + -- Function: magit-insert-bisect-rest + + While bisecting, insert section visualizing the bisect state. + + -- Function: magit-insert-bisect-log + + While bisecting, insert section logging bisect progress. + + -- Function: magit-insert-untracked-files + + Maybe insert a list or tree of untracked files. Do so depending on + the value of ‘status.showUntrackedFiles’. + + -- Function: magit-insert-unstaged-changes + + Insert section showing unstaged changes. + + -- Function: magit-insert-staged-changes + + Insert section showing staged changes. + + -- Function: magit-insert-stashes &optional ref heading + + Insert the ‘stashes’ section showing reflog for "refs/stash". If + optional REF is non-nil show reflog for that instead. If optional + HEADING is non-nil use that as section heading instead of + "Stashes:". + + -- Function: magit-insert-unpulled-from-upstream + + Insert section showing commits that haven’t been pulled from the + upstream branch yet. + + -- Function: magit-insert-unpulled-from-pushremote + + Insert section showing commits that haven’t been pulled from the + push-remote branch yet. + + -- Function: magit-insert-unpushed-to-upstream + + Insert section showing commits that haven’t been pushed to the + upstream yet. + + -- Function: magit-insert-unpushed-to-pushremote + + Insert section showing commits that haven’t been pushed to the + push-remote yet. + + The following functions can also be added to the above hook: + + -- Function: magit-insert-tracked-files + + Insert a tree of tracked files. + + -- Function: magit-insert-unpulled-or-recent-commits + + Insert section showing unpulled or recent commits. If an upstream + is configured for the current branch and it is ahead of the current + branch, then show the missing commits. Otherwise, show the last + ‘magit-log-section-commit-count’ commits. + + -- Function: magit-insert-recent-commits + + Insert section showing the last ‘magit-log-section-commit-count’ + commits. + + -- User Option: magit-log-section-commit-count + + How many recent commits ‘magit-insert-recent-commits’ and + ‘magit-insert-unpulled-or-recent-commits’ (provided there are no + unpulled commits) show. + + -- Function: magit-insert-unpulled-cherries + + Insert section showing unpulled commits. Like + ‘magit-insert-unpulled-commits’ but prefix each commit that has not + been applied yet (i.e. a commit with a patch-id not shared with + any local commit) with "+", and all others with "-". + + -- Function: magit-insert-unpulled-module-commits + + Insert sections for all submodules with unpulled commits. These + sections can be expanded to show the respective commits. + + -- Function: magit-insert-unpushed-cherries + + Insert section showing unpushed commits. Like + ‘magit-insert-unpushed-commits’ but prefix each commit which has + not been applied to upstream yet (i.e. a commit with a patch-id + not shared with any upstream commit) with "+" and all others with + "-". + + -- Function: magit-insert-unpushed-module-commits + + Insert sections for all submodules with unpushed commits. These + sections can be expanded to show the respective commits. + + See *note References buffer: References buffer. for some more section +inserters, which could be used here. + + +File: magit.info, Node: Status header sections, Next: Status options, Prev: Status sections, Up: Status buffer + +5.1.2 Status header sections +---------------------------- + +The contents of status buffers is controlled using the hook +‘magit-status-sections-hook’, as described in the previous section. By +default ‘magit-insert-status-headers’ is the first member of that hook +variable. + + -- Function: magit-insert-status-headers + + Insert headers sections appropriate for ‘magit-status-mode’ + buffers. The sections are inserted by running the functions on the + hook ‘magit-status-headers-hook’. + + -- User Option: magit-status-headers-hook + + Hook run to insert headers sections into the status buffer. + + This hook is run by ‘magit-insert-status-headers’, which in turn + has to be a member of ‘magit-insert-status-sections’ to be used at + all. + + By default the following functions are members of the above hook: + + -- Function: magit-insert-error-header + + Insert a header line showing the message about the Git error that + just occurred. + + This function is only aware of the last error that occur when Git + was run for side-effects. If, for example, an error occurs while + generating a diff, then that error won’t be inserted. Refreshing + the status buffer causes this section to disappear again. + + -- Function: magit-insert-diff-filter-header + + Insert a header line showing the effective diff filters. + + -- Function: magit-insert-head-branch-header + + Insert a header line about the current branch or detached ‘HEAD’. + + -- Function: magit-insert-upstream-branch-header + + Insert a header line about the branch that is usually pulled into + the current branch. + + -- Function: magit-insert-push-branch-header + + Insert a header line about the branch that the current branch is + usually pushed to. + + -- Function: magit-insert-tags-header + + Insert a header line about the current and/or next tag. + + The following functions can also be added to the above hook: + + -- Function: magit-insert-repo-header + + Insert a header line showing the path to the repository top-level. + + -- Function: magit-insert-remote-header + + Insert a header line about the remote of the current branch. + + If no remote is configured for the current branch, then fall back + showing the "origin" remote, or if that does not exist the first + remote in alphabetic order. + + -- Function: magit-insert-user-header + + Insert a header line about the current user. + + +File: magit.info, Node: Status options, Prev: Status header sections, Up: Status buffer + +5.1.3 Status options +-------------------- + + -- User Option: magit-status-refresh-hook + + Hook run after a status buffer has been refreshed. + + -- User Option: magit-log-section-args + + Additional Git arguments used when creating log sections. Only + ‘--graph’, ‘--decorate’, and ‘--show-signature’ are supported. + This option is only a temporary kludge and will be removed. + + Note that due to an issue in Git the use of ‘--graph’ is very slow + with long histories, so you probably don’t want to add this here. + + Also see the proceeding section for more options concerning status +buffers. + + +File: magit.info, Node: Logging, Next: Diffing, Prev: Status buffer, Up: Inspecting + +5.2 Logging +=========== + +The status buffer contains logs for the unpushed and unpulled commits, +but that obviously isn’t enough. The prefix command ‘magit-log-popup’, +on ‘l’, features several suffix commands, which show a specific log in a +separate log buffer. + + Like other popups, the log popup also features several arguments that +can be changed before invoking one of the suffix commands. However in +case of the log popup these arguments correspond to those currently in +use in the current repository’s log buffer. When the log popup is +invoked while no log buffer exists for the current repository yet, then +the default value of ‘magit-log-arguments’ is used instead. + + For information about the various arguments, see *note +(gitman)git-log:: . + + The log popup also features several reflog commands. See *note +Reflog: Reflog. + +‘l’ (‘magit-log-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘l l’ (‘magit-log-current’) + + Show log for the current branch. When ‘HEAD’ is detached or with a + prefix argument, show log for one or more revs read from the + minibuffer. + +‘l o’ (‘magit-log’) + + Show log for one or more revs read from the minibuffer. The user + can input any revision or revisions separated by a space, or even + ranges, but only branches, tags, and a representation of the commit + at point are available as completion candidates. + +‘l h’ (‘magit-log-head’) + + Show log for ‘HEAD’. + +‘l L’ (‘magit-log-branches’) + + Show log for all local branches and ‘HEAD’. + +‘l b’ (‘magit-log-all-branches’) + + Show log for all local and remote branches and ‘HEAD’. + +‘l a’ (‘magit-log-all’) + + Show log for all references and ‘HEAD’. + + The following related commands are not available from the popup. + +‘Y’ (‘magit-cherry’) + + Show commits in a branch that are not merged in the upstream + branch. + +‘M-x magit-log-buffer-file’ (‘magit-log-buffer-file’) + + Show log for the file visited in the current buffer. + +* Menu: + +* Refreshing logs:: +* Log Buffer:: +* Select from log:: +* Reflog:: + + +File: magit.info, Node: Refreshing logs, Next: Log Buffer, Up: Logging + +5.2.1 Refreshing logs +--------------------- + +The prefix command ‘magit-log-refresh-popup’, on ‘L’, can be used to +change the log arguments used in the current buffer, without changing +which log is shown. This works in dedicated log buffers, but also in +the status buffer. + +‘L’ (‘magit-log-refresh-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘L g’ (‘magit-log-refresh’) + + This suffix command sets the local log arguments for the current + buffer. + +‘L s’ (‘magit-log-set-default-arguments’) + + This suffix command sets the default log arguments for buffers of + the same type as that of the current buffer. Other existing + buffers of the same type are not affected because their local + values have already been initialized. + +‘L w’ (‘magit-log-save-default-arguments’) + + This suffix command sets the default log arguments for buffers of + the same type as that of the current buffer, and saves the value + for future sessions. Other existing buffers of the same type are + not affected because their local values have already been + initialized. + +‘L t’ (‘magit-toggle-margin’) + + Show or hide the margin. + + +File: magit.info, Node: Log Buffer, Next: Select from log, Prev: Refreshing logs, Up: Logging + +5.2.2 Log Buffer +---------------- + +‘L’ (‘magit-log-refresh-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. See *note + Refreshing logs: Refreshing logs. + +‘q’ (‘magit-log-bury-buffer’) + + Bury the current buffer or the revision buffer in the same frame. + Like ‘magit-mode-bury-buffer’ (which see) but with a negative + prefix argument instead bury the revision buffer, provided it is + displayed in the current frame. + +‘C-c C-b’ (‘magit-go-backward’) + + Move backward in current buffer’s history. + +‘C-c C-f’ (‘magit-go-forward’) + + Move forward in current buffer’s history. + +‘SPC’ (‘magit-diff-show-or-scroll-up’) + + Update the commit or diff buffer for the thing at point. + + Either show the commit or stash at point in the appropriate buffer, + or if that buffer is already being displayed in the current frame + and contains information about that commit or stash, then instead + scroll the buffer up. If there is no commit or stash at point, + then prompt for a commit. + +‘DEL’ (‘magit-diff-show-or-scroll-down’) + + Update the commit or diff buffer for the thing at point. + + Either show the commit or stash at point in the appropriate buffer, + or if that buffer is already being displayed in the current frame + and contains information about that commit or stash, then instead + scroll the buffer down. If there is no commit or stash at point, + then prompt for a commit. + +‘=’ (‘magit-log-toggle-commit-limit’) + + Toggle the number of commits the current log buffer is limited to. + If the number of commits is currently limited, then remove that + limit. Otherwise set it to 256. + +‘+’ (‘magit-log-double-commit-limit’) + + Double the number of commits the current log buffer is limited to. + +‘=’ (‘magit-log-half-commit-limit’) + + Half the number of commits the current log buffer is limited to. + + -- User Option: magit-log-auto-more + + Insert more log entries automatically when moving past the last + entry. Only considered when moving past the last entry with + ‘magit-goto-*-section’ commands. + + -- User Option: magit-log-show-margin + + Whether to initially show the margin in log buffers. + + When non-nil the author name and date are initially displayed in + the margin of log buffers. The margin can be shown or hidden in + the current buffer using the command ‘magit-toggle-margin’. + + When a log buffer contains a verbose log, then the margin is never + displayed. In status buffers this option is ignored, but it is + possible to show the margin using the mentioned command. + + -- User Option: magit-log-show-refname-after-summary + + Whether to show the refnames after the commit summaries. This is + useful if you use really long branch names. + + +File: magit.info, Node: Select from log, Next: Reflog, Prev: Log Buffer, Up: Logging + +5.2.3 Select from log +--------------------- + +When the user has to select a recent commit that is reachable from +‘HEAD’, using regular completion would be inconvenient (because most +humans cannot remember hashes or "HEAD~5", at least not without double +checking). Instead a log buffer is used to select the commit, which has +the advantage that commits are presented in order and with the commit +message. The following additional key bindings are available when a log +is used for selection: + +‘C-c C-c’ (‘magit-log-select-pick’) + + Select the commit at point and act on it. Call + ‘magit-log-select-pick-function’ with the selected commit as + argument. + +‘C-c C-k’ (‘magit-log-select-quit’) + + Abort selecting a commit, don’t act on any commit. + + This feature is used by rebase and squash commands. + + +File: magit.info, Node: Reflog, Prev: Select from log, Up: Logging + +5.2.4 Reflog +------------ + +Also see *note (gitman)git-reflog:: . + + These reflog commands are available from the log popup. See *note +Logging: Logging. + +‘l r’ (‘magit-reflog-current’) + + Display the reflog of the current branch. + +‘l O’ (‘magit-reflog-other’) + + Display the reflog of a branch. + +‘l H’ (‘magit-reflog-head’) + + Display the ‘HEAD’ reflog. + + +File: magit.info, Node: Diffing, Next: Ediffing, Prev: Logging, Up: Inspecting + +5.3 Diffing +=========== + +The status buffer contains diffs for the staged and unstaged commits, +but that obviously isn’t enough. The prefix command ‘magit-diff-popup’, +on ‘d’, features several suffix commands, which show a specific diff in +a separate diff buffer. + + Like other popups, the diff popup also features several arguments +that can be changed before invoking one of the suffix commands. However +in case of the diff popup these arguments correspond to those currently +in use in the current repository’s diff buffer. When the diff popup is +invoked while no diff buffer exists for the current repository yet, then +the default value of ‘magit-diff-arguments’ is used instead. + + Also see *note (gitman)git-diff:: . + +‘d’ (‘magit-diff-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘d d’ (‘magit-diff-dwim’) + + Show changes for the thing at point. + +‘d r’ (‘magit-diff’) + + Show differences between two commits. + + RANGE should be a range (A..B or A…B) but can also be a single + commit. If one side of the range is omitted, then it defaults to + HEAD. If just a commit is given, then changes in the working tree + relative to that commit are shown. + + If the region is active, use the revisions on the first and last + line of the region. With a prefix argument, instead of diffing the + revisions, choose a revision to view changes along, starting at the + common ancestor of both revisions (i.e., use a "…" range). + +‘d w’ (‘magit-diff-worktree’) + + Show changes between the current working tree and the ‘HEAD’ + commit. With a prefix argument show changes between the working + tree and a commit read from the minibuffer. + +‘d s’ (‘magit-diff-staged’) + + Show changes between the index and the ‘HEAD’ commit. With a + prefix argument show changes between the index and a commit read + from the minibuffer. + +‘d u’ (‘magit-diff-unstaged’) + + Show changes between the working tree and the index. + +‘d p’ (‘magit-diff-paths’) + + Show changes between any two files on disk. + + All of the above suffix commands update the repository’s diff buffer. +The diff popup also features two commands which show differences in +another buffer: + +‘d c’ (‘magit-show-commit’) + + Show the commit at point. If there is no commit at point or with a + prefix argument, prompt for a commit. + +‘d t’ (‘magit-stash-show’) + + Show all diffs of a stash in a buffer. + +* Menu: + +* Refreshing diffs:: +* Diff buffer:: +* Diff options:: +* Revision buffer:: + + +File: magit.info, Node: Refreshing diffs, Next: Diff buffer, Up: Diffing + +5.3.1 Refreshing diffs +---------------------- + +The prefix command ‘magit-diff-refresh-popup’, on ‘D’, can be used to +change the diff arguments used in the current buffer, without changing +which diff is shown. This works in dedicated diff buffers, but also in +the status buffer. + +‘D’ (‘magit-diff-refresh-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘D g’ (‘magit-diff-refresh’) + + This suffix command sets the local diff arguments for the current + buffer. + +‘D s’ (‘magit-diff-set-default-arguments’) + + This suffix command sets the default diff arguments for buffers of + the same type as that of the current buffer. Other existing + buffers of the same type are not affected because their local + values have already been initialized. + +‘D w’ (‘magit-diff-save-default-arguments’) + + This suffix command sets the default diff arguments for buffers of + the same type as that of the current buffer, and saves the value + for future sessions. Other existing buffers of the same type are + not affected because their local values have already been + initialized. + +‘D t’ (‘magit-diff-toggle-refine-hunk’) + + This command toggles hunk refinement on or off. + +‘D r’ (‘magit-diff-switch-range-type’) + + This command converts the diff range type from "revA..revB" to + "revB…revA", or vice versa. + +‘D f’ (‘magit-diff-flip-revs’) + + This command swaps revisions in the diff range from "revA..revB" to + "revB..revA", or vice versa. + + In addition to the above popup, which allows changing any of the +supported arguments, there also exist some commands which change a +particular argument. + +‘-’ (‘magit-diff-less-context’) + + This command decreases the context for diff hunks by COUNT lines. + +‘+’ (‘magit-diff-more-context’) + + This command increases the context for diff hunks by COUNT lines. + +‘0’ (‘magit-diff-default-context’) + + This command resets the context for diff hunks to the default + height. + + The following commands quickly change what diff is being displayed +without having to using one of the diff popups. + +‘C-c C-d’ (‘magit-diff-while-committing’) + + While committing, this command shows the changes that are about to + be committed. While amending, invoking the command again toggles + between showing just the new changes or all the changes that will + be committed. + + This binding is available in the diff buffer as well as the commit + message buffer. + +‘C-c C-b’ (‘magit-go-backward’) + + This command moves backward in current buffer’s history. + +‘C-c C-f’ (‘magit-go-forward’) + + This command moves forward in current buffer’s history. + + +File: magit.info, Node: Diff buffer, Next: Diff options, Prev: Refreshing diffs, Up: Diffing + +5.3.2 Diff buffer +----------------- + +‘RET’ (‘magit-diff-visit-file’) + + From a diff, visit the corresponding file at the appropriate + position. + + When the file is already being displayed in another window of the + same frame, then just select that window and adjust point. With a + prefix argument also display in another window. + + If the diff shows changes in the worktree, the index, or ‘HEAD’, + then visit the actual file. Otherwise when the diff is about an + older commit, then visit the respective blob using + ‘magit-find-file’. Also see ‘magit-diff-visit-file-worktree’, + which, as the name suggests, always visits the actual file. + +‘C-’ (‘magit-diff-visit-file-worktree’) + + From a diff, visit the corresponding file at the appropriate + position. + + When the file is already being displayed in another window of the + same frame, then just select that window and adjust point. With a + prefix argument also display in another window. + + The actual file in the worktree is visited. The positions in the + hunk headers get less useful the "older" the changes are, and as a + result, jumping to the appropriate position gets less reliable. + + Also see ‘magit-diff-visit-file-worktree’, which visits the + respective blob, unless the diff shows changes in the worktree, the + index, or ‘HEAD’. + +‘j’ (‘magit-jump-to-diffstat-or-diff’) + + Jump to the diffstat or diff. When point is on a file inside the + diffstat section, then jump to the respective diff section. + Otherwise, jump to the diffstat section or a child thereof. + +‘SPC’ (‘scroll-up’) + + Scroll text upward. + +‘DEL’ (‘scroll-down’) + + Scroll text downward. + + +File: magit.info, Node: Diff options, Next: Revision buffer, Prev: Diff buffer, Up: Diffing + +5.3.3 Diff options +------------------ + + -- User Option: magit-diff-refine-hunk + + Whether to show word-granularity differences within diff hunks. + + • ‘nil’ never show fine differences. + + • ‘t’ show fine differences for the current diff hunk only. + + • ‘all’ show fine differences for all displayed diff hunks. + + -- User Option: magit-diff-paint-whitespace + + Specify where to highlight whitespace errors. + + See ‘magit-highlight-trailing-whitespace’, + ‘magit-highlight-indentation’. The symbol ‘t’ means in all diffs, + ‘status’ means only in the status buffer, and nil means nowhere. + + -- User Option: magit-diff-highlight-trailing + + Whether to highlight whitespace at the end of a line in diffs. + Used only when ‘magit-diff-paint-whitespace’ is non-nil. + + -- User Option: magit-diff-highlight-indentation + + Highlight the "wrong" indentation style. Used only when + ‘magit-diff-paint-whitespace’ is non-nil. + + The value is a list of cons cells. The car is a regular + expression, and the cdr is the value that applies to repositories + whose directory matches the regular expression. If more than one + element matches, then the *last* element in the list applies. The + default value should therefore come first in the list. + + If the value is ‘tabs’, highlight indentation with tabs. If the + value is an integer, highlight indentation with at least that many + spaces. Otherwise, highlight neither. + + +File: magit.info, Node: Revision buffer, Prev: Diff options, Up: Diffing + +5.3.4 Revision buffer +--------------------- + + -- User Option: magit-revision-insert-related-refs + + Whether to show related refs in revision buffers. + + -- User Option: magit-revision-show-gravatar + + Whether to show gravatar images in revision buffers. + + If non-nil, then the value has to be a cons-cell which specifies + where the gravatar images for the author and/or the committer are + inserted inside the text that was previously inserted according to + ‘magit-revision-header-format’. + + Both cells are regular expressions. The car specifies where to + insert the author gravatar image. The top halve of the image is + inserted right after the matched text, the bottom halve on the next + line at the same offset. The cdr specifies where to insert the + committer image, accordingly. Either the car or the cdr may be + nil. + + +File: magit.info, Node: Ediffing, Next: References buffer, Prev: Diffing, Up: Inspecting + +5.4 Ediffing +============ + +‘e’ (‘magit-ediff-dwim’) + + Compare, stage, or resolve using Ediff. + + This command tries to guess what file, and what commit or range the + user wants to compare, stage, or resolve using Ediff. It might + only be able to guess either the file, or range/commit, in which + case the user is asked about the other. It might not always guess + right, in which case the appropriate ‘magit-ediff-*’ command has to + be used explicitly. If it cannot read the user’s mind at all, then + it asks the user for a command to run. + +‘E’ (‘magit-ediff-popup’) + + This prefix command shows the following suffix commands in a popup + buffer. + +‘E r’ (‘magit-ediff-compare’) + + Compare two revisions of a file using Ediff. + + If the region is active, use the revisions on the first and last + line of the region. With a prefix argument, instead of diffing the + revisions, choose a revision to view changes along, starting at the + common ancestor of both revisions (i.e., use a "…" range). + +‘E m’ (‘magit-ediff-resolve’) + + Resolve outstanding conflicts in a file using Ediff, defaulting to + the file at point. + + Provided that the value of ‘merge.conflictstyle’ is ‘diff3’, you + can view the file’s merge-base revision using ‘/’ in the Ediff + control buffer. + + In the rare event that you want to manually resolve all conflicts, + including those already resolved by Git, use + ‘ediff-merge-revisions-with-ancestor’. + +‘E s’ (‘magit-ediff-stage’) + + Stage and unstage changes to a file using Ediff, defaulting to the + file at point. + +‘E u’ (‘magit-ediff-show-unstaged’) + + Show unstaged changes to a file using Ediff. + +‘E i’ (‘magit-ediff-show-staged’) + + Show staged changes to a file using Ediff. + +‘E w’ (‘magit-ediff-show-working-tree’) + + Show changes in a file between HEAD and working tree using Ediff. + +‘E c’ (‘magit-ediff-show-commit’) + + Show changes to a file introduced by a commit using Ediff. + + -- User Option: magit-ediff-dwim-show-on-hunks + + This option controls what command ‘magit-ediff-dwim’ calls when + point is on uncommitted hunks. When nil, always run + ‘magit-ediff-stage’. Otherwise, use ‘magit-ediff-show-staged’ and + ‘magit-ediff-show-unstaged’ to show staged and unstaged changes, + respectively. + + -- User Option: magit-ediff-quit-hook + + This hook is run after quitting an Ediff session that was created + using a Magit command. The hook functions are run inside the Ediff + control buffer, and should not change the current buffer. + + This is similar to ‘ediff-quit-hook’ but takes the needs of Magit + into account. The regular ‘ediff-quit-hook’ is ignored by Ediff + sessions that were created using a Magit command. + + +File: magit.info, Node: References buffer, Next: Bisecting, Prev: Ediffing, Up: Inspecting + +5.5 References buffer +===================== + +‘y’ (‘magit-show-refs-popup’) + + List and compare references in a dedicated buffer. By default all + refs are compared with ‘HEAD’, but with a prefix argument this + command instead acts as a prefix command and shows the following + suffix commands along with the appropriate infix arguments in a + popup buffer. + +‘y y’ (‘magit-show-refs-head’) + + List and compare references in a dedicated buffer. Refs are + compared with ‘HEAD’. + +‘y c’ (‘magit-show-refs-current’) + + List and compare references in a dedicated buffer. Refs are + compared with the current branch or ‘HEAD’ if it is detached. + +‘y o’ (‘magit-show-refs’) + + List and compare references in a dedicated buffer. Refs are + compared with a branch read from the user. + + -- User Option: magit-refs-show-commit-count + + Whether to show commit counts in Magit-Refs mode buffers. + + • ‘all’ Show counts for branches and tags. + + • ‘branch’ Show counts for branches only. + + • ‘nil’ Never show counts. + The default is ‘nil’ because anything else can be very expensive. + + -- User Option: magit-refs-show-margin + + Whether to initially show the margin in refs buffers. + + When non-nil the committer name and date are initially displayed in + the margin of refs buffers. The margin can be shown or hidden in + the current buffer using the command ‘magit-toggle-margin’. + + The following variables control how individual refs are displayed. +If you change one of these variables (especially the "%c" part), then +you should also change the others to keep things aligned. The following +%-sequences are supported: + + • ‘%a’ Number of commits this ref has over the one we compare to. + + • ‘%b’ Number of commits the ref we compare to has over this one. + + • ‘%c’ Number of commits this ref has over the one we compare to. + For the ref which all other refs are compared this is instead "@", + if it is the current branch, or "#" otherwise. + + • ‘%C’ For the ref which all other refs are compared this is "@", if + it is the current branch, or "#" otherwise. For all other refs " + ". + + • ‘%h’ Hash of this ref’s tip. + + • ‘%m’ Commit summary of the tip of this ref. + + • ‘%n’ Name of this ref. + + • ‘%u’ Upstream of this local branch and additional local vs. + upstream information. + + • ‘%U’ Upstream of this local branch. + + -- Variable: magit-refs-local-branch-format + + Format used for local branches in refs buffers. + + -- Variable: magit-refs-remote-branch-format + + Format used for remote branches in refs buffers. + + -- Variable: magit-refs-tags-format + + Format used for tags in refs buffers. + + -- Variable: magit-refs-indent-cherry-lines + + Indentation of cherries in refs buffers. This should be N-1 where + N is taken from "%Nc" in the above format strings. + + Everywhere in Magit ‘RET’ visits the thing represented by the section +at point. In almost all cases visiting is done by showing some +information in another buffer and *not* doing anything else. In refs +buffers ‘RET’ behaves differently, and because many users have grown +accustomed to that inconsistency we are keeping it that way. + +‘RET’ (‘magit-visit-ref’) + + Everywhere except in refs buffers this command behaves exactly like + ‘magit-show-commit’; it shows the commit at point in another + buffer. + + In refs buffers, when there is a local branch at point, then this + command instead checks out that branch. When there is a remote + branch or a tag at point then the respective commit is checked out + causing ‘HEAD’ to be detached. + + When a prefix argument it used, then this command only *focuses* on + the reference at point, i.e. the commit counts and cherries are + updated to be relative to that reference, but nothing is checked + out. + + -- User Option: magit-visit-ref-create + + When this is non-nil and ‘magit-visit-ref’ is called inside a refs + buffer, then it "visits" the remote branch at point by creating a + new local branch which tracks that remote branch and then checking + out the newly created branch. + + This is not enabled by default because one has to use an extremely + loose definition of the verb "to visit" to be able to argue that + creating and then checking out a new local branch is a form of + visiting a remote branch. + +* Menu: + +* References sections:: + + +File: magit.info, Node: References sections, Up: References buffer + +5.5.1 References sections +------------------------- + +The contents of references buffers is controlled using the hook +‘magit-refs-sections-hook’. See *note Section hooks: Section hooks. to +learn about such hooks and how to customize them. All of the below +functions are members of the default value. Note that it makes much +less sense to customize this hook than it does for the respective hook +used for the status buffer. + + -- User Option: magit-refs-sections-hook + + Hook run to insert sections into a references buffer. + + -- Function: magit-insert-local-branches + + Insert sections showing all local branches. + + -- Function: magit-insert-remote-branches + + Insert sections showing all remote-tracking branches. + + -- Function: magit-insert-tags + + Insert sections showing all tags. + + +File: magit.info, Node: Bisecting, Next: Visiting blobs, Prev: References buffer, Up: Inspecting + +5.6 Bisecting +============= + +Also see *note (gitman)git-bisect:: . + +‘B’ (‘magit-bisect-popup’) + + This prefix command shows the following suffix commands in a popup + buffer. + + When bisecting is not in progress, then the popup buffer features the +following commands. + +‘B s’ (‘magit-bisect-start’) + + Start a bisect session. + + Bisecting a bug means to find the commit that introduced it. This + command starts such a bisect session by asking for a known good and + a bad commit. + +‘B u’ (‘magit-bisect-run’) + + Bisect automatically by running commands after each step. + + When bisecting is in progress, then the popup buffer features these +commands instead. + +‘B b’ (‘magit-bisect-bad’) + + Mark the current commit as bad. Use this after you have asserted + that the commit does contain the bug in question. + +‘B g’ (‘magit-bisect-good’) + + Mark the current commit as good. Use this after you have asserted + that the commit does not contain the bug in question. + +‘B k’ (‘magit-bisect-skip’) + + Skip the current commit. Use this if for some reason the current + commit is not a good one to test. This command lets Git choose a + different one. + +‘B r’ (‘magit-bisect-reset’) + + After bisecting, cleanup bisection state and return to original + ‘HEAD’. + + +File: magit.info, Node: Visiting blobs, Next: Blaming, Prev: Bisecting, Up: Inspecting + +5.7 Visiting blobs +================== + +‘M-x magit-find-file’ (‘magit-find-file’) + + View FILE from REV. Switch to a buffer visiting blob REV:FILE, + creating one if none already exists. + +‘M-x magit-find-file-other-window’ (‘magit-find-file-other-window’) + + View FILE from REV, in another window. Like ‘magit-find-file’, but + create a new window or reuse an existing one. + + +File: magit.info, Node: Blaming, Prev: Visiting blobs, Up: Inspecting + +5.8 Blaming +=========== + +Also see *note (gitman)git-blame:: . + +‘M-x magit-blame’ (‘magit-blame’) + + Display edit history of FILE up to REVISION. + + Interactively blame the file being visited in the current buffer. + If the buffer visits a revision of that file, then blame up to that + revision. Otherwise, blame the file’s full history, including + uncommitted changes. + + If Magit-Blame mode is already turned on then blame recursively, by + visiting REVISION:FILE (using ‘magit-find-file’), where revision is + the revision before the revision that added the lines at point. + + ARGS is a list of additional arguments to pass to ‘git blame’; only + arguments available from ‘magit-blame-popup’ should be used. + +‘M-x magit-blame-popup’ (‘magit-blame-popup’) + + This prefix command shows the above suffix command along with the + appropriate infix arguments in a popup buffer. + +‘RET’ (‘magit-show-commit’) + + Show the commit at point. If there is no commit at point or with a + prefix argument, prompt for a commit. + +‘SPC’ (‘magit-diff-show-or-scroll-up’) + + Update the commit or diff buffer for the thing at point. + + Either show the commit or stash at point in the appropriate buffer, + or if that buffer is already being displayed in the current frame + and contains information about that commit or stash, then instead + scroll the buffer up. If there is no commit or stash at point, + then prompt for a commit. + +‘DEL’ (‘magit-diff-show-or-scroll-down’) + + Update the commit or diff buffer for the thing at point. + + Either show the commit or stash at point in the appropriate buffer, + or if that buffer is already being displayed in the current frame + and contains information about that commit or stash, then instead + scroll the buffer down. If there is no commit or stash at point, + then prompt for a commit. + +‘n’ (‘magit-blame-next-chunk’) + + Move to the next chunk. + +‘N’ (‘magit-blame-next-chunk-same-commit’) + + Move to the next chunk from the same commit. + +‘p’ (‘magit-blame-previous-chunk’) + + Move to the previous chunk. + +‘P’ (‘magit-blame-previous-chunk-same-commit’) + + Move to the previous chunk from the same commit. + +‘q’ (‘magit-blame-quit’) + + Turn off Magit-Blame mode. If the buffer was created during a + recursive blame, then also kill the buffer. + +‘M-w’ (‘magit-blame-copy-hash’) + + Save the hash of the current chunk’s commit to the kill ring. + +‘t’ (‘magit-blame-toggle-headings’) + + Show or hide blame chunk headings. + + -- User Option: magit-blame-heading-format + + Format string used for blame headings. + + -- User Option: magit-blame-time-format + + Format string used for time strings in blame headings. + + -- User Option: magit-blame-show-headings + + Whether to initially show blame block headings. The headings can + also be toggled locally using command + ‘magit-blame-toggle-headings’. + + -- User Option: magit-blame-goto-chunk-hook + + Hook run by ‘magit-blame-next-chunk’ and + ‘magit-blame-previous-chunk’. + + +File: magit.info, Node: Manipulating, Next: Transferring, Prev: Inspecting, Up: Top + +6 Manipulating +************** + +* Menu: + +* Repository setup:: +* Staging and unstaging:: +* Applying:: +* Committing:: +* Branching:: +* Merging:: +* Rebasing:: +* Cherry picking:: +* Resetting:: +* Stashing:: + + +File: magit.info, Node: Repository setup, Next: Staging and unstaging, Up: Manipulating + +6.1 Repository setup +==================== + +‘M-x magit-init’ (‘magit-init’) + + This command initializes a repository and then shows the status + buffer for the new repository. + + If the directory is below an existing repository, then the user has + to confirm that a new one should be created inside. If the + directory is the root of the existing repository, then the user has + to confirm that it should be reinitialized. + +‘M-x magit-clone’ (‘magit-clone’) + + This command clones a repository and then shows the status buffer + for the new repository. + + The user is queried for a remote url and a local directory. + + -- User Option: magit-clone-set-branch.pushDefault + + Whether to set the value of ‘branch.pushDefault’ after cloning. + + If ‘t’, then set without asking. If ‘nil’, then don’t set. If + ‘ask’, then ask the user every time she clones a repository. + + +File: magit.info, Node: Staging and unstaging, Next: Applying, Prev: Repository setup, Up: Manipulating + +6.2 Staging and unstaging +========================= + +Like Git, Magit can of course stage and unstage complete files. Unlike +Git, it also allows users to gracefully un-/stage individual hunks and +even just part of a hunk. To stage individual hunks and parts of hunks +using Git directly, one has to use the very modal and rather clumsy +interface of a ‘git add --interactive’ session. + + With Magit, on the other hand, one can un-/stage individual hunks by +just moving point into the respective section inside a diff displayed in +the status buffer or a separate diff buffer and typing ‘s’ or ‘u’. To +operate on just parts of a hunk, mark the changes that should be +un-/staged using the region and then press the same key that would be +used to un-/stage. To stage multiple files or hunks at once use a +region that starts inside the heading of such a section and ends inside +the heading of a sibling section of the same type. + + Besides staging and unstaging, Magit also provides several other +"apply variants" that can also operate on a file, multiple files at +once, a hunk, multiple hunks at once, and on parts of a hunk. These +apply variants are described in the next section. + +‘s’ (‘magit-stage’) + + Add the change at point to the staging area. + +‘S’ (‘magit-stage-modified’) + + Stage all changes to files modified in the worktree. Stage all new + content of tracked files and remove tracked files that no longer + exist in the working tree from the index also. With a prefix + argument also stage previously untracked (but not ignored) files. + +‘u’ (‘magit-unstage’) + + Remove the change at point from the staging area. + +‘U’ (‘magit-unstage-all’) + + Remove all changes from the staging area. + +‘M-x magit-reset-index’ (‘magit-reset-index’) + + Reset the index to some commit. The commit is read from the user + and defaults to the commit at point. If there is no commit at + point, then it defaults to ‘HEAD’. + + To stage a smaller unit than a range of lines, similar to ‘git add +--patch’ followed by ‘e’ would do, then you can use ‘magit-ediff-stage’ +to do so. + +* Menu: + +* Staging from file-visiting buffers:: + + +File: magit.info, Node: Staging from file-visiting buffers, Up: Staging and unstaging + +6.2.1 Staging from file-visiting buffers +---------------------------------------- + +Fine-grained un-/staging has to be done from the status or a diff +buffer, but it’s also possible to un-/stage all changes made to the file +visited in the current buffer right from inside that buffer. + +‘M-x magit-stage-file’ (‘magit-stage-file’) + + When invoked inside a file-visiting buffer, then stage all changes + to that file. In a Magit buffer, stage the file at point if any. + Otherwise prompt for a file to be staged. With a prefix argument + always prompt the user for a file, even in a file-visiting buffer + or when there is a file section at point. + +‘M-x magit-unstage-file’ (‘magit-unstage-file’) + + When invoked inside a file-visiting buffer, then unstage all + changes to that file. In a Magit buffer, unstage the file at point + if any. Otherwise prompt for a file to be unstaged. With a prefix + argument always prompt the user for a file, even in a file-visiting + buffer or when there is a file section at point. + + +File: magit.info, Node: Applying, Next: Committing, Prev: Staging and unstaging, Up: Manipulating + +6.3 Applying +============ + +Magit provides several "apply variants": stage, unstage, discard, +reverse, and "regular apply". At least when operating on a hunk they +are all implemented using ‘git apply’, which is why they are called +"apply variants". + + • Stage. Apply a change from the working tree to the index. The + change also remains in the working tree. + + • Unstage. Remove a change from the index. The change remains in + the working tree. + + • Discard. On a staged change, remove it from the working tree and + the index. On an unstaged change, remove it from the working tree + only. + + • Reverse. Reverse a change in the working tree. Both committed and + staged changes can be reversed. Unstaged changes cannot be + reversed. Discard them instead. + + • Apply. Apply a change to the working tree. Both committed and + staged changes can be applied. Unstaged changes cannot be applied + - as they already have been applied. + + The previous section described the staging and unstaging commands. +What follows are the commands which implement the remaining apply +variants. + +‘a’ (‘magit-apply’) + + Apply the change at point to the working tree. + +‘k’ (‘magit-discard’) + + Remove the change at point from the working tree. + +‘v’ (‘magit-reverse’) + + Reverse the change at point in the working tree. + + With a prefix argument all apply variants attempt a 3-way merge when +appropriate (i.e. when ‘git apply’ is used internally). + + +File: magit.info, Node: Committing, Next: Branching, Prev: Applying, Up: Manipulating + +6.4 Committing +============== + +When the user initiates a commit, Magit calls ‘git commit’ without any +arguments, so Git has to get it from the user. It creates the file +‘.git/COMMIT_EDITMSG’ and then opens that file in an editor. Magit +arranges for that editor to be the Emacsclient. Once the user finishes +the editing session, the Emacsclient exits and Git creates the commit +using the file’s content as message. + +* Menu: + +* Initiating a commit:: +* Editing commit messages:: + + +File: magit.info, Node: Initiating a commit, Next: Editing commit messages, Up: Committing + +6.4.1 Initiating a commit +------------------------- + +Also see *note (gitman)git-commit:: . + +‘c’ (‘magit-commit-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘c c’ (‘magit-commit’) + + Create a new commit on ‘HEAD’. With a prefix argument amend to the + commit at ‘HEAD’ instead. + +‘c a’ (‘magit-commit-amend’) + + Amend the last commit. + +‘c e’ (‘magit-commit-extend’) + + Amend the last commit, without editing the message. With a prefix + argument keep the committer date, otherwise change it. The option + ‘magit-commit-extend-override-date’ can be used to inverse the + meaning of the prefix argument. + + Non-interactively respect the optional OVERRIDE-DATE argument and + ignore the option. + +‘c w’ (‘magit-commit-reword’) + + Reword the last commit, ignoring staged changes. With a prefix + argument keep the committer date, otherwise change it. The option + ‘magit-commit-reword-override-date’ can be used to inverse the + meaning of the prefix argument. + + Non-interactively respect the optional OVERRIDE-DATE argument and + ignore the option. + +‘c f’ (‘magit-commit-fixup’) + + Create a fixup commit. + + With a prefix argument the target commit has to be confirmed. + Otherwise the commit at point may be used without confirmation + depending on the value of option ‘magit-commit-squash-confirm’. + +‘c F’ (‘magit-commit-instant-fixup’) + + Create a fixup commit and instantly rebase. + +‘c s’ (‘magit-commit-squash’) + + Create a squash commit, without editing the squash message. + + With a prefix argument the target commit has to be confirmed. + Otherwise the commit at point may be used without confirmation + depending on the value of option ‘magit-commit-squash-confirm’. + +‘c S’ (‘magit-commit-instant-squash’) + + Create a squash commit and instantly rebase. + +‘c A’ (‘magit-commit-augment’) + + Create a squash commit, editing the squash message. + + With a prefix argument the target commit has to be confirmed. + Otherwise the commit at point may be used without confirmation + depending on the value of option ‘magit-commit-squash-confirm’. + + -- User Option: magit-commit-ask-to-stage + + Whether to ask to stage everything when committing and nothing is + staged. + + -- User Option: magit-commit-extend-override-date + + Whether using ‘magit-commit-extend’ changes the committer date. + + -- User Option: magit-commit-reword-override-date + + Whether using ‘magit-commit-reword’ changes the committer date. + + -- User Option: magit-commit-squash-confirm + + Whether the commit targeted by squash and fixup has to be + confirmed. When non-nil then the commit at point (if any) is used + as default choice. Otherwise it has to be confirmed. This option + only affects ‘magit-commit-squash’ and ‘magit-commit-fixup’. The + "instant" variants always require confirmation because making an + error while using those is harder to recover from. + + +File: magit.info, Node: Editing commit messages, Prev: Initiating a commit, Up: Committing + +6.4.2 Editing commit messages +----------------------------- + +After initiating a commit as described in the previous section, two new +buffers appear. One shows the changes that are about to committed, +while the other is used to write the message. All regular editing +commands are available in the commit message buffer. This section only +describes the additional commands. + + Commit messages are edited in an edit session - in the background Git +is waiting for the editor, in our case the Emacsclient, to save the +commit message in a file (in most cases ‘.git/COMMIT_EDITMSG’) and then +return. If the Emacsclient returns with a non-zero exit status then Git +does not create the commit. So the most important commands are those +for finishing and aborting the commit. + +‘C-c C-c’ (‘with-editor-finish’) + + Finish the current editing session by returning with exit code 0. + Git then creates the commit using the message it finds in the file. + +‘C-c C-k’ (‘with-editor-cancel’) + + Cancel the current editing session by returning with exit code 1. + Git then cancels the commit, but leaves the file untouched. + + In addition to being used by Git, these messages may also be stored +in a ring that persists until Emacs is closed. By default the message +is stored at the beginning and the end of an edit session (regardless of +whether the session is finished successfully or was canceled). It is +sometimes useful to bring back messages from that ring. + +‘C-s M-s’ (‘git-commit-save-message’) + + Save the current buffer content to the commit message ring. + +‘M-p’ (‘git-commit-prev-message’) + + Cycle backward through the commit message ring, after saving the + current message to the ring. With a numeric prefix ARG, go back + ARG comments. + +‘M-n’ (‘git-commit-next-message’) + + Cycle forward through the commit message ring, after saving the + current message to the ring. With a numeric prefix ARG, go back + ARG comments. + + By default the diff for the changes that are about to be committed +are automatically shown when invoking the commit. When amending to an +existing commit it may be useful to show either the changes that are +about to be added to that commit or to show those changes together with +those that are already committed. + +‘C-c C-d’ (‘magit-diff-while-committing’) + + While committing, show the changes that are about to be committed. + While amending, invoking the command again toggles between showing + just the new changes or all the changes that will be committed. + +‘C-c C-w’ (‘magit-pop-revision-stack’) + + This command inserts a representation of a revision into the + current buffer. It can be used inside buffers used to write commit + messages but also in other buffers such as buffers used to edit + emails or ChangeLog files. + + By default this command pops the revision which was last added to + the ‘magit-revision-stack’ and inserts it into the current buffer + according to ‘magit-pop-revision-stack-format’. Revisions can be + put on the stack using ‘magit-copy-section-value’ and + ‘magit-copy-buffer-revision’. + + If the stack is empty or with a prefix argument it instead reads a + revision in the minibuffer. By using the minibuffer history this + allows selecting an item which was popped earlier or to insert an + arbitrary reference or revision without first pushing it onto the + stack. + + When reading the revision from the minibuffer, then it might not be + possible to guess the correct repository. When this command is + called inside a repository (e.g. while composing a commit + message), then that repository is used. Otherwise (e.g. while + composing an email) then the repository recorded for the top + element of the stack is used (even though we insert another + revision). If not called inside a repository and with an empty + stack, or with two prefix arguments, then read the repository in + the minibuffer too. + + -- User Option: magit-pop-revision-stack-format + + This option controls how the command ‘magit-pop-revision-stack’ + inserts a revision into the current buffer. + + The entries on the stack have the format ‘(HASH TOPLEVEL)’ and this + option has the format ‘(POINT-FORMAT EOB-FORMAT INDEX-REGEXP)’, all + of which may be nil or a string (though either one of EOB-FORMAT or + POINT-FORMAT should be a string, and if INDEX-REGEXP is non-nil, + then the two formats should be too). + + First INDEX-REGEXP is used to find the previously inserted entry, + by searching backward from point. The first submatch must match + the index number. That number is incremented by one, and becomes + the index number of the entry to be inserted. If you don’t want to + number the inserted revisions, then use nil for INDEX-REGEXP. + + If INDEX-REGEXP is non-nil then both POINT-FORMAT and EOB-FORMAT + should contain \"%N\", which is replaced with the number that was + determined in the previous step. + + Both formats, if non-nil and after removing %N, are then expanded + using ‘git show –format=FORMAT …’ inside TOPLEVEL. + + The expansion of POINT-FORMAT is inserted at point, and the + expansion of EOB-FORMAT is inserted at the end of the buffer (if + the buffer ends with a comment, then it is inserted right before + that). + + Some projects use pseudo headers in commit messages. Magit colorizes +such headers and provides some commands to insert such headers. + + -- User Option: git-commit-known-pseudo-headers + + A list of Git pseudo headers to be highlighted. + +‘C-c C-a’ (‘git-commit-ack’) + + Insert a header acknowledging that you have looked at the commit. + +‘C-c C-r’ (‘git-commit-review’) + + Insert a header acknowledging that you have reviewed the commit. + +‘C-c C-s’ (‘git-commit-signoff’) + + Insert a header to sign off the commit. + +‘C-c C-t’ (‘git-commit-test’) + + Insert a header acknowledging that you have tested the commit. + +‘C-c C-o’ (‘git-commit-cc’) + + Insert a header mentioning someone who might be interested. + +‘C-c C-p’ (‘git-commit-reported’) + + Insert a header mentioning the person who reported the issue being + fixed by the commit. + +‘C-c C-i’ (‘git-commit-suggested’) + + Insert a header mentioning the person who suggested the change. + + ‘git-commit-mode’ is a minor mode that is only used to establish the +above key bindings. This allows using an arbitrary major mode when +editing the commit message. It’s even possible to use a different major +mode in different repositories, which is useful when different projects +impose different commit message conventions. + + -- User Option: git-commit-major-mode + + The value of this option is the major mode used to edit Git commit + messages. + + Because ‘git-commit-mode’ is a minor mode, we don’t use its mode hook +to setup the buffer, except for the key bindings. All other setup +happens in the function ‘git-commit-setup’, which among other things +runs the hook ‘git-commit-setup-hook’. The following functions are +suitable for that hook. + + -- User Option: git-commit-setup-hook + + Hook run at the end of ‘git-commit-setup’. + + -- Function: magit-revert-buffers &optional force + + Revert unmodified file-visiting buffers of the current repository. + + If either ‘magit-revert-buffers’ is non-nil and + ‘inhibit-magit-revert’ is nil, or if optional FORCE is non-nil, + then revert all unmodified buffers that visit files being tracked + in the current repository. + + -- Function: git-commit-save-message + + Save the current buffer content to the commit message ring. + + -- Function: git-commit-setup-changelog-support + + After this function is called, ChangeLog entries are treated as + paragraphs. + + -- Function: git-commit-turn-on-auto-fill + + Turn on ‘auto-fill-mode’ and set ‘fill-column’ to the value of + ‘git-commit-fill-column’. + + -- Function: git-commit-turn-on-flyspell + + Turn on Flyspell mode. Also prevent comments from being checked + and finally check current non-comment text. + + -- Function: git-commit-propertize-diff + + Propertize the diff shown inside the commit message buffer. Git + inserts such diffs into the commit message template when the + ‘--verbose’ argument is used. Magit’s commit popup by default does + not offer that argument because the diff that is shown in a + separate buffer is more useful. But some users disagree, which is + why this function exists. + + -- Function: with-editor-usage-message + + Show usage information in the echo area. + + Magit also helps with writing *good* commit messages by complaining +when certain rules are violated. + + -- User Option: git-commit-summary-max-length + + The intended maximal length of the summary line of commit messages. + Characters beyond this column are colorized to indicate that this + preference has been violated. + + -- User Option: git-commit-fill-column + + Column beyond which automatic line-wrapping should happen in commit + message buffers. + + -- User Option: git-commit-finish-query-functions + + List of functions called to query before performing commit. + + The commit message buffer is current while the functions are + called. If any of them returns nil, then the commit is not + performed and the buffer is not killed. The user should then fix + the issue and try again. + + The functions are called with one argument. If it is non-nil then + that indicates that the user used a prefix argument to force + finishing the session despite issues. Functions should usually + honor this wish and return non-nil. + + -- Function: git-commit-check-style-conventions + + Check for violations of certain basic style conventions. For each + violation ask the user if she wants to proceed anyway. This makes + sure the summary line isn’t too long and that the second line is + empty. + + To show no diff while committing remove ‘magit-commit-diff’ from +‘server-switch-hook’. + + +File: magit.info, Node: Branching, Next: Merging, Prev: Committing, Up: Manipulating + +6.5 Branching +============= + +The upstream branch of some local branch is the branch into which the +commits on that local branch should eventually be merged, usually +something like ‘origin/master’. For the ‘master’ branch itself the +upstream branch and the branch it is being pushed to, are usually the +same remote branch. But for a feature branch the upstream branch and +the branch it is being pushed to should differ. + + Feature branches too should _eventually_ end up in a remote branch +such as ‘origin/master’ or ‘origin/maint’. Such a branch should +therefore be used as the upstream. But feature branches shouldn’t be +pushed directly to such branches. Instead a feature branch ‘my-feature’ +is usually pushed to ‘my-fork/my-feature’ or ‘origin/my-feature’. After +the new feature has been reviewed, the maintainer merges the feature +into ‘master’. And finally ‘master’ (not ‘my-feature’ itself) is pushed +to ‘origin/master’. + + But new features seldom are perfect on the first try, and so feature +branches usually have to be improved and re-pushed many times. Pushing +should therefore be easy to do, and for that reason some users have +concluded that the remote branch to which a feature branch is being +pushed should be set as the upstream. Luckily Git has long ago gained +support for a push-remote which can be configured separately from the +upstream branch, using the variables ‘branch..pushRemote’ and +‘remote.pushDefault’, so we no longer have to choose which of the two +remotes should be used as "the remote". + + Each of the fetching, pulling, and pushing popups features three +commands which act on the current branch and some other branch. Of +these, ‘p’ is bound to a command which acts on the push-remote, ‘u’ is +bound to a command which acts on the upstream, and ‘e’ is bound to a +command which acts on any other branch. The status buffer shows +unpushed and unpulled for both the push-remote and the upstream. + + It’s fairly simple to configure these two remotes. The values of all +the variables that are related to fetching, pulling, and pushing (as +well as some other branch-related variables) can be inspected and +changed in the branching popup. It is also possible to set the +push-remote and/or upstream while pushing (see *note Pushing: Pushing.). + +‘b’ (‘magit-branch-popup’) + + This prefix command shows the following suffix commands in a popup + buffer. It also displays the values of the following variables and + allows changing their values. + + The following variables are used to configure a specific branch. The +values are being displayed for the current branch (if any). To change +the value for another branch use a prefix argument. + + -- Variable: branch.NAME.merge + + Together with ‘branch.NAME.remote’ this variable defines the + upstream branch of the local branch named NAME. The value of this + variable is the full reference of the upstream _branch_. + + -- Variable: branch.NAME.remote + + Together with ‘branch.NAME.merge’ this variable defines the + upstream branch of the local branch named NAME. The value of this + variable is the name of the upstream _remote_. + + -- Variable: branch.NAME.rebase + + This variable controls whether pulling into the branch named NAME + is done by rebasing or by merging the fetched branch. + + • When ‘true’ then pulling is done by rebasing. + + • When ‘false’ then pulling is done by merging. + + • When undefined then the value of ‘pull.rebase’ is used. The + default of that variable is ‘false’. + + -- Variable: branch.NAME.pushRemote + + This variable specifies the remote that the branch named NAME is + usually pushed to. The value has to be the name of an existing + remote. + + It is not possible to specify the name of _branch_ to push the + local branch to. The name of the remote branch is always the same + as the name of the local branch. + + If this variable is undefined but ‘remote.pushDefault’ is defined, + then the value of the latter is used. By default + ‘remote.pushDefault’ is undefined. + + -- Variable: branch.NAME.description + + This variable can be used to describe the branch named NAME. That + description is used e.g. when turning the branch into a series of + patches. + + The following variables specify defaults which are used if the above +branch-specific variables are not set. + + -- Variable: pull.rebase + + This variable specifies whether pulling is done by rebasing or by + merging. It can be overwritten using ‘branch.NAME.rebase’. + + • When ‘true’ then pulling is done by rebasing. + + • When ‘false’ (the default) then pulling is done by merging. + Since it is never a good idea to merge the upstream branch into a + feature or hotfix branch and most branches are such branches, you + should consider setting this to ‘true’, and ‘branch.master.rebase’ + to ‘false’. + + -- Variable: remote.pushDefault + + This variable specifies what remote the local branches are usually + pushed to. This can be overwritten per branch using + ‘branch.NAME.pushRemote’. + + The following variables are used during the creation of a branch and +control whether the various branch-specific variables are automatically +set at this time. + + -- Variable: branch.autoSetupMerge + + This variable specifies under what circumstances creating a branch + NAME should result in the variables ‘branch.NAME.merge’ and + ‘branch.NAME.remote’ being set according to the starting point used + to create the branch. If the starting point isn’t a branch, then + these variables are never set. + + • When ‘always’ then the variables are set regardless of whether + the starting point is a local or a remote branch. + + • When ‘true’ (the default) then the variable are set when the + staring point is a remote branch, but not when it is a local + branch. + + • When ‘false’ then the variables are never set. + + -- Variable: branch.autoSetupRebase + + This variable specifies whether creating a branch NAME should + result in the variable ‘branch.NAME.rebase’ being set to ‘true’. + + • When ‘always’ then the variable is set regardless of whether + the starting point is a local or a remote branch. + + • When ‘local’ then the variable are set when the starting point + is a local branch, but not when it is a remote branch. + + • When ‘remote’ then the variable are set when the starting + point is a remote branch, but not when it is a local branch. + + • When ‘never’ (the default) then the variable is never set. + + Note that the respective commands always change the repository-local +values. If you want to change the global value, which is used when the +local value is undefined, then you have to do so on the command line, +e.g.: + + git config --global remote.autoSetupMerge always + + For more information about these variables you should also see + + *note (gitman)git-config:: . Also see *note (gitman)git-branch:: , + + *note (gitman)git-checkout:: , and *note Pushing: Pushing. + +‘b b’ (‘magit-checkout’) + + Checkout a revision read in the minibuffer and defaulting to the + branch or arbitrary revision at point. If the revision is a local + branch then that becomes the current branch. If it is something + else then ‘HEAD’ becomes detached. Checkout fails if the working + tree or the staging area contain changes. + +‘b n’ (‘magit-branch’) + + Create a new branch. The user is asked for a branch or arbitrary + revision to use as the starting point of the new branch. When a + branch name is provided, then that becomes the upstream branch of + the new branch. The name of the new branch is also read in the + minibuffer. + + Also see option ‘magit-branch-prefer-remote-upstream’. + +‘b c’ (‘magit-branch-and-checkout’) + + This command creates a new branch like ‘magit-branch’, but then + also checks it out. + + Also see option ‘magit-branch-prefer-remote-upstream’. + +‘b s’ (‘magit-branch-spinoff’) + + This command creates and checks out a new branch starting at and + tracking the current branch. That branch in turn is reset to the + last commit it shares with its upstream. If the current branch has + no upstream or no unpushed commits, then the new branch is created + anyway and the previously current branch is not touched. + + This is useful to create a feature branch after work has already + began on the old branch (likely but not necessarily "master"). + + If the current branch is a member of the value of option + ‘magit-branch-prefer-remote-upstream’ (which see), then the current + branch will be used as the starting point as usual, but the + upstream of the starting-point may be used as the upstream of the + new branch, instead of the starting-point itself. + +‘b x’ (‘magit-branch-reset’) + + This command resets a branch, defaulting to the branch at point, to + the tip of another branch or any other commit. + + When resetting to another branch, then that branch is also set as + the upstream of the branch being reset. + + When the branch being reset is the current branch, then a hard + reset is performed. If there are any uncommitted changes, then the + user has to confirming the reset because those changes would be + lost. + + This is useful when you have started work on a feature branch but + realize it’s all crap and want to start over. + +‘b d’ (‘magit-branch-delete’) + + Delete one or multiple branches. If the region marks multiple + branches, then offer to delete those. Otherwise, prompt for a + single branch to be deleted, defaulting to the branch at point. + +‘b r’ (‘magit-branch-rename’) + + Rename a branch. The branch and the new name are read in the + minibuffer. With prefix argument the branch is renamed even if + that name conflicts with an existing branch. + + -- User Option: magit-branch-read-upstream-first + + When creating a branch, whether to read the upstream branch before + the name of the branch that is to be created. The default is + ‘nil’, and I recommend you leave it at that. + + -- User Option: magit-branch-prefer-remote-upstream + + This option specifies whether remote upstreams are favored over + local upstreams when creating new branches. + + When a new branch is created, Magit offers the branch, commit, or + stash as the default starting point of the new branch. If there is + no such thing at point, then it falls back to offer the current + branch as starting-point. The user may then accept that default or + pick something else. + + If the chosen starting-point is a branch, then it may also be set + as the upstream of the new branch, depending on the value of the + Git variable ‘branch.autoSetupMerge’. By default this is done for + remote branches, but not for local branches. + + You might prefer to always use some remote branch as upstream. If + the chosen starting-point is (1) a local branch, (2) whose name is + a member of the value of this option, (3) the upstream of that + local branch is a remote branch with the same name, and (4) that + remote branch can be fast-forwarded to the local branch, then the + chosen branch is used as starting-point, but its own upstream is + used as the upstream of the new branch. + + Assuming the chosen branch matches these conditions you would end + up with with e.g.: + + feature --upstream--> origin/master + + instead of + + feature --upstream--> master --upstream--> origin/master + + Which you prefer is a matter of personal preference. If you do + prefer the former, then you should add branches such as ‘master’, + ‘next’, and ‘maint’ to the value of this options. + + +File: magit.info, Node: Merging, Next: Rebasing, Prev: Branching, Up: Manipulating + +6.6 Merging +=========== + +Also see *note (gitman)git-merge:: . + +‘m’ (‘magit-merge-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + + When no merge is in progress, then the popup buffer features the +following commands. + +‘m m’ (‘magit-merge’) + + Merge another branch or an arbitrary revision into the current + branch. The branch or revision to be merged is read in the + minibuffer and defaults to the one at point. + + Unless there are conflicts or a prefix argument is used, the + resulting merge commit uses a generic commit message, and the user + does not get a chance to inspect or change it before the commit is + created. With a prefix argument this does not actually create the + merge commit, which makes it possible to inspect how conflicts were + resolved and to adjust the commit message. + +‘m e’ (‘magit-merge-editmsg’) + + Merge another branch or an arbitrary revision into the current + branch and open a commit message buffer, so that the user can make + adjustments. The commit is not actually created until the user + finishes with ‘C-c C-c’. + +‘m n’ (‘magit-merge-nocommit’) + + Merge another branch or an arbitrary revision into the current + branch, but do not actually create the commit. The user can then + further adjust the merge, even when automatic conflict resolution + succeeded and/or adjust the commit message. + +‘m p’ (‘magit-merge-preview’) + + Preview result of merging another branch or an arbitrary revision + into the current branch. + + When a merge is in progress, then the popup buffer features these +commands instead. + +‘m m’ (‘magit-merge’) + + After resolving conflicts, proceed with the merge. If there are + still conflicts, then this fails. + +‘m a’ (‘magit-merge-abort’) + + Abort the current merge operation. + + +File: magit.info, Node: Rebasing, Next: Cherry picking, Prev: Merging, Up: Manipulating + +6.7 Rebasing +============ + +Also see *note (gitman)git-rebase:: . + +‘r’ (‘magit-rebase-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + + When no rebase is in progress, then the popup buffer features the +following commands. + +‘r p’ (‘magit-rebase-onto-pushremote’) + + Rebase the current branch onto ‘branch..pushRemote’. If that + variable is unset, then rebase onto ‘remote.pushDefault’. + +‘r u’ (‘magit-rebase-onto-upstream’) + + Rebase the current branch onto its upstream branch. + +‘r e’ (‘magit-rebase’) + + Rebase the current branch onto a branch read in the minibuffer. + All commits that are reachable from head but not from the selected + branch TARGET are being rebased." + +‘r o’ (‘magit-rebase-subset’) + + Start a non-interactive rebase sequence with commits from START to + ‘HEAD’ onto NEWBASE. START has to be selected from a list of recent + commits. + + Note that the popup also features the infix argument ‘--interactive’. +This can be used to turn one of the above non-interactive rebase +variants into an interactive rebase. + + For example if you want to clean up a feature branch and at the same +time rebase it onto ‘master’, then you could use ‘r-iu’. But we +recommend that you instead do that in two steps. First use ‘ri’ to +cleanup the feature branch, and then in a second step ‘ru’ to rebase it +onto ‘master’. That way if things turn out to be more complicated than +you thought and/or you make a mistake and have to start over, then you +only have to redo half the work. + + Explicitly enabling ‘--interactive’ won’t have an effect on the +following commands as they always use that argument anyway, even if it +is not enabled in the popup. + +‘r i’ (‘magit-rebase-interactive’) + + Start an interactive rebase sequence. + +‘r f’ (‘magit-rebase-autosquash’) + + Combine squash and fixup commits with their intended targets. + +‘r m’ (‘magit-rebase-edit-commit’) + + Edit a single older commit using rebase. + +‘r w’ (‘magit-rebase-reword-commit’) + + Reword a single older commit using rebase. + + When a rebase is in progress, then the popup buffer features these +commands instead. + +‘r r’ (‘magit-rebase-continue’) + + Restart the current rebasing operation. + +‘r s’ (‘magit-rebase-skip’) + + Skip the current commit and restart the current rebase operation. + +‘r e’ (‘magit-rebase-edit’) + + Edit the todo list of the current rebase operation. + +‘r a’ (‘magit-rebase-abort’) + + Abort the current rebase operation, restoring the original branch. + +* Menu: + +* Editing rebase sequences:: +* Rebase sequence log:: + + +File: magit.info, Node: Editing rebase sequences, Next: Rebase sequence log, Up: Rebasing + +6.7.1 Editing rebase sequences +------------------------------ + +‘C-c C-c’ (‘with-editor-finish’) + + Finish the current editing session by returning with exit code 0. + Git then creates the commit using the message it finds in the file. + +‘C-c C-k’ (‘with-editor-cancel’) + + Cancel the current editing session by returning with exit code 1. + Git then cancels the commit, but leaves the file untouched. + +‘RET’ (‘git-rebase-show-commit’) + + Show the commit on the current line in another buffer and select + that buffer. + +‘SPC’ (‘magit-diff-show-or-scroll-up’) + + Show the commit on the current line in another buffer without + selecting that buffer. If the revision buffer is already visible + in another window of the current frame, then instead scroll that + window up. + +‘DEL’ (‘magit-diff-show-or-scroll-down’) + + Show the commit on the current line in another buffer without + selecting that buffer. If the revision buffer is already visible + in another window of the current frame, then instead scroll that + window down. + +‘p’ (‘git-rebase-backward-line’) + + Move to previous line. + +‘n’ (‘forward-line’) + + Move to next line. + +‘M-p’ (‘git-rebase-move-line-up’) + + Move the current commit (or command) up. + +‘M-n’ (‘git-rebase-move-line-down’) + + Move the current commit (or command) down. + +‘r’ (‘git-rebase-reword’) + + Edit message of commit on current line. + +‘e’ (‘git-rebase-edit’) + + Stop at the commit on the current line. + +‘s’ (‘git-rebase-squash’) + + Meld commit on current line into previous commit, and edit message. + +‘f’ (‘git-rebase-fixup’) + + Meld commit on current line into previous commit, discarding the + current commit’s message. + +‘k’ (‘git-rebase-kill-line’) + + Kill the current action line. + +‘c’ (‘git-rebase-pick’) + + Use commit on current line. + +‘x’ (‘git-rebase-exec’) + + Insert a shell command to be run after the proceeding commit. + + If there already is such a command on the current line, then edit + that instead. With a prefix argument insert a new command even + when there already is one on the current line. With empty input + remove the command on the current line, if any. + +‘y’ (‘git-rebase-insert’) + + Read an arbitrary commit and insert it below current line. + +‘C-x u’ (‘git-rebase-undo’) + + Undo some previous changes. Like ‘undo’ but works in read-only + buffers. + + -- User Option: git-rebase-auto-advance + + Whether to move to next line after changing a line. + + -- User Option: git-rebase-show-instructions + + Whether to show usage instructions inside the rebase buffer. + + -- User Option: git-rebase-confirm-cancel + + Whether confirmation is required to cancel. + + +File: magit.info, Node: Rebase sequence log, Prev: Editing rebase sequences, Up: Rebasing + +6.7.2 Rebase sequence log +------------------------- + +While a rebase sequence is in progress, the status buffer features a +section which lists the commits that have already been applied as well +as the commits that still have to be applied. + + The commits are split in two halves. When rebase stops at a commit, +either because the user has to deal with a conflict or explicitly +requested that rebase stops at that commit, then point is placed on the +commit that separates the two groups, i.e. on ‘HEAD’. The commits +above it have not been applied yet, while it and the commits below it +have already been applied. In between these two groups or applied and +yet-to-be applied commits, there sometimes is a commit which has been +dropped. + + Each commit is prefixed with a word and these words are additionally +shown in different colors to indicate the status of the commits. + + The following colors are used: + + • Yellow commits have not been applied yet. + + • Gray commits have already been applied. + + • The blue commit is the ‘HEAD’ commit. + + • The green commit is the commit the rebase sequence stopped at. If + this is the same commit as ‘HEAD’ (e.g. because you haven’t done + anything yet after rebase stopped at the commit, then this commit + is shown in blue, not green. There can only be a green and a blue + commit at the same time, if you create one or more new commits + after rebase stops at a commit. + + • Red commits have been dropped. They are shown for reference only, + e.g. to make it easier to diff. + + Of course these colors are subject to the color-theme in use. + + The following words are used: + + • Commits prefixed with ‘pick’, ‘reword’, ‘edit’, ‘squash’, and + ‘fixup’ have not been applied yet. These words have the same + meaning here as they do in the buffer used to edit the rebase + sequence. See *note Editing rebase sequences: Editing rebase + sequences. + + • The commit prefixed with ‘onto’ is the commit on top of which all + the other commits are being re-applied. Like the commits that have + already been re-applied, it is reachable from ‘HEAD’, but unlike + those it has not actually been re-applied during the current + session - it wasn’t touched at all. + + • Commits prefixed with ‘done’ have already been re-applied. Not all + commits that have already been applied are prefixed with this word, + though. + + • When a commit is prefixed with ‘void’, then that indicates that + Magit knows for sure that all the changes in that commit have been + applied using several new commits. This commit is no longer + reachable from ‘HEAD’, and it also isn’t one of the commits that + will be applied when resuming the session. + + • When a commit is prefixed with ‘join’, then that indicates that the + rebase sequence stopped at that commit due to a conflict - you now + have to join (merge) the changes with what has already been + applied. In a sense this is the commit rebase stopped at, but + while its effect is already in the index and in the worktree (with + conflict markers), the commit itself has not actually been applied + yet (it isn’t the ‘HEAD’). So it is shown in yellow, like the + other commits that still have to be applied. + + • When a commit is prefixed with ‘goal’, ‘same’, or ‘work’, then that + indicates that you reset to an earlier commit (and that this commit + therefore is no longer reachable from ‘HEAD’), but that it might + still be possible to create a new commit with the exact same tree + or at least the same patch-id, without manually editing any file. + Or at the very least that there are some uncommitted remaining, + which may or may not originate from that commit. + + • When a commit is prefixed with ‘goal’, then that indicates + that it is still possible to create a commit with the exact + same tree (the "goal") without manually editing a file, by + simply committing the index (or, provided nothing is already + staged, by staging all unstaged changes and then committing + that). This is the case when the original tree exists in the + index or worktree in untainted form. + + • When a commit is prefixed with ‘same’, then that indicates + that it is no longer possible to create a commit with the + exact same tree, but that it is still possible to create a + commit with the same patch-id. This would be the case if you + created a new commit with other changes, but the changes from + the original commit still exist in the index and/or working + tree in untainted form. + + • When a commit is prefixed with ‘work’, then that indicates + that you are working with the changes from that commit after + resetting to an earlier commit. There are changes in the + index and/or working tree and some of them likely originate + from that commit. + + • When a commit is prefixed with ‘poof’ or ‘gone’, then that + indicates that you reset to an earlier commit (and that this commit + therefore is no longer reachable from ‘HEAD’), and that there are + no uncommitted changes remaining which might allow you to create a + new commit with the same tree or at least the same patch-id. + + • When a commit is prefixed with ‘poof’, then that indicates + that it is no longer reachable from ‘HEAD’, but that it has + been replaced with one or more commits, which together have + the exact same effect. + + • When a commit is prefixed with ‘gone’, then that indicates + that it is no longer reachable from ‘HEAD’ and that we also + cannot determine whether its changes are still in effect in + one or more new commits. They might be, but if so, then there + must also be other changes which makes it impossible to know + for sure. + + Do not worry if you do not fully understand the above. That’s okay, +you will acquire a good enough understanding through practice. + + For other sequence operations such as cherry-picking, a similar +section is displayed, but they lack some of the features described +below, due to limitations in the git commands used to implement them. +Most importantly these sequences only support "picking" a commit but not +other actions such as "rewording", and they do not keep track of the +commits which have already been applied. + + +File: magit.info, Node: Cherry picking, Next: Resetting, Prev: Rebasing, Up: Manipulating + +6.8 Cherry picking +================== + +Also see *note (gitman)git-cherry-pick:: . + +‘A’ (‘magit-cherry-pick-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + + When no cherry-pick or revert is in progress, then the popup buffer +features the following commands. + +‘A A’ (‘magit-cherry-pick’) + + Cherry-pick a commit. Prompt for a commit, defaulting to the + commit at point. If the region selects multiple commits, then pick + all of them, without prompting. + +‘A a’ (‘magit-cherry-apply’) + + Apply the changes in a commit to the working tree, but do not + commit them. Prompt for a commit, defaulting to the commit at + point. If the region selects multiple commits, then apply all of + them, without prompting. + + This command also has a top-level binding, which can be invoked + without using the popup by typing ‘a’ at the top-level. + + When a cherry-pick or revert is in progress, then the popup buffer +features these commands instead. + +‘A A’ (‘magit-sequence-continue’) + + Resume the current cherry-pick or revert sequence. + +‘A s’ (‘magit-sequence-skip’) + + Skip the stopped at commit during a cherry-pick or revert sequence. + +‘A a’ (‘magit-sequence-abort’) + + Abort the current cherry-pick or revert sequence. This discards + all changes made since the sequence started. + +* Menu: + +* Reverting:: + + +File: magit.info, Node: Reverting, Up: Cherry picking + +6.8.1 Reverting +--------------- + +‘V’ (‘magit-revert-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + + When no cherry-pick or revert is in progress, then the popup buffer +features the following commands. + +‘V V’ (‘magit-revert’) + + Revert a commit by creating a new commit. Prompt for a commit, + defaulting to the commit at point. If the region selects multiple + commits, then revert all of them, without prompting. + +‘V v’ (‘magit-revert-no-commit’) + + Revert a commit by applying it in reverse to the working tree. + Prompt for a commit, defaulting to the commit at point. If the + region selects multiple commits, then revert all of them, without + prompting. + + When a cherry-pick or revert is in progress, then the popup buffer +features these commands instead. + +‘V A’ (‘magit-sequence-continue’) + + Resume the current cherry-pick or revert sequence. + +‘V s’ (‘magit-sequence-skip’) + + Skip the stopped at commit during a cherry-pick or revert sequence. + +‘V a’ (‘magit-sequence-abort’) + + Abort the current cherry-pick or revert sequence. This discards + all changes made since the sequence started. + + +File: magit.info, Node: Resetting, Next: Stashing, Prev: Cherry picking, Up: Manipulating + +6.9 Resetting +============= + +Also see *note (gitman)git-reset:: . + +‘x’ (‘magit-reset’) + + Reset the head and index to some commit read from the user and + defaulting to the commit at point. The working tree is kept as-is. + With a prefix argument also reset the working tree. + +‘M-x magit-reset-index’ (‘magit-reset-index’) + + Reset the index to some commit read from the user and defaulting to + the commit at point. Keep the ‘HEAD’ and working tree as-is, so if + the commit refers to the ‘HEAD’, then this effectively unstages all + changes. + +‘M-x magit-reset-head’ (‘magit-reset-head’) + + Reset the ‘HEAD’ and index to some commit read from the user and + defaulting to the commit at point. The working tree is kept as-is. + +‘M-x magit-reset-soft’ (‘magit-reset-soft’) + + Reset the ‘HEAD’ to some commit read from the user and defaulting + to the commit at point. The index and the working tree are kept + as-is. + +‘M-x magit-reset-hard’ (‘magit-reset-hard’) + + Reset the ‘HEAD’, index, and working tree to some commit read from + the user and defaulting to the commit at point. + +‘M-x magit-checkout-file’ (‘magit-checkout-file’) + + Update file in the working tree and index to the contents from a + revision. + + Both the revision and file are read from the user. + + +File: magit.info, Node: Stashing, Prev: Resetting, Up: Manipulating + +6.10 Stashing +============= + +Also see *note (gitman)git-stash:: . + +‘z’ (‘magit-stash-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘z z’ (‘magit-stash’) + + Create a stash of the index and working tree. Untracked files are + included according to popup arguments. One prefix argument is + equivalent to ‘--include-untracked’ while two prefix arguments are + equivalent to ‘--all’. + +‘z i’ (‘magit-stash-index’) + + Create a stash of the index only. Unstaged and untracked changes + are not stashed. + +‘z w’ (‘magit-stash-worktree’) + + Create a stash of the working tree only. Untracked files are + included according to popup arguments. One prefix argument is + equivalent to ‘--include-untracked’ while two prefix arguments are + equivalent to ‘--all’. + +‘z x’ (‘magit-stash-keep-index’) + + Create a stash of the index and working tree, keeping index intact. + Untracked files are included according to popup arguments. One + prefix argument is equivalent to ‘--include-untracked’ while two + prefix arguments are equivalent to ‘--all’. + +‘z Z’ (‘magit-snapshot’) + + Create a snapshot of the index and working tree. Untracked files + are included according to popup arguments. One prefix argument is + equivalent to ‘--include-untracked’ while two prefix arguments are + equivalent to ‘--all’. + +‘z I’ (‘magit-snapshot-index’) + + Create a snapshot of the index only. Unstaged and untracked + changes are not stashed. + +‘z W’ (‘magit-snapshot-worktree’) + + Create a snapshot of the working tree only. Untracked files are + included according to popup arguments. One prefix argument is + equivalent to ‘--include-untracked’ while two prefix arguments are + equivalent to ‘--all’-. + +‘z a’ (‘magit-stash-apply’) + + Apply a stash to the working tree. Try to preserve the stash + index. If that fails because there are staged changes, apply + without preserving the stash index. + +‘z p’ (‘magit-stash-pop’) + + Apply a stash to the working tree and remove it from stash list. + Try to preserve the stash index. If that fails because there are + staged changes, apply without preserving the stash index and forgo + removing the stash. + +‘z d’ (‘magit-stash-drop’) + + Remove a stash from the stash list. When the region is active, + offer to drop all contained stashes. + +‘z l’ (‘magit-stash-list’) + + List all stashes in a buffer. + +‘z v’ (‘magit-stash-show’) + + Show all diffs of a stash in a buffer. + +‘z b’ (‘magit-stash-branch’) + + Create and checkout a new BRANCH from STASH. + +‘z f’ (‘magit-stash-format-patch’) + + Create a patch from STASH. + +‘k’ (‘magit-stash-clear’) + + Remove all stashes saved in REF’s reflog by deleting REF. + + +File: magit.info, Node: Transferring, Next: Miscellaneous, Prev: Manipulating, Up: Top + +7 Transferring +************** + +* Menu: + +* Remotes:: +* Fetching:: +* Pulling:: +* Pushing:: +* Creating and sending patches:: +* Applying patches:: + + +File: magit.info, Node: Remotes, Next: Fetching, Up: Transferring + +7.1 Remotes +=========== + +Also see *note (gitman)git-remote:: . + +‘M’ (‘magit-remote-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘M a’ (‘magit-remote-add’) + + Add a remote and fetch it. The remote name and url are read in the + minibuffer. + +‘M r’ (‘magit-remote-rename’) + + Rename a remote. Both the old and the new names are read in the + minibuffer. + +‘M u’ (‘magit-remote-set-url’) + + Change the url of a remote. Both the remote and the new url are + read in the minibuffer. + +‘M k’ (‘magit-remote-remove’) + + Delete a remote, read from the minibuffer. + + -- User Option: magit-remote-add-set-branch.pushDefault + + Whether to set the value of ‘branch.pushDefault’ after adding a + remote. + + If ‘ask’, then always ask. If ‘ask-if-unset’, then ask, but only + if the variable isn’t set already. If ‘nil’, then don’t ever set. + If the value is a string, then set without asking, provided the + name of the name of the added remote is equal to that string and + the variable isn’t already set. + + +File: magit.info, Node: Fetching, Next: Pulling, Prev: Remotes, Up: Transferring + +7.2 Fetching +============ + +Also see *note (gitman)git-fetch:: . + +‘f’ (‘magit-fetch-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘f p’ (‘magit-fetch-from-pushremote’) + + Fetch from the push-remote of the current branch. + +‘f u’ (‘magit-fetch-from-upstream’) + + Fetch from the push-remote of the current branch. + +‘f e’ (‘magit-fetch’) + + Fetch from another repository. + +‘f a’ (‘magit-fetch-all’) + + Fetch from all remotes. + +‘f m’ (‘magit-submodule-fetch’) + + Fetch all submodules. With a prefix argument fetch all remotes of + all submodules. + + Instead of using one popup for fetching and another for pulling, you +could also use ‘magit-pull-and-fetch-popup’. See its doc-string for +more information. + + +File: magit.info, Node: Pulling, Next: Pushing, Prev: Fetching, Up: Transferring + +7.3 Pulling +=========== + +Also see *note (gitman)git-pull:: . + +‘F’ (‘magit-pull-popup’) + + This prefix command shows the following suffix commands in a popup + buffer. + +‘F p’ (‘magit-pull-from-pushremote’) + + Pull from the push-remote of the current branch. + +‘F u’ (‘magit-pull-from-upstream’) + + Pull from the upstream of the current branch. + +‘F e’ (‘magit-pull’) + + Pull from a branch read in the minibuffer. + + Instead of using one popup for fetching and another for pulling, you +could also use ‘magit-pull-and-fetch-popup’. See its doc-string for +more information. + + +File: magit.info, Node: Pushing, Next: Creating and sending patches, Prev: Pulling, Up: Transferring + +7.4 Pushing +=========== + +Also see *note (gitman)git-push:: . + +‘P’ (‘magit-push-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘P p’ (‘magit-push-current-to-pushremote’) + + Push the current branch to ‘branch..pushRemote’ or if that is + unset to ‘remote.pushDefault’. + + When ‘magit-push-current-set-remote-if-missing’ is non-nil and the + push-remote is not configured, then read the push-remote from the + user, set it, and then push to it. With a prefix argument the + push-remote can be changed before pushed to it. + +‘P u’ (‘magit-push-current-to-upstream’) + + Push the current branch to its upstream branch. + + When ‘magit-push-current-set-remote-if-missing’ is non-nil and the + push-remote is not configured, then read the upstram from the user, + set it, and then push to it. With a prefix argument the + push-remote can be changed before pushed to it. + +‘P e’ (‘magit-push-current’) + + Push the current branch to a branch read in the minibuffer. + +‘P o’ (‘magit-push’) + + Push an arbitrary branch or commit somewhere. Both the source and + the target are read in the minibuffer. + +‘P m’ (‘magit-push-matching’) + + Push all matching branches to another repository. If multiple + remotes exit, then read one from the user. If just one exists, use + that without requiring confirmation. + +‘P t’ (‘magit-push-tags’) + + Push all tags to another repository. If only one remote exists, + then push to that. Otherwise prompt for a remote, offering the + remote configured for the current branch as default. + +‘P T’ (‘magit-push-tag’) + + Push a tag to another repository. + + Two more push commands exist, which by default are not available from +the push popup. See their doc-strings for instructions on how to add +them to the popup. + + -- Command: magit-push-implicitly args + + Push somewhere without using an explicit refspec. + + This command simply runs ‘git push -v [ARGS]’. ARGS are the + arguments specified in the popup buffer. No explicit refspec + arguments are used. Instead the behavior depends on at least these + Git variables: ‘push.default’, ‘branch.pushDefault’, + ‘branch..pushRemote’, ‘branch..remote’, + ‘branch..merge’, and ‘remote..push’. + + -- Command: magit-push-to-remote remote args + + Push to the remote REMOTE without using an explicit refspec. The + remote is read in the minibuffer. + + This command simply runs ‘git push -v [ARGS] REMOTE’. ARGS are the + arguments specified in the popup buffer. No refspec arguments are + used. Instead the behavior depends on at least these Git + variables: ‘push.default’, ‘branch.pushDefault’, + ‘branch..pushRemote’, ‘branch..remote’, + ‘branch..merge’, and ‘remote..push’. + + -- User Option: magit-push-current-set-remote-if-missing + + This option controls whether missing remotes are configured before + pushing. + + When ‘nil’, then the command ‘magit-push-current-to-pushremote’ and + ‘magit-push-current-to-upstream’ do not appear in the push popup if + the push-remote resp. upstream is not configured. If the user + invokes one of these commands anyway, then it raises an error. + + When ‘non-nil’, then these commands always appear in the push + popup. But if the required configuration is missing, then they do + appear in a way that indicates that this is the case. If the user + invokes one of them, then it asks for the necessary configuration, + stores the configuration, and then uses it to push a first time. + + This option also affects whether the argument ‘--set-upstream’ is + available in the popup. If the value is ‘non-nil’, then that + argument is redundant. But note that changing the value of this + option does not take affect immediately, the argument will only be + added or removed after restarting Emacs. + + +File: magit.info, Node: Creating and sending patches, Next: Applying patches, Prev: Pushing, Up: Transferring + +7.5 Creating and sending patches +================================ + +‘W’ (‘magit-patch-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘W p’ (‘magit-format-patch’) + + Create patches for a set commits. If the region marks commits, + then create patches for those. Otherwise prompt for a range or a + single commit, defaulting to the commit at point. + +‘W r’ (‘magit-request-pull’) + + Request that upstream pulls from your public repository. + + +File: magit.info, Node: Applying patches, Prev: Creating and sending patches, Up: Transferring + +7.6 Applying patches +==================== + +Also see *note (gitman)git-am:: . + +‘w’ (‘magit-am-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘w w’ (‘magit-am-apply-patches’) + + Apply one or more patches. If the region marks files, then apply + those patches. Otherwise read a file name in the minibuffer + defaulting to the file at point. + +‘w m’ (‘magit-am-apply-maildir’) + + Apply the patches from a maildir. + +‘w w’ (‘magit-am-continue’) + + Resume the current patch applying sequence. + +‘w s’ (‘magit-am-skip’) + + Skip the stopped at patch during a patch applying sequence. + +‘w a’ (‘magit-am-abort’) + + Abort the current patch applying sequence. This discards all + changes made since the sequence started. + + +File: magit.info, Node: Miscellaneous, Next: Customizing, Prev: Transferring, Up: Top + +8 Miscellaneous +*************** + +* Menu: + +* Tagging:: +* Notes:: +* Submodules:: +* Common commands:: +* Wip modes:: +* Minor mode for buffers visiting files:: +* Minor mode for buffers visiting blobs:: + + +File: magit.info, Node: Tagging, Next: Notes, Up: Miscellaneous + +8.1 Tagging +=========== + +Also see *note (gitman)git-tag:: . + +‘t’ (‘magit-tag-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘t t’ (‘magit-tag’) + + Create a new tag with the given NAME at REV. With a prefix argument + annotate the tag. + +‘t k’ (‘magit-tag-delete’) + + Delete one or more tags. If the region marks multiple tags (and + nothing else), then offer to delete those. Otherwise, prompt for a + single tag to be deleted, defaulting to the tag at point. + +‘t p’ (‘magit-tag-prune’) + + Offer to delete tags missing locally from REMOTE, and vice versa. + + +File: magit.info, Node: Notes, Next: Submodules, Prev: Tagging, Up: Miscellaneous + +8.2 Notes +========= + +Also see *note (gitman)git-notes:: . + +‘T’ (‘magit-notes-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘T T’ (‘magit-notes-edit’) + + Edit the note attached to a commit, defaulting to the commit at + point. + + By default use the value of Git variable ‘core.notesRef’ or + "refs/notes/commits" if that is undefined. + +‘T r’ (‘magit-notes-remove’) + + Remove the note attached to a commit, defaulting to the commit at + point. + + By default use the value of Git variable ‘core.notesRef’ or + "refs/notes/commits" if that is undefined. + +‘T p’ (‘magit-notes-prune’) + + Remove notes about unreachable commits. + +‘T s’ (‘magit-notes-set-ref’) + + Set the current notes ref to a the value read from the user. The + ref is made current by setting the value of the Git variable + ‘core.notesRef’. With a prefix argument change the global value + instead of the value in the current repository. When this is + undefined, then "refs/notes/commit" is used. + + Other ‘magit-notes-*’ commands, as well as the sub-commands of + Git’s ‘note’ command, default to operate on that ref. + +‘T S’ (‘magit-notes-set-display-refs’) + + Set notes refs to be display in addition to "core.notesRef". This + reads a colon separated list of notes refs from the user. The + values are stored in the Git variable ‘notes.displayRef’. With a + prefix argument GLOBAL change the global values instead of the + values in the current repository. + + It is possible to merge one note ref into another. That may result +in conflicts which have to resolved in the temporary worktree +".git/NOTES_MERGE_WORKTREE". + +‘T m’ (‘magit-notes-merge’) + + Merge the notes of a ref read from the user into the current notes + ref. The current notes ref is the value of Git variable + ‘core.notesRef’ or "refs/notes/commits" if that is undefined. + + When a notes merge is in progress then the popup features the +following suffix commands, instead of those listed above. + +‘T c’ (‘magit-notes-merge-commit’) + + Commit the current notes ref merge, after manually resolving + conflicts. + +‘T a’ (‘magit-notes-merge-abort’) + + Abort the current notes ref merge. + + +File: magit.info, Node: Submodules, Next: Common commands, Prev: Notes, Up: Miscellaneous + +8.3 Submodules +============== + +Also see *note (gitman)git-submodule:: . + +‘o’ (‘magit-submodule-popup’) + + This prefix command shows the following suffix commands along with + the appropriate infix arguments in a popup buffer. + +‘o a’ (‘magit-submodule-add’) + + Add the repository at URL as a submodule. Optional PATH is the + path to the submodule relative to the root of the super-project. + If it is nil then the path is determined based on URL. + +‘o b’ (‘magit-submodule-setup’) + + Clone and register missing submodules and checkout appropriate + commits. + +‘o i’ (‘magit-submodule-init’) + + Register submodules listed in ".gitmodules" into ".git/config". + +‘o u’ (‘magit-submodule-update’) + + Clone missing submodules and checkout appropriate commits. With a + prefix argument also register submodules in ".git/config". + +‘o s’ (‘magit-submodule-sync’) + + Update each submodule’s remote URL according to ".gitmodules". + +‘o f’ (‘magit-submodule-fetch’) + + Fetch submodule. With a prefix argument fetch all remotes. + +‘o i’ (‘magit-submodule-init’) + + Unregister the submodule at PATH. + + +File: magit.info, Node: Common commands, Next: Wip modes, Prev: Submodules, Up: Miscellaneous + +8.4 Common commands +=================== + +These are some of the commands that can be used in all buffers whose +major-modes derive from ‘magit-mode’. There are other common commands +beside the ones below, but these didn’t fit well anywhere else. + +‘M-w’ (‘magit-copy-section-value’) + + This command saves the value of the current section to the + ‘kill-ring’, and, provided that the current section is a commit, + branch, or tag section, it also pushes the (referenced) revision to + the ‘magit-revision-stack’. + + When the current section is a branch or a tag, and a prefix + argument is used, then it saves the revision at its tip to the + ‘kill-ring’ instead of the reference name. + +‘C-w’ (‘magit-copy-buffer-revision’) + + This command save the revision being displayed in the current + buffer to the ‘kill-ring’ and also pushes it to the + ‘magit-revision-stack’. It is mainly intended for use in + ‘magit-revision-mode’ buffers, the only buffers where it is always + unambiguous exactly which revision should be saved. + + Most other Magit buffers usually show more than one revision, in + some way or another, so this command has to select one of them, and + that choice might not always be the one you think would have been + the best pick. + + Outside of Magit ‘M-w’ and ‘C-w’ are usually bound to +‘kill-ring-save’ and ‘kill-region’, and these commands would also be +useful in Magit buffers. Therefore when the region is active, then both +of these commands behave like ‘kill-ring-save’ instead of as described +above. + + +File: magit.info, Node: Wip modes, Next: Minor mode for buffers visiting files, Prev: Common commands, Up: Miscellaneous + +8.5 Wip modes +============= + +Git keeps *committed* changes around long enough for users to recover +changes they have accidentally deleted. It does so by not garbage +collecting any committed but no longer referenced objects for a certain +period of time, by default 30 days. + + But Git does *not* keep track of *uncommitted* changes in the working +tree and not even the index (the staging area). Because Magit makes it +so convenient to modify uncommitted changes, it also makes it easy to +shoot yourself in the foot in the process. + + For that reason Magit provides three global modes that save *tracked* +files to work-in-progress references after or before certain actions. +(Untracked files are never saved and these modes also only work after +the first commit has been created). + + Two separate work-in-progress references are used to track the state +of the index and of the working tree: "refs/wip/index/" and +"refs/wip/wtree/", where ‘’ is the full ref of the +current branch, e.g. "refs/heads/master". When the ‘HEAD’ is detached +then "HEAD" is in place of ‘’. + + Checking out another branch (or detaching ‘HEAD’) causes the use of +different wip refs for subsequent changes, but the old refs are not +deleted. + + Creating a commit and then making a change causes the wip refs to be +recreated to fork from the new commit. But the old commits on the wip +refs are not lost. They are still available from the reflog. To make +it easier to see when the fork point of a wip ref was changed, an +additional commit with the message "restart autosaving" is created on it +(‘xxO’ commits below are such boundary commits). + + Starting with + + BI0---BI1 refs/wip/index/refs/heads/master + / +A---B refs/heads/master + \ + BW0---BW1 refs/wip/wtree/refs/heads/master + + and committing the staged changes and editing and saving a file would +result in + + BI0---BI1 refs/wip/index/refs/heads/master + / +A---B---C refs/heads/master + \ \ + \ CW0---CW1 refs/wip/wtree/refs/heads/master + \ + BW0---BW1 refs/wip/wtree/refs/heads/master@{2} + + The fork-point of the index wip ref is not changed until some change +is being staged. Likewise just checking out a branch or creating a +commit does not change the fork-point of the working tree wip ref. The +fork-points are not adjusted until there actually is a change that +should be committed to the respective wip ref. + + To view the log for the a branch and its wip refs use the commands +‘magit-wip-log’ and ‘magit-wip-log-current’. You should use ‘--graph’ +when using these commands. Alternatively you can use the reflog to show +all commits that ever existed on a wip ref. You can then recover lost +changes from the commits shown in the log or reflog. + + -- Command: magit-wip-log + + This command shows the log for a branch and its wip refs. + + With a negative prefix argument only the worktree wip ref is shown. + The absolute numeric value of the prefix argument controls how many + "branches" of each wip ref are shown. + + -- Command: magit-wip-log-current + + This command shows the log for the current branch and its wip refs. + + With a negative prefix argument only the worktree wip ref is shown. + The absolute numeric value of the prefix argument controls how many + "branches" of each wip ref are shown. + + There exists a total of three global modes that save to the wip refs, +which might seem excessive, but allows fine tuning of when exactly +changes are being committed to the wip refs. Enabling all modes makes +it less likely that a change slips through the cracks. + + Setting the below variable directly does not take effect; either +customize them or call the respective mode function. + + -- User Option: magit-wip-after-save-mode + + When this mode is enabled, then saving a buffer that visits a file + tracked in a Git repository causes its current state to be + committed to the working tree wip ref for the current branch. + + -- User Option: magit-wip-after-apply-mode + + When this mode is enabled, then applying (i.e. staging, unstaging, + discarding, reversing, and regularly applying) a change to a file + tracked in a Git repository causes its current state to be + committed to the index and/or working tree wip refs for the current + branch. + + If you only ever edit files using Emacs and only ever interact with +Git using Magit, then the above two modes should be enough to protect +each and every change from accidental loss. In practice nobody does +that. So an additional mode exists that does commit to the wip refs +before making changes that could cause the loss of earlier changes. + + -- User Option: magit-wip-before-change-mode + + When this mode is enabled, then certain commands commit the + existing changes to the files they are about to make changes to. + + Note that even if you enable all three modes this won’t give you +perfect protection. The most likely scenario for losing changes despite +the use of these modes is making a change outside Emacs and then +destroying it also outside Emacs. In such a scenario, Magit, being an +Emacs package, didn’t get the opportunity to keep you from shooting +yourself in the foot. + + When you are unsure whether Magit did commit a change to the wip +refs, then you can explicitly request that all changes to all tracked +files are being committed. + +‘M-x magit-wip-commit’ (‘magit-wip-commit’) + + This command commits all changes to all tracked files to the index + and working tree work-in-progress refs. Like the modes described + above, it does not commit untracked files, but it does check all + tracked files for changes. Use this command when you suspect that + the modes might have overlooked a change made outside Emacs/Magit. + + -- User Option: magit-wip-after-save-local-mode-lighter + + Mode-line lighter for ‘magit-wip-after-save-local-mode’. + + -- User Option: magit-wip-after-apply-mode-lighter + + Mode-line lighter for ‘magit-wip-after-apply-mode’. + + -- User Option: magit-wip-before-change-mode-lighter + + Mode-line lighter for ‘magit-wip-before-change-mode’. + + -- User Option: magit-wip-namespace + + The namespace used for work-in-progress refs. It has to end with a + slash. The wip refs are named "index/" and + "wtree/". When snapshots are created while + the ‘HEAD’ is detached then "HEAD" is used in place of + ‘’. + + +File: magit.info, Node: Minor mode for buffers visiting files, Next: Minor mode for buffers visiting blobs, Prev: Wip modes, Up: Miscellaneous + +8.6 Minor mode for buffers visiting files +========================================= + +The ‘magit-file-mode’ enables certain Magit features in file-visiting +buffers belonging to a Git repository. It should be enabled globally +using ‘global-magit-file-mode’. Currently this mode only establishes a +few key bindings, but this might be extended in the future. + + -- User Option: global-magit-file-mode + + Whether to establish certain Magit key bindings in all + file-visiting buffers belonging to a Git repository. This + establishes the bindings suggested in *note Getting started: + Getting started. (but only for file-visiting buffers), and + additionally binds ‘C-c M-g’ to ‘magit-file-popup’. + +‘C-c M-g’ (‘magit-file-popup’) + + This prefix command shows a popup buffer featuring suffix commands + that operate on the file being visited in the current buffer. + +‘C-c M-g s’ (‘magit-stage-file’) + + Stage all changes to the file being visited in the current buffer. + +‘C-c M-g u’ (‘magit-unstage-file’) + + Unstage all changes to the file being visited in the current + buffer. + +‘C-c M-g l’ (‘magit-log-buffer-file’) + + This command shows the log for the file of blob that the current + buffer visits. Renames are followed when a prefix argument is used + or when ‘--follow’ is part of ‘magit-log-arguments’. + +‘C-c M-g b’ (‘magit-blame-popup’) + + This prefix command shows the ‘magit-blame’ suffix command along + with the appropriate infix arguments in a popup buffer. See *note + Initiating a commit: Initiating a commit. + +‘C-c M-g p’ (‘magit-blob-previous’) + + Visit the previous blob which modified the current file. + +‘C-c M-g c’ (‘magit-commit-popup’) + + This prefix command shows suffix commands along with the + appropriate infix arguments in a popup buffer. See *note + Initiating a commit: Initiating a commit. + + +File: magit.info, Node: Minor mode for buffers visiting blobs, Prev: Minor mode for buffers visiting files, Up: Miscellaneous + +8.7 Minor mode for buffers visiting blobs +========================================= + +The ‘magit-blob-mode’ enables certain Magit features in blob-visiting +buffers. Such buffers can be created using ‘magit-find-file’ and some +of the commands mentioned below, which also take care of turning on this +minor mode. Currently this mode only establishes a few key bindings, +but this might be e + +‘p’ (‘magit-blob-previous’) + + Visit the previous blob which modified the current file. + +‘n’ (‘magit-blob-next’) + + Visit the next blob which modified the current file. + +‘q’ (‘magit-kill-this-buffer’) + + Kill the current buffer. + + +File: magit.info, Node: Customizing, Next: Plumbing, Prev: Miscellaneous, Up: Top + +9 Customizing +************* + +Both Git and Emacs are highly customizable. Magit is both a Git +porcelain as well as an Emacs package, so it makes sense to customize it +using both Git variables as well as Emacs options. However this +flexibility doesn’t come without problems, including but not limited to +the following. + + • Some Git variables automatically have an effect in Magit without + requiring any explicit support. Sometimes that is desirable - in + other cases, it breaks Magit. + + When a certain Git setting breaks Magit but you want to keep using + that setting on the command line, then that can be accomplished by + overriding the value for Magit only by appending something like + ‘("-c" "some.variable=compatible-value")’ to + ‘magit-git-global-arguments’. + + • Certain settings like ‘fetch.prune=true’ are respected by Magit + commands (because they simply call the respective Git command) but + their value is not reflected in the respective popup buffers. In + this case the ‘--prune’ argument in ‘magit-fetch-popup’ might be + active or inactive depending on the value of + ‘magit-fetch-arguments’ only, but that doesn’t keep the Git + variable from being honored by the suffix commands anyway. So + pruning might happen despite the the ‘--prune’ arguments being + displayed in a way that seems to indicate that no pruning will + happen. + + I intend to address these and similar issues in a future release. + +* Menu: + +* Per-repository configuration:: +* Essential settings:: + + +File: magit.info, Node: Per-repository configuration, Next: Essential settings, Up: Customizing + +9.1 Per-repository configuration +================================ + +Magit can be configured on a per-repository level using both Git +variables as well as Emacs options. + + To set a Git variable for one repository only, simply set it in +‘/path/to/repo/.git/config’ instead of ‘$HOME/.gitconfig’ or +‘/etc/gitconfig’. See *note (gitman)git-config:: . + + Similarly, Emacs options can be set for one repository only by +editing ‘/path/to/repo/.dir-locals.el’. See *note (emacs)Directory +Variables::. For example to disable automatic refreshes of +file-visiting buffers in just one huge repository use this: + + • ‘/path/to/huge/repo/.dir-locals.el’ + + ((nil . ((magit-refresh-buffers . nil)) + + If you want to apply the same settings to several, but not all, +repositories then keeping the repository-local config files in sync +would quickly become annoying. To avoid that you can create config +files for certain classes of repositories (e.g. "huge repositories") +and then include those files in the per-repository config files. For +example: + + • ‘/path/to/huge/repo/.git/config’ + + [include] + path = /path/to/huge-gitconfig + + • ‘/path/to/huge-gitconfig’ + + [status] + showUntrackedFiles = no + + • ‘$HOME/.emacs.d/init.el’ + + (dir-locals-set-class-variables 'huge-git-repository + '((nil . ((magit-refresh-buffers . nil))))) + + (dir-locals-set-directory-class + "/path/to/huge/repo/" 'huge-git-repository) + + +File: magit.info, Node: Essential settings, Prev: Per-repository configuration, Up: Customizing + +9.2 Essential settings +====================== + +The next two sections list and discuss several variables that many users +might want to customize, for safety and/or performance reasons. + +* Menu: + +* Safety:: +* Performance:: + + +File: magit.info, Node: Safety, Next: Performance, Up: Essential settings + +9.2.1 Safety +------------ + +This section discusses various variables that you might want to change +(or *not* change) for safety reasons. + + Git keeps *committed* changes around long enough for users to recover +changes they have accidentally deleted. It does not do the same for +*uncommitted* changes in the working tree and not even the index (the +staging area). Because Magit makes it so easy to modify uncommitted +changes, it also makes it easy to shoot yourself in the foot in the +process. For that reason Magit provides three global modes that save +*tracked* files to work-in-progress references after or before certain +actions. See *note Wip modes: Wip modes. + + These modes are not enabled by default because of performance +concerns. Instead a lot of potentially destructive commands require +confirmation every time they are used. In many cases this can be +disabled by adding a symbol to ‘magit-no-confirm’ (see *note Completion +and confirmation: Completion and confirmation.). If you enable the +various wip modes then you should add ‘safe-with-wip’ to this list. + + Similarly it isn’t necessary to require confirmation before moving a +file to the system trash - if you trashed a file by mistake then you can +recover it from the there. Option ‘magit-delete-by-moving-to-trash’ +controls whether the system trash is used, which is the case by default. +Nevertheless, ‘trash’ isn’t a member of ‘magit-no-confirm’ - you might +want to change that. + + Buffers visiting files tracked in the current repository are being +refreshed before certain actions. See *note Automatic refresh and +revert: Automatic refresh and revert. This isn’t as risky as it might +seem. If a buffer is modified (i.e. it contains changes that haven’t +been saved yet), then Emacs/Magit would refuse to revert it. If the +buffer has been saved resulting in what is seen by Git as an uncommitted +change, then Git in turn would refuse to carry out the action that would +cause these changes to be lost. Since Git doesn’t do anything, the file +doesn’t change on disk, and Emacs/Magit has nothing to revert. + + However if you do modify some files, visit the respective files in +Emacs, somehow discard the changes (not using Magit and probably even +outside Emacs), and then expect the respective file-visiting buffers to +retain the uncommitted changes, then the automatic reverting would +actually be harmful. In other words if you use file-visiting buffers as +a sort of "staging area", then you should set ‘magit-revert-buffers’ to +‘nil’. + + So far I have only heard from one user who uses such a workflow. But +because there might be some other users doing such things, and I don’t +want to be responsible for data loss, these reverts by default happen +quite verbosely, allowing these few users to undo the reverts using the +‘undo’ command and then disabling the automatic reverts for the future. +Most users should however keep automatic reverts turned on and instead +configure it to be less verbose by setting ‘magit-revert-buffers’ to ‘t’ +or even ‘silent’. This option is mentioned again in the next section. + + +File: magit.info, Node: Performance, Prev: Safety, Up: Essential settings + +9.2.2 Performance +----------------- + +Magit is slower than raw Git because it does more. For example ‘git +commit’ creates a commit and that’s it. ‘magit-commit’ also updates the +current Magit buffer to make sure you are not looking at outdated +information without noticing it. To refresh the status buffer, Magit +has to run Git a dozen times or more, making it slower than ‘git +status’, but also much more informative. Magit also optionally reverts +file-visiting buffers, creates backups, runs hooks where third-party +extensions can do their slow thing, etc. + + I do care about performance and try to optimize for it as much as +possible, but many features simply come with an inherent performance +penalty. When a feature is just too slow given certain usage and +repository characteristics, then it often can be disabled, globally or +on a per-repository basis. + + But first a short list of performance issues that cannot easily be +worked around: + + • Creating a new process on MS Windows is much slower than on + POSIX-compatible systems. This is a problem because Magit creates + a lot of child processes to retrieve information from Git. In the + short run, only switching to a POSIX system can fix this. Of + course this could also be fixed in Windows itself, but I am just + one unpaid person while Microsoft is a billion dollar company, so I + will leave it to them to fix this grave flaw in their OS. + + • When showing logs, Magit limits the number of commits initially + shown in the hope that this avoids unnecessary work. When using + ‘--graph’ this unfortunately does not have the desired effect for + large histories. Junio said on the git mailing list + (): "‘--graph’ + wants to compute the whole history and the max-count only affects + the output phase after ‘--graph’ does its computation". + + In other words, it’s not that Git is slow at outputting the + differences, or that Magit is slow at parsing the output - the + problem is that Git first goes outside and has a smoke. + + We actually work around this issue by limiting the commit not only + using ‘-’ but also using a range. But unfortunately that’s not + always possible. + + • Whenever "something changes", Magit "refreshes" the status buffer + and the current Magit buffer by recreating them from scratch. This + is an old design decision that we couldn’t depart from easily. And + it has its benefits too - most importantly it’s much simpler and + less error prone to do it this way than to only refreshing "what + actually has changed" (that would basically be a huge collection of + special cases). So for now at least, we don’t avoid recreating the + buffer content and instead focus on making doing so faster. + + Now for the things that you can do to improve performance: + + Most optional features which can have a negative effect on +performance are disabled by default. So start by checking the options +you have explicitly enabled. Even the potentially slow features are +expected to only lead to barely noticeable delays, but your mileage may +vary. Also note that it is now possible to set options on a +per-repository or per-repository-class basis. See *note Per-repository +configuration: Per-repository configuration. + + You should check the values of at least the following variables: + + • ‘magit-after-revert-hook’ + + • ‘magit-diff-auto-show’ + + • ‘magit-diff-highlight-hunk-body’ + + • ‘magit-diff-highlight-indentation’ + + • ‘magit-diff-highlight-trailing’ + + • ‘magit-diff-paint-whitespace’ + + • ‘magit-diff-refine-hunk’ + + • ‘magit-log-arguments’, ‘magit-log-select-arguments’, and + ‘magit-log-section-arguments’ + + In repositories with more than a few thousand commits ‘--graph’ + should never be a member of ‘magit-log-section-arguments’. That + variable is in the status buffer which is refreshed every time you + run any Magit command. + + Using ‘--color --graph’ is even slower. Magit uses code that is + part of Emacs to turn control characters into faces. That code is + pretty slow and this is quite noticeable when showing a log with + many branches and merges. For that reason ‘--color’ is not enabled + by default anymore. Consider leaving it at that. + + • ‘magit-revert-buffers’ + + After running certain commands, after refreshing the current Magit + buffer, unmodified buffers visiting files belonging to the current + repository are reverted. By default that happens synchronously, + which can be an issue if you visit many buffers. Set this variable + to a number to revert asynchronously. It’s best to use a negative + number because that causes the reverts to happen silently (which is + desirable because the revert messages would otherwise shadow other, + more important messages). + + • ‘magit-not-reverted-hook’ + + • ‘magit-refresh-buffer-hook’ + + If third-party packages add functions to these hooks, then you + might want to consider removing them again. + + • ‘magit-refs-sections-hook’ + + When refreshing the "references buffer" is slow, then that’s + usually because several hundred refs are being displayed. The best + way to address that is to display fewer refs, obviously. + + If you are not, or only mildly, interested in seeing the list of + tags, then start by not displaying them: + + (remove-hook 'magit-refs-sections-hook 'magit-insert-tags) + + Then you should also make sure that the listed remote branches + actually all exist. You can do so by pruning branches which no + longer exist using ‘f-pa’. + + • ‘magit-status-refresh-hook’ + + • ‘magit-wip-after-apply-mode’ + + • ‘magit-wip-after-save-mode’ + + • ‘magit-wip-before-change-mode’ + + Also note that everything involving "cherry commits" is slow. + + If, after actually trying the above suggestions, performance is still +bad, and the above does not contain a statement explaining why that is +so in that particular case and that there is nothing that we can +currently do about it, then comment on the appropriate existing issue +(see ), or if +necessary open a new issue. Note that "something is slow, I am using +v2.2" is not helpful, you have to be a bit more specific. Benchmarks +are a start. + + +File: magit.info, Node: Plumbing, Next: FAQ, Prev: Customizing, Up: Top + +10 Plumbing +*********** + +The following sections describe how to use several of Magit’s core +abstractions to extend Magit itself or implement a separate extension. + + A few of the low-level features used by Magit have been factored out +into separate libraries/packages, so that they can be used by other +packages, without having to depend on Magit. These libraries are +described in separate manuals, see *note (with-editor)Top:: and *note +(magit-popup)Top::. + +* Menu: + +* Calling Git:: +* Section plumbing:: +* Refreshing buffers:: +* Conventions:: + + +File: magit.info, Node: Calling Git, Next: Section plumbing, Up: Plumbing + +10.1 Calling Git +================ + +Magit provides many specialized functions for calling Git. All of these +functions are defined in either ‘magit-git.el’ or ‘magit-process.el’ and +have one of the prefixes ‘magit-run-’, ‘magit-call-’, ‘magit-start-’, or +‘magit-git-’ (which is also used for other things). + + All of these functions accept an indefinite number of arguments, +which are strings that specify command line arguments for git (or in +some cases an arbitrary executable). These arguments are flattened +before being passed on to the executable; so instead of strings they can +also be lists of strings and arguments that are ‘nil’ are silently +dropped. Some of these functions also require a single mandatory +argument before these command line arguments. + + Roughly speaking these functions run Git either to get some value or +for side-effect. The functions that return a value are useful to +collect the information necessary to populate a Magit buffer, while the +others are used to implement Magit commands. + + The functions in the value-only group always run synchronously, and +they never trigger a refresh. The function in the side-effect group can +be further divided into subgroups depending on whether they run Git +synchronously or asynchronously, and depending on whether they trigger a +refresh when the executable has finished. + +* Menu: + +* Getting a value from Git:: +* Calling Git for effect:: + + +File: magit.info, Node: Getting a value from Git, Next: Calling Git for effect, Up: Calling Git + +10.1.1 Getting a value from Git +------------------------------- + +These functions run Git in order to get a value, either its exit status +or its output. Of course you could also use them to run Git commands +that have side-effects, but that should be avoided. + + -- Function: magit-git-exit-code &rest args + + Executes git with ARGS and returns its exit code. + + -- Function: magit-git-success &rest args + + Executes git with ARGS and returns ‘t’ if the exit code is ‘0’, + ‘nil’ otherwise. + + -- Function: magit-git-failure &rest args + + Executes git with ARGS and returns ‘t’ if the exit code is ‘1’, + ‘nil’ otherwise. + + -- Function: magit-git-true &rest args + + Executes git with ARGS and returns ‘t’ if the first line printed by + git is the string "true", ‘nil’ otherwise. + + -- Function: magit-git-false &rest args + + Executes git with ARGS and returns ‘t’ if the first line printed by + git is the string "false", ‘nil’ otherwise. + + -- Function: magit-git-insert &rest args + + Executes git with ARGS and inserts its output at point. + + -- Function: magit-git-string &rest args + + Executes git with ARGS and returns the first line of its output. + If there is no output or if it begins with a newline character, + then this returns ‘nil’. + + -- Function: magit-git-lines &rest args + + Executes git with ARGS and returns its output as a list of lines. + Empty lines anywhere in the output are omitted. + + -- Function: magit-git-items &rest args + + Executes git with ARGS and returns its null-separated output as a + list. Empty items anywhere in the output are omitted. + + If the value of option ‘magit-git-debug’ is non-nil and git exits + with a non-zero exit status, then warn about that in the echo area + and add a section containing git’s standard error in the current + repository’s process buffer. + + When an error occurs when using one of the above functions, then that +is usually due to a bug, i.e. the use of an argument which is not +actually supported. Such errors are usually not reported, but when they +occur we need to be able to debug them. + + -- User Option: magit-git-debug + + Whether to report errors that occur when using ‘magit-git-insert’, + ‘magit-git-string’, ‘magit-git-lines’, or ‘magit-git-items’. This + does not actually raise an error. Instead a message is shown in + the echo area, and git’s standard error is insert into a new + section in the current repository’s process buffer. + + -- Function: magit-git-str &rest args + + This is a variant of ‘magit-git-string’ that ignores the option + ‘magit-git-debug’. It is mainly intended to be used while handling + errors in functions that do respect that option. Using such a + function while handing an error could cause yet another error and + therefore lead to an infinite recursion. You probably won’t ever + need to use this function. + + +File: magit.info, Node: Calling Git for effect, Prev: Getting a value from Git, Up: Calling Git + +10.1.2 Calling Git for effect +----------------------------- + +These functions are used to run git to produce some effect. Most Magit +commands that actually run git do so by using such a function. + + Because we do not need to consume git’s output when using these +functions, their output is instead logged into a per-repository buffer, +which can be shown using ‘$’ from a Magit buffer or ‘M-x magit-process’ +elsewhere. + + These functions can have an effect in two distinct ways. Firstly, +running git may change something, i.e. create or push a new commit. +Secondly, that change may require that Magit buffers are refreshed to +reflect the changed state of the repository. But refreshing isn’t +always desirable, so only some of these functions do perform such a +refresh after git has returned. + + Sometimes it is useful to run git asynchronously. For example, when +the user has just initiated a push, then there is no reason to make her +wait until that has completed. In other cases it makes sense to wait +for git to complete before letting the user do something else. For +example after staging a change it is useful to wait until after the +refresh because that also automatically moves to the next change. + + -- Function: magit-call-git &rest args + + Calls git synchronously with ARGS. + + -- Function: magit-call-process program &rest args + + Calls PROGRAM synchronously with ARGS. + + -- Function: magit-run-git &rest args + + Calls git synchronously with ARGS and then refreshes. + + -- Function: magit-run-git-with-input input &rest args + + Calls git synchronously with ARGS and sends it INPUT on standard + input. + + INPUT should be a buffer or the name of an existing buffer. The + content of that buffer is used as the process’ standard input. + After the process returns a refresh is performed. + + As a special case, INPUT may also be nil. In that case the content + of the current buffer is used as standard input and *no* refresh is + performed. + + This function actually runs git asynchronously. But then it waits + for the process to return, so the function itself is synchronous. + + -- Function: magit-run-git-with-logfile file &rest args + + Calls git synchronously with ARGS. The process’ output is saved in + FILE. This is rarely useful and so this function might be removed + in the future. + + This function actually runs git asynchronously. But then it waits + for the process to return, so the function itself is synchronous. + + -- Function: magit-git &rest args + + Calls git synchronously with ARGS for side-effects only. This + function does not refresh the buffer. + + -- Function: magit-git-wash washer &rest args + + Execute Git with ARGS, inserting washed output at point. Actually + first insert the raw output at point. If there is no output call + ‘magit-cancel-section’. Otherwise temporarily narrow the buffer to + the inserted text, move to its beginning, and then call function + WASHER with no argument. + + And now for the asynchronous variants. + + -- Function: magit-run-git-async &rest args + + Start Git, prepare for refresh, and return the process object. + ARGS is flattened and then used as arguments to Git. + + Display the command line arguments in the echo area. + + After Git returns some buffers are refreshed: the buffer that was + current when this function was called (if it is a Magit buffer and + still alive), as well as the respective Magit status buffer. + Unmodified buffers visiting files that are tracked in the current + repository are reverted if ‘magit-revert-buffers’ is non-nil. + + -- Function: magit-run-git-with-editor &rest args + + Export GIT_EDITOR and start Git. Also prepare for refresh and + return the process object. ARGS is flattened and then used as + arguments to Git. + + Display the command line arguments in the echo area. + + After Git returns some buffers are refreshed: the buffer that was + current when this function was called (if it is a Magit buffer and + still alive), as well as the respective Magit status buffer. + + -- Function: magit-start-git &rest args + + Start Git, prepare for refresh, and return the process object. + + If INPUT is non-nil, it has to be a buffer or the name of an + existing buffer. The buffer content becomes the processes standard + input. + + Option ‘magit-git-executable’ specifies the Git executable and + option ‘magit-git-global-arguments’ specifies constant arguments. + The remaining arguments ARGS specify arguments to Git. They are + flattened before use. + + After Git returns, some buffers are refreshed: the buffer that was + current when this function was called (if it is a Magit buffer and + still alive), as well as the respective Magit status buffer. + Unmodified buffers visiting files that are tracked in the current + repository are reverted if ‘magit-revert-buffers’ is non-nil. + + -- Function: magit-start-process &rest args + + Start PROGRAM, prepare for refresh, and return the process object. + + If optional argument INPUT is non-nil, it has to be a buffer or the + name of an existing buffer. The buffer content becomes the + processes standard input. + + The process is started using ‘start-file-process’ and then setup to + use the sentinel ‘magit-process-sentinel’ and the filter + ‘magit-process-filter’. Information required by these functions is + stored in the process object. When this function returns the + process has not started to run yet so it is possible to override + the sentinel and filter. + + After the process returns, ‘magit-process-sentinel’ refreshes the + buffer that was current when ‘magit-start-process’ was called (if + it is a Magit buffer and still alive), as well as the respective + Magit status buffer. Unmodified buffers visiting files that are + tracked in the current repository are reverted if + ‘magit-revert-buffers’ is non-nil. + + -- Variable: magit-this-process + + The child process which is about to start. This can be used to + change the filter and sentinel. + + -- Variable: magit-process-raise-error + + When this is non-nil, then ‘magit-process-sentinel’ raises an error + if git exits with a non-zero exit status. For debugging purposes. + + +File: magit.info, Node: Section plumbing, Next: Refreshing buffers, Prev: Calling Git, Up: Plumbing + +10.2 Section plumbing +===================== + +* Menu: + +* Creating sections:: +* Section selection:: +* Matching sections:: + + +File: magit.info, Node: Creating sections, Next: Section selection, Up: Section plumbing + +10.2.1 Creating sections +------------------------ + + -- Macro: magit-insert-section &rest args + + Insert a section at point. + + TYPE is the section type, a symbol. Many commands that act on the + current section behave differently depending on that type. Also if + a variable ‘magit-TYPE-section-map’ exists, then use that as the + text-property ‘keymap’ of all text belonging to the section (but + this may be overwritten in subsections). + + Optional VALUE is the value of the section, usually a string that + is required when acting on the section. + + When optional HIDE is non-nil collapse the section body by default, + i.e. when first creating the section, but not when refreshing the + buffer. Otherwise, expand it by default. This can be overwritten + using ‘magit-section-set-visibility-hook’. When a section is + recreated during a refresh, then the visibility of predecessor is + inherited and HIDE is ignored (but the hook is still honored). + + BODY is any number of forms that actually insert the section’s + heading and body. Optional NAME, if specified, has to be a symbol, + which is then bound to the struct of the section being inserted. + + Before BODY is evaluated the ‘start’ of the section object is set + to the value of ‘point’ and after BODY was evaluated its ‘end’ is + set to the new value of ‘point’; BODY is responsible for moving + ‘point’ forward. + + If it turns out inside BODY that the section is empty, then + ‘magit-cancel-section’ can be used to abort and remove all traces + of the partially inserted section. This can happen when creating a + section by washing Git’s output and Git didn’t actually output + anything this time around. + + -- Function: magit-insert-heading &rest args + + Insert the heading for the section currently being inserted. + + This function should only be used inside ‘magit-insert-section’. + + When called without any arguments, then just set the ‘content’ slot + of the object representing the section being inserted to a marker + at ‘point’. The section should only contain a single line when + this function is used like this. + + When called with arguments ARGS, which have to be strings, then + insert those strings at point. The section should not contain any + text before this happens and afterwards it should again only + contain a single line. If the ‘face’ property is set anywhere + inside any of these strings, then insert all of them unchanged. + Otherwise use the ‘magit-section-heading’ face for all inserted + text. + + The ‘content’ property of the section struct is the end of the + heading (which lasts from ‘start’ to ‘content’) and the beginning + of the body (which lasts from ‘content’ to ‘end’). If the value of + ‘content’ is nil, then the section has no heading and its body + cannot be collapsed. If a section does have a heading then its + height must be exactly one line, including a trailing newline + character. This isn’t enforced; you are responsible for getting it + right. The only exception is that this function does insert a + newline character if necessary. + + -- Function: magit-cancel-section + + Cancel the section currently being inserted. This exits the + innermost call to ‘magit-insert-section’ and removes all traces of + what has already happened inside that call. + + -- Function: magit-define-section-jumper sym title &optional value + + Define an interactive function to go to section SYM. TITLE is the + displayed title of the section. + + +File: magit.info, Node: Section selection, Next: Matching sections, Prev: Creating sections, Up: Section plumbing + +10.2.2 Section selection +------------------------ + + -- Function: magit-current-section + + Return the section at point. + + -- Function: magit-region-sections + + Return a list of the selected sections. + + When the region is active and constitutes a valid section + selection, then return a list of all selected sections. This is + the case when the region begins in the heading of a section and + ends in the heading of a sibling of that first section. When the + selection is not valid then return nil. Most commands that can act + on the selected sections, then instead just act on the current + section, the one point is in. + + When the region looks like it would in any other buffer then the + selection is invalid. When the selection is valid then the region + uses the ‘magit-section-highlight’. This does not apply to diffs + where things get a bit more complicated, but even here if the + region looks like it usually does, then that’s not a valid + selection as far as this function is concerned. + + -- Function: magit-region-values &rest types + + Return a list of the values of the selected sections. + + Also see ‘magit-region-sections’ whose doc-string explains when a + region is a valid section selection. If the region is not active + or is not a valid section selection, then return nil. If optional + TYPES is non-nil then the selection not only has to be valid; the + types of all selected sections additionally have to match one of + TYPES, or nil is returned. + + +File: magit.info, Node: Matching sections, Prev: Section selection, Up: Section plumbing + +10.2.3 Matching sections +------------------------ + +‘M-x magit-describe-section’ (‘magit-describe-section’) + + Show information about the section at point. This command is + intended for debugging purposes. + + -- Function: magit-section-ident + + Return an unique identifier for SECTION. The return value has the + form ‘((TYPE . VALUE)...)’. + + -- Function: magit-get-section + + Return the section identified by IDENT. IDENT has to be a list as + returned by ‘magit-section-ident’. + + -- Function: magit-section-match condition &optional section + + Return ‘t’ if SECTION matches CONDITION. SECTION defaults to the + section at point. + + Conditions can take the following forms: + • ‘(CONDITION...)’ + + matches if any of the CONDITIONs matches. + + • ‘[TYPE...]’ + + matches if the first TYPE matches the type of the section at + point, the second matches that of its parent, and so on. + + • ‘[* TYPE...]’ + + matches sections that match [TYPE…] and also recursively all + their child sections. + + • ‘TYPE’ + + matches TYPE regardless of its parents. + Each TYPE is a symbol. Note that is not necessary to specify all + TYPEs up to the root section as printed by ‘magit-describe-type’, + unless of course your want to be that precise. + + -- Function: magit-section-when condition &rest body + + If the section at point matches CONDITION evaluate BODY. + + If the section matches evaluate BODY forms sequentially and return + the value of the last one, or if there are no BODY forms return the + value of the section. If the section does not match return nil. + + See ‘magit-section-match’ for the forms CONDITION can take. + + -- Function: magit-section-case &rest clauses + + Choose among clauses on the type of the section at point. + + Each clause looks like (CONDITION BODY…). The type of the section + is compared against each CONDITION; the BODY forms of the first + match are evaluated sequentially and the value of the last form is + returned. Inside BODY the symbol ‘it’ is bound to the section at + point. If no clause succeeds or if there is no section at point + return nil. + + See ‘magit-section-match’ for the forms CONDITION can take. + Additionally a CONDITION of t is allowed in the final clause and + matches if no other CONDITION match, even if there is no section at + point. + + -- Variable: magit-root-section + + The root section in the current buffer. All other sections are + descendants of this section. The value of this variable is set by + ‘magit-insert-section’ and you should never modify it. + + For diff related sections a few additional tools exist. + + -- Function: magit-diff-type &optional section + + Return the diff type of SECTION. + + The returned type is one of the symbols ‘staged’, ‘unstaged’, + ‘committed’, or ‘undefined’. This type serves a similar purpose as + the general type common to all sections (which is stored in the + ‘type’ slot of the corresponding ‘magit-section’ struct) but takes + additional information into account. When the SECTION isn’t + related to diffs and the buffer containing it also isn’t a + diff-only buffer, then return nil. + + Currently the type can also be one of ‘tracked’ and ‘untracked’, + but these values are not handled explicitly in every place they + should be. A possible fix could be to just return nil here. + + The section has to be a ‘diff’ or ‘hunk’ section, or a section + whose children are of type ‘diff’. If optional SECTION is nil, + return the diff type for the current section. In buffers whose + major mode is ‘magit-diff-mode’ SECTION is ignored and the type is + determined using other means. In ‘magit-revision-mode’ buffers the + type is always ‘committed’. + + -- Function: magit-diff-scope &optional section strict + + Return the diff scope of SECTION or the selected section(s). + + A diff’s "scope" describes what part of a diff is selected, it is a + symbol, one of ‘region’, ‘hunk’, ‘hunks’, ‘file’, ‘files’, or + ‘list’. Do not confuse this with the diff "type", as returned by + ‘magit-diff-type’. + + If optional SECTION is non-nil, then return the scope of that, + ignoring the sections selected by the region. Otherwise return the + scope of the current section, or if the region is active and + selects a valid group of diff related sections, the type of these + sections, i.e. ‘hunks’ or ‘files’. If SECTION (or if the current + section that is nil) is a ‘hunk’ section and the region starts and + ends inside the body of a that section, then the type is ‘region’. + + If optional STRICT is non-nil then return nil if the diff type of + the section at point is ‘untracked’ or the section at point is not + actually a ‘diff’ but a ‘diffstat’ section. + + +File: magit.info, Node: Refreshing buffers, Next: Conventions, Prev: Section plumbing, Up: Plumbing + +10.3 Refreshing buffers +======================= + +All commands that create a new Magit buffer or change what is being +displayed in an existing buffer do so by calling ‘magit-mode-setup’. +Among other things, that function sets the buffer local values of +‘default-directory’ (to the top-level of the repository), +‘magit-refresh-function’, and ‘magit-refresh-args’. + + Buffers are refreshed by calling the function that is the local value +of ‘magit-refresh-function’ (a function named ‘magit-*-refresh-buffer’, +where ‘*’ may be something like ‘diff’) with the value of +‘magit-refresh-args’ as arguments. + + -- Macro: magit-mode-setup buffer switch-func mode refresh-func + &optional refresh-args + + This function displays and selects BUFFER, turns on MODE, and + refreshes a first time. + + This function displays and optionally selects BUFFER by calling + ‘magit-mode-display-buffer’ with BUFFER, MODE and SWITCH-FUNC as + arguments. Then it sets the local value of + ‘magit-refresh-function’ to REFRESH-FUNC and that of + ‘magit-refresh-args’ to REFRESH-ARGS. Finally it creates the buffer + content by calling REFRESH-FUNC with REFRESH-ARGS as arguments. + + All arguments are evaluated before switching to BUFFER. + + -- Function: magit-mode-display-buffer buffer mode &optional + switch-function + + This function display BUFFER in some window and select it. BUFFER + may be a buffer or a string, the name of a buffer. The buffer is + returned. + + Unless BUFFER is already displayed in the selected frame, store the + previous window configuration as a buffer local value, so that it + can later be restored by ‘magit-mode-bury-buffer’. + + The buffer is displayed and selected using SWITCH-FUNCTION. If that + is ‘nil’ then ‘pop-to-buffer’ is used if the current buffer’s major + mode derives from ‘magit-mode’. Otherwise ‘switch-to-buffer’ is + used. + + -- Variable: magit-refresh-function + + The value of this buffer-local variable is the function used to + refresh the current buffer. It is called with ‘magit-refresh-args’ + as arguments. + + -- Variable: magit-refresh-args + + The list of arguments used by ‘magit-refresh-function’ to refresh + the current buffer. ‘magit-refresh-function’ is called with these + arguments. + + The value is usually set using ‘magit-mode-setup’, but in some + cases it’s also useful to provide commands which can change the + value. For example, the ‘magit-diff-refresh-popup’ can be used to + change any of the arguments used to display the diff, without + having to specify again which differences should be shown. + ‘magit-diff-more-context’, ‘magit-diff-less-context’, and + ‘magit-diff-default-context’ change just the ‘-U’ argument. In + both case this is done by changing the value of this variable and + then calling this ‘magit-refresh-function’. + + +File: magit.info, Node: Conventions, Prev: Refreshing buffers, Up: Plumbing + +10.4 Conventions +================ + +* Menu: + +* Confirmation and completion:: +* Theming Faces:: + + +File: magit.info, Node: Confirmation and completion, Next: Theming Faces, Up: Conventions + +10.4.1 Confirmation and completion +---------------------------------- + +Dangerous operations that may lead to data loss have to be confirmed by +default. With a multi-section selection, this is done using questions +that can be answered with "yes" or "no". When the region isn’t active, +or if it doesn’t constitute a valid section selection, then such +commands instead read a single item in the minibuffer. When the value +of the current section is among the possible choices, then that is +presented as default choice. To confirm the action on a single item, +the user has to answer ‘RET’ (instead of "yes"), and to abort, ‘C-g’ +(instead of "no"). But alternatively the user may also select another +item, just like if the command had been invoked with no suitable section +at point at all. + + +File: magit.info, Node: Theming Faces, Prev: Confirmation and completion, Up: Conventions + +10.4.2 Theming Faces +-------------------- + +The default theme uses blue for local branches, green for remote +branches, and goldenrod (brownish yellow) for tags. When creating a new +theme, you should probably follow that example. If your theme already +uses other colors, then stick to that. + + In older releases these reference faces used to have a background +color and a box around them. The basic default faces no longer do so, +to make Magit buffers much less noisy, and you should follow that +example at least with regards to boxes. (Boxes were used in the past to +work around a conflict between the highlighting overlay and text +property backgrounds. That’s no longer necessary because highlighting +no longer causes other background colors to disappear.) Alternatively +you can keep the background color and/or box, but then have to take +special care to adjust ‘magit-branch-current’ accordingly. By default +it looks mostly like ‘magit-branch-local’, but with a box (by default +the former is the only face that uses a box, exactly so that it sticks +out). If the former also uses a box, then you have to make sure that it +differs in some other way from the latter. + + The most difficult faces to theme are those related to diffs, +headings, highlighting, and the region. There are faces that fall into +all four groups - expect to spend some time getting this right. + + The ‘region’ face in the default theme, in both the light and dark +variants, as well as in many other themes, distributed with Emacs or by +third-parties, is very ugly. It is common to use a background color +that really sticks out, which is ugly but if that were the only problem +then it would be acceptable. Unfortunately many themes also set the +foreground color, which ensures that all text within the region is +readable. Without doing that there might be cases where some foreground +color is too close to the region background color to still be readable. +But it also means that text within the region loses all syntax +highlighting. + + I consider the work that went into getting the ‘region’ face right to +be a good indicator for the general quality of a theme. My +recommendation for the ‘region’ face is this: use a background color +slightly different from the background color of the ‘default’ face, and +do not set the foreground color at all. So for a light theme you might +use a light (possibly tinted) gray as the background color of ‘default’ +and a somewhat darker gray for the background of ‘region’. That should +usually be enough to not collide with the foreground color of any other +face. But if some other faces also set a light gray as background +color, then you should also make sure it doesn’t collide with those (in +some cases it might be acceptable though). + + Magit only uses the ‘region’ face when the region is "invalid" by its +own definition. In a Magit buffer the region is used to either select +multiple sibling sections, so that commands which support it act on all +of these sections instead of just the current section, or to select +lines within a single hunk section. In all other cases, the section is +considered invalid and Magit won’t act on it. But such invalid sections +happen, either because the user has not moved point enough yet to make +it valid or because she wants to use a non-magit command to act on the +region, e.g. ‘kill-region’. + + So using the regular ‘region’ face for invalid sections is a feature. +It tells the user that Magit won’t be able to act on it. It’s +acceptable if that face looks a bit odd and even (but less so) if it +collides with the background colors of section headings and other things +that have a background color. + + Magit highlights the current section. If a section has subsections, +then all of them are highlighted. This is done using faces that have +"highlight" in their names. For most sections, +‘magit-section-highlight’ is used for both the body and the heading. +Like the ‘region’ face, it should only set the background color to +something similar to that of ‘default’. The highlight background color +must be different from both the ‘region’ background color and the +‘default’ background color. + + For diff related sections Magit uses various faces to highlight +different parts of the selected section(s). Note that hunk headings, +unlike all other section headings, by default have a background color, +because it is useful to have very visible separators between hunks. +That face ‘magit-diff-hunk-heading’, should be different from both +‘magit-diff-hunk-heading-highlight’ and ‘magit-section-highlight’, as +well as from ‘magit-diff-context’ and ‘magit-diff-context-highlight’. +By default we do that by changing the foreground color. Changing the +background color would lead to complications, and there are already +enough we cannot get around. (Also note that it is generally a good +idea for section headings to always be bold, but only for sections that +have subsections). + + When there is a valid region selecting diff-related sibling sections, +i.e. multiple files or hunks, then the bodies of all these sections use +the respective highlight faces, but additionally the headings instead +use one of the faces ‘magit-diff-file-heading-selection’ or +‘magit-diff-hunk-heading-selection’. These faces have to be different +from the regular highlight variants to provide explicit visual +indication that the region is active. + + When theming diff related faces, start by setting the option +‘magit-diff-refine-hunk’ to ‘all’. You might personally prefer to only +refine the current hunk or not use hunk refinement at all, but some of +the users of your theme want all hunks to be refined, so you have to +cater to that. + + (Also turn on ‘magit-diff-highlight-indentation’, +‘magit-diff-highlight-trailing’, and ‘magit-diff-paint-whitespace’; and +insert some whitespace errors into the code you use for testing.) + + For e.g. "added lines" you have to adjust three faces: +‘magit-diff-added’, ‘magit-diff-added-highlight’, and +‘smerge-refined-added’. Make sure that the latter works well with both +of the former, as well as ‘smerge-other’ and ‘diff-added’. Then do the +same for the removed lines, context lines, lines added by us, and lines +added by them. Also make sure the respective added, removed, and +context faces use approximately the same saturation for both the +highlighted and unhighlighted variants. Also make sure the file and +diff headings work nicely with context lines (e.g. make them look +different). Line faces should set both the foreground and the +background color. For example, for added lines use two different +greens. + + It’s best if the foreground color of both the highlighted and the +unhighlighted variants are the same, so you will need to have to find a +color that works well on the highlight and unhighlighted background, the +refine background, and the highlight context background. When there is +an hunk internal region, then the added- and removed-lines background +color is used only within that region. Outside the region the +highlighted context background color is used. This makes it easier to +see what is being staged. With an hunk internal region the hunk heading +is shown using ‘magit-diff-hunk-heading-selection’, and so are the thin +lines that are added around the lines that fall within the region. The +background color of that has to be distinct enough from the various +other involved background colors. + + Nobody said this would be easy. If your theme restricts itself to a +certain set of colors, then you should make an exception here. +Otherwise it would be impossible to make the diffs look good in each and +every variation. Actually you might want to just stick to the default +definitions for these faces. You have been warned. Also please note +that if you do not get this right, this will in some cases look to users +like bugs in Magit - so please do it right or not at all. + + +File: magit.info, Node: FAQ, Next: Keystroke Index, Prev: Plumbing, Up: Top + +Appendix A FAQ +************** + +Below you find a list of frequently asked questions. For a list of +frequently *and recently* asked questions, i.e. questions that haven’t +made it into the manual yet, see +. + +* Menu: + +* Magit is slow:: +* I changed several thousand files at once and now Magit is unusable:: +* I am having problems committing:: +* I don't like how branching and pushing works:: +* I cannot install the pre-requisites for Magit v2:: +* I am using an Emacs release older than v24.4: I am using an Emacs release older than v244. +* I am using a Git release older than v1.9.4: I am using a Git release older than v194. +* I am using MS Windows and cannot push with Magit:: +* How to install the gitman info manual?:: +* How can I show Git's output?:: +* Expanding a file to show the diff causes it to disappear:: +* Point is wrong in the COMMIT_EDITMSG buffer:: +* Can Magit be used as ediff-version-control-package?:: +* How to show diffs for gpg-encrypted files?:: +* Emacs 24.5 hangs when loading Magit: Emacs 245 hangs when loading Magit. + + +File: magit.info, Node: Magit is slow, Next: I changed several thousand files at once and now Magit is unusable, Up: FAQ + +A.1 Magit is slow +================= + +See *note Performance: Performance. + + +File: magit.info, Node: I changed several thousand files at once and now Magit is unusable, Next: I am having problems committing, Prev: Magit is slow, Up: FAQ + +A.2 I changed several thousand files at once and now Magit is unusable +====================================================================== + +Magit is *currently* not expected to work under such conditions. It +sure would be nice if it did, and v2.5 will hopefully be a big step into +that direction. But it might take until v3.1 to accomplish fully +satisfactory performance, because that requires some heavy refactoring. + + But for now we recommend you use the command line to complete this +one commit. Also see *note Performance: Performance. + + +File: magit.info, Node: I am having problems committing, Next: I don't like how branching and pushing works, Prev: I changed several thousand files at once and now Magit is unusable, Up: FAQ + +A.3 I am having problems committing +=================================== + +That likely means that Magit is having problems finding an appropriate +emacsclient executable. See *note (with-editor)Configuring +With-Editor:: and *note (with-editor)Debugging::. + + +File: magit.info, Node: I don't like how branching and pushing works, Next: I cannot install the pre-requisites for Magit v2, Prev: I am having problems committing, Up: FAQ + +A.4 I don’t like how branching and pushing works +================================================ + +In v2.1 the default behavior of the branch and push commands changed, +which has taken a few users by surprise and left more unsatisfied. The +next release, v2.4, will try to address these concerns. + + +File: magit.info, Node: I cannot install the pre-requisites for Magit v2, Next: I am using an Emacs release older than v244, Prev: I don't like how branching and pushing works, Up: FAQ + +A.5 I cannot install the pre-requisites for Magit v2 +==================================================== + +An Elpa archive featuring obsolete Magit v1.4.2 and its dependencies is +available from . But note that v1.4.2 is +obsolete and no longer maintained. + + +File: magit.info, Node: I am using an Emacs release older than v244, Next: I am using a Git release older than v194, Prev: I cannot install the pre-requisites for Magit v2, Up: FAQ + +A.6 I am using an Emacs release older than v24.4 +================================================ + +At least Emacs v24.4 is required. There is no way around it, if you +want to use Magit v2. + + If you own the machine you work on, then consider updating to the +latest release provided by your distribution. If it doesn’t feature a +recent enough release, then you will have to use a backport package or +build Emacs from source. + + Installing Emacs from source is quite simple. See the instructions +at and + to get an +idea of that this involves. But when you perform the installation then +use the instructions for the release you are actually installing. + + Unfortunately these instructions do not cover the hardest part (which +is the hardest part exactly because it is not covered there): installing +the build time dependencies. + + For that you’ll need to perform a web search and find an appropriate +tutorial for your distribution. If you think you should not have had to +do that yourself, then consider informing me about the resources that +helped you figure what to do for your specific setup, so that I can post +a link here. That way those coming after you have it easier. + + An Elpa archive featuring obsolete Magit v1.4.2 and its dependencies +is available from . + + +File: magit.info, Node: I am using a Git release older than v194, Next: I am using MS Windows and cannot push with Magit, Prev: I am using an Emacs release older than v244, Up: FAQ + +A.7 I am using a Git release older than v1.9.4 +============================================== + +At least Git v1.9.4 is required. There is no way around it, if you want +to use Magit v2. + + If you own the machine, then consider updating to the latest release +provided by your distribution. If it doesn’t feature a recent enough +release, then you will have to use a backport package or build Git from +source. + + Installing Git from source is quite simple. See the instructions at + to get an idea of that +this involves. But when you perform the installation then use the +instructions for the release you are actually installing. + + An Elpa archive featuring obsolete Magit v1.4.2 and its dependencies +is available from . + + +File: magit.info, Node: I am using MS Windows and cannot push with Magit, Next: How to install the gitman info manual?, Prev: I am using a Git release older than v194, Up: FAQ + +A.8 I am using MS Windows and cannot push with Magit +==================================================== + +It’s almost certain that Magit is only incidental to this issue. It is +much more likely that this is a configuration issue, even if you can +push on the command line. + + Detailed setup instructions can be found at +. + + +File: magit.info, Node: How to install the gitman info manual?, Next: How can I show Git's output?, Prev: I am using MS Windows and cannot push with Magit, Up: FAQ + +A.9 How to install the gitman info manual? +========================================== + +Git’s manpages can be exported as an info manual called ‘gitman’. +Magit’s own info manual links to nodes in that manual instead of the +actual manpages because texinfo sadly doesn’t support linking to +manpages. + + Unfortunately many distributions do not install the ‘gitman’ manual +by default. Some distributions may provide a separate package +containing the info manual. Please let me know the name of that package +for your distribution, so that I can mention here. + + If the distribution you are using does not offer a package that +contains the ‘gitman’ manual, then you have to install it manually. +Clone Git’s own Git repository, checkout the tag corresponding to the +Git release you have installed, and follow the instructions in +‘INSTALL’. The relevant make targets are ‘info’ and ‘install-info’. + + Alternatively you may add this advice to your ‘init.el’ file. + + (defadvice Info-follow-nearest-node (around gitman activate) + "When encountering a cross reference to the `gitman' info + manual, then instead of following that cross reference show + the actual manpage using the function `man'." + (let ((node (Info-get-token + (point) "\\*note[ \n\t]+" + "\\*note[ \n\t]+\\([^:]*\\):\\(:\\|[ \n\t]*(\\)?"))) + (if (and node (string-match "^(gitman)\\(.+\\)" node)) + (progn (require 'man) + (man (match-string 1 node))) + ad-do-it))) + + Or if you are using MS Windows and ‘man’ is not available, use this +variation with used the Emacs Lisp implementation provided by the +‘woman’ package. + + (defadvice Info-follow-nearest-node (around gitman activate) + "When encountering a cross reference to the `gitman' info + manual, then instead of following that cross reference show + the actual manpage using the function `woman'." + (let ((node (Info-get-token + (point) "\\*note[ \n\t]+" + "\\*note[ \n\t]+\\([^:]*\\):\\(:\\|[ \n\t]*(\\)?"))) + (if (and node (string-match "^(gitman)\\(.+\\)" node)) + (progn (require 'woman) + (woman (match-string 1 node))) + ad-do-it))) + + Did I mention that texinfo cross reference are just awful? (This is +just one of many issues.) + + +File: magit.info, Node: How can I show Git's output?, Next: Expanding a file to show the diff causes it to disappear, Prev: How to install the gitman info manual?, Up: FAQ + +A.10 How can I show Git’s output? +================================= + +To show the output of recently run git commands, press ‘$’ (or, if that +isn’t available, ‘M-x magit-process-buffer’). This will show a buffer +containing a section per git invocation; as always press ‘TAB’ to expand +or collapse them. + + By default git’s output is only inserted into the process buffer if +it is run for side-effects. When the output is consumed in some way +then also inserting it into the process buffer would be to expensive. +For debugging purposes it’s possible to do so anyway by setting +‘magit-git-debug’ to ‘t’. + + +File: magit.info, Node: Expanding a file to show the diff causes it to disappear, Next: Point is wrong in the COMMIT_EDITMSG buffer, Prev: How can I show Git's output?, Up: FAQ + +A.11 Expanding a file to show the diff causes it to disappear +============================================================= + +This is probably caused by a change of a ‘diff.*’ Git variable. You +probably set that variable for a reason, and should therefore only undo +that setting in Magit by customizing ‘magit-git-global-arguments’. + + +File: magit.info, Node: Point is wrong in the COMMIT_EDITMSG buffer, Next: Can Magit be used as ediff-version-control-package?, Prev: Expanding a file to show the diff causes it to disappear, Up: FAQ + +A.12 Point is wrong in the COMMIT_EDITMSG buffer +================================================ + +Neither Magit nor ‘git-commit‘ fiddle with point in the buffer used to +write commit messages, so something else must be doing it. + + You have probably globally enabled a mode which does restore point in +file-visiting buffers. It might be a bit surprising, but when you write +a commit message, then you are actually editing a file. + + So you have to figure out which package is doing. ‘saveplace’, +‘pointback’, and ‘session’ are likely candidates. These snippets might +help: + + (setq session-name-disable-regexp "\\(?:\\`'\\.git/[A-Z_]+\\'\\)") + + (with-eval-after-load 'pointback + (lambda () + (when (or git-commit-mode git-rebase-mode) + (pointback-mode -1)))) + + +File: magit.info, Node: Can Magit be used as ediff-version-control-package?, Next: How to show diffs for gpg-encrypted files?, Prev: Point is wrong in the COMMIT_EDITMSG buffer, Up: FAQ + +A.13 Can Magit be used as ediff-version-control-package? +======================================================== + +No, it cannot. For that to work the functions ‘ediff-magit-internal’ +and ‘ediff-magit-merge-internal’ would have to be implemented, and they +are not. These two functions are only used by the three commands +‘ediff-revision’, ‘ediff-merge-revisions-with-ancestor’, and +‘ediff-merge-revisions’. + + These commands only delegate the task of populating buffers with +certain revisions to the "internal" functions. The equally important +task of determining which revisions are to be compared/merged is not +delegated. Instead this is done without any support whatsoever, from +the version control package/system - meaning that the user has to enter +the revisions explicitly. Instead of implementing +‘ediff-magit-internal’ we provide ‘magit-ediff-compare’, which handles +both tasks like it is 2005. + + The other commands ‘ediff-merge-revisions’ and +‘ediff-merge-revisions-with-ancestor’ are normally not what you want +when using a modern version control system like Git. Instead of letting +the user resolve only those conflicts which Git could not resolve on its +own, they throw away all work done by Git and then expect the user to +manually merge all conflicts, including those that had already been +resolved. That made sense back in the days when version control systems +couldn’t merge (or so I have been told), but not anymore. Once in a +blue moon you might actually want to see all conflicts, in which case +you *can* use these commands, which then use ‘ediff-vc-merge-internal’. +So we don’t actually have to implement ‘ediff-magit-merge-internal’. +Instead we provide the more useful command ‘magit-ediff-resolve’ which +only shows yet-to-be resolved conflicts. + + +File: magit.info, Node: How to show diffs for gpg-encrypted files?, Next: Emacs 245 hangs when loading Magit, Prev: Can Magit be used as ediff-version-control-package?, Up: FAQ + +A.14 How to show diffs for gpg-encrypted files? +=============================================== + +Git supports showing diffs for encrypted files, but has to be told to do +so. Since Magit just uses Git to get the diffs, configuring Git also +affects the diffs displayed inside Magit. + + git config --global diff.gpg.textconv "gpg --no-tty --decrypt" + echo "*.gpg filter=gpg diff=gpg" > .gitattributes + + +File: magit.info, Node: Emacs 245 hangs when loading Magit, Prev: How to show diffs for gpg-encrypted files?, Up: FAQ + +A.15 Emacs 24.5 hangs when loading Magit +======================================== + +This is actually triggered by loading Tramp. See + for details. You +can work around the problem by setting +‘tramp-ssh-controlmaster-options’. Changing your DNS server (e.g. to +Google’s ‘8.8.8.8’) may also be sufficient to work around the issue. + + +File: magit.info, Node: Keystroke Index, Next: Command Index, Prev: FAQ, Up: Top + +Appendix B Keystroke Index +************************** + +[index] +* Menu: + +* !: Running Git manually. + (line 12) +* ! !: Running Git manually. + (line 19) +* ! a: Running Git manually. + (line 51) +* ! b: Running Git manually. + (line 55) +* ! g: Running Git manually. + (line 59) +* ! k: Running Git manually. + (line 47) +* ! p: Running Git manually. + (line 24) +* ! s: Running Git manually. + (line 33) +* ! S: Running Git manually. + (line 38) +* $: Viewing Git output. (line 11) +* +: Log Buffer. (line 53) +* + <1>: Refreshing diffs. (line 58) +* -: Refreshing diffs. (line 54) +* 0: Refreshing diffs. (line 62) +* 1: Section visibility. (line 26) +* 2: Section visibility. (line 26) +* 3: Section visibility. (line 26) +* 4: Section visibility. (line 26) +* =: Log Buffer. (line 47) +* = <1>: Log Buffer. (line 57) +* ^: Section movement. (line 31) +* a: Applying. (line 33) +* A: Cherry picking. (line 8) +* A A: Cherry picking. (line 16) +* A a: Cherry picking. (line 22) +* A A <1>: Cherry picking. (line 35) +* A a <1>: Cherry picking. (line 43) +* A s: Cherry picking. (line 39) +* B: Bisecting. (line 8) +* b: Branching. (line 45) +* B b: Bisecting. (line 31) +* b b: Branching. (line 171) +* b c: Branching. (line 189) +* b d: Branching. (line 229) +* B g: Bisecting. (line 36) +* B k: Bisecting. (line 41) +* b n: Branching. (line 179) +* B r: Bisecting. (line 47) +* b r: Branching. (line 235) +* B s: Bisecting. (line 16) +* b s: Branching. (line 196) +* B u: Bisecting. (line 24) +* b x: Branching. (line 213) +* c: Initiating a commit. (line 8) +* c <1>: Editing rebase sequences. + (line 72) +* c a: Initiating a commit. (line 18) +* c A: Initiating a commit. (line 66) +* c c: Initiating a commit. (line 13) +* c e: Initiating a commit. (line 22) +* c f: Initiating a commit. (line 42) +* c F: Initiating a commit. (line 50) +* c s: Initiating a commit. (line 54) +* c S: Initiating a commit. (line 62) +* c w: Initiating a commit. (line 32) +* C-: Diff buffer. (line 21) +* C-: Section visibility. (line 13) +* C-c C-a: Editing commit messages. + (line 128) +* C-c C-b: Log Buffer. (line 19) +* C-c C-b <1>: Refreshing diffs. (line 80) +* C-c C-c: Popup buffers and prefix commands. + (line 20) +* C-c C-c <1>: Select from log. (line 14) +* C-c C-c <2>: Editing commit messages. + (line 19) +* C-c C-c <3>: Editing rebase sequences. + (line 6) +* C-c C-d: Refreshing diffs. (line 70) +* C-c C-d <1>: Editing commit messages. + (line 57) +* C-c C-f: Log Buffer. (line 23) +* C-c C-f <1>: Refreshing diffs. (line 84) +* C-c C-i: Editing commit messages. + (line 153) +* C-c C-k: Select from log. (line 20) +* C-c C-k <1>: Editing commit messages. + (line 24) +* C-c C-k <2>: Editing rebase sequences. + (line 11) +* C-c C-o: Editing commit messages. + (line 144) +* C-c C-p: Editing commit messages. + (line 148) +* C-c C-r: Editing commit messages. + (line 132) +* C-c C-s: Editing commit messages. + (line 136) +* C-c C-t: Editing commit messages. + (line 140) +* C-c C-w: Editing commit messages. + (line 63) +* C-c M-g: Minor mode for buffers visiting files. + (line 19) +* C-c M-g b: Minor mode for buffers visiting files. + (line 39) +* C-c M-g c: Minor mode for buffers visiting files. + (line 49) +* C-c M-g l: Minor mode for buffers visiting files. + (line 33) +* C-c M-g p: Minor mode for buffers visiting files. + (line 45) +* C-c M-g s: Minor mode for buffers visiting files. + (line 24) +* C-c M-g u: Minor mode for buffers visiting files. + (line 28) +* C-s M-s: Editing commit messages. + (line 35) +* C-w: Common commands. (line 21) +* C-x g: Status buffer. (line 22) +* C-x u: Editing rebase sequences. + (line 89) +* d: Diffing. (line 20) +* D: Refreshing diffs. (line 11) +* d c: Diffing. (line 67) +* d d: Diffing. (line 25) +* D f: Refreshing diffs. (line 45) +* D g: Refreshing diffs. (line 16) +* d p: Diffing. (line 59) +* d r: Diffing. (line 29) +* D r: Refreshing diffs. (line 40) +* d s: Diffing. (line 49) +* D s: Refreshing diffs. (line 21) +* d t: Diffing. (line 72) +* D t: Refreshing diffs. (line 36) +* d u: Diffing. (line 55) +* d w: Diffing. (line 43) +* D w: Refreshing diffs. (line 28) +* DEL: Log Buffer. (line 37) +* DEL <1>: Diff buffer. (line 48) +* DEL <2>: Blaming. (line 44) +* DEL <3>: Editing rebase sequences. + (line 28) +* e: Ediffing. (line 6) +* E: Ediffing. (line 18) +* e <1>: Editing rebase sequences. + (line 55) +* E c: Ediffing. (line 62) +* E i: Ediffing. (line 54) +* E m: Ediffing. (line 32) +* E r: Ediffing. (line 23) +* E s: Ediffing. (line 45) +* E u: Ediffing. (line 50) +* E w: Ediffing. (line 58) +* f: Editing rebase sequences. + (line 63) +* f <1>: Fetching. (line 8) +* F: Pulling. (line 8) +* f a: Fetching. (line 25) +* f e: Fetching. (line 21) +* F e: Pulling. (line 21) +* f m: Fetching. (line 29) +* f p: Fetching. (line 13) +* F p: Pulling. (line 13) +* f u: Fetching. (line 17) +* F u: Pulling. (line 17) +* g: Automatic refresh and revert. + (line 68) +* G: Automatic refresh and revert. + (line 77) +* j: Diff buffer. (line 38) +* k: Viewing Git output. (line 19) +* k <1>: Applying. (line 37) +* k <2>: Editing rebase sequences. + (line 68) +* k <3>: Stashing. (line 92) +* l: Logging. (line 24) +* L: Refreshing logs. (line 11) +* L <1>: Log Buffer. (line 6) +* l a: Logging. (line 54) +* l b: Logging. (line 50) +* L g: Refreshing logs. (line 16) +* l h: Logging. (line 42) +* l H: Reflog. (line 19) +* l l: Logging. (line 29) +* l L: Logging. (line 46) +* l o: Logging. (line 35) +* l O: Reflog. (line 15) +* l r: Reflog. (line 11) +* L s: Refreshing logs. (line 21) +* L t: Refreshing logs. (line 36) +* L w: Refreshing logs. (line 28) +* m: Merging. (line 8) +* M: Remotes. (line 8) +* m a: Merging. (line 56) +* M a: Remotes. (line 13) +* m e: Merging. (line 29) +* M k: Remotes. (line 28) +* m m: Merging. (line 16) +* m m <1>: Merging. (line 51) +* m n: Merging. (line 36) +* m p: Merging. (line 43) +* M r: Remotes. (line 18) +* M u: Remotes. (line 23) +* M-1: Section visibility. (line 34) +* M-2: Section visibility. (line 34) +* M-3: Section visibility. (line 34) +* M-4: Section visibility. (line 34) +* M-: Section visibility. (line 17) +* M-n: Section movement. (line 26) +* M-n <1>: Editing commit messages. + (line 45) +* M-n <2>: Editing rebase sequences. + (line 47) +* M-p: Section movement. (line 20) +* M-p <1>: Editing commit messages. + (line 39) +* M-p <2>: Editing rebase sequences. + (line 43) +* M-w: Blaming. (line 75) +* M-w <1>: Common commands. (line 10) +* M-x magit-blame: Blaming. (line 8) +* M-x magit-blame-popup: Blaming. (line 24) +* M-x magit-checkout-file: Resetting. (line 37) +* M-x magit-clone: Repository setup. (line 16) +* M-x magit-describe-section: Section types and values. + (line 13) +* M-x magit-describe-section <1>: Matching sections. (line 6) +* M-x magit-find-file: Visiting blobs. (line 6) +* M-x magit-find-file-other-window: Visiting blobs. (line 11) +* M-x magit-init: Repository setup. (line 6) +* M-x magit-log-buffer-file: Logging. (line 65) +* M-x magit-reset-hard: Resetting. (line 32) +* M-x magit-reset-head: Resetting. (line 21) +* M-x magit-reset-index: Staging and unstaging. + (line 45) +* M-x magit-reset-index <1>: Resetting. (line 14) +* M-x magit-reset-soft: Resetting. (line 26) +* M-x magit-stage-file: Staging from file-visiting buffers. + (line 10) +* M-x magit-toggle-buffer-lock: Modes and Buffers. (line 17) +* M-x magit-unstage-file: Staging from file-visiting buffers. + (line 18) +* M-x magit-version: Git executable. (line 17) +* M-x magit-wip-commit: Wip modes. (line 129) +* n: Section movement. (line 16) +* n <1>: Blaming. (line 54) +* N: Blaming. (line 58) +* n <2>: Editing rebase sequences. + (line 39) +* n <3>: Minor mode for buffers visiting blobs. + (line 16) +* o: Submodules. (line 8) +* o a: Submodules. (line 13) +* o b: Submodules. (line 19) +* o f: Submodules. (line 37) +* o i: Submodules. (line 24) +* o i <1>: Submodules. (line 41) +* o s: Submodules. (line 33) +* o u: Submodules. (line 28) +* p: Section movement. (line 10) +* p <1>: Blaming. (line 62) +* P: Blaming. (line 66) +* p <2>: Editing rebase sequences. + (line 35) +* P <1>: Pushing. (line 8) +* p <3>: Minor mode for buffers visiting blobs. + (line 12) +* P e: Pushing. (line 32) +* P m: Pushing. (line 41) +* P o: Pushing. (line 36) +* P p: Pushing. (line 13) +* P t: Pushing. (line 47) +* P T: Pushing. (line 53) +* P u: Pushing. (line 23) +* q: Quitting Windows. (line 6) +* q <1>: Log Buffer. (line 12) +* q <2>: Blaming. (line 70) +* q <3>: Minor mode for buffers visiting blobs. + (line 20) +* r: Rebasing. (line 8) +* r <1>: Editing rebase sequences. + (line 51) +* r a: Rebasing. (line 84) +* r e: Rebasing. (line 25) +* r e <1>: Rebasing. (line 80) +* r f: Rebasing. (line 57) +* r i: Rebasing. (line 53) +* r m: Rebasing. (line 61) +* r o: Rebasing. (line 31) +* r p: Rebasing. (line 16) +* r r: Rebasing. (line 72) +* r s: Rebasing. (line 76) +* r u: Rebasing. (line 21) +* r w: Rebasing. (line 65) +* RET: Diff buffer. (line 6) +* RET <1>: References buffer. (line 99) +* RET <2>: Blaming. (line 29) +* RET <3>: Editing rebase sequences. + (line 16) +* s: Staging and unstaging. + (line 26) +* S: Staging and unstaging. + (line 30) +* s <1>: Editing rebase sequences. + (line 59) +* s-: Section visibility. (line 22) +* SPC: Log Buffer. (line 27) +* SPC <1>: Diff buffer. (line 44) +* SPC <2>: Blaming. (line 34) +* SPC <3>: Editing rebase sequences. + (line 21) +* t: Blaming. (line 79) +* t <1>: Tagging. (line 8) +* T: Notes. (line 8) +* T a: Notes. (line 70) +* T c: Notes. (line 65) +* t k: Tagging. (line 18) +* T m: Notes. (line 56) +* t p: Tagging. (line 24) +* T p: Notes. (line 29) +* T r: Notes. (line 21) +* T s: Notes. (line 33) +* T S: Notes. (line 44) +* t t: Tagging. (line 13) +* T T: Notes. (line 13) +* TAB: Section visibility. (line 9) +* u: Staging and unstaging. + (line 37) +* U: Staging and unstaging. + (line 41) +* v: Applying. (line 41) +* V: Reverting. (line 6) +* V A: Reverting. (line 30) +* V a: Reverting. (line 38) +* V s: Reverting. (line 34) +* V V: Reverting. (line 14) +* V v: Reverting. (line 20) +* W: Creating and sending patches. + (line 6) +* w: Applying patches. (line 8) +* w a: Applying patches. (line 31) +* w m: Applying patches. (line 19) +* W p: Creating and sending patches. + (line 11) +* W r: Creating and sending patches. + (line 17) +* w s: Applying patches. (line 27) +* w w: Applying patches. (line 13) +* w w <1>: Applying patches. (line 23) +* x: Editing rebase sequences. + (line 76) +* x <1>: Resetting. (line 8) +* Y: Logging. (line 60) +* y: References buffer. (line 6) +* y <1>: Editing rebase sequences. + (line 85) +* y c: References buffer. (line 19) +* y o: References buffer. (line 24) +* y y: References buffer. (line 14) +* z: Stashing. (line 8) +* z a: Stashing. (line 58) +* z b: Stashing. (line 84) +* z d: Stashing. (line 71) +* z f: Stashing. (line 88) +* z i: Stashing. (line 20) +* z I: Stashing. (line 46) +* z l: Stashing. (line 76) +* z p: Stashing. (line 64) +* z v: Stashing. (line 80) +* z w: Stashing. (line 25) +* z W: Stashing. (line 51) +* z x: Stashing. (line 32) +* z z: Stashing. (line 13) +* z Z: Stashing. (line 39) + + +File: magit.info, Node: Command Index, Next: Function Index, Prev: Keystroke Index, Up: Top + +Appendix C Command Index +************************ + +[index] +* Menu: + +* forward-line: Editing rebase sequences. + (line 39) +* git-commit-ack: Editing commit messages. + (line 128) +* git-commit-cc: Editing commit messages. + (line 144) +* git-commit-next-message: Editing commit messages. + (line 45) +* git-commit-prev-message: Editing commit messages. + (line 39) +* git-commit-reported: Editing commit messages. + (line 148) +* git-commit-review: Editing commit messages. + (line 132) +* git-commit-save-message: Editing commit messages. + (line 35) +* git-commit-signoff: Editing commit messages. + (line 136) +* git-commit-suggested: Editing commit messages. + (line 153) +* git-commit-test: Editing commit messages. + (line 140) +* git-rebase-backward-line: Editing rebase sequences. + (line 35) +* git-rebase-edit: Editing rebase sequences. + (line 55) +* git-rebase-exec: Editing rebase sequences. + (line 76) +* git-rebase-fixup: Editing rebase sequences. + (line 63) +* git-rebase-insert: Editing rebase sequences. + (line 85) +* git-rebase-kill-line: Editing rebase sequences. + (line 68) +* git-rebase-move-line-down: Editing rebase sequences. + (line 47) +* git-rebase-move-line-up: Editing rebase sequences. + (line 43) +* git-rebase-pick: Editing rebase sequences. + (line 72) +* git-rebase-reword: Editing rebase sequences. + (line 51) +* git-rebase-show-commit: Editing rebase sequences. + (line 16) +* git-rebase-squash: Editing rebase sequences. + (line 59) +* git-rebase-undo: Editing rebase sequences. + (line 89) +* ido-enter-magit-status: Status buffer. (line 42) +* magit-am-abort: Applying patches. (line 31) +* magit-am-apply-maildir: Applying patches. (line 19) +* magit-am-apply-patches: Applying patches. (line 13) +* magit-am-continue: Applying patches. (line 23) +* magit-am-popup: Applying patches. (line 8) +* magit-am-skip: Applying patches. (line 27) +* magit-apply: Applying. (line 33) +* magit-bisect-bad: Bisecting. (line 31) +* magit-bisect-good: Bisecting. (line 36) +* magit-bisect-popup: Bisecting. (line 8) +* magit-bisect-reset: Bisecting. (line 47) +* magit-bisect-run: Bisecting. (line 24) +* magit-bisect-skip: Bisecting. (line 41) +* magit-bisect-start: Bisecting. (line 16) +* magit-blame: Blaming. (line 8) +* magit-blame-copy-hash: Blaming. (line 75) +* magit-blame-next-chunk: Blaming. (line 54) +* magit-blame-next-chunk-same-commit: Blaming. (line 58) +* magit-blame-popup: Blaming. (line 24) +* magit-blame-popup <1>: Minor mode for buffers visiting files. + (line 39) +* magit-blame-previous-chunk: Blaming. (line 62) +* magit-blame-previous-chunk-same-commit: Blaming. (line 66) +* magit-blame-quit: Blaming. (line 70) +* magit-blame-toggle-headings: Blaming. (line 79) +* magit-blob-next: Minor mode for buffers visiting blobs. + (line 16) +* magit-blob-previous: Minor mode for buffers visiting files. + (line 45) +* magit-blob-previous <1>: Minor mode for buffers visiting blobs. + (line 12) +* magit-branch: Branching. (line 179) +* magit-branch-and-checkout: Branching. (line 189) +* magit-branch-delete: Branching. (line 229) +* magit-branch-popup: Branching. (line 45) +* magit-branch-rename: Branching. (line 235) +* magit-branch-reset: Branching. (line 213) +* magit-branch-spinoff: Branching. (line 196) +* magit-checkout: Branching. (line 171) +* magit-checkout-file: Resetting. (line 37) +* magit-cherry: Logging. (line 60) +* magit-cherry-apply: Cherry picking. (line 22) +* magit-cherry-pick: Cherry picking. (line 16) +* magit-cherry-pick-popup: Cherry picking. (line 8) +* magit-clone: Repository setup. (line 16) +* magit-commit: Initiating a commit. (line 13) +* magit-commit-amend: Initiating a commit. (line 18) +* magit-commit-augment: Initiating a commit. (line 66) +* magit-commit-extend: Initiating a commit. (line 22) +* magit-commit-fixup: Initiating a commit. (line 42) +* magit-commit-instant-fixup: Initiating a commit. (line 50) +* magit-commit-instant-squash: Initiating a commit. (line 62) +* magit-commit-popup: Initiating a commit. (line 8) +* magit-commit-popup <1>: Minor mode for buffers visiting files. + (line 49) +* magit-commit-reword: Initiating a commit. (line 32) +* magit-commit-squash: Initiating a commit. (line 54) +* magit-copy-buffer-revision: Common commands. (line 21) +* magit-copy-section-value: Common commands. (line 10) +* magit-describe-section: Section types and values. + (line 13) +* magit-describe-section <1>: Matching sections. (line 6) +* magit-diff: Diffing. (line 29) +* magit-diff-default-context: Refreshing diffs. (line 62) +* magit-diff-dwim: Diffing. (line 25) +* magit-diff-flip-revs: Refreshing diffs. (line 45) +* magit-diff-less-context: Refreshing diffs. (line 54) +* magit-diff-more-context: Refreshing diffs. (line 58) +* magit-diff-paths: Diffing. (line 59) +* magit-diff-popup: Diffing. (line 20) +* magit-diff-refresh: Refreshing diffs. (line 16) +* magit-diff-refresh-popup: Refreshing diffs. (line 11) +* magit-diff-save-default-arguments: Refreshing diffs. (line 28) +* magit-diff-set-default-arguments: Refreshing diffs. (line 21) +* magit-diff-show-or-scroll-down: Log Buffer. (line 37) +* magit-diff-show-or-scroll-down <1>: Blaming. (line 44) +* magit-diff-show-or-scroll-down <2>: Editing rebase sequences. + (line 28) +* magit-diff-show-or-scroll-up: Log Buffer. (line 27) +* magit-diff-show-or-scroll-up <1>: Blaming. (line 34) +* magit-diff-show-or-scroll-up <2>: Editing rebase sequences. + (line 21) +* magit-diff-staged: Diffing. (line 49) +* magit-diff-switch-range-type: Refreshing diffs. (line 40) +* magit-diff-toggle-refine-hunk: Refreshing diffs. (line 36) +* magit-diff-unstaged: Diffing. (line 55) +* magit-diff-visit-file: Diff buffer. (line 6) +* magit-diff-visit-file-worktree: Diff buffer. (line 21) +* magit-diff-while-committing: Refreshing diffs. (line 70) +* magit-diff-while-committing <1>: Editing commit messages. + (line 57) +* magit-diff-worktree: Diffing. (line 43) +* magit-discard: Applying. (line 37) +* magit-dispatch-popup: Popup buffers and prefix commands. + (line 20) +* magit-ediff-compare: Ediffing. (line 23) +* magit-ediff-dwim: Ediffing. (line 6) +* magit-ediff-popup: Ediffing. (line 18) +* magit-ediff-resolve: Ediffing. (line 32) +* magit-ediff-show-commit: Ediffing. (line 62) +* magit-ediff-show-staged: Ediffing. (line 54) +* magit-ediff-show-unstaged: Ediffing. (line 50) +* magit-ediff-show-working-tree: Ediffing. (line 58) +* magit-ediff-stage: Ediffing. (line 45) +* magit-fetch: Fetching. (line 21) +* magit-fetch-all: Fetching. (line 25) +* magit-fetch-from-pushremote: Fetching. (line 13) +* magit-fetch-from-upstream: Fetching. (line 17) +* magit-fetch-popup: Fetching. (line 8) +* magit-file-popup: Minor mode for buffers visiting files. + (line 19) +* magit-find-file: Visiting blobs. (line 6) +* magit-find-file-other-window: Visiting blobs. (line 11) +* magit-format-patch: Creating and sending patches. + (line 11) +* magit-git-command: Running Git manually. + (line 24) +* magit-git-command-topdir: Running Git manually. + (line 19) +* magit-go-backward: Log Buffer. (line 19) +* magit-go-backward <1>: Refreshing diffs. (line 80) +* magit-go-forward: Log Buffer. (line 23) +* magit-go-forward <1>: Refreshing diffs. (line 84) +* magit-init: Repository setup. (line 6) +* magit-jump-to-diffstat-or-diff: Diff buffer. (line 38) +* magit-kill-this-buffer: Minor mode for buffers visiting blobs. + (line 20) +* magit-log: Logging. (line 35) +* magit-log-all: Logging. (line 54) +* magit-log-all-branches: Logging. (line 50) +* magit-log-branches: Logging. (line 46) +* magit-log-buffer-file: Logging. (line 65) +* magit-log-buffer-file <1>: Minor mode for buffers visiting files. + (line 33) +* magit-log-bury-buffer: Log Buffer. (line 12) +* magit-log-current: Logging. (line 29) +* magit-log-double-commit-limit: Log Buffer. (line 53) +* magit-log-half-commit-limit: Log Buffer. (line 57) +* magit-log-head: Logging. (line 42) +* magit-log-popup: Logging. (line 24) +* magit-log-refresh: Refreshing logs. (line 16) +* magit-log-refresh-popup: Refreshing logs. (line 11) +* magit-log-refresh-popup <1>: Log Buffer. (line 6) +* magit-log-save-default-arguments: Refreshing logs. (line 28) +* magit-log-select-pick: Select from log. (line 14) +* magit-log-select-quit: Select from log. (line 20) +* magit-log-set-default-arguments: Refreshing logs. (line 21) +* magit-log-toggle-commit-limit: Log Buffer. (line 47) +* magit-merge: Merging. (line 16) +* magit-merge <1>: Merging. (line 51) +* magit-merge-abort: Merging. (line 56) +* magit-merge-editmsg: Merging. (line 29) +* magit-merge-nocommit: Merging. (line 36) +* magit-merge-popup: Merging. (line 8) +* magit-merge-preview: Merging. (line 43) +* magit-mode-bury-buffer: Quitting Windows. (line 6) +* magit-notes-edit: Notes. (line 13) +* magit-notes-merge: Notes. (line 56) +* magit-notes-merge-abort: Notes. (line 70) +* magit-notes-merge-commit: Notes. (line 65) +* magit-notes-popup: Notes. (line 8) +* magit-notes-prune: Notes. (line 29) +* magit-notes-remove: Notes. (line 21) +* magit-notes-set-display-refs: Notes. (line 44) +* magit-notes-set-ref: Notes. (line 33) +* magit-patch-popup: Creating and sending patches. + (line 6) +* magit-pop-revision-stack: Editing commit messages. + (line 63) +* magit-process: Viewing Git output. (line 11) +* magit-process-kill: Viewing Git output. (line 19) +* magit-pull: Pulling. (line 21) +* magit-pull-from-pushremote: Pulling. (line 13) +* magit-pull-from-upstream: Pulling. (line 17) +* magit-pull-popup: Pulling. (line 8) +* magit-push: Pushing. (line 36) +* magit-push-current: Pushing. (line 32) +* magit-push-current-to-pushremote: Pushing. (line 13) +* magit-push-current-to-upstream: Pushing. (line 23) +* magit-push-implicitly args: Pushing. (line 61) +* magit-push-matching: Pushing. (line 41) +* magit-push-popup: Pushing. (line 8) +* magit-push-tag: Pushing. (line 53) +* magit-push-tags: Pushing. (line 47) +* magit-push-to-remote remote args: Pushing. (line 72) +* magit-rebase: Rebasing. (line 25) +* magit-rebase-abort: Rebasing. (line 84) +* magit-rebase-autosquash: Rebasing. (line 57) +* magit-rebase-continue: Rebasing. (line 72) +* magit-rebase-edit: Rebasing. (line 80) +* magit-rebase-edit-commit: Rebasing. (line 61) +* magit-rebase-interactive: Rebasing. (line 53) +* magit-rebase-onto-pushremote: Rebasing. (line 16) +* magit-rebase-onto-upstream: Rebasing. (line 21) +* magit-rebase-popup: Rebasing. (line 8) +* magit-rebase-reword-commit: Rebasing. (line 65) +* magit-rebase-skip: Rebasing. (line 76) +* magit-rebase-subset: Rebasing. (line 31) +* magit-reflog-current: Reflog. (line 11) +* magit-reflog-head: Reflog. (line 19) +* magit-reflog-other: Reflog. (line 15) +* magit-refresh: Automatic refresh and revert. + (line 68) +* magit-refresh-all: Automatic refresh and revert. + (line 77) +* magit-remote-add: Remotes. (line 13) +* magit-remote-popup: Remotes. (line 8) +* magit-remote-remove: Remotes. (line 28) +* magit-remote-rename: Remotes. (line 18) +* magit-remote-set-url: Remotes. (line 23) +* magit-request-pull: Creating and sending patches. + (line 17) +* magit-reset: Resetting. (line 8) +* magit-reset-hard: Resetting. (line 32) +* magit-reset-head: Resetting. (line 21) +* magit-reset-index: Staging and unstaging. + (line 45) +* magit-reset-index <1>: Resetting. (line 14) +* magit-reset-soft: Resetting. (line 26) +* magit-reverse: Applying. (line 41) +* magit-revert: Reverting. (line 14) +* magit-revert-no-commit: Reverting. (line 20) +* magit-revert-popup: Reverting. (line 6) +* magit-run-git-gui: Running Git manually. + (line 59) +* magit-run-gitk: Running Git manually. + (line 47) +* magit-run-gitk-all: Running Git manually. + (line 51) +* magit-run-gitk-branches: Running Git manually. + (line 55) +* magit-run-popup: Running Git manually. + (line 12) +* magit-section-backward: Section movement. (line 10) +* magit-section-backward-siblings: Section movement. (line 20) +* magit-section-cycle: Section visibility. (line 13) +* magit-section-cycle-diffs: Section visibility. (line 17) +* magit-section-cycle-global: Section visibility. (line 22) +* magit-section-forward: Section movement. (line 16) +* magit-section-forward-siblings: Section movement. (line 26) +* magit-section-hide: Section visibility. (line 51) +* magit-section-hide-children: Section visibility. (line 66) +* magit-section-show: Section visibility. (line 47) +* magit-section-show-children: Section visibility. (line 60) +* magit-section-show-headings: Section visibility. (line 55) +* magit-section-show-level-1: Section visibility. (line 26) +* magit-section-show-level-1-all: Section visibility. (line 34) +* magit-section-show-level-2: Section visibility. (line 27) +* magit-section-show-level-2-all: Section visibility. (line 35) +* magit-section-show-level-3: Section visibility. (line 28) +* magit-section-show-level-3-all: Section visibility. (line 36) +* magit-section-show-level-4: Section visibility. (line 29) +* magit-section-show-level-4-all: Section visibility. (line 37) +* magit-section-toggle: Section visibility. (line 9) +* magit-section-toggle-children: Section visibility. (line 70) +* magit-section-up: Section movement. (line 31) +* magit-sequence-abort: Cherry picking. (line 43) +* magit-sequence-abort <1>: Reverting. (line 38) +* magit-sequence-continue: Cherry picking. (line 35) +* magit-sequence-continue <1>: Reverting. (line 30) +* magit-sequence-skip: Cherry picking. (line 39) +* magit-sequence-skip <1>: Reverting. (line 34) +* magit-shell-command: Running Git manually. + (line 38) +* magit-shell-command-topdir: Running Git manually. + (line 33) +* magit-show-commit: Diffing. (line 67) +* magit-show-commit <1>: Blaming. (line 29) +* magit-show-refs: References buffer. (line 24) +* magit-show-refs-current: References buffer. (line 19) +* magit-show-refs-head: References buffer. (line 14) +* magit-show-refs-popup: References buffer. (line 6) +* magit-snapshot: Stashing. (line 39) +* magit-snapshot-index: Stashing. (line 46) +* magit-snapshot-worktree: Stashing. (line 51) +* magit-stage: Staging and unstaging. + (line 26) +* magit-stage-file: Staging from file-visiting buffers. + (line 10) +* magit-stage-file <1>: Minor mode for buffers visiting files. + (line 24) +* magit-stage-modified: Staging and unstaging. + (line 30) +* magit-stash: Stashing. (line 13) +* magit-stash-apply: Stashing. (line 58) +* magit-stash-branch: Stashing. (line 84) +* magit-stash-clear: Stashing. (line 92) +* magit-stash-drop: Stashing. (line 71) +* magit-stash-format-patch: Stashing. (line 88) +* magit-stash-index: Stashing. (line 20) +* magit-stash-keep-index: Stashing. (line 32) +* magit-stash-list: Stashing. (line 76) +* magit-stash-pop: Stashing. (line 64) +* magit-stash-popup: Stashing. (line 8) +* magit-stash-show: Diffing. (line 72) +* magit-stash-show <1>: Stashing. (line 80) +* magit-stash-worktree: Stashing. (line 25) +* magit-status: Status buffer. (line 22) +* magit-submodule-add: Submodules. (line 13) +* magit-submodule-fetch: Fetching. (line 29) +* magit-submodule-fetch <1>: Submodules. (line 37) +* magit-submodule-init: Submodules. (line 24) +* magit-submodule-init <1>: Submodules. (line 41) +* magit-submodule-popup: Submodules. (line 8) +* magit-submodule-setup: Submodules. (line 19) +* magit-submodule-sync: Submodules. (line 33) +* magit-submodule-update: Submodules. (line 28) +* magit-tag: Tagging. (line 13) +* magit-tag-delete: Tagging. (line 18) +* magit-tag-popup: Tagging. (line 8) +* magit-tag-prune: Tagging. (line 24) +* magit-toggle-buffer-lock: Modes and Buffers. (line 17) +* magit-toggle-margin: Refreshing logs. (line 36) +* magit-unstage: Staging and unstaging. + (line 37) +* magit-unstage-all: Staging and unstaging. + (line 41) +* magit-unstage-file: Staging from file-visiting buffers. + (line 18) +* magit-unstage-file <1>: Minor mode for buffers visiting files. + (line 28) +* magit-version: Git executable. (line 17) +* magit-visit-ref: References buffer. (line 99) +* magit-wip-commit: Wip modes. (line 129) +* magit-wip-log: Wip modes. (line 69) +* magit-wip-log-current: Wip modes. (line 77) +* scroll-down: Diff buffer. (line 48) +* scroll-up: Diff buffer. (line 44) +* with-editor-cancel: Editing commit messages. + (line 24) +* with-editor-cancel <1>: Editing rebase sequences. + (line 11) +* with-editor-finish: Editing commit messages. + (line 19) +* with-editor-finish <1>: Editing rebase sequences. + (line 6) + diff --git a/elpa/magit-20151223.1425/magit.info-2 b/elpa/magit-20151223.1425/magit.info-2 new file mode 100644 index 00000000..b53236ba Binary files /dev/null and b/elpa/magit-20151223.1425/magit.info-2 differ diff --git a/elpa/magit-popup-20151119.201/dir b/elpa/magit-popup-20151119.201/dir deleted file mode 100644 index c276dafb..00000000 --- a/elpa/magit-popup-20151119.201/dir +++ /dev/null @@ -1,18 +0,0 @@ -This is the file .../info/dir, which contains the -topmost node of the Info hierarchy, called (dir)Top. -The first time you invoke Info you start off looking at this node. - -File: dir, Node: Top This is the top of the INFO tree - - This (the Directory node) gives a menu of major topics. - Typing "q" exits, "?" lists all Info commands, "d" returns here, - "h" gives a primer for first-timers, - "mEmacs" visits the Emacs manual, etc. - - In Emacs, you can click mouse button 2 on a menu item or cross reference - to select it. - -* Menu: - -Emacs -* Magit-Popup: (magit-popup). Infix arguments with feedback. diff --git a/elpa/magit-popup-20151119.201/magit-popup-autoloads.el b/elpa/magit-popup-20151119.201/magit-popup-autoloads.el deleted file mode 100644 index a115cbd0..00000000 --- a/elpa/magit-popup-20151119.201/magit-popup-autoloads.el +++ /dev/null @@ -1,16 +0,0 @@ -;;; magit-popup-autoloads.el --- automatically extracted autoloads -;; -;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) - -;;;### (autoloads nil nil ("magit-popup-pkg.el" "magit-popup.el") -;;;;;; (22093 56175 131955 0)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: -;;; magit-popup-autoloads.el ends here diff --git a/elpa/magit-popup-20151119.201/magit-popup-pkg.el b/elpa/magit-popup-20151119.201/magit-popup-pkg.el deleted file mode 100644 index 0321691c..00000000 --- a/elpa/magit-popup-20151119.201/magit-popup-pkg.el +++ /dev/null @@ -1,9 +0,0 @@ -(define-package "magit-popup" "20151119.201" "Define prefix-infix-suffix command combos" - '((emacs "24.4") - (async "20150909.2257") - (dash "20151021.113")) - :url "https://github.com/magit/magit" :keywords - '("bindings")) -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/magit-popup-20151119.201/magit-popup.el b/elpa/magit-popup-20151119.201/magit-popup.el deleted file mode 100644 index cfc10f3a..00000000 --- a/elpa/magit-popup-20151119.201/magit-popup.el +++ /dev/null @@ -1,1113 +0,0 @@ -;;; magit-popup.el --- Define prefix-infix-suffix command combos - -;; Copyright (C) 2010-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; This library was inspired by and replaces library `magit-key-mode', -;; which was written by Phil Jackson and is -;; distributed under the GNU General Public License version 3 or later. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; Package-Requires: ((emacs "24.4") (async "20150909.2257") (dash "20151021.113")) -;; Keywords: bindings -;; Homepage: https://github.com/magit/magit - -;; 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: - -;; This library implements a generic interface for toggling switches -;; and setting options and then invoking an Emacs command which does -;; something with these arguments. The prototypical use is for the -;; command to call an external process, passing on the arguments as -;; command line arguments. But this is only one of many possible -;; uses (though the one this library is optimized for). - -;; With the Emacs concept of "prefix arguments" in mind this could be -;; described as "infix arguments with feedback in a buffer". - -;; Commands that set the prefix argument for the subsequent command do -;; not limit what that next command could be. But entering a command -;; console popup does limit the selection to the commands defined for -;; that popup, and so we use the term "infix" instead of "prefix". - -;;; Code: - -(require 'button) -(require 'cl-lib) -(require 'dash) -(require 'format-spec) - -(and (require 'async-bytecomp nil t) - (memq 'magit (bound-and-true-p async-bytecomp-allowed-packages)) - (fboundp 'async-bytecomp-package-mode) - (async-bytecomp-package-mode 1)) - -(declare-function info 'info) -(declare-function Man-find-section 'man) -(declare-function Man-next-section 'man) - -;;; Settings -;;;; Custom Groups - -(defgroup magit-popup nil - "Infix arguments with a popup as feedback." - :group 'bindings) - -(defgroup magit-popup-faces nil - "Faces used by Magit-Popup." - :group 'magit-popup) - -;;;; Custom Options - -(defcustom magit-popup-manpage-package - (if (memq system-type '(windows-nt ms-dos)) 'woman 'man) - "The package used to display manpages. -One of `man' or `woman'." - :group 'magit-popup - :type '(choice (const man) (const woman))) - -(defcustom magit-popup-show-help-echo t - "Show usage information in the echo area." - :group 'magit-popup - :type 'boolean) - -(defcustom magit-popup-show-common-commands t - "Initially show section with commands common to all popups. -This section can also be toggled temporarily using \ -\\\\[magit-popup-toggle-show-common-commands]." - :group 'magit-popup - :type 'boolean) - -(defcustom magit-popup-use-prefix-argument 'disabled - "Control how prefix arguments affect infix argument popups. - -This option controls the effect that the use of a prefix argument -before entering a popup has. The *intended* default is `default', -but the *actual* default is `disabled'. This is necessary because -the old popup implementation did simply forward such a pre-popup -prefix argument to the action invoked from the popup, and changing -that without users being aware of it could lead to tears. - -`disabled' Bring up a Custom option buffer so that the user reads - this and then makes an informed choice. - -`default' With a prefix argument directly invoke the popup's - default action (an Emacs command), instead of bringing - up the popup. - -`popup' With a prefix argument bring up the popup, otherwise - directly invoke the popup's default action. - -`nil' Ignore prefix arguments." - :group 'magit-popup - :type '(choice - (const :tag "Call default action instead of showing popup" default) - (const :tag "Show popup instead of calling default action" popup) - (const :tag "Ignore prefix argument" nil) - (const :tag "Abort and show usage information" disabled))) - -;;;; Custom Faces - -(defface magit-popup-heading - '((t :inherit font-lock-keyword-face)) - "Face for key mode header lines." - :group 'magit-popup-faces) - -(defface magit-popup-key - '((t :inherit font-lock-builtin-face)) - "Face for key mode buttons." - :group 'magit-popup-faces) - -(defface magit-popup-argument - '((t :inherit font-lock-warning-face)) - "Face used to display enabled arguments in popups." - :group 'magit-popup-faces) - -(defface magit-popup-disabled-argument - '((t :inherit shadow)) - "Face used to display disabled arguments in popups." - :group 'magit-popup-faces) - -(defface magit-popup-option-value - '((t :inherit font-lock-string-face)) - "Face used to display option values in popups." - :group 'magit-popup-faces) - -;;;; Keymap - -(defvar magit-popup-mode-map - (let ((map (make-sparse-keymap))) - (define-key map [remap self-insert-command] 'magit-invoke-popup-action) - (define-key map [?- t] 'magit-invoke-popup-switch) - (define-key map [?= t] 'magit-invoke-popup-option) - (define-key map [?\C-c ?\C-c] 'magit-popup-set-default-arguments) - (define-key map [?\C-x ?\C-s] 'magit-popup-save-default-arguments) - (define-key map [?\C-g] 'magit-popup-quit) - (define-key map [??] 'magit-popup-help) - (define-key map [?\C-h ?i] 'magit-popup-info) - (define-key map [?\C-t] 'magit-popup-toggle-show-common-commands) - (define-key map [?\d] 'backward-button) - (define-key map [?\C-p] 'backward-button) - (define-key map [?\t] 'forward-button) - (define-key map [?\C-n] 'forward-button) - (define-key map [?\r] 'push-button) - map) - "Keymap for `magit-popup-mode'. - -\\\ -This keymap contains bindings common to all popups. A section -listing these commands can be shown or hidden using \ -\\[magit-popup-toggle-show-common-commands]. - -The prefix used to toggle any switch can be changed by binding -another key to `magit-invoke-popup-switch'. Likewise binding -another key to `magit-invoke-popup-option' changes the prefixed -used to set any option. The two prefixes have to be different. -If you change these bindings you should also change the `prefix' -property of the button types `magit-popup-switch-button' and -`magit-popup-option-button'. - -If you change any other binding, then you might have to also edit -`magit-popup-common-commands' for things to align correctly in -the section listing these commands. - -Never bind an alphabetic character in this keymap or you might -make it impossible to invoke certain actions.") - -(defvar magit-popup-common-commands - '(("Set defaults" magit-popup-set-default-arguments) - ("View popup manual" magit-popup-info) - ("Toggle this section" magit-popup-toggle-show-common-commands) - ("Save defaults" magit-popup-save-default-arguments) - (" Popup help prefix" magit-popup-help) - ("Abort" magit-popup-quit))) - -;;;; Buttons - -(define-button-type 'magit-popup-button - 'face nil - 'action (lambda (button) - (funcall (button-get button 'function) - (button-get button 'event)))) - -(define-button-type 'magit-popup-switch-button - 'supertype 'magit-popup-button - 'function 'magit-invoke-popup-switch - 'property :switches - 'heading "Switches\n" - 'formatter 'magit-popup-format-argument-button - 'format " %k %d (%a)" - 'prefix ?- - 'maxcols 1) - -(define-button-type 'magit-popup-option-button - 'supertype 'magit-popup-button - 'function 'magit-invoke-popup-option - 'property :options - 'heading "Options\n" - 'formatter 'magit-popup-format-argument-button - 'format " %k %d (%a%v)" - 'prefix ?= - 'maxcols 1) - -(define-button-type 'magit-popup-action-button - 'supertype 'magit-popup-button - 'function 'magit-invoke-popup-action - 'property :actions - 'heading "Actions\n" - 'formatter 'magit-popup-format-action-button - 'format " %k %d" - 'prefix nil - 'maxcols :max-action-columns) - -(define-button-type 'magit-popup-command-button - 'supertype 'magit-popup-action-button - 'formatter 'magit-popup-format-command-button - 'action (lambda (button) - (let ((command (button-get button 'function))) - (unless (eq command 'push-button) - (call-interactively command))))) - -(define-button-type 'magit-popup-internal-command-button - 'supertype 'magit-popup-command-button - 'heading "Common Commands\n" - 'maxcols 3) - -;;; Events - -(defvar-local magit-this-popup nil - "The popup which is currently active. -This is intended for internal use only. -Don't confuse this with `magit-current-popup'.") - -(defvar-local magit-this-popup-events nil - "The events known to the active popup. -This is intended for internal use only. -Don't confuse this with `magit-current-popup-args'.") - -(defun magit-popup-get (prop) - "While a popup is active, get the value of PROP." - (if (memq prop '(:switches :options :actions)) - (plist-get magit-this-popup-events prop) - (plist-get (symbol-value magit-this-popup) prop))) - -(defun magit-popup-put (prop val) - "While a popup is active, set the value of PROP to VAL." - (if (memq prop '(:switches :options :actions)) - (setq magit-this-popup-events - (plist-put magit-this-popup-events prop val)) - (error "Property %s isn't supported" prop))) - -(defvar magit-current-popup nil - "The popup from which this editing command was invoked. - -Use this inside the `interactive' form of a popup aware command -to determine whether it was invoked from a popup and if so from -which popup. If the current command was invoked without the use -of a popup then this is nil.") - -(defvar magit-current-popup-args nil - "The value of the popup arguments for this editing command. - -If the current command was invoked from a popup, then this is -a list of strings of all the set switches and options. This -includes arguments which are set by default not only those -explicitly set during this invocation. - -When the value is nil, then that can be because no argument is -set, or because the current command wasn't invoked from a popup; -consult `magit-current-popup' to tell the difference. - -Generally it is better to use `NAME-arguments', which is created -by `magit-define-popup', instead of this variable or the function -by the same name, because `NAME-argument' uses the default value -for the arguments when the editing command is invoked directly -instead of from a popup. When the command is bound in several -popups that might not be feasible though.") - -(defun magit-current-popup-args (&rest filter) - "Return the value of the popup arguments for this editing command. - -The value is the same as that of the variable by the same name -\(which see), except that FILTER is applied. FILTER is a list -of regexps; only arguments that match one of them are returned. -The first element of FILTER may also be `:not' in which case -only arguments that don't match any of the regexps are returned, -or `:only' which doesn't change the behaviour." - (let ((-compare-fn (lambda (a b) (magit-popup-arg-match b a)))) - (-filter (if (eq (car filter) :not) - (lambda (arg) (not (-contains? (cdr filter) arg))) - (when (eq (car filter) :only) - (pop filter)) - (lambda (arg) (-contains? filter arg))) - magit-current-popup-args))) - -(defun magit-popup-arg-match (pattern string) - (if (or (string-match-p "=$" pattern) - (string-match-p "^-[A-Z]$" pattern)) - (string-match (format "^%s\\(.*\\)$" pattern) string) - (string-equal string pattern))) - -(cl-defstruct magit-popup-event key dsc arg fun use val) - -(defun magit-popup-event-keydsc (ev) - (let ((key (magit-popup-event-key ev))) - (key-description (if (vectorp key) key (vector key))))) - -(defun magit-popup-lookup (event type) - (--first (equal (magit-popup-event-key it) event) - (-filter 'magit-popup-event-p (magit-popup-get type)))) - -(defun magit-popup-get-args () - (--mapcat (when (magit-popup-event-use it) - (list (format "%s%s" - (magit-popup-event-arg it) - (or (magit-popup-event-val it) "")))) - (append (magit-popup-get :switches) - (magit-popup-get :options)))) - -(defmacro magit-popup-convert-events (def form) - (declare (indent 1) (debug (form form))) - `(--map (if (or (null it) (stringp it)) it ,form) ,def)) - -(defun magit-popup-convert-switches (val def) - (magit-popup-convert-events def - (let ((a (nth 2 it))) - (make-magit-popup-event - :key (car it) :dsc (cadr it) :arg a - :use (and (member a val) t))))) - -(defun magit-popup-convert-options (val def) - (magit-popup-convert-events def - (let* ((a (nth 2 it)) - (r (format "^%s\\(.*\\)" a)) - (v (--first (string-match r it) val))) - (make-magit-popup-event - :key (car it) :dsc (cadr it) :arg a - :use (and v t) :val (and v (match-string 1 v)) - :fun (or (nth 3 it) 'read-from-minibuffer))))) - -(defun magit-popup-convert-actions (val def) - (magit-popup-convert-events def - (make-magit-popup-event - :key (car it) :dsc (cadr it) :fun (nth 2 it)))) - -;;; Define - -(defmacro magit-define-popup (name doc &rest args) - "Define a popup command named NAME. - -NAME should begin with the package prefix and by convention end -with `-popup'. That name is used for the actual command as well -as for a variable used internally. DOC is used as the doc-string -of that command. - -Also define an option and a function named `SHORTNAME-arguments', -where SHORTNAME is NAME with the trailing `-popup' removed. The -name of this option and this function can be overwritten using -the optional argument OPTION, but that is rarely advisable. As a -special case if OPTION is specified but nil, do not define this -option and this function at all. - -The option `SHORTNAME-arguments' holds the default value for the -popup arguments. It can be customized from within the popup or -using the Custom interface. - -The function `SHORTNAME-arguments' is a wrapper around the -variable `magit-current-popup-args', both of which are intended -to be used inside the `interactive' form of commands commonly -invoked from the popup `NAME'. When such a command is invoked -from that popup, then the function `SHORTNAME-arguments' returns -the value of the variable `magit-current-popup-args'; however -when the command is invoked directly, then it returns the default -value of the variable `SHORTNAME-arguments'. - -Optional argument GROUP specifies the Custom group in which the -option is placed. If ommitted then the option is placed in some -group the same way it is done when directly using `defcustom'. - -Optional argument MODE is deprecated, instead use the keyword -arguments `:setup-function' and/or `:refresh-function'. If MODE -is non-nil, then it specifies the mode used by the popup buffer, -instead of the default, which is `magit-popup-mode'. - -The remaining arguments should have the form - - [KEYWORD VALUE]... - -The following keywords are meaningful (and by convention are -usually specified in that order): - -`:actions' - The actions which can be invoked from the popup. VALUE is a - list whose members have the form (KEY DESC COMMAND), see - `magit-define-popup-action' for details. - - Actions are regular Emacs commands, which usually have an - `interactive' form setup to consume the values of the popup - `:switches' and `:options' when invoked from the corresponding - popup, else when invoked as the default action or directly - without using the popup, the default value of the variable - `SHORTNAME-arguments'. This is usually done by calling the - function `SHORTNAME-arguments'. - - Members of VALUE may also be strings, assuming the first member - is also a string. Instead of just one action section with the - heading \"Actions\", multiple sections are then inserted into - the popup buffer, using these strings as headings. - - Members of VALUE may also be nil. This should only be used - together with `:max-action-columns' and allows having gaps in - the action grit, which can help arranging actions sensibly. - -`:default-action' - The default action of the popup which is used directly instead - of displaying the popup buffer, when the popup is invoked with - a prefix argument. Also see `magit-popup-use-prefix-argument' - and `:use-prefix', which can be used to inverse the meaning of - the prefix argument. - -`:use-prefix' - Controls when to display the popup buffer and when to invoke - the default action (if any) directly. This overrides the - global default set using `magit-popup-use-prefix-argument'. - The value, if specified, should be one of `default' or `popup'. - -`:max-action-columns' - The maximum number of actions to display on a single line. - This helps arranging actions more sensibly. If there is not - enough room to display that many actions on one line, then - this is ignored. - -`:switches' - The popup arguments which can be toggled on and off. VALUE - is a list whose members have the form (KEY DESC SWITCH), see - `magit-define-popup-switch' for defails. - -`:options' - The popup arguments which take a value, as in \"--opt=OPTVAL\". - VALUE is a list whose members have the form (KEY DESC OPTION - READER), see `magit-define-popup-option' for details. - -`:default-arguments' - The default arguments, a list of switches (which are then - enabled by default) and options with there default values, as - in \"--OPT=OPTVAL\". - -`:sequence-predicate' - When this function returns non-nil, then the popup uses - `:sequence-actions' instead of `:actions', and does not show - the `:switches' and `:options'. - -`:sequence-actions' - The actions which can be invoked from the popup, when - `:sequence-predicate' returns non-nil. - -`:setup-function' - When this function is specified, then it is used instead of - `magit-popup-default-setup'. - -`:refresh-function' - When this function is specified, then it is used instead of - calling `magit-popup-insert-section' three times with symbols - `magit-popup-switch-button', `magit-popup-option-button', and - finally `magit-popup-action-button' as argument. - -`:man-page' - The name of the manpage to be displayed when the user requests - help for a switch or argument. - -\(fn NAME DOC [GROUP [MODE [OPTION]]] :KEYWORD VALUE...)" - (declare (indent defun) (doc-string 2)) - (let* ((grp (unless (keywordp (car args)) (pop args))) - (mode (unless (keywordp (car args)) (pop args))) - (opt (symbol-name name)) - (opt (if (keywordp (car args)) - (intern (concat (if (string-suffix-p "-popup" opt) - (substring opt 0 -6) - opt) - "-arguments")) - (eval (pop args))))) - `(progn - (defun ,name (&optional arg) ,doc - (interactive "P") - (magit-invoke-popup ',name ,mode arg)) - (defvar ,name - (list :variable ',opt ,@args)) - (magit-define-popup-keys-deferred ',name) - ,@(when opt - `((defcustom ,opt (plist-get ,name :default-arguments) - "" - ,@(and grp (list :group grp)) - :type '(repeat (string :tag "Argument"))) - (defun ,opt () - (if (eq magit-current-popup ',name) - magit-current-popup-args - ,opt)) - (put ',opt 'definition-name ',name)))))) - -(defun magit-define-popup-switch (popup key desc switch - &optional enable at prepend) - "In POPUP, define KEY as SWITCH. - -POPUP is a popup command defined using `magit-define-popup'. -SWITCH is a string representing an argument that takes no value. -KEY is a character representing the second event in the sequence -of keystrokes used to toggle the argument. (The first event, the -prefix, is shared among all switches, defaults to -, and can be -changed in `magit-popup-mode-keymap'). - -DESC is a string describing the purpose of the argument, it is -displayed in the popup. - -If optional ENABLE is non-nil then the switch is on by default. - -SWITCH is inserted after all other switches already defined for -POPUP, unless optional PREPEND is non-nil, in which case it is -placed first. If optional AT is non-nil then it should be the -KEY of another switch already defined for POPUP, the argument -is then placed before or after AT, depending on PREPEND." - (declare (indent defun)) - (magit-define-popup-key popup :switches key - (list desc switch enable) at prepend)) - -(defun magit-define-popup-option (popup key desc option - &optional reader value at prepend) - "In POPUP, define KEY as OPTION. - -POPUP is a popup command defined using `magit-define-popup'. -OPTION is a string representing an argument that takes a value. -KEY is a character representing the second event in the sequence -of keystrokes used to set the argument's value. (The first -event, the prefix, is shared among all options, defaults to =, -and can be changed in `magit-popup-mode-keymap'). - -DESC is a string describing the purpose of the argument, it is -displayed in the popup. - -If optional VALUE is non-nil then the option is on by default, -and VALUE is its default value. - -OPTION is inserted after all other options already defined for -POPUP, unless optional PREPEND is non-nil, in which case it is -placed first. If optional AT is non-nil then it should be the -KEY of another option already defined for POPUP, the argument -is then placed before or after AT, depending on PREPEND." - (declare (indent defun)) - (magit-define-popup-key popup :options key - (list desc option reader value) at prepend)) - -(defun magit-define-popup-action (popup key desc command - &optional at prepend) - "In POPUP, define KEY as COMMAND. - -POPUP is a popup command defined using `magit-define-popup'. -COMMAND can be any command but should usually consume the popup -arguments in its `interactive' form. -KEY is a character representing the event used invoke the action, -i.e. to interactively call the COMMAND. - -DESC is a string describing the purpose of the action, it is -displayed in the popup. - -COMMAND is inserted after all other commands already defined for -POPUP, unless optional PREPEND is non-nil, in which case it is -placed first. If optional AT is non-nil then it should be the -KEY of another command already defined for POPUP, the command -is then placed before or after AT, depending on PREPEND." - (declare (indent defun)) - (magit-define-popup-key popup :actions key - (list desc command) at prepend)) - -(defun magit-define-popup-sequence-action - (popup key desc command &optional at prepend) - "Like `magit-define-popup-action' but for `:sequence-action'." - (declare (indent defun)) - (magit-define-popup-key popup :sequence-actions key - (list desc command) at prepend)) - -(defconst magit-popup-type-plural-alist - '((:switch . :switches) - (:option . :options) - (:action . :actions) - (:sequence-action . :sequence-actions))) - -(defun magit-popup-pluralize-type (type) - (or (cdr (assq type magit-popup-type-plural-alist)) - type)) - -(defun magit-define-popup-key - (popup type key def &optional at prepend) - "In POPUP, define KEY as an action, switch, or option. -It's better to use one of the specialized functions - `magit-define-popup-action', - `magit-define-popup-sequence-action', - `magit-define-popup-switch', or - `magit-define-popup-option'." - (declare (indent defun)) - (setq type (magit-popup-pluralize-type type)) - (if (memq type '(:switches :options :actions :sequence-actions)) - (if (boundp popup) - (let* ((plist (symbol-value popup)) - (value (plist-get plist type)) - (elt (assoc key value))) - (if elt - (setcdr elt def) - (setq elt (cons key def))) - (if at - (when (setq at (cl-member at value :key 'car-safe :test 'equal)) - (setq value (cl-delete key value :key 'car-safe :test 'equal)) - (if prepend - (progn (push (car at) (cdr at)) - (setcar at elt)) - (push elt (cdr at)))) - (setq value (cl-delete key value :key 'car-safe :test 'equal))) - (unless (assoc key value) - (setq value (if prepend - (cons elt value) - (append value (list elt))))) - (set popup (plist-put plist type value))) - (push (list type key def at prepend) - (get popup 'magit-popup-deferred))) - (error "Unknown popup event type: %s" type))) - -(defun magit-define-popup-keys-deferred (popup) - (dolist (args (get popup 'magit-popup-deferred)) - (condition-case err - (apply #'magit-define-popup-key popup args) - ((debug error) - (display-warning 'magit (error-message-string err) :error)))) - (put popup 'magit-popup-deferred nil)) - -(defun magit-change-popup-key (popup type from to) - "In POPUP, bind TO to what FROM was bound to. -TYPE is one of `:action', `:sequence-action', `:switch', or -`:option'. Bind TO and unbind FROM, both are characters." - (--if-let (assoc from (plist-get (symbol-value popup) - (magit-popup-pluralize-type type))) - (setcar it to) - (message "magit-change-popup-key: FROM key %c is unbound" from))) - -(defun magit-remove-popup-key (popup type key) - "In POPUP, remove KEY's binding of TYPE. -POPUP is a popup command defined using `magit-define-popup'. -TYPE is one of `:action', `:sequence-action', `:switch', or -`:option'. KEY is the character which is to be unbound." - (setq type (magit-popup-pluralize-type type)) - (let* ((plist (symbol-value popup)) - (alist (plist-get plist type)) - (value (assoc key alist))) - (set popup (plist-put plist type (delete value alist))))) - -;;; Invoke - -(defvar-local magit-popup-previous-winconf nil) - -(defun magit-invoke-popup (popup mode arg) - (let* ((def (symbol-value popup)) - (val (symbol-value (plist-get def :variable))) - (default (plist-get def :default-action)) - (local (plist-get def :use-prefix)) - (use-prefix (or local magit-popup-use-prefix-argument))) - (cond - ((and arg (eq magit-popup-use-prefix-argument 'disabled)) - (customize-option-other-window 'magit-popup-use-prefix-argument) - (error (concat "The meaning of prefix arguments has changed. " - "Please explicitly enable their use again."))) - ((or (and (eq use-prefix 'default) arg) - (and (eq use-prefix 'popup) (not arg))) - (if default - (let ((magit-current-popup (list popup 'default)) - (magit-current-popup-args - (let ((magit-this-popup popup) - (magit-this-popup-events nil)) - (magit-popup-default-setup val def) - (magit-popup-get-args)))) - (when (and arg (listp arg)) - (setq current-prefix-arg (and (not (= (car arg) 4)) - (list (/ (car arg) 4))))) - (call-interactively default)) - (message "%s has no default action; showing popup instead." popup) - (magit-popup-mode-setup popup mode))) - ((memq use-prefix '(disabled default popup nil)) - (magit-popup-mode-setup popup mode) - (when magit-popup-show-help-echo - (message (concat "Type C-h i to view popup manual, " - "? to describe an argument or action.")))) - (local - (error "Invalid :use-prefix popup property value: %s" use-prefix)) - (t - (error "Invalid magit-popup-use-prefix-argument value: %s" use-prefix))))) - -(defun magit-invoke-popup-switch (event) - (interactive (list last-command-event)) - (--if-let (magit-popup-lookup event :switches) - (progn - (setf (magit-popup-event-use it) - (not (magit-popup-event-use it))) - (magit-refresh-popup-buffer)) - (user-error "%c isn't bound to any switch" event))) - -(defun magit-invoke-popup-option (event) - (interactive (list last-command-event)) - (--if-let (magit-popup-lookup event :options) - (progn - (if (magit-popup-event-use it) - (setf (magit-popup-event-use it) nil) - (let* ((arg (magit-popup-event-arg it)) - (val (funcall - (magit-popup-event-fun it) - (concat arg (unless (string-match-p "=$" arg) ": ")) - (magit-popup-event-val it)))) - (setf (magit-popup-event-use it) t) - (setf (magit-popup-event-val it) val))) - (magit-refresh-popup-buffer)) - (user-error "%c isn't bound to any option" event))) - -(defun magit-invoke-popup-action (event) - (interactive (list last-command-event)) - (--if-let (magit-popup-lookup event :actions) - (let ((magit-current-popup magit-this-popup) - (magit-current-popup-args (magit-popup-get-args)) - (command (magit-popup-event-fun it))) - (magit-popup-quit) - (call-interactively command) - (setq this-command command)) - (if (eq event ?q) - (magit-popup-quit) - (user-error "%c isn't bound to any action" event)))) - -(defun magit-popup-quit () - "Quit the current popup command without invoking an action." - (interactive) - (let ((buf (current-buffer)) - (winconf magit-popup-previous-winconf)) - (if (derived-mode-p 'magit-popup-mode) - (kill-buffer) - (magit-popup-help-mode -1) - (kill-local-variable 'magit-popup-previous-winconf)) - (when winconf - (set-window-configuration winconf)))) - -(defun magit-popup-read-number (prompt &optional default) - "Like `read-number' but DEFAULT may be a numeric string." - (read-number prompt (if (stringp default) - (string-to-number default) - default))) - -;;; Save - -(defun magit-popup-set-default-arguments (arg) - "Set default value for the arguments for the current popup. -Then close the popup without invoking an action; unless a prefix -argument is used in which case the popup remains open. - -For a popup named `NAME-popup' that usually means setting the -value of the custom option `NAME-arguments'." - (interactive "P") - (customize-set-variable (magit-popup-get :variable) - (magit-popup-get-args)) - (unless arg (magit-popup-quit))) - -(defun magit-popup-save-default-arguments (arg) - "Save default value for the arguments for the current popup. -Then close the popup without invoking an action; unless a prefix -argument is used in which case the popup remains open. - -For a popup named `NAME-popup' that usually means saving the -value of the custom option `NAME-arguments'." - (interactive "P") - (customize-save-variable (magit-popup-get :variable) - (magit-popup-get-args)) - (unless arg (magit-popup-quit))) - -;;; Help - -(defun magit-popup-toggle-show-common-commands () - "Show or hide an additional section with common commands. -The commands listed in this section are common to all popups -and are defined in `magit-popup-mode-map' (which see)." - (interactive) - (setq magit-popup-show-common-commands - (not magit-popup-show-common-commands)) - (magit-refresh-popup-buffer) - (fit-window-to-buffer)) - -(defun magit-popup-help () - "Show help for the argument or action at point." - (interactive) - (let* ((man (magit-popup-get :man-page)) - (key (read-key-sequence - (concat "Describe key" (and man " (? for manpage)") ": "))) - (int (aref key (1- (length key)))) - (def (or (lookup-key (current-local-map) key t) - (lookup-key (current-global-map) key)))) - (pcase def - (`magit-invoke-popup-switch - (magit-popup-manpage man (magit-popup-lookup int :switches))) - (`magit-invoke-popup-option - (magit-popup-manpage man (magit-popup-lookup int :options))) - (`magit-popup-help - (magit-popup-manpage man nil)) - (`self-insert-command - (setq def (magit-popup-lookup int :actions)) - (if def - (magit-popup-describe-function (magit-popup-event-fun def)) - (ding) - (message nil))) - (`nil (ding) - (message nil)) - (_ (magit-popup-describe-function def))))) - -(defun magit-popup-manpage (topic arg) - (unless topic - (user-error "No man page associated with %s" - (magit-popup-get :man-page))) - (when arg - (setq arg (magit-popup-event-arg arg))) - (let ((winconf (current-window-configuration)) buffer) - (pcase magit-popup-manpage-package - (`woman (delete-other-windows) - (split-window-below) - (with-no-warnings ; display-buffer-function is obsolete - (let ((display-buffer-alist nil) - (display-buffer-function nil)) - (woman topic))) - (setq buffer (current-buffer))) - (`man (cl-letf (((symbol-function #'fboundp) (lambda (_) nil))) - (setq buffer (man topic))) - (delete-other-windows) - (split-window-below) - (set-window-buffer (selected-window) buffer))) - (with-current-buffer buffer - (setq magit-popup-previous-winconf winconf) - (magit-popup-help-mode) - (fit-window-to-buffer (next-window)) - (if (and arg - (Man-find-section "OPTIONS") - (re-search-forward (format "^[\t\s]+\\(-., \\)*?%s[=\n]" arg) - (save-excursion - (Man-next-section 1) - (point)) - t)) - (goto-char (1+ (match-beginning 0))) - (goto-char (point-min)))))) - -(defun magit-popup-describe-function (function) - (let ((winconf (current-window-configuration))) - (delete-other-windows) - (split-window-below) - (other-window 1) - (with-no-warnings ; display-buffer-function is obsolete - (let ((display-buffer-alist nil) - (display-buffer-function nil)) - (describe-function function))) - (fit-window-to-buffer) - (other-window 1) - (setq magit-popup-previous-winconf winconf) - (magit-popup-help-mode))) - -(defun magit-popup-info () - "Show the popup manual." - (interactive) - (let ((winconf (current-window-configuration))) - (delete-other-windows) - (split-window-below) - (info "(magit-popup.info)Usage") - (magit-popup-help-mode) - (setq magit-popup-previous-winconf winconf)) - (magit-popup-help-mode) - (fit-window-to-buffer (next-window))) - -(define-minor-mode magit-popup-help-mode - "Auxiliary minor mode used to restore previous window configuration. -When some sort of help buffer is created from within a popup, -then this minor mode is turned on in that buffer, so that when -the user quits it, the previous window configuration is also -restored." - :keymap '(([remap Man-quit] . magit-popup-quit) - ([remap Info-exit] . magit-popup-quit) - ([remap quit-window] . magit-popup-quit))) - -;;; Modes - -(define-derived-mode magit-popup-mode fundamental-mode "MagitPopup" - "Major mode for infix argument popups." - :mode 'magit-popup - (setq buffer-read-only t) - (setq-local scroll-margin 0) - (setq-local magit-popup-show-common-commands magit-popup-show-common-commands) - (hack-dir-local-variables-non-file-buffer)) - -(put 'magit-popup-mode 'mode-class 'special) - -(defun magit-popup-default-setup (val def) - (if (--when-let (magit-popup-get :sequence-predicate) - (funcall it)) - (magit-popup-put :actions (magit-popup-convert-actions - val (magit-popup-get :sequence-actions))) - (magit-popup-put :switches (magit-popup-convert-switches - val (plist-get def :switches))) - (magit-popup-put :options (magit-popup-convert-options - val (plist-get def :options))) - (magit-popup-put :actions (magit-popup-convert-actions - val (plist-get def :actions))))) - -(defun magit-popup-mode-setup (popup mode) - (let ((val (symbol-value (plist-get (symbol-value popup) :variable))) - (def (symbol-value popup))) - (magit-popup-mode-display-buffer (get-buffer-create - (format "*%s*" popup)) - (or mode 'magit-popup-mode)) - (setq magit-this-popup popup) - (if (bound-and-true-p magit-popup-setup-hook) ; obsolete - (run-hook-with-args 'magit-popup-setup-hook val def) - (funcall (or (magit-popup-get :setup-function) - 'magit-popup-default-setup) - val def))) - (magit-refresh-popup-buffer) - (fit-window-to-buffer nil nil (line-number-at-pos (point-max)))) - -(defun magit-popup-mode-display-buffer (buffer mode) - (let ((winconf (current-window-configuration))) - (split-window-vertically) - (other-window 1) - (switch-to-buffer buffer) - (funcall mode) - (setq magit-popup-previous-winconf winconf))) - -(defvar magit-refresh-popup-buffer-hook nil - "Hook run by `magit-refresh-popup-buffer'. - -The hook is run right after inserting the representation of the -popup events but before optionally inserting the representation -of events shared by all popups and before point is adjusted.") - -(defun magit-refresh-popup-buffer () - (let* ((inhibit-read-only t) - (button (button-at (point))) - (prefix (and button (button-get button 'prefix))) - (event (and button (button-get button 'event)))) - (erase-buffer) - (save-excursion - (--if-let (magit-popup-get :refresh-function) - (funcall it) - (magit-popup-insert-section 'magit-popup-switch-button) - (magit-popup-insert-section 'magit-popup-option-button) - (magit-popup-insert-section 'magit-popup-action-button)) - (run-hooks 'magit-refresh-popup-buffer-hook) - (when magit-popup-show-common-commands - (magit-popup-insert-command-section - 'magit-popup-internal-command-button - magit-popup-common-commands))) - (set-buffer-modified-p nil) - (if event - (while (and (ignore-errors (forward-button 1)) - (let ((b (button-at (point)))) - (or (not (equal (button-get b 'prefix) prefix)) - (not (equal (button-get b 'event) event)))))) - (re-search-forward "^Actions" nil t) - (ignore-errors (forward-button 1))))) - -;;; Draw - -(defvar magit-popup-min-padding 3 - "Minimal amount of whitespace between columns in popup buffers.") - -(defun magit-popup-insert-section (type &optional spec heading) - (if (not spec) - (progn (setq spec (magit-popup-get (button-type-get type 'property))) - (when spec - (if (stringp (car spec)) - (--each (-partition-by-header 'stringp spec) - (magit-popup-insert-section type (cdr it) (car it))) - (magit-popup-insert-section type spec)))) - (unless heading - (setq heading (button-type-get type 'heading))) - (let* ((formatter (button-type-get type 'formatter)) - (items (mapcar (lambda (ev) - (and ev (funcall formatter type ev))) - (or spec (magit-popup-get - (button-type-get type 'property))))) - (maxcols (button-type-get type 'maxcols)) - (pred (magit-popup-get :sequence-predicate))) - (if (and pred (funcall pred)) - (setq maxcols nil) - (cl-typecase maxcols - (keyword (setq maxcols (magit-popup-get maxcols))) - (symbol (setq maxcols (symbol-value maxcols))))) - (when items - (insert (propertize heading 'face 'magit-popup-heading)) - (unless (string-match "\n$" heading) - (insert "\n")) - (let ((colwidth - (+ (apply 'max (mapcar (lambda (e) (length (car e))) items)) - magit-popup-min-padding))) - (dolist (item items) - (unless (bolp) - (let ((padding (- colwidth (% (current-column) colwidth)))) - (if (and (< (+ (current-column) padding colwidth) - (window-width)) - (< (ceiling (/ (current-column) (* colwidth 1.0))) - (or maxcols 1000))) - (insert (make-string padding ?\s)) - (insert "\n")))) - (if item - (apply 'insert-button item) - (insert ?\s)))) - (insert (if (= (char-before) ?\n) "\n" "\n\n")))))) - -(defun magit-popup-format-argument-button (type ev) - (list (format-spec - (button-type-get type 'format) - `((?k . ,(propertize (concat - (--when-let (button-type-get type 'prefix) - (char-to-string it)) - (magit-popup-event-keydsc ev)) - 'face 'magit-popup-key)) - (?d . ,(magit-popup-event-dsc ev)) - (?a . ,(propertize (magit-popup-event-arg ev) - 'face (if (magit-popup-event-use ev) - 'magit-popup-argument - 'magit-popup-disabled-argument))) - (?v . ,(let ((val (magit-popup-event-val ev))) - (if (and (magit-popup-event-use ev) - (not (equal val ""))) - (propertize (format "\"%s\"" val) - 'face 'magit-popup-option-value) - ""))))) - 'type type 'event (magit-popup-event-key ev))) - -(defun magit-popup-format-action-button (type ev) - (list (format-spec - (button-type-get type 'format) - `((?k . ,(propertize (magit-popup-event-keydsc ev) - 'face 'magit-popup-key)) - (?d . ,(magit-popup-event-dsc ev)) - (?D . ,(if (eq (magit-popup-event-fun ev) - (magit-popup-get :default-action)) - (propertize (magit-popup-event-dsc ev) 'face 'bold) - (magit-popup-event-dsc ev))))) - 'type type 'event (magit-popup-event-key ev))) - -(defun magit-popup-insert-command-section (type spec) - (magit-popup-insert-section - type (mapcar (lambda (elt) - (list (car (where-is-internal (cadr elt) - (current-local-map))) - (car elt))) - spec))) - -(defun magit-popup-format-command-button (type elt) - (nconc (magit-popup-format-action-button - type (make-magit-popup-event :key (car elt) - :dsc (cadr elt))) - (list 'function (lookup-key (current-local-map) (car elt))))) - -;;; Utilities - -(defun magit-popup-import-file-args (args files) - (if files - (cons (concat "-- " (mapconcat #'identity files ",")) args) - args)) - -(defun magit-popup-export-file-args (args) - (let ((files (--first (string-prefix-p "-- " it) args))) - (when files - (setq args (remove files args) - files (split-string (substring files 3) ","))) - (list args files))) - -;;; magit-popup.el ends soon - -(defconst magit-popup-font-lock-keywords - (eval-when-compile - `((,(concat "(\\(magit-define-popup\\)\\_>" - "[ \t'\(]*" - "\\(\\(?:\\sw\\|\\s_\\)+\\)?") - (1 'font-lock-keyword-face) - (2 'font-lock-function-name-face nil t))))) - -(font-lock-add-keywords 'emacs-lisp-mode magit-popup-font-lock-keywords) - -(provide 'magit-popup) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; magit-popup.el ends here diff --git a/elpa/magit-popup-20151119.201/magit-popup.info b/elpa/magit-popup-20151119.201/magit-popup.info deleted file mode 100644 index 62ef7e06..00000000 --- a/elpa/magit-popup-20151119.201/magit-popup.info +++ /dev/null @@ -1,675 +0,0 @@ -This is magit-popup.info, produced by makeinfo version 5.2 from -magit-popup.texi. - -Taking inspiration from regular prefix commands and prefix arguments, -this library implements a similar abstraction; a new kind of prefix -command that is associated with a specific set of infix arguments and -suffix commands. - - Copyright (C) 2015 Jonas Bernoulli - - You can redistribute this document 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 document 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. -INFO-DIR-SECTION Emacs -START-INFO-DIR-ENTRY -* Magit-Popup: (magit-popup). Infix arguments with feedback. -END-INFO-DIR-ENTRY - - -File: magit-popup.info, Node: Top, Next: Introduction, Up: (dir) - -Magit-Popup User Manual -*********************** - -Taking inspiration from regular prefix commands and prefix arguments, -this library implements a similar abstraction; a new kind of prefix -command that is associated with a specific set of infix arguments and -suffix commands. - - Copyright (C) 2015 Jonas Bernoulli - - You can redistribute this document 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 document 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. - -* Menu: - -* Introduction:: -* Usage:: -* Defining prefix and suffix commands:: - -— The Detailed Node Listing — - -Usage - -* Customizing existing popups:: -* Other options:: - -Defining prefix and suffix commands - -* Defining prefix commands:: -* Defining suffix commands:: - - - -File: magit-popup.info, Node: Introduction, Next: Usage, Prev: Top, Up: Top - -1 Introduction -************** - -Taking inspiration from regular prefix commands and prefix arguments, -this library implements a similar abstraction; a new kind of prefix -command that is associated with a specific set of infix arguments and -suffix commands. - - Invoking such a prefix command displays a popup buffer which lists -the associated infix arguments and suffix commands. In that buffer each -argument is prefixes with the key sequence that can be used to toggle it -or change its value. Likewise each suffix command is prefixed with the -key used to invoke it. Such a popup buffer might look like this: - -,----------------------------------------- -|Switches -| -l Show graph (--graph) -| -d Show refnames (--decorate) -| -|Options -| =m Search messages (--grep="popup") -| =p Search patches (-G) -| -|Action -| l Show log for current branch -| o Show log for another branch -'----------------------------------------- - - The user could then for example type ‘-l’ to toggle the ‘--graph’ -*switch* (when it is on then it is shown in green, otherwise in gray), -or ‘=m’ to change the value of the *option* ‘--grep’. - - Once all arguments are as desired one invokes a suffix command, which -causes the popup buffer to disappears. The suffix command should then -retrieve the infix arguments in its ‘interactive’ form like this is done -for prefix arguments. - - While such "prefix-infix-suffix" combos were inspired by regular -prefix commands and prefix arguments, they are also quite different. -This should illustrate the most basic differences: - - • A regular prefix commands - - /- command1 - prefix --- command2 - \- command3 - - • Prefix arguments - - /- command1 - C-u ... --- command2 - \- well *any* command - - • A Prefix-Infix-Suffix combo - - /- argument1 -\ /- suffix1 - prefix----- argument2 --+-- suffix2 - ^ \- argument3 -/ - | | - '--------' - (refresh buffer) - - This library was written as a replacement for ‘magit-key-mode’ which -was used in Magit releases before 2.1.0. It is used to implement all -"popups" in the current Magit release but a future release will switch -to yet another implementation. - - This library does not depend on any other Magit libraries and it is -distributed as a separate package, which makes it possible to use it in -packages that are not related to Magit. But keep in mind that it will -be deprecated eventually. - - -File: magit-popup.info, Node: Usage, Next: Defining prefix and suffix commands, Prev: Introduction, Up: Top - -2 Usage -******* - -Every popup buffers created with a prefix command contains a section -named "Actions" listing the available suffix commands. Most buffers -also contain a "Switches" and/or an "Options" section which list the two -types of infix arguments separately. - - Switches are arguments that can be toggled on or off. When a switch -is active then it is shown in color, when it is off then it is shown in -gray (of course the details depend on the color theme in use). - - Options are arguments that have a value. When an option has a value -then that is shown after the option itself. Because for some options -the empty string is a valid value, options are additionally colorized -like switches to indicate whether they are active or not. - - The events bound to suffix commands are always single alphabetic -characters. The bindings for arguments are always two events long. For -switches the first key is always ‘-’, for options it is always ‘=’. The -second key is always an alphabetic character. - - By default popup buffers also feature a section listing commands -common to all popups. To avoid conflicts with suffix commands, the -bindings of these common commands are not alphabetic characters. This -section is shown by default so that documentation-resistant users get a -change to notice them. - - -- User Option: magit-popup-show-common-commands - - This option controls whether the section which lists the commands - that are common to all popups is initially show. We recommend you - set this to ‘nil’ - after you have memorized that it can be shown - on demand using ‘C-t’. - -‘C-t’ (‘magit-popup-toggle-show-common-commands’) - - Show or hide the section listing the commands shared by all popups. - -‘C-g’ (‘magit-popup-quit’) - - Quit popup buffer without invoking a suffix command. - - Without further action, setting arguments only affects the next -suffix command. Invoking the same prefix command again resets the -arguments to their default value, but the defaults can be changed -directly from the popup buffer itself. For a prefix command named -‘NAME-popup’ the default values are stored as the value of the custom -option named ‘NAME-arguments’. While this option can be customized -using the Custom interface, it is better to do so directly from the -popup buffer. - -‘C-c C-c’ (‘magit-popup-set-default-arguments’) - - This sets the default value for the arguments for the current - popup. - - Then the popup buffer is closed without invoking a suffix command; - unless a prefix argument is used in which case the popup remains - open. - -‘C-x C-s’ (‘magit-popup-save-default-arguments’) - - This sets the default value for the arguments for the current popup - and saves it for future Emacs sessions. - - Then the popup buffer is closed without invoking an action; unless - a prefix argument is used in which case the popup remains open. - - It is also possible to add additional arguments and commands to an -existing popup, but that cannot be done directly from the popup (or the -Custom interface). See *note Customizing existing popups: Customizing -existing popups. - - Documentation about a popup’s arguments and commands can be shown -directly from the popup. - -‘C-h i’ (‘magit-popup-info’) - - Show this manual. - -‘?’ (‘magit-popup-help’) - - This command reads a key sequence and then shows the documentation - of the argument or command that sequence is bound to. In other - words type the same keys that you would use to invoke the argument - or command, but prefix the sequence with ‘?’. - - For suffix commands this shows the doc-string. For arguments this - command can only show something for popups that have an associated - man-page. If the man-page is set, then this command displays it in - a separate buffer and puts point on the entry about the argument in - question. - - The buffer which is used to display the documentation is selected. - Simply press ‘q’ to leave that buffer and restore the old window - configuration. - - While it isn’t very useful, it is possible to move around in a popup -buffer using ‘C-p’ and ‘C-n’, and to invoke the argument or command at -point using ‘RET’. But it is much more efficient to use the dedicated -key bindings instead, so these commands are not listed in popup buffers -along with the other common commands. - -* Menu: - -* Customizing existing popups:: -* Other options:: - - -File: magit-popup.info, Node: Customizing existing popups, Next: Other options, Up: Usage - -2.1 Customizing existing popups -=============================== - -It is possible to define additional infix arguments and suffix commands -to an existing popup using the following functions. - - You can find some examples which use the below commands at -. - - -- Function: magit-define-popup-switch popup key desc switch &optional - enable at prepend - - In POPUP, define KEY as SWITCH. - - POPUP is a popup command defined using ‘magit-define-popup’. - SWITCH is a string representing an argument that takes no value. - KEY is a character representing the second event in the sequence of - keystrokes used to toggle the argument. (The first event, the - prefix, is shared among all switches, defaults to ‘-’, and can be - changed in ‘magit-popup-mode-keymap’). - - DESC is a string describing the purpose of the argument, it is - displayed in the popup. - - If optional ENABLE is non-nil then the switch is on by default. - - SWITCH is inserted after all other switches already defined for - POPUP, unless optional PREPEND is non-nil, in which case it is - placed first. If optional AT is non-nil then it should be the KEY - of another switch already defined for POPUP, the argument is then - placed before or after AT, depending on PREPEND. - - -- Function: magit-define-popup-option popup key desc option &optional - reader value at prepend - - In POPUP, define KEY as OPTION. - - POPUP is a popup command defined using ‘magit-define-popup’. - OPTION is a string representing an argument that takes a value. - KEY is a character representing the second event in the sequence of - keystrokes used to set the argument’s value. (The first event, the - prefix, is shared among all options, defaults to ‘=’, and can be - changed in ‘magit-popup-mode-keymap’). - - DESC is a string describing the purpose of the argument, it is - displayed in the popup. - - If optional VALUE is non-nil then the option is on by default, and - VALUE is its default value. - - OPTION is inserted after all other options already defined for - POPUP, unless optional PREPEND is non-nil, in which case it is - placed first. If optional AT is non-nil then it should be the KEY - of another option already defined for POPUP, the argument is then - placed before or after AT, depending on PREPEND. - - -- Function: magit-define-popup-action popup key desc command &optional - at prepend - - In POPUP, define KEY as COMMAND. - - POPUP is a popup command defined using ‘magit-define-popup’. - COMMAND can be any command but should usually consume the popup - arguments in its ‘interactive’ form. KEY is a character - representing the event used invoke the action, i.e. to - interactively call the COMMAND. - - DESC is a string describing the purpose of the action, it is - displayed in the popup. - - COMMAND is inserted after all other commands already defined for - POPUP, unless optional PREPEND is non-nil, in which case it is - placed first. If optional AT is non-nil then it should be the KEY - of another command already defined for POPUP, the command is then - placed before or after AT, depending on PREPEND. - - -- Function: magit-define-popup-sequence-action popup key desc command - &optional at prepend - - Like ‘magit-define-popup-action’, but modifies the value of the - ‘:sequence-actions’ property instead of ‘:actions’. - - -- Function: magit-change-popup-key popup type from to - - In POPUP, bind TO to what FROM was bound to. TYPE is one of - ‘:action’, ‘:sequence-action’, ‘:switch’, or ‘:option’. Bind TO - and unbind FROM, both are characters. - - -- Function: magit-remove-popup-key popup type key - - In POPUP, remove KEY’s binding of TYPE. POPUP is a popup command - defined using ‘magit-define-popup’. TYPE is one of ‘:action’, - ‘:sequence-action’, ‘:switch’, or ‘:option’. KEY is the character - which is to be unbound. - - It is also possible to change other aspects of a popup by setting a -property using ‘plist-put’. See *note Defining prefix commands: -Defining prefix commands. for valid properties. The most likely change -Magit users might want to make is: - - (plist-put magit-show-refs-popup :use-prefix nil) - - -File: magit-popup.info, Node: Other options, Prev: Customizing existing popups, Up: Usage - -2.2 Other options -================= - - -- User Option: magit-popup-use-prefix-argument - - This option controls the effect that the use of a prefix argument - before entering a popup has. The *intended* default is ‘default’, - but the *actual* default is ‘disabled’. This is necessary because - the old popup implementation did simply forward such a pre-popup - prefix argument to the suffix command invoked from the popup, and - changing that without users being aware of it could lead to tears. - - • ‘disabled’ - - Bring up a Custom option buffer so that the user reads this - and then makes an informed choice. - - • ‘default’ - - With a prefix argument directly invoke the popup’s default - action (an Emacs command), instead of bringing up the popup. - - • ‘popup’ - - With a prefix argument bring up the popup, otherwise directly - invoke the popup’s default action. - - • ‘nil’ - - Ignore prefix arguments. - This option can be overridden for individual popups. - ‘magit-show-refs-popup’ for example defaults to invoking the - default action directly. It only shows the popup buffer when a - prefix argument is used. See *note Customizing existing popups: - Customizing existing popups. - - -- User Option: magit-popup-manpage-package - - The Emacs package used to display man-pages, one of ‘man’ or - ‘woman’. - - To emphasize the default action by making it bold use this: - - (button-type-put 'magit-popup-action-button 'format " %k %D") - - -File: magit-popup.info, Node: Defining prefix and suffix commands, Prev: Usage, Up: Top - -3 Defining prefix and suffix commands -************************************* - -If you write an extension for Magit then you should use this library now -and later when ‘transient’ is released port to that. - - If you are considering using this library to define popups for -packages not related to Magit, then keep in mind that it will be -superseded eventually. Once ‘transient’ has been released I will only -fix bugs in ‘magit-popup’ but not implement any new features. - - Also consider using ‘hydra’ instead. To some extend ‘magit-popup’ -and ‘hydra’ are similar but have a different focus. The main purpose of -‘magit-popup’ is to pass infix arguments to suffix commands. If all you -need is a command dispatcher then you are better of using ‘hydra’. Of -course ‘hydra’ may also be a better fit not only because of the features -it lacks, but also because of the features it provides, which are in -turn missing from ‘magit-popup’. - - Here is an example of how one defines a prefix command along with its -infix arguments, and then also one of its suffix commands. - - ;;;###autoload (autoload 'magit-tag-popup "magit" nil t) - (magit-define-popup magit-tag-popup - "Show popup buffer featuring tagging commands." - 'magit-commands - :man-page "git-tag" - :switches '((?a "Annotate" "--annotate") - (?s "Sign" "--sign") - (?f "Force" "--force")) - :actions '((?t "Create" magit-tag) - (?k "Delete" magit-tag-delete) - (?p "Prune" magit-tag-prune)) - :default-action 'magit-tag) - - ;;;###autoload - (defun magit-tag (name rev &optional args) - "Create a new tag with the given NAME at REV." - (interactive (list (magit-read-tag "Tag name") - (magit-read-branch-or-commit "Place tag on") - (magit-tag-arguments))) - (magit-run-git-with-editor "tag" args name rev)) - -* Menu: - -* Defining prefix commands:: -* Defining suffix commands:: - - -File: magit-popup.info, Node: Defining prefix commands, Next: Defining suffix commands, Up: Defining prefix and suffix commands - -3.1 Defining prefix commands -============================ - -Prefix commands and their infix arguments are defined using the macro -‘magit-define-popup’. The key bindings and descriptions of suffix -commands are also defined using that macro, but the actual interactive -commands have to be defined separately using plain ‘defun’. - - -- Macro: magit-define-popup name doc [group [mode [option]]] :keyword - value… - - This macro defines a popup named NAME. The NAME should begin with - the package prefix and by convention end with ‘-popup’, it is used - as the name of the command which shows the popup and for an - internal variable (whose value is used to store information about - the popup and should not be accessed directly). DOC is the - doc-string of the popup command. - - This macro also defines an option and a function both named - ‘SHORTNAME-arguments’, where SHORTNAME is NAME with the trailing - ‘-popup’ removed. The name of this option and this function can be - overwritten using the optional argument OPTION, but that is rarely - advisable. As a special case if OPTION is specified but ‘nil’, - then this option and this function are not defined at all, which is - useful for popups that are used as simple dispatchers that offer no - arguments. - - The option ‘SHORTNAME-arguments’ holds the value for the popup - arguments. It can be customized from within the popup or using the - Custom interface. It can also have a buffer local value in any - non-popup buffer. The local value for the buffer from which the - popup command was invoked, can be set from within the popup buffer. - - The function ‘SHORTNAME-arguments’ returns the currently effective - value of the variable by the same name. See below for more - information. - - The optional argument GROUP specifies the Custom group in which the - option is placed. If omitted then the option is placed in some - group the same way it is done when directly using ‘defcustom’ and - omitting the group. - - The optional argument MODE specifies the mode used by the popup - buffer. If it is omitted or ‘nil’ then ‘magit-popup-mode’ is used. - - The remaining arguments should have the form ‘[KEYWORD VALUE]...’. - - The following keywords are meaningful (and by convention are - usually specified in that order): - - • ‘:actions’ - - The actions which can be invoked from the popup. VALUE is a - list whose members have the form (KEY DESC COMMAND), see - ‘magit-define-popup-action’ for details. - - How the actions are split into rows and columns currently - depends on the available space and ‘:max-action-columns’. - - WARNING: This will likely be change to use a more explicit - format (((KEY DESC COMMAND)…)…) before the release. - - Actions are regular Emacs commands, which usually have an - ‘interactive’ form setup to consume the values of the popup - ‘:switches’ and ‘:options’ when invoked from the corresponding - popup, else when invoked as the default action or directly - without using the popup, the default value of the variable - ‘SHORTNAME-arguments’. This is usually done by calling the - function ‘SHORTNAME-arguments’. - - Members of VALUE may also be strings, assuming the first - member is also a string. Instead of just one action section - with the heading \"Actions\", multiple sections are then - inserted into the popup buffer, using these strings as - headings. - - Members of VALUE may also be nil. This should only be used - together with ‘:max-action-columns’ and allows having gaps in - the action grit, which can help arranging actions sensibly. - - • ‘:default-action’ - - The default action of the popup which is used directly instead - of displaying the popup buffer, when the popup is invoked with - a prefix argument. Also see ‘magit-popup-use-prefix-argument’ - and ‘:use-prefix’, which can be used to inverse the meaning of - the prefix argument. - - • ‘:use-prefix’ - - Controls when to display the popup buffer and when to invoke - the default action (if any) directly. This overrides the - global default set using ‘magit-popup-use-prefix-argument’. - The value, if specified, should be one of ‘default’ or - ‘prefix’. - - • ‘:switches’ - - The popup arguments which can be toggled on and off. VALUE is - a list whose members have the form ‘(KEY DESC SWITCH)’, see - ‘magit-define-popup-switch’ for details. - - • ‘:options’ - - The popup arguments which take a value, as in "–opt~OPTVAL". - VALUE is a list whose members have the form (KEY DESC OPTION - READER), see ‘magit-define-popup-option’ for details. - - • ‘:default-arguments’ - - The default arguments, a list of switches (which are then - enabled by default) and options with there default values, as - in "–OPT~OPTVAL\". - - • ‘:sequence-predicate’ - - When this function returns non-nil, then the popup uses - ‘:sequence-actions’ instead of ‘:actions’, and does not show - the ‘:switches’ and ‘:options’. - - • ‘:sequence-actions’ - - The actions which can be invoked from the popup, when - ‘:sequence-predicate’ returns non-nil. - - • ‘:setup-function’ - - When this function is specified, then it is used instead of - ‘magit-popup-default-setup’. - - • ‘:refresh-function’ - - When this function is specified, then it is used instead of - calling ‘magit-popup-insert-section’ three times with symbols - ‘magit-popup-switch-button’, ‘magit-popup-option-button’, and - finally ‘magit-popup-action-button’ as argument. - - • ‘:man-page’ - - The name of the manpage to be displayed when the user requests - help for an argument. - - -File: magit-popup.info, Node: Defining suffix commands, Prev: Defining prefix commands, Up: Defining prefix and suffix commands - -3.2 Defining suffix commands -============================ - -Commands intended to be invoked from a particular popup should determine -the currently effective arguments by calling the function -‘SHORTNAME-arguments’ inside their ‘interactive’ form. This function is -created by the ‘magit-define-popup’ macro. For a popup named -‘prefix-foo-popup’ the name of this function is ‘prefix-foo-arguments’. - - When the command was invoked as an action in the respective popup, -then this function returns the arguments that were set in the popup. -Otherwise when the command was invoked as the default of the popup (by -calling the popup command with a prefix argument), or without using the -popup command at all, then this function returns the buffer-local or -global value of the variable ‘SHORTNAME-arguments’. - - Internally arguments are handled as a list of strings. This might -not be appropriate for the intended use inside commands, or it might be -necessary to manipulate that list somehow, i.e. to split "–ARG=VAL" -into "–ARG""VAL". This should be done by advising or redefining the -function ‘SHORTNAME-arguments’. - - Internally ‘SHORNAME-arguments’ used following variables and -function. Except when redefining the former, you should not use these -directly. - - -- Variable: magit-current-popup - - The popup from which this editing command was invoked. - - -- Variable: magit-current-popup-args - - The value of the popup arguments for this editing command. - - If the current command was invoked from a popup, then this is a - list of strings of all the set switches and options. This includes - arguments which are set by default not only those explicitly set - during this invocation. - - When the value is nil, then that can be because no argument is set, - or because the current command wasn’t invoked from a popup at all. - - -- Function: magit-current-popup-args &rest args - - This function returns the value of the popup arguments for this - editing command. The value is the same as that of the variable by - the same name, except that FILTER is applied. FILTER is a list of - regexps; only arguments that match one of them are returned. The - first element of FILTER may also be ‘:not’ in which case only - arguments that don’t match any of the regexps are returned, or - ‘:only’ which doesn’t change the behavior. - - - -Tag Table: -Node: Top989 -Node: Introduction2158 -Node: Usage4735 -Node: Customizing existing popups9392 -Node: Other options13961 -Node: Defining prefix and suffix commands15667 -Node: Defining prefix commands17819 -Node: Defining suffix commands24265 - -End Tag Table - - -Local Variables: -coding: utf-8 -End: diff --git a/elpa/magit-popup-20151223.1341/dir b/elpa/magit-popup-20151223.1341/dir new file mode 100644 index 00000000..c276dafb --- /dev/null +++ b/elpa/magit-popup-20151223.1341/dir @@ -0,0 +1,18 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "?" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Emacs +* Magit-Popup: (magit-popup). Infix arguments with feedback. diff --git a/elpa/magit-popup-20151223.1341/magit-popup-autoloads.el b/elpa/magit-popup-20151223.1341/magit-popup-autoloads.el new file mode 100644 index 00000000..e6311a39 --- /dev/null +++ b/elpa/magit-popup-20151223.1341/magit-popup-autoloads.el @@ -0,0 +1,16 @@ +;;; magit-popup-autoloads.el --- automatically extracted autoloads +;; +;;; Code: +(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +;;;### (autoloads nil nil ("magit-popup-pkg.el" "magit-popup.el") +;;;;;; (22140 7078 82837 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; End: +;;; magit-popup-autoloads.el ends here diff --git a/elpa/magit-popup-20151223.1341/magit-popup-pkg.el b/elpa/magit-popup-20151223.1341/magit-popup-pkg.el new file mode 100644 index 00000000..c21b3be0 --- /dev/null +++ b/elpa/magit-popup-20151223.1341/magit-popup-pkg.el @@ -0,0 +1,9 @@ +(define-package "magit-popup" "20151223.1341" "Define prefix-infix-suffix command combos" + '((emacs "24.4") + (async "20150909.2257") + (dash "20151021.113")) + :url "https://github.com/magit/magit" :keywords + '("bindings")) +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/magit-popup-20151223.1341/magit-popup.el b/elpa/magit-popup-20151223.1341/magit-popup.el new file mode 100644 index 00000000..2a11aa74 --- /dev/null +++ b/elpa/magit-popup-20151223.1341/magit-popup.el @@ -0,0 +1,1256 @@ +;;; magit-popup.el --- Define prefix-infix-suffix command combos -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; This library was inspired by and replaces library `magit-key-mode', +;; which was written by Phil Jackson and is +;; distributed under the GNU General Public License version 3 or later. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Package-Requires: ((emacs "24.4") (async "20150909.2257") (dash "20151021.113")) +;; Keywords: bindings +;; Homepage: https://github.com/magit/magit + +;; 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: + +;; This library implements a generic interface for toggling switches +;; and setting options and then invoking an Emacs command which does +;; something with these arguments. The prototypical use is for the +;; command to call an external process, passing on the arguments as +;; command line arguments. But this is only one of many possible +;; uses (though the one this library is optimized for). + +;; With the Emacs concept of "prefix arguments" in mind this could be +;; described as "infix arguments with feedback in a buffer". + +;; Commands that set the prefix argument for the subsequent command do +;; not limit what that next command could be. But entering a command +;; console popup does limit the selection to the commands defined for +;; that popup, and so we use the term "infix" instead of "prefix". + +;;; Code: + +(require 'button) +(require 'cl-lib) +(require 'dash) +(require 'format-spec) + +(and (require 'async-bytecomp nil t) + (memq 'magit (bound-and-true-p async-bytecomp-allowed-packages)) + (fboundp 'async-bytecomp-package-mode) + (async-bytecomp-package-mode 1)) + +(declare-function info 'info) +(declare-function Man-find-section 'man) +(declare-function Man-next-section 'man) + +;; For the `:variable' event type. +(declare-function magit-call-git 'magit-process) +(declare-function magit-git-string 'magit-git) +(declare-function magit-refresh 'magit-mode) +(declare-function magit-set 'magit-git) + +;; For branch actions. +(declare-function magit-branch-set-face 'magit-git) +(declare-function magit-local-branch-p 'magit-git) + +;;; Settings +;;;; Custom Groups + +(defgroup magit-popup nil + "Infix arguments with a popup as feedback." + :group 'bindings) + +(defgroup magit-popup-faces nil + "Faces used by Magit-Popup." + :group 'magit-popup) + +;;;; Custom Options + +(defcustom magit-popup-manpage-package + (if (memq system-type '(windows-nt ms-dos)) 'woman 'man) + "The package used to display manpages. +One of `man' or `woman'." + :group 'magit-popup + :type '(choice (const man) (const woman))) + +(defcustom magit-popup-show-help-echo t + "Show usage information in the echo area." + :group 'magit-popup + :type 'boolean) + +(defcustom magit-popup-show-common-commands t + "Initially show section with commands common to all popups. +This section can also be toggled temporarily using \ +\\\\[magit-popup-toggle-show-common-commands]." + :group 'magit-popup + :type 'boolean) + +(defcustom magit-popup-use-prefix-argument 'disabled + "Control how prefix arguments affect infix argument popups. + +This option controls the effect that the use of a prefix argument +before entering a popup has. The *intended* default is `default', +but the *actual* default is `disabled'. This is necessary because +the old popup implementation did simply forward such a pre-popup +prefix argument to the action invoked from the popup, and changing +that without users being aware of it could lead to tears. + +`disabled' Bring up a Custom option buffer so that the user reads + this and then makes an informed choice. + +`default' With a prefix argument directly invoke the popup's + default action (an Emacs command), instead of bringing + up the popup. + +`popup' With a prefix argument bring up the popup, otherwise + directly invoke the popup's default action. + +`nil' Ignore prefix arguments." + :group 'magit-popup + :type '(choice + (const :tag "Call default action instead of showing popup" default) + (const :tag "Show popup instead of calling default action" popup) + (const :tag "Ignore prefix argument" nil) + (const :tag "Abort and show usage information" disabled))) + +;;;; Custom Faces + +(defface magit-popup-heading + '((t :inherit font-lock-keyword-face)) + "Face for key mode header lines." + :group 'magit-popup-faces) + +(defface magit-popup-key + '((t :inherit font-lock-builtin-face)) + "Face for key mode buttons." + :group 'magit-popup-faces) + +(defface magit-popup-argument + '((t :inherit font-lock-warning-face)) + "Face used to display enabled arguments in popups." + :group 'magit-popup-faces) + +(defface magit-popup-disabled-argument + '((t :inherit shadow)) + "Face used to display disabled arguments in popups." + :group 'magit-popup-faces) + +(defface magit-popup-option-value + '((t :inherit font-lock-string-face)) + "Face used to display option values in popups." + :group 'magit-popup-faces) + +;;;; Keymap + +(defvar magit-popup-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [remap self-insert-command] 'magit-invoke-popup-action) + (define-key map [?- t] 'magit-invoke-popup-switch) + (define-key map [?= t] 'magit-invoke-popup-option) + (define-key map [?\C-c ?\C-c] 'magit-popup-set-default-arguments) + (define-key map [?\C-x ?\C-s] 'magit-popup-save-default-arguments) + (define-key map [?\C-g] 'magit-popup-quit) + (define-key map [??] 'magit-popup-help) + (define-key map [?\C-h ?i] 'magit-popup-info) + (define-key map [?\C-t] 'magit-popup-toggle-show-common-commands) + (define-key map [?\d] 'backward-button) + (define-key map [?\C-p] 'backward-button) + (define-key map [?\t] 'forward-button) + (define-key map [?\C-n] 'forward-button) + (define-key map [?\r] 'push-button) + map) + "Keymap for `magit-popup-mode'. + +\\\ +This keymap contains bindings common to all popups. A section +listing these commands can be shown or hidden using \ +\\[magit-popup-toggle-show-common-commands]. + +The prefix used to toggle any switch can be changed by binding +another key to `magit-invoke-popup-switch'. Likewise binding +another key to `magit-invoke-popup-option' changes the prefixed +used to set any option. The two prefixes have to be different. +If you change these bindings you should also change the `prefix' +property of the button types `magit-popup-switch-button' and +`magit-popup-option-button'. + +If you change any other binding, then you might have to also edit +`magit-popup-common-commands' for things to align correctly in +the section listing these commands. + +Never bind an alphabetic character in this keymap or you might +make it impossible to invoke certain actions.") + +(defvar magit-popup-common-commands + '(("Set defaults" magit-popup-set-default-arguments) + ("View popup manual" magit-popup-info) + ("Toggle this section" magit-popup-toggle-show-common-commands) + ("Save defaults" magit-popup-save-default-arguments) + (" Popup help prefix" magit-popup-help) + ("Abort" magit-popup-quit))) + +;;;; Buttons + +(define-button-type 'magit-popup-button + 'face nil + 'action (lambda (button) + (funcall (button-get button 'function) + (button-get button 'event)))) + +(define-button-type 'magit-popup-switch-button + 'supertype 'magit-popup-button + 'function 'magit-invoke-popup-switch + 'property :switches + 'heading "Switches\n" + 'formatter 'magit-popup-format-argument-button + 'format " %k %d (%a)" + 'prefix ?- + 'maxcols 1) + +(define-button-type 'magit-popup-option-button + 'supertype 'magit-popup-button + 'function 'magit-invoke-popup-option + 'property :options + 'heading "Options\n" + 'formatter 'magit-popup-format-argument-button + 'format " %k %d (%a%v)" + 'prefix ?= + 'maxcols 1) + +(define-button-type 'magit-popup-variable-button + 'supertype 'magit-popup-button + 'function 'magit-invoke-popup-variable + 'property :variables + 'heading "Variables\n" + 'formatter 'magit-popup-format-variable-button + 'format " %k %d" + 'prefix nil + 'maxcols 1) + +(define-button-type 'magit-popup-action-button + 'supertype 'magit-popup-button + 'function 'magit-invoke-popup-action + 'property :actions + 'heading "Actions\n" + 'formatter 'magit-popup-format-action-button + 'format " %k %d" + 'prefix nil + 'maxcols :max-action-columns) + +(define-button-type 'magit-popup-command-button + 'supertype 'magit-popup-action-button + 'formatter 'magit-popup-format-command-button + 'action (lambda (button) + (let ((command (button-get button 'function))) + (unless (eq command 'push-button) + (call-interactively command))))) + +(define-button-type 'magit-popup-internal-command-button + 'supertype 'magit-popup-command-button + 'heading "Common Commands\n" + 'maxcols 3) + +;;; Events + +(defvar-local magit-this-popup nil + "The popup which is currently active. +This is intended for internal use only. +Don't confuse this with `magit-current-popup'.") + +(defvar-local magit-this-popup-events nil + "The events known to the active popup. +This is intended for internal use only. +Don't confuse this with `magit-current-popup-args'.") + +(defun magit-popup-get (prop) + "While a popup is active, get the value of PROP." + (if (memq prop '(:switches :options :variables :actions)) + (plist-get magit-this-popup-events prop) + (plist-get (symbol-value magit-this-popup) prop))) + +(defun magit-popup-put (prop val) + "While a popup is active, set the value of PROP to VAL." + (if (memq prop '(:switches :options :variables :actions)) + (setq magit-this-popup-events + (plist-put magit-this-popup-events prop val)) + (error "Property %s isn't supported" prop))) + +(defvar magit-current-popup nil + "The popup from which this editing command was invoked. + +Use this inside the `interactive' form of a popup aware command +to determine whether it was invoked from a popup and if so from +which popup. If the current command was invoked without the use +of a popup then this is nil.") + +(defvar magit-current-popup-args nil + "The value of the popup arguments for this editing command. + +If the current command was invoked from a popup, then this is +a list of strings of all the set switches and options. This +includes arguments which are set by default not only those +explicitly set during this invocation. + +When the value is nil, then that can be because no argument is +set, or because the current command wasn't invoked from a popup; +consult `magit-current-popup' to tell the difference. + +Generally it is better to use `NAME-arguments', which is created +by `magit-define-popup', instead of this variable or the function +by the same name, because `NAME-argument' uses the default value +for the arguments when the editing command is invoked directly +instead of from a popup. When the command is bound in several +popups that might not be feasible though.") + +(defun magit-current-popup-args (&rest filter) + "Return the value of the popup arguments for this editing command. + +The value is the same as that of the variable by the same name +\(which see), except that FILTER is applied. FILTER is a list +of regexps; only arguments that match one of them are returned. +The first element of FILTER may also be `:not' in which case +only arguments that don't match any of the regexps are returned, +or `:only' which doesn't change the behaviour." + (let ((-compare-fn (lambda (a b) (magit-popup-arg-match b a)))) + (-filter (if (eq (car filter) :not) + (lambda (arg) (not (-contains? (cdr filter) arg))) + (when (eq (car filter) :only) + (pop filter)) + (lambda (arg) (-contains? filter arg))) + magit-current-popup-args))) + +(defun magit-popup-arg-match (pattern string) + (if (or (string-match-p "=$" pattern) + (string-match-p "^-[A-Z]$" pattern)) + (string-match (format "^%s\\(.*\\)$" pattern) string) + (string-equal string pattern))) + +(cl-defstruct magit-popup-event key dsc arg fun use val) + +(defun magit-popup-event-keydsc (ev) + (let ((key (magit-popup-event-key ev))) + (key-description (if (vectorp key) key (vector key))))) + +(defun magit-popup-lookup (event type) + (--first (equal (magit-popup-event-key it) event) + (-filter 'magit-popup-event-p (magit-popup-get type)))) + +(defun magit-popup-get-args () + (--mapcat (when (and (magit-popup-event-p it) + (magit-popup-event-use it)) + (list (format "%s%s" + (magit-popup-event-arg it) + (or (magit-popup-event-val it) "")))) + (append (magit-popup-get :switches) + (magit-popup-get :options)))) + +(defmacro magit-popup-convert-events (def form) + (declare (indent 1) (debug (form form))) + `(--map (if (or (null it) (stringp it) (functionp it)) it ,form) ,def)) + +(defun magit-popup-convert-switches (val def) + (magit-popup-convert-events def + (let ((a (nth 2 it))) + (make-magit-popup-event + :key (car it) :dsc (cadr it) :arg a + :use (and (member a val) t))))) + +(defun magit-popup-convert-options (val def) + (magit-popup-convert-events def + (let* ((a (nth 2 it)) + (r (format "^%s\\(.*\\)" a)) + (v (--first (string-match r it) val))) + (make-magit-popup-event + :key (car it) :dsc (cadr it) :arg a + :use (and v t) :val (and v (match-string 1 v)) + :fun (or (nth 3 it) 'read-from-minibuffer))))) + +(defun magit-popup-convert-variables (_val def) + (magit-popup-convert-events def + (make-magit-popup-event + :key (car it) :dsc (cadr it) :fun (nth 2 it) :arg (nth 3 it)))) + +(defun magit-popup-convert-actions (_val def) + (magit-popup-convert-events def + (make-magit-popup-event + :key (car it) :dsc (cadr it) :fun (nth 2 it)))) + +;;; Define + +(defmacro magit-define-popup (name doc &rest args) + "Define a popup command named NAME. + +NAME should begin with the package prefix and by convention end +with `-popup'. That name is used for the actual command as well +as for a variable used internally. DOC is used as the doc-string +of that command. + +Also define an option and a function named `SHORTNAME-arguments', +where SHORTNAME is NAME with the trailing `-popup' removed. The +name of this option and this function can be overwritten using +the optional argument OPTION, but that is rarely advisable. As a +special case if OPTION is specified but nil, do not define this +option and this function at all. + +The option `SHORTNAME-arguments' holds the default value for the +popup arguments. It can be customized from within the popup or +using the Custom interface. + +The function `SHORTNAME-arguments' is a wrapper around the +variable `magit-current-popup-args', both of which are intended +to be used inside the `interactive' form of commands commonly +invoked from the popup `NAME'. When such a command is invoked +from that popup, then the function `SHORTNAME-arguments' returns +the value of the variable `magit-current-popup-args'; however +when the command is invoked directly, then it returns the default +value of the variable `SHORTNAME-arguments'. + +Optional argument GROUP specifies the Custom group in which the +option is placed. If omitted then the option is placed in some +group the same way it is done when directly using `defcustom'. + +Optional argument MODE is deprecated, instead use the keyword +arguments `:setup-function' and/or `:refresh-function'. If MODE +is non-nil, then it specifies the mode used by the popup buffer, +instead of the default, which is `magit-popup-mode'. + +The remaining arguments should have the form + + [KEYWORD VALUE]... + +The following keywords are meaningful (and by convention are +usually specified in that order): + +`:actions' + The actions which can be invoked from the popup. VALUE is a + list whose members have the form (KEY DESC COMMAND), see + `magit-define-popup-action' for details. + + Actions are regular Emacs commands, which usually have an + `interactive' form setup to consume the values of the popup + `:switches' and `:options' when invoked from the corresponding + popup, else when invoked as the default action or directly + without using the popup, the default value of the variable + `SHORTNAME-arguments'. This is usually done by calling the + function `SHORTNAME-arguments'. + + Members of VALUE may also be strings, assuming the first member + is also a string. Instead of just one action section with the + heading \"Actions\", multiple sections are then inserted into + the popup buffer, using these strings as headings. + + Members of VALUE may also be nil. This should only be used + together with `:max-action-columns' and allows having gaps in + the action grit, which can help arranging actions sensibly. + +`:default-action' + The default action of the popup which is used directly instead + of displaying the popup buffer, when the popup is invoked with + a prefix argument. Also see `magit-popup-use-prefix-argument' + and `:use-prefix', which can be used to inverse the meaning of + the prefix argument. + +`:use-prefix' + Controls when to display the popup buffer and when to invoke + the default action (if any) directly. This overrides the + global default set using `magit-popup-use-prefix-argument'. + The value, if specified, should be one of `default' or `popup'. + +`:max-action-columns' + The maximum number of actions to display on a single line. + This helps arranging actions more sensibly. If there is not + enough room to display that many actions on one line, then + this is ignored. + +`:switches' + The popup arguments which can be toggled on and off. VALUE + is a list whose members have the form (KEY DESC SWITCH), see + `magit-define-popup-switch' for details. + +`:options' + The popup arguments which take a value, as in \"--opt=OPTVAL\". + VALUE is a list whose members have the form (KEY DESC OPTION + READER), see `magit-define-popup-option' for details. + +`:default-arguments' + The default arguments, a list of switches (which are then + enabled by default) and options with there default values, as + in \"--OPT=OPTVAL\". + +`:sequence-predicate' + When this function returns non-nil, then the popup uses + `:sequence-actions' instead of `:actions', and does not show + the `:switches' and `:options'. + +`:sequence-actions' + The actions which can be invoked from the popup, when + `:sequence-predicate' returns non-nil. + +`:setup-function' + When this function is specified, then it is used instead of + `magit-popup-default-setup'. + +`:refresh-function' + When this function is specified, then it is used instead of + calling `magit-popup-insert-section' three times with symbols + `magit-popup-switch-button', `magit-popup-option-button', and + finally `magit-popup-action-button' as argument. + +`:man-page' + The name of the manpage to be displayed when the user requests + help for a switch or argument. + +\(fn NAME DOC [GROUP [MODE [OPTION]]] :KEYWORD VALUE...)" + (declare (indent defun) (doc-string 2)) + (let* ((grp (unless (keywordp (car args)) (pop args))) + (mode (unless (keywordp (car args)) (pop args))) + (opt (symbol-name name)) + (opt (if (keywordp (car args)) + (intern (concat (if (string-suffix-p "-popup" opt) + (substring opt 0 -6) + opt) + "-arguments")) + (eval (pop args))))) + `(progn + (defun ,name (&optional arg) ,doc + (interactive "P") + (magit-invoke-popup ',name ,mode arg)) + (defvar ,name + (list :variable ',opt ,@args)) + (magit-define-popup-keys-deferred ',name) + ,@(when opt + `((defcustom ,opt (plist-get ,name :default-arguments) + "" + ,@(and grp (list :group grp)) + :type '(repeat (string :tag "Argument"))) + (defun ,opt () + (if (eq magit-current-popup ',name) + magit-current-popup-args + ,opt)) + (put ',opt 'definition-name ',name)))))) + +(defun magit-define-popup-switch (popup key desc switch + &optional enable at prepend) + "In POPUP, define KEY as SWITCH. + +POPUP is a popup command defined using `magit-define-popup'. +SWITCH is a string representing an argument that takes no value. +KEY is a character representing the second event in the sequence +of keystrokes used to toggle the argument. (The first event, the +prefix, is shared among all switches, defaults to -, and can be +changed in `magit-popup-mode-keymap'). + +DESC is a string describing the purpose of the argument, it is +displayed in the popup. + +If optional ENABLE is non-nil then the switch is on by default. + +SWITCH is inserted after all other switches already defined for +POPUP, unless optional PREPEND is non-nil, in which case it is +placed first. If optional AT is non-nil then it should be the +KEY of another switch already defined for POPUP, the argument +is then placed before or after AT, depending on PREPEND." + (declare (indent defun)) + (magit-define-popup-key popup :switches key + (list desc switch enable) at prepend)) + +(defun magit-define-popup-option (popup key desc option + &optional reader value at prepend) + "In POPUP, define KEY as OPTION. + +POPUP is a popup command defined using `magit-define-popup'. +OPTION is a string representing an argument that takes a value. +KEY is a character representing the second event in the sequence +of keystrokes used to set the argument's value. (The first +event, the prefix, is shared among all options, defaults to =, +and can be changed in `magit-popup-mode-keymap'). + +DESC is a string describing the purpose of the argument, it is +displayed in the popup. + +If optional VALUE is non-nil then the option is on by default, +and VALUE is its default value. + +OPTION is inserted after all other options already defined for +POPUP, unless optional PREPEND is non-nil, in which case it is +placed first. If optional AT is non-nil then it should be the +KEY of another option already defined for POPUP, the argument +is then placed before or after AT, depending on PREPEND." + (declare (indent defun)) + (magit-define-popup-key popup :options key + (list desc option reader value) at prepend)) + +(defun magit-define-popup-variable (popup key desc command formatter + &optional at prepend) + "In POPUP, define KEY as COMMAND. + +POPUP is a popup command defined using `magit-define-popup'. +COMMAND is a command which calls `magit-popup-set-variable'. +FORMATTER is a function which calls `magit-popup-format-variable'. +These two functions have to be called with the same arguments. + +KEY is a character representing the event used interactively call +the COMMAND. + +DESC is the variable or a representation thereof. It's not +actually used for anything. + +COMMAND is inserted after all other commands already defined for +POPUP, unless optional PREPEND is non-nil, in which case it is +placed first. If optional AT is non-nil then it should be the +KEY of another command already defined for POPUP, the command +is then placed before or after AT, depending on PREPEND." + (declare (indent defun)) + (magit-define-popup-key popup :variables key + (list desc command formatter) at prepend)) + +(defun magit-define-popup-action (popup key desc command + &optional at prepend) + "In POPUP, define KEY as COMMAND. + +POPUP is a popup command defined using `magit-define-popup'. +COMMAND can be any command but should usually consume the popup +arguments in its `interactive' form. +KEY is a character representing the event used invoke the action, +i.e. to interactively call the COMMAND. + +DESC is a string describing the purpose of the action, it is +displayed in the popup. + +COMMAND is inserted after all other commands already defined for +POPUP, unless optional PREPEND is non-nil, in which case it is +placed first. If optional AT is non-nil then it should be the +KEY of another command already defined for POPUP, the command +is then placed before or after AT, depending on PREPEND." + (declare (indent defun)) + (magit-define-popup-key popup :actions key + (list desc command) at prepend)) + +(defun magit-define-popup-sequence-action + (popup key desc command &optional at prepend) + "Like `magit-define-popup-action' but for `:sequence-action'." + (declare (indent defun)) + (magit-define-popup-key popup :sequence-actions key + (list desc command) at prepend)) + +(defconst magit-popup-type-plural-alist + '((:switch . :switches) + (:option . :options) + (:variable . :variables) + (:action . :actions) + (:sequence-action . :sequence-actions))) + +(defun magit-popup-pluralize-type (type) + (or (cdr (assq type magit-popup-type-plural-alist)) + type)) + +(defun magit-define-popup-key + (popup type key def &optional at prepend) + "In POPUP, define KEY as an action, switch, or option. +It's better to use one of the specialized functions + `magit-define-popup-action', + `magit-define-popup-sequence-action', + `magit-define-popup-switch', + `magit-define-popup-option', or + `magit-define-popup-variable'." + (declare (indent defun)) + (setq type (magit-popup-pluralize-type type)) + (if (memq type '(:switches :options :variables :actions :sequence-actions)) + (if (boundp popup) + (let* ((plist (symbol-value popup)) + (value (plist-get plist type)) + (elt (assoc key value))) + (if elt + (setcdr elt def) + (setq elt (cons key def))) + (if at + (when (setq at (cl-member at value :key 'car-safe :test 'equal)) + (setq value (cl-delete key value :key 'car-safe :test 'equal)) + (if prepend + (progn (push (car at) (cdr at)) + (setcar at elt)) + (push elt (cdr at)))) + (setq value (cl-delete key value :key 'car-safe :test 'equal))) + (unless (assoc key value) + (setq value (if prepend + (cons elt value) + (append value (list elt))))) + (set popup (plist-put plist type value))) + (push (list type key def at prepend) + (get popup 'magit-popup-deferred))) + (error "Unknown popup event type: %s" type))) + +(defun magit-define-popup-keys-deferred (popup) + (dolist (args (get popup 'magit-popup-deferred)) + (condition-case err + (apply #'magit-define-popup-key popup args) + ((debug error) + (display-warning 'magit (error-message-string err) :error)))) + (put popup 'magit-popup-deferred nil)) + +(defun magit-change-popup-key (popup type from to) + "In POPUP, bind TO to what FROM was bound to. +TYPE is one of `:action', `:sequence-action', `:switch', or +`:option'. Bind TO and unbind FROM, both are characters." + (--if-let (assoc from (plist-get (symbol-value popup) + (magit-popup-pluralize-type type))) + (setcar it to) + (message "magit-change-popup-key: FROM key %c is unbound" from))) + +(defun magit-remove-popup-key (popup type key) + "In POPUP, remove KEY's binding of TYPE. +POPUP is a popup command defined using `magit-define-popup'. +TYPE is one of `:action', `:sequence-action', `:switch', or +`:option'. KEY is the character which is to be unbound." + (setq type (magit-popup-pluralize-type type)) + (let* ((plist (symbol-value popup)) + (alist (plist-get plist type)) + (value (assoc key alist))) + (set popup (plist-put plist type (delete value alist))))) + +;;; Invoke + +(defvar-local magit-popup-previous-winconf nil) + +(defun magit-invoke-popup (popup mode arg) + (let* ((def (symbol-value popup)) + (val (symbol-value (plist-get def :variable))) + (default (plist-get def :default-action)) + (local (plist-get def :use-prefix)) + (use-prefix (or local magit-popup-use-prefix-argument))) + (cond + ((and arg (eq magit-popup-use-prefix-argument 'disabled)) + (customize-option-other-window 'magit-popup-use-prefix-argument) + (error (concat "The meaning of prefix arguments has changed. " + "Please explicitly enable their use again."))) + ((or (and (eq use-prefix 'default) arg) + (and (eq use-prefix 'popup) (not arg))) + (if default + (let ((magit-current-popup (list popup 'default)) + (magit-current-popup-args + (let ((magit-this-popup popup) + (magit-this-popup-events nil)) + (magit-popup-default-setup val def) + (magit-popup-get-args)))) + (when (and arg (listp arg)) + (setq current-prefix-arg (and (not (= (car arg) 4)) + (list (/ (car arg) 4))))) + (call-interactively default)) + (message "%s has no default action; showing popup instead." popup) + (magit-popup-mode-setup popup mode))) + ((memq use-prefix '(disabled default popup nil)) + (magit-popup-mode-setup popup mode) + (when magit-popup-show-help-echo + (message (concat "Type C-h i to view popup manual, " + "? to describe an argument or action.")))) + (local + (error "Invalid :use-prefix popup property value: %s" use-prefix)) + (t + (error "Invalid magit-popup-use-prefix-argument value: %s" use-prefix))))) + +(defun magit-invoke-popup-switch (event) + (interactive (list last-command-event)) + (--if-let (magit-popup-lookup event :switches) + (progn + (setf (magit-popup-event-use it) + (not (magit-popup-event-use it))) + (magit-refresh-popup-buffer)) + (user-error "%c isn't bound to any switch" event))) + +(defun magit-invoke-popup-option (event) + (interactive (list last-command-event)) + (--if-let (magit-popup-lookup event :options) + (progn + (if (magit-popup-event-use it) + (setf (magit-popup-event-use it) nil) + (let* ((arg (magit-popup-event-arg it)) + (val (funcall + (magit-popup-event-fun it) + (concat arg (unless (string-match-p "=$" arg) ": ")) + (magit-popup-event-val it)))) + (setf (magit-popup-event-use it) t) + (setf (magit-popup-event-val it) val))) + (magit-refresh-popup-buffer)) + (user-error "%c isn't bound to any option" event))) + +(defun magit-invoke-popup-action (event) + (interactive (list last-command-event)) + (let ((action (magit-popup-lookup event :actions)) + (variable (magit-popup-lookup event :variables))) + (if (or action variable) + (let ((magit-current-popup magit-this-popup) + (magit-current-popup-args (magit-popup-get-args)) + (command (magit-popup-event-fun (or action variable)))) + (when action + (magit-popup-quit)) + (call-interactively command) + (setq this-command command) + (unless action + (magit-refresh-popup-buffer))) + (if (eq event ?q) + (magit-popup-quit) + (user-error "%c isn't bound to any action" event))))) + +(defun magit-popup-set-variable + (variable choices &optional default other) + (--if-let (--if-let (magit-git-string "config" "--local" variable) + (cadr (member it choices)) + (car choices)) + (magit-set it variable) + (magit-call-git "config" "--unset" variable)) + (magit-refresh) + (message "%s %s" variable + (magit-popup-format-variable-1 variable choices default other))) + +(defun magit-popup-quit () + "Quit the current popup command without invoking an action." + (interactive) + (let ((winconf magit-popup-previous-winconf)) + (if (derived-mode-p 'magit-popup-mode) + (kill-buffer) + (magit-popup-help-mode -1) + (kill-local-variable 'magit-popup-previous-winconf)) + (when winconf + (set-window-configuration winconf)))) + +(defun magit-popup-read-number (prompt &optional default) + "Like `read-number' but DEFAULT may be a numeric string." + (read-number prompt (if (stringp default) + (string-to-number default) + default))) + +;;; Save + +(defun magit-popup-set-default-arguments (arg) + "Set default value for the arguments for the current popup. +Then close the popup without invoking an action; unless a prefix +argument is used in which case the popup remains open. + +For a popup named `NAME-popup' that usually means setting the +value of the custom option `NAME-arguments'." + (interactive "P") + (customize-set-variable (magit-popup-get :variable) + (magit-popup-get-args)) + (unless arg (magit-popup-quit))) + +(defun magit-popup-save-default-arguments (arg) + "Save default value for the arguments for the current popup. +Then close the popup without invoking an action; unless a prefix +argument is used in which case the popup remains open. + +For a popup named `NAME-popup' that usually means saving the +value of the custom option `NAME-arguments'." + (interactive "P") + (customize-save-variable (magit-popup-get :variable) + (magit-popup-get-args)) + (unless arg (magit-popup-quit))) + +;;; Help + +(defun magit-popup-toggle-show-common-commands () + "Show or hide an additional section with common commands. +The commands listed in this section are common to all popups +and are defined in `magit-popup-mode-map' (which see)." + (interactive) + (setq magit-popup-show-common-commands + (not magit-popup-show-common-commands)) + (magit-refresh-popup-buffer) + (fit-window-to-buffer)) + +(defun magit-popup-help () + "Show help for the argument or action at point." + (interactive) + (let* ((man (magit-popup-get :man-page)) + (key (read-key-sequence + (concat "Describe key" (and man " (? for manpage)") ": "))) + (int (aref key (1- (length key)))) + (def (or (lookup-key (current-local-map) key t) + (lookup-key (current-global-map) key)))) + (pcase def + (`magit-invoke-popup-switch + (magit-popup-manpage man (magit-popup-lookup int :switches))) + (`magit-invoke-popup-option + (magit-popup-manpage man (magit-popup-lookup int :options))) + (`magit-popup-help + (magit-popup-manpage man nil)) + ((or `self-insert-command + `magit-invoke-popup-action) + (setq def (or (magit-popup-lookup int :actions) + (magit-popup-lookup int :variables))) + (if def + (magit-popup-describe-function (magit-popup-event-fun def)) + (ding) + (message nil))) + (`nil (ding) + (message nil)) + (_ (magit-popup-describe-function def))))) + +(defun magit-popup-manpage (topic arg) + (unless topic + (user-error "No man page associated with %s" + (magit-popup-get :man-page))) + (when arg + (setq arg (magit-popup-event-arg arg))) + (let ((winconf (current-window-configuration)) buffer) + (pcase magit-popup-manpage-package + (`woman (delete-other-windows) + (split-window-below) + (with-no-warnings ; display-buffer-function is obsolete + (let ((display-buffer-alist nil) + (display-buffer-function nil)) + (woman topic))) + (setq buffer (current-buffer))) + (`man (cl-letf (((symbol-function #'fboundp) (lambda (_) nil))) + (setq buffer (man topic))) + (delete-other-windows) + (split-window-below) + (set-window-buffer (selected-window) buffer))) + (with-current-buffer buffer + (setq magit-popup-previous-winconf winconf) + (magit-popup-help-mode) + (fit-window-to-buffer (next-window)) + (if (and arg + (Man-find-section "OPTIONS") + (re-search-forward (format "^[\t\s]+\\(-., \\)*?%s[=\n]" arg) + (save-excursion + (Man-next-section 1) + (point)) + t)) + (goto-char (1+ (match-beginning 0))) + (goto-char (point-min)))))) + +(defun magit-popup-describe-function (function) + (let ((winconf (current-window-configuration))) + (delete-other-windows) + (split-window-below) + (other-window 1) + (with-no-warnings ; display-buffer-function is obsolete + (let ((display-buffer-alist nil) + (display-buffer-function nil)) + (describe-function function))) + (fit-window-to-buffer) + (other-window 1) + (setq magit-popup-previous-winconf winconf) + (magit-popup-help-mode))) + +(defun magit-popup-info () + "Show the popup manual." + (interactive) + (let ((winconf (current-window-configuration))) + (delete-other-windows) + (split-window-below) + (info "(magit-popup.info)Usage") + (magit-popup-help-mode) + (setq magit-popup-previous-winconf winconf)) + (magit-popup-help-mode) + (fit-window-to-buffer (next-window))) + +(define-minor-mode magit-popup-help-mode + "Auxiliary minor mode used to restore previous window configuration. +When some sort of help buffer is created from within a popup, +then this minor mode is turned on in that buffer, so that when +the user quits it, the previous window configuration is also +restored." + :keymap '(([remap Man-quit] . magit-popup-quit) + ([remap Info-exit] . magit-popup-quit) + ([remap quit-window] . magit-popup-quit))) + +;;; Modes + +(define-derived-mode magit-popup-mode fundamental-mode "MagitPopup" + "Major mode for infix argument popups." + :mode 'magit-popup + (setq truncate-lines t) + (setq buffer-read-only t) + (setq-local scroll-margin 0) + (setq-local magit-popup-show-common-commands magit-popup-show-common-commands) + (hack-dir-local-variables-non-file-buffer)) + +(put 'magit-popup-mode 'mode-class 'special) + +(defun magit-popup-default-setup (val def) + (if (--when-let (magit-popup-get :sequence-predicate) + (funcall it)) + (magit-popup-put :actions (magit-popup-convert-actions + val (magit-popup-get :sequence-actions))) + (magit-popup-put :variables (magit-popup-convert-variables + val (plist-get def :variables))) + (magit-popup-put :switches (magit-popup-convert-switches + val (plist-get def :switches))) + (magit-popup-put :options (magit-popup-convert-options + val (plist-get def :options))) + (magit-popup-put :actions (magit-popup-convert-actions + val (plist-get def :actions))))) + +(defun magit-popup-mode-setup (popup mode) + (let ((val (symbol-value (plist-get (symbol-value popup) :variable))) + (def (symbol-value popup))) + (magit-popup-mode-display-buffer (get-buffer-create + (format "*%s*" popup)) + (or mode 'magit-popup-mode)) + (setq magit-this-popup popup) + (if (bound-and-true-p magit-popup-setup-hook) ; obsolete + (run-hook-with-args 'magit-popup-setup-hook val def) + (funcall (or (magit-popup-get :setup-function) + 'magit-popup-default-setup) + val def))) + (magit-refresh-popup-buffer) + (fit-window-to-buffer nil nil (line-number-at-pos (point-max)))) + +(defun magit-popup-mode-display-buffer (buffer mode) + (let ((winconf (current-window-configuration))) + (split-window-vertically) + (other-window 1) + (switch-to-buffer buffer) + (funcall mode) + (setq magit-popup-previous-winconf winconf))) + +(defvar magit-refresh-popup-buffer-hook nil + "Hook run by `magit-refresh-popup-buffer'. + +The hook is run right after inserting the representation of the +popup events but before optionally inserting the representation +of events shared by all popups and before point is adjusted.") + +(defun magit-refresh-popup-buffer () + (let* ((inhibit-read-only t) + (button (button-at (point))) + (prefix (and button (button-get button 'prefix))) + (event (and button (button-get button 'event)))) + (erase-buffer) + (save-excursion + (--if-let (magit-popup-get :refresh-function) + (funcall it) + (magit-popup-insert-section 'magit-popup-switch-button) + (magit-popup-insert-section 'magit-popup-option-button) + (magit-popup-insert-section 'magit-popup-variable-button) + (magit-popup-insert-section 'magit-popup-action-button)) + (run-hooks 'magit-refresh-popup-buffer-hook) + (when magit-popup-show-common-commands + (magit-popup-insert-command-section + 'magit-popup-internal-command-button + magit-popup-common-commands))) + (set-buffer-modified-p nil) + (when event + (while (and (ignore-errors (forward-button 1)) + (let ((b (button-at (point)))) + (or (not (equal (button-get b 'prefix) prefix)) + (not (equal (button-get b 'event) event))))))))) + +;;; Draw + +(defvar magit-popup-min-padding 3 + "Minimal amount of whitespace between columns in popup buffers.") + +(defun magit-popup-insert-section (type &optional spec heading) + (if (not spec) + (progn (setq spec (magit-popup-get (button-type-get type 'property))) + (when spec + (if (or (stringp (car spec)) + (functionp (car spec))) + (--each (--partition-by-header + (or (stringp it) (functionp it)) + spec) + (magit-popup-insert-section type (cdr it) (car it))) + (magit-popup-insert-section type spec)))) + (let* ((formatter (button-type-get type 'formatter)) + (items (mapcar (lambda (ev) + (and ev (or (funcall formatter type ev) '("")))) + (or spec (magit-popup-get + (button-type-get type 'property))))) + (maxcols (button-type-get type 'maxcols)) + (pred (magit-popup-get :sequence-predicate))) + (if (and pred (funcall pred)) + (setq maxcols nil) + (cl-typecase maxcols + (keyword (setq maxcols (magit-popup-get maxcols))) + (symbol (setq maxcols (symbol-value maxcols))))) + (when items + (if (functionp heading) + (when (setq heading (funcall heading)) + (insert heading ?\n)) + (unless heading + (setq heading (button-type-get type 'heading))) + (insert (propertize heading 'face 'magit-popup-heading)) + (unless (string-match "\n$" heading) + (insert "\n"))) + (when heading + (let ((colwidth + (+ (apply 'max (mapcar (lambda (e) (length (car e))) items)) + magit-popup-min-padding))) + (dolist (item items) + (unless (bolp) + (let ((padding (- colwidth (% (current-column) colwidth)))) + (if (and (< (+ (current-column) padding colwidth) + (window-width)) + (< (ceiling (/ (current-column) (* colwidth 1.0))) + (or maxcols 1000))) + (insert (make-string padding ?\s)) + (insert "\n")))) + (unless (equal item '("")) + (if item + (apply 'insert-button item) + (insert ?\s))))) + (insert (if (= (char-before) ?\n) "\n" "\n\n"))))))) + +(defun magit-popup-format-argument-button (type ev) + (list (format-spec + (button-type-get type 'format) + `((?k . ,(propertize (concat + (--when-let (button-type-get type 'prefix) + (char-to-string it)) + (magit-popup-event-keydsc ev)) + 'face 'magit-popup-key)) + (?d . ,(magit-popup-event-dsc ev)) + (?a . ,(propertize (magit-popup-event-arg ev) + 'face (if (magit-popup-event-use ev) + 'magit-popup-argument + 'magit-popup-disabled-argument))) + (?v . ,(let ((val (magit-popup-event-val ev))) + (if (and (magit-popup-event-use ev) + (not (equal val ""))) + (propertize (format "\"%s\"" val) + 'face 'magit-popup-option-value) + ""))))) + 'type type 'event (magit-popup-event-key ev))) + +(defun magit-popup-format-variable-button (type ev) + (list (format-spec + (button-type-get type 'format) + `((?k . ,(propertize (magit-popup-event-keydsc ev) + 'face 'magit-popup-key)) + (?d . ,(funcall (magit-popup-event-arg ev))))) + 'type type 'event (magit-popup-event-key ev))) + +(defun magit-popup-format-variable + (variable choices &optional default other width) + (concat variable + (if width (make-string (- width (length variable)) ?\s) " ") + (magit-popup-format-variable-1 variable choices default other))) + +(defun magit-popup-format-variable-1 + (variable choices &optional default other) + (let ((local (magit-git-string "config" "--local" variable)) + (global (magit-git-string "config" "--global" variable))) + (when other + (--if-let (magit-git-string "config" other) + (setq other (concat other ":" it)) + (setq other nil))) + (concat + (propertize "[" 'face 'magit-popup-disabled-argument) + (mapconcat + (lambda (choice) + (propertize choice 'face (if (equal choice local) + 'magit-popup-option-value + 'magit-popup-disabled-argument))) + choices + (propertize "|" 'face 'magit-popup-disabled-argument)) + (when (or global other default) + (concat + (propertize "|" 'face 'magit-popup-disabled-argument) + (cond (global + (propertize (concat "global:" global) + 'face (cond (local + 'magit-popup-disabled-argument) + ((member global choices) + 'magit-popup-option-value) + (t + 'font-lock-warning-face)))) + (other + (propertize other + 'face (if local + 'magit-popup-disabled-argument + 'magit-popup-option-value))) + (default + (propertize (concat "default:" default) + 'face (if local + 'magit-popup-disabled-argument + 'magit-popup-option-value)))))) + (propertize "]" 'face 'magit-popup-disabled-argument)))) + +(defun magit-popup-format-action-button (type ev) + (let* ((dsc (magit-popup-event-dsc ev)) + (fun (and (functionp dsc) dsc))) + (when fun + (setq dsc + (-when-let (branch (funcall fun)) + (if (next-single-property-change 0 'face (concat "0" branch)) + branch + (magit-branch-set-face branch))))) + (when dsc + (list (format-spec + (button-type-get type 'format) + `((?k . ,(propertize (magit-popup-event-keydsc ev) + 'face 'magit-popup-key)) + (?d . ,dsc) + (?D . ,(if (and (not fun) + (eq (magit-popup-event-fun ev) + (magit-popup-get :default-action))) + (propertize dsc 'face 'bold) + dsc)))) + 'type type 'event (magit-popup-event-key ev))))) + +(defun magit-popup-insert-command-section (type spec) + (magit-popup-insert-section + type (mapcar (lambda (elt) + (list (car (where-is-internal (cadr elt) + (current-local-map))) + (car elt))) + spec))) + +(defun magit-popup-format-command-button (type elt) + (nconc (magit-popup-format-action-button + type (make-magit-popup-event :key (car elt) + :dsc (cadr elt))) + (list 'function (lookup-key (current-local-map) (car elt))))) + +;;; Utilities + +(defun magit-popup-import-file-args (args files) + (if files + (cons (concat "-- " (mapconcat #'identity files ",")) args) + args)) + +(defun magit-popup-export-file-args (args) + (let ((files (--first (string-prefix-p "-- " it) args))) + (when files + (setq args (remove files args) + files (split-string (substring files 3) ","))) + (list args files))) + +;;; magit-popup.el ends soon + +(defconst magit-popup-font-lock-keywords + (eval-when-compile + `((,(concat "(\\(magit-define-popup\\)\\_>" + "[ \t'\(]*" + "\\(\\(?:\\sw\\|\\s_\\)+\\)?") + (1 'font-lock-keyword-face) + (2 'font-lock-function-name-face nil t))))) + +(font-lock-add-keywords 'emacs-lisp-mode magit-popup-font-lock-keywords) + +(provide 'magit-popup) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; magit-popup.el ends here diff --git a/elpa/magit-popup-20151223.1341/magit-popup.info b/elpa/magit-popup-20151223.1341/magit-popup.info new file mode 100644 index 00000000..00b61d5a --- /dev/null +++ b/elpa/magit-popup-20151223.1341/magit-popup.info @@ -0,0 +1,703 @@ +This is magit-popup.info, produced by makeinfo version 5.2 from +magit-popup.texi. + +Taking inspiration from regular prefix commands and prefix arguments, +this library implements a similar abstraction; a new kind of prefix +command that is associated with a specific set of infix arguments and +suffix commands. + + Copyright (C) 2015 Jonas Bernoulli + + You can redistribute this document 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 document 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. +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Magit-Popup: (magit-popup). Infix arguments with feedback. +END-INFO-DIR-ENTRY + + +File: magit-popup.info, Node: Top, Next: Introduction, Up: (dir) + +Magit-Popup User Manual +*********************** + +Taking inspiration from regular prefix commands and prefix arguments, +this library implements a similar abstraction; a new kind of prefix +command that is associated with a specific set of infix arguments and +suffix commands. + + Copyright (C) 2015 Jonas Bernoulli + + You can redistribute this document 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 document 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. + +* Menu: + +* Introduction:: +* Usage:: +* Defining prefix and suffix commands:: + +— The Detailed Node Listing — + +Usage + +* Customizing existing popups:: +* Other options:: + +Defining prefix and suffix commands + +* Defining prefix commands:: +* Defining suffix commands:: + + + +File: magit-popup.info, Node: Introduction, Next: Usage, Prev: Top, Up: Top + +1 Introduction +************** + +Taking inspiration from regular prefix commands and prefix arguments, +this library implements a similar abstraction; a new kind of prefix +command that is associated with a specific set of infix arguments and +suffix commands. + + Invoking such a prefix command displays a popup buffer which lists +the associated infix arguments and suffix commands. In that buffer each +argument is prefixes with the key sequence that can be used to toggle it +or change its value. Likewise each suffix command is prefixed with the +key used to invoke it. Such a popup buffer might look like this: + +,----------------------------------------- +|Switches +| -l Show graph (--graph) +| -d Show refnames (--decorate) +| +|Options +| =m Search messages (--grep="popup") +| =p Search patches (-G) +| +|Action +| l Show log for current branch +| o Show log for another branch +'----------------------------------------- + + The user could then for example type ‘-l’ to toggle the ‘--graph’ +*switch* (when it is on then it is shown in green, otherwise in gray), +or ‘=m’ to change the value of the *option* ‘--grep’. + + Once all arguments are as desired one invokes a suffix command, which +causes the popup buffer to disappears. The suffix command should then +retrieve the infix arguments in its ‘interactive’ form like this is done +for prefix arguments. + + While such "prefix-infix-suffix" combos were inspired by regular +prefix commands and prefix arguments, they are also quite different. +This should illustrate the most basic differences: + + • A regular prefix commands + + /- command1 + prefix --- command2 + \- command3 + + • Prefix arguments + + /- command1 + C-u ... --- command2 + \- well *any* command + + • A Prefix-Infix-Suffix combo + + /- argument1 -\ /- suffix1 + prefix----- argument2 --+-- suffix2 + ^ \- argument3 -/ + | | + '--------' + (refresh buffer) + + This library was written as a replacement for ‘magit-key-mode’ which +was used in Magit releases before 2.1.0. It is used to implement all +"popups" in the current Magit release but a future release will switch +to yet another implementation. + + This library does not depend on any other Magit libraries and it is +distributed as a separate package, which makes it possible to use it in +packages that are not related to Magit. But keep in mind that it will +be deprecated eventually. + + +File: magit-popup.info, Node: Usage, Next: Defining prefix and suffix commands, Prev: Introduction, Up: Top + +2 Usage +******* + +Every popup buffers created with a prefix command contains a section +named "Actions" listing the available suffix commands. Most buffers +also contain a "Switches" and/or an "Options" section which list the two +types of infix arguments separately. + + Switches are arguments that can be toggled on or off. When a switch +is active then it is shown in color, when it is off then it is shown in +gray (of course the details depend on the color theme in use). + + Options are arguments that have a value. When an option has a value +then that is shown after the option itself. Because for some options +the empty string is a valid value, options are additionally colorized +like switches to indicate whether they are active or not. + + The events bound to suffix commands are always single alphabetic +characters. The bindings for arguments are always two events long. For +switches the first key is always ‘-’, for options it is always ‘=’. The +second key is always an alphabetic character. + + By default popup buffers also feature a section listing commands +common to all popups. To avoid conflicts with suffix commands, the +bindings of these common commands are not alphabetic characters. This +section is shown by default so that documentation-resistant users get a +change to notice them. + + -- User Option: magit-popup-show-common-commands + + This option controls whether the section which lists the commands + that are common to all popups is initially show. We recommend you + set this to ‘nil’ - after you have memorized that it can be shown + on demand using ‘C-t’. + +‘C-t’ (‘magit-popup-toggle-show-common-commands’) + + Show or hide the section listing the commands shared by all popups. + +‘C-g’ (‘magit-popup-quit’) + + Quit popup buffer without invoking a suffix command. + + Without further action, setting arguments only affects the next +suffix command. Invoking the same prefix command again resets the +arguments to their default value, but the defaults can be changed +directly from the popup buffer itself. For a prefix command named +‘NAME-popup’ the default values are stored as the value of the custom +option named ‘NAME-arguments’. While this option can be customized +using the Custom interface, it is better to do so directly from the +popup buffer. + +‘C-c C-c’ (‘magit-popup-set-default-arguments’) + + This sets the default value for the arguments for the current + popup. + + Then the popup buffer is closed without invoking a suffix command; + unless a prefix argument is used in which case the popup remains + open. + +‘C-x C-s’ (‘magit-popup-save-default-arguments’) + + This sets the default value for the arguments for the current popup + and saves it for future Emacs sessions. + + Then the popup buffer is closed without invoking an action; unless + a prefix argument is used in which case the popup remains open. + + It is also possible to add additional arguments and commands to an +existing popup, but that cannot be done directly from the popup (or the +Custom interface). See *note Customizing existing popups: Customizing +existing popups. + + Documentation about a popup’s arguments and commands can be shown +directly from the popup. + +‘C-h i’ (‘magit-popup-info’) + + Show this manual. + +‘?’ (‘magit-popup-help’) + + This command reads a key sequence and then shows the documentation + of the argument or command that sequence is bound to. In other + words type the same keys that you would use to invoke the argument + or command, but prefix the sequence with ‘?’. + + For suffix commands this shows the doc-string. For arguments this + command can only show something for popups that have an associated + man-page. If the man-page is set, then this command displays it in + a separate buffer and puts point on the entry about the argument in + question. + + The buffer which is used to display the documentation is selected. + Simply press ‘q’ to leave that buffer and restore the old window + configuration. + + While it isn’t very useful, it is possible to move around in a popup +buffer using ‘C-p’ and ‘C-n’, and to invoke the argument or command at +point using ‘RET’. But it is much more efficient to use the dedicated +key bindings instead, so these commands are not listed in popup buffers +along with the other common commands. + +* Menu: + +* Customizing existing popups:: +* Other options:: + + +File: magit-popup.info, Node: Customizing existing popups, Next: Other options, Up: Usage + +2.1 Customizing existing popups +=============================== + +It is possible to define additional infix arguments and suffix commands +to an existing popup using the following functions. + + You can find some examples which use the below commands at +. + + -- Function: magit-define-popup-switch popup key desc switch &optional + enable at prepend + + In POPUP, define KEY as SWITCH. + + POPUP is a popup command defined using ‘magit-define-popup’. + SWITCH is a string representing an argument that takes no value. + KEY is a character representing the second event in the sequence of + keystrokes used to toggle the argument. (The first event, the + prefix, is shared among all switches, defaults to ‘-’, and can be + changed in ‘magit-popup-mode-keymap’). + + DESC is a string describing the purpose of the argument, it is + displayed in the popup. + + If optional ENABLE is non-nil then the switch is on by default. + + SWITCH is inserted after all other switches already defined for + POPUP, unless optional PREPEND is non-nil, in which case it is + placed first. If optional AT is non-nil then it should be the KEY + of another switch already defined for POPUP, the argument is then + placed before or after AT, depending on PREPEND. + + -- Function: magit-define-popup-option popup key desc option &optional + reader value at prepend + + In POPUP, define KEY as OPTION. + + POPUP is a popup command defined using ‘magit-define-popup’. + OPTION is a string representing an argument that takes a value. + KEY is a character representing the second event in the sequence of + keystrokes used to set the argument’s value. (The first event, the + prefix, is shared among all options, defaults to ‘=’, and can be + changed in ‘magit-popup-mode-keymap’). + + DESC is a string describing the purpose of the argument, it is + displayed in the popup. + + If optional VALUE is non-nil then the option is on by default, and + VALUE is its default value. + + OPTION is inserted after all other options already defined for + POPUP, unless optional PREPEND is non-nil, in which case it is + placed first. If optional AT is non-nil then it should be the KEY + of another option already defined for POPUP, the argument is then + placed before or after AT, depending on PREPEND. + + -- Function: magit-define-popup-action popup key desc command &optional + at prepend + + In POPUP, define KEY as COMMAND. + + POPUP is a popup command defined using ‘magit-define-popup’. + COMMAND can be any command but should usually consume the popup + arguments in its ‘interactive’ form. KEY is a character + representing the event used invoke the action, i.e. to + interactively call the COMMAND. + + DESC is a string describing the purpose of the action, it is + displayed in the popup. + + COMMAND is inserted after all other commands already defined for + POPUP, unless optional PREPEND is non-nil, in which case it is + placed first. If optional AT is non-nil then it should be the KEY + of another command already defined for POPUP, the command is then + placed before or after AT, depending on PREPEND. + + -- Function: magit-define-popup-sequence-action popup key desc command + &optional at prepend + + Like ‘magit-define-popup-action’, but modifies the value of the + ‘:sequence-actions’ property instead of ‘:actions’. + + -- Function: magit-define-popup-variable popup key desc command + formatter &optional at prepend + + In POPUP, define KEY as COMMAND. + + POPUP is a popup command defined using ‘magit-define-popup’. + COMMAND is a command which calls ‘magit-popup-set-variable’. + FORMATTER is a function which calls ‘magit-popup-format-variable’. + These two functions have to be called with the same arguments. + + KEY is a character representing the event used interactively call + the COMMAND. + + DESC is the variable or a representation thereof. It’s not + actually used for anything. + + COMMAND is inserted after all other commands already defined for + POPUP, unless optional PREPEND is non-nil, in which case it is + placed first. If optional AT is non-nil then it should be the KEY + of another command already defined for POPUP, the command is then + placed before or after AT, depending on PREPEND." + + -- Function: magit-change-popup-key popup type from to + + In POPUP, bind TO to what FROM was bound to. TYPE is one of + ‘:action’, ‘:sequence-action’, ‘:switch’, or ‘:option’. Bind TO + and unbind FROM, both are characters. + + -- Function: magit-remove-popup-key popup type key + + In POPUP, remove KEY’s binding of TYPE. POPUP is a popup command + defined using ‘magit-define-popup’. TYPE is one of ‘:action’, + ‘:sequence-action’, ‘:switch’, or ‘:option’. KEY is the character + which is to be unbound. + + It is also possible to change other aspects of a popup by setting a +property using ‘plist-put’. See *note Defining prefix commands: +Defining prefix commands. for valid properties. The most likely change +Magit users might want to make is: + + (plist-put magit-show-refs-popup :use-prefix nil) + + +File: magit-popup.info, Node: Other options, Prev: Customizing existing popups, Up: Usage + +2.2 Other options +================= + + -- User Option: magit-popup-use-prefix-argument + + This option controls the effect that the use of a prefix argument + before entering a popup has. The *intended* default is ‘default’, + but the *actual* default is ‘disabled’. This is necessary because + the old popup implementation did simply forward such a pre-popup + prefix argument to the suffix command invoked from the popup, and + changing that without users being aware of it could lead to tears. + + • ‘disabled’ + + Bring up a Custom option buffer so that the user reads this + and then makes an informed choice. + + • ‘default’ + + With a prefix argument directly invoke the popup’s default + action (an Emacs command), instead of bringing up the popup. + + • ‘popup’ + + With a prefix argument bring up the popup, otherwise directly + invoke the popup’s default action. + + • ‘nil’ + + Ignore prefix arguments. + This option can be overridden for individual popups. + ‘magit-show-refs-popup’ for example defaults to invoking the + default action directly. It only shows the popup buffer when a + prefix argument is used. See *note Customizing existing popups: + Customizing existing popups. + + -- User Option: magit-popup-manpage-package + + The Emacs package used to display man-pages, one of ‘man’ or + ‘woman’. + + To emphasize the default action by making it bold use this: + + (button-type-put 'magit-popup-action-button 'format " %k %D") + + +File: magit-popup.info, Node: Defining prefix and suffix commands, Prev: Usage, Up: Top + +3 Defining prefix and suffix commands +************************************* + +If you write an extension for Magit then you should use this library now +and later when ‘transient’ is released port to that. + + If you are considering using this library to define popups for +packages not related to Magit, then keep in mind that it will be +superseded eventually. Once ‘transient’ has been released I will only +fix bugs in ‘magit-popup’ but not implement any new features. + + Also consider using ‘hydra’ instead. To some extend ‘magit-popup’ +and ‘hydra’ are similar but have a different focus. The main purpose of +‘magit-popup’ is to pass infix arguments to suffix commands. If all you +need is a command dispatcher then you are better of using ‘hydra’. Of +course ‘hydra’ may also be a better fit not only because of the features +it lacks, but also because of the features it provides, which are in +turn missing from ‘magit-popup’. + + Here is an example of how one defines a prefix command along with its +infix arguments, and then also one of its suffix commands. + + ;;;###autoload (autoload 'magit-tag-popup "magit" nil t) + (magit-define-popup magit-tag-popup + "Show popup buffer featuring tagging commands." + 'magit-commands + :man-page "git-tag" + :switches '((?a "Annotate" "--annotate") + (?s "Sign" "--sign") + (?f "Force" "--force")) + :actions '((?t "Create" magit-tag) + (?k "Delete" magit-tag-delete) + (?p "Prune" magit-tag-prune)) + :default-action 'magit-tag) + + ;;;###autoload + (defun magit-tag (name rev &optional args) + "Create a new tag with the given NAME at REV." + (interactive (list (magit-read-tag "Tag name") + (magit-read-branch-or-commit "Place tag on") + (magit-tag-arguments))) + (magit-run-git-with-editor "tag" args name rev)) + +* Menu: + +* Defining prefix commands:: +* Defining suffix commands:: + + +File: magit-popup.info, Node: Defining prefix commands, Next: Defining suffix commands, Up: Defining prefix and suffix commands + +3.1 Defining prefix commands +============================ + +Prefix commands and their infix arguments are defined using the macro +‘magit-define-popup’. The key bindings and descriptions of suffix +commands are also defined using that macro, but the actual interactive +commands have to be defined separately using plain ‘defun’. + + -- Macro: magit-define-popup name doc [group [mode [option]]] :keyword + value… + + This macro defines a popup named NAME. The NAME should begin with + the package prefix and by convention end with ‘-popup’, it is used + as the name of the command which shows the popup and for an + internal variable (whose value is used to store information about + the popup and should not be accessed directly). DOC is the + doc-string of the popup command. + + This macro also defines an option and a function both named + ‘SHORTNAME-arguments’, where SHORTNAME is NAME with the trailing + ‘-popup’ removed. The name of this option and this function can be + overwritten using the optional argument OPTION, but that is rarely + advisable. As a special case if OPTION is specified but ‘nil’, + then this option and this function are not defined at all, which is + useful for popups that are used as simple dispatchers that offer no + arguments. + + The option ‘SHORTNAME-arguments’ holds the value for the popup + arguments. It can be customized from within the popup or using the + Custom interface. It can also have a buffer local value in any + non-popup buffer. The local value for the buffer from which the + popup command was invoked, can be set from within the popup buffer. + + The function ‘SHORTNAME-arguments’ returns the currently effective + value of the variable by the same name. See below for more + information. + + The optional argument GROUP specifies the Custom group in which the + option is placed. If omitted then the option is placed in some + group the same way it is done when directly using ‘defcustom’ and + omitting the group. + + The optional argument MODE specifies the mode used by the popup + buffer. If it is omitted or ‘nil’ then ‘magit-popup-mode’ is used. + + The remaining arguments should have the form ‘[KEYWORD VALUE]...’. + + The following keywords are meaningful (and by convention are + usually specified in that order): + + • ‘:actions’ + + The actions which can be invoked from the popup. VALUE is a + list whose members have the form (KEY DESC COMMAND), see + ‘magit-define-popup-action’ for details. + + How the actions are split into rows and columns currently + depends on the available space and ‘:max-action-columns’. + + WARNING: This will likely be change to use a more explicit + format (((KEY DESC COMMAND)…)…) before the release. + + Actions are regular Emacs commands, which usually have an + ‘interactive’ form setup to consume the values of the popup + ‘:switches’ and ‘:options’ when invoked from the corresponding + popup, else when invoked as the default action or directly + without using the popup, the default value of the variable + ‘SHORTNAME-arguments’. This is usually done by calling the + function ‘SHORTNAME-arguments’. + + Members of VALUE may also be strings, assuming the first + member is also a string. Instead of just one action section + with the heading \"Actions\", multiple sections are then + inserted into the popup buffer, using these strings as + headings. + + Members of VALUE may also be nil. This should only be used + together with ‘:max-action-columns’ and allows having gaps in + the action grit, which can help arranging actions sensibly. + + • ‘:default-action’ + + The default action of the popup which is used directly instead + of displaying the popup buffer, when the popup is invoked with + a prefix argument. Also see ‘magit-popup-use-prefix-argument’ + and ‘:use-prefix’, which can be used to inverse the meaning of + the prefix argument. + + • ‘:use-prefix’ + + Controls when to display the popup buffer and when to invoke + the default action (if any) directly. This overrides the + global default set using ‘magit-popup-use-prefix-argument’. + The value, if specified, should be one of ‘default’ or + ‘prefix’. + + • ‘:switches’ + + The popup arguments which can be toggled on and off. VALUE is + a list whose members have the form ‘(KEY DESC SWITCH)’, see + ‘magit-define-popup-switch’ for details. + + • ‘:options’ + + The popup arguments which take a value, as in "–opt~OPTVAL". + VALUE is a list whose members have the form (KEY DESC OPTION + READER), see ‘magit-define-popup-option’ for details. + + • ‘:variables’ + + Git variables which can be set from the popup. VALUE is a + list whose members have the form (KEY DESC COMMAND FORMATTER), + see ‘magit-define-popup-variable’ for details. + + • ‘:default-arguments’ + + The default arguments, a list of switches (which are then + enabled by default) and options with there default values, as + in "–OPT~OPTVAL\". + + • ‘:sequence-predicate’ + + When this function returns non-nil, then the popup uses + ‘:sequence-actions’ instead of ‘:actions’, and does not show + the ‘:switches’ and ‘:options’. + + • ‘:sequence-actions’ + + The actions which can be invoked from the popup, when + ‘:sequence-predicate’ returns non-nil. + + • ‘:setup-function’ + + When this function is specified, then it is used instead of + ‘magit-popup-default-setup’. + + • ‘:refresh-function’ + + When this function is specified, then it is used instead of + calling ‘magit-popup-insert-section’ three times with symbols + ‘magit-popup-switch-button’, ‘magit-popup-option-button’, and + finally ‘magit-popup-action-button’ as argument. + + • ‘:man-page’ + + The name of the manpage to be displayed when the user requests + help for an argument. + + +File: magit-popup.info, Node: Defining suffix commands, Prev: Defining prefix commands, Up: Defining prefix and suffix commands + +3.2 Defining suffix commands +============================ + +Commands intended to be invoked from a particular popup should determine +the currently effective arguments by calling the function +‘SHORTNAME-arguments’ inside their ‘interactive’ form. This function is +created by the ‘magit-define-popup’ macro. For a popup named +‘prefix-foo-popup’ the name of this function is ‘prefix-foo-arguments’. + + When the command was invoked as an action in the respective popup, +then this function returns the arguments that were set in the popup. +Otherwise when the command was invoked as the default of the popup (by +calling the popup command with a prefix argument), or without using the +popup command at all, then this function returns the buffer-local or +global value of the variable ‘SHORTNAME-arguments’. + + Internally arguments are handled as a list of strings. This might +not be appropriate for the intended use inside commands, or it might be +necessary to manipulate that list somehow, i.e. to split "–ARG=VAL" +into "–ARG""VAL". This should be done by advising or redefining the +function ‘SHORTNAME-arguments’. + + Internally ‘SHORNAME-arguments’ used following variables and +function. Except when redefining the former, you should not use these +directly. + + -- Variable: magit-current-popup + + The popup from which this editing command was invoked. + + -- Variable: magit-current-popup-args + + The value of the popup arguments for this editing command. + + If the current command was invoked from a popup, then this is a + list of strings of all the set switches and options. This includes + arguments which are set by default not only those explicitly set + during this invocation. + + When the value is nil, then that can be because no argument is set, + or because the current command wasn’t invoked from a popup at all. + + -- Function: magit-current-popup-args &rest args + + This function returns the value of the popup arguments for this + editing command. The value is the same as that of the variable by + the same name, except that FILTER is applied. FILTER is a list of + regexps; only arguments that match one of them are returned. The + first element of FILTER may also be ‘:not’ in which case only + arguments that don’t match any of the regexps are returned, or + ‘:only’ which doesn’t change the behavior. + + + +Tag Table: +Node: Top989 +Node: Introduction2158 +Node: Usage4735 +Node: Customizing existing popups9392 +Node: Other options14920 +Node: Defining prefix and suffix commands16626 +Node: Defining prefix commands18722 +Node: Defining suffix commands25402 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/with-editor-20150701.1246/dir b/elpa/with-editor-20150701.1246/dir deleted file mode 100644 index 93a7ef74..00000000 --- a/elpa/with-editor-20150701.1246/dir +++ /dev/null @@ -1,18 +0,0 @@ -This is the file .../info/dir, which contains the -topmost node of the Info hierarchy, called (dir)Top. -The first time you invoke Info you start off looking at this node. - -File: dir, Node: Top This is the top of the INFO tree - - This (the Directory node) gives a menu of major topics. - Typing "q" exits, "?" lists all Info commands, "d" returns here, - "h" gives a primer for first-timers, - "mEmacs" visits the Emacs manual, etc. - - In Emacs, you can click mouse button 2 on a menu item or cross reference - to select it. - -* Menu: - -Emacs -* With-Editor: (with-editor). Using the Emacsclient as $EDITOR. diff --git a/elpa/with-editor-20150701.1246/with-editor-autoloads.el b/elpa/with-editor-20150701.1246/with-editor-autoloads.el deleted file mode 100644 index 6b889de3..00000000 --- a/elpa/with-editor-20150701.1246/with-editor-autoloads.el +++ /dev/null @@ -1,16 +0,0 @@ -;;; with-editor-autoloads.el --- automatically extracted autoloads -;; -;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) - -;;;### (autoloads nil nil ("with-editor-pkg.el" "with-editor.el") -;;;;;; (21910 48887 384174 0)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: -;;; with-editor-autoloads.el ends here diff --git a/elpa/with-editor-20150701.1246/with-editor-pkg.el b/elpa/with-editor-20150701.1246/with-editor-pkg.el deleted file mode 100644 index cb0c5265..00000000 --- a/elpa/with-editor-20150701.1246/with-editor-pkg.el +++ /dev/null @@ -1,8 +0,0 @@ -(define-package "with-editor" "20150701.1246" "Use the Emacsclient as $EDITOR" - '((emacs "24.4") - (dash "2.10.0")) - :url "https://github.com/magit/magit" :keywords - '("tools")) -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/with-editor-20150701.1246/with-editor.el b/elpa/with-editor-20150701.1246/with-editor.el deleted file mode 100644 index d581ef16..00000000 --- a/elpa/with-editor-20150701.1246/with-editor.el +++ /dev/null @@ -1,687 +0,0 @@ -;;; with-editor.el --- Use the Emacsclient as $EDITOR -*- lexical-binding: t -*- - -;; Copyright (C) 2014-2015 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; Package-Requires: ((emacs "24.4") (dash "2.10.0")) -;; Keywords: tools -;; Homepage: https://github.com/magit/magit - -;; This file is not part of GNU Emacs. - -;; This file 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. - -;; This file 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 file. If not, see . - -;;; Commentary: - -;; Use the Emacsclient as `$EDITOR' of child processes, making sure -;; they know how to call home. For remote processes a substitute is -;; provided, which communicates with Emacs on stdout instead of using -;; a socket as the Emacsclient does. - -;; The commands `with-editor-async-shell-command' and -;; `with-editor-shell-command' are intended as drop in replacements -;; for `async-shell-command' and `shell-command'. They automatically -;; export `$EDITOR' making sure the executed command uses the current -;; Emacs instance as "the editor". With a prefix argument these -;; commands prompt for an alternative environment variable such as -;; `$GIT_EDITOR'. To always use these variants add this to you init -;; file: -;; -;; (define-key (current-global-map) -;; [remap async-shell-command] 'with-editor-async-shell-command) -;; (define-key (current-global-map) -;; [remap shell-command] 'with-editor-shell-command) - -;; Alternatively use the global `shell-command-with-editor-mode', -;; which always sets `$EDITOR' for all Emacs commands which ultimately -;; use `shell-command' to asynchronously run some shell command. - -;; The command `with-editor-export-editor' exports `$EDITOR' or -;; another such environment variable in `shell-mode', `term-mode' and -;; `eshell-mode' buffers. Use this Emacs command before executing a -;; shell command which needs the editor set, or always arrange for the -;; current Emacs instance to be used as editor by adding it to the -;; appropriate mode hooks: -;; -;; (add-hook 'shell-mode-hook 'with-editor-export-editor) -;; (add-hook 'term-mode-hook 'with-editor-export-editor) -;; (add-hook 'eshell-mode-hook 'with-editor-export-editor) - -;; Some variants of this function exist, these two forms are -;; equivalent: -;; -;; (add-hook 'shell-mode-hook -;; (apply-partially 'with-editor-export-editor "GIT_EDITOR")) -;; (add-hook 'shell-mode-hook 'with-editor-export-git-editor) - -;; This library can also be used by other packages which need to use -;; the current Emacs instance as editor. In fact this library was -;; written for Magit and its `git-commit-mode' and `git-rebase-mode'. -;; Consult `git-rebase.el' and the related code in `magit-sequence.el' -;; for a simple example. - -;;; Code: - -(require 'cl-lib) -(require 'dash) -(require 'server) -(require 'tramp) -(require 'tramp-sh nil t) - -(eval-when-compile - (progn (require 'dired nil t) - (require 'eshell nil t) - (require 'term nil t) - (require 'warnings nil t))) -(declare-function dired-get-filename 'dired) -(declare-function term-emulate-terminal 'term) -(defvar eshell-preoutput-filter-functions) - -;;; Options - -(defgroup with-editor nil - "Use the Emacsclient as $EDITOR." - :group 'external - :group 'server) - -(defun with-editor-locate-emacsclient () - "Search for a suitable Emacsclient executable." - (--if-let (with-editor-locate-emacsclient-1 (with-editor-emacsclient-path) 3) - (shell-quote-argument it) - (display-warning 'with-editor (format "\ -Cannot determine a suitable Emacsclient - -Determining an Emacsclient executable suitable for the -current Emacs instance failed. For more information -please see https://github.com/magit/magit/wiki/Emacsclient.")) - nil)) - -(defun with-editor-locate-emacsclient-1 (path depth) - (let* ((version-lst (-take depth (split-string emacs-version "\\."))) - (version-reg (concat "^" (mapconcat #'identity version-lst "\\.")))) - (or (locate-file-internal - "emacsclient" path - (cl-mapcan - (lambda (v) (cl-mapcar (lambda (e) (concat v e)) exec-suffixes)) - (nconc (cl-mapcon (lambda (v) - (setq v (mapconcat #'identity (reverse v) ".")) - (list v (concat "-" v))) - (reverse version-lst)) - (list ""))) - (lambda (exec) - (ignore-errors - (string-match-p version-reg - (with-editor-emacsclient-version exec))))) - (and (> depth 1) - (with-editor-locate-emacsclient-1 path (1- depth)))))) - -(defun with-editor-emacsclient-version (exec) - (cadr (split-string (car (process-lines exec "--version"))))) - -(defun with-editor-emacsclient-path () - (let ((path exec-path)) - (when invocation-directory - (push (directory-file-name invocation-directory) path) - (let* ((linkname (expand-file-name invocation-name invocation-directory)) - (truename (file-chase-links linkname))) - (unless (equal truename linkname) - (push (directory-file-name (file-name-directory truename)) path))) - (when (eq system-type 'darwin) - (let ((dir (expand-file-name "bin" invocation-directory))) - (when (file-directory-p dir) - (push dir path))) - (when (string-match-p "Cellar" invocation-directory) - (let ((dir (expand-file-name "../../../bin" invocation-directory))) - (when (file-directory-p dir) - (push dir path)))))) - (cl-remove-duplicates path :test 'equal))) - -(defcustom with-editor-emacsclient-executable (with-editor-locate-emacsclient) - "The Emacsclient executable used by the `with-editor' macro." - :group 'with-editor - :type '(choice (string :tag "Executable") - (const :tag "Don't use Emacsclient" nil))) - -(defcustom with-editor-sleeping-editor "\ -sh -c '\ -echo \"WITH-EDITOR: $$ OPEN $0\"; \ -sleep 604800 & sleep=$!; \ -trap \"kill $sleep; exit 0\" USR1; \ -trap \"kill $sleep; exit 1\" USR2; \ -wait $sleep'" - "The looping editor, used when the Emacsclient cannot be used. - -This fallback is used for asynchronous process started inside the -macro `with-editor', when the process runs on a remote machine or -for local processes when `with-editor-emacsclient-executable' is -nil (i.e. when no suitable Emacsclient was found, or the user -decided not to use it). - -Where the latter uses a socket to communicate with Emacs' server, -this substitute prints edit requests to its standard output on -which a process filter listens for such requests. As such it is -not a complete substitute for a proper Emacsclient, it can only -be used as $EDITOR of child process of the current Emacs instance." - :group 'with-editor - :type 'string) - -(defcustom with-editor-finish-query-functions nil - "List of functions called to query before finishing session. - -The buffer in question is current while the functions are called. -If any of them returns nil, then the session is not finished and -the buffer is not killed. The user should then fix the issue and -try again. The functions are called with one argument. If it is -non-nil then that indicates that the user used a prefix argument -to force finishing the session despite issues. Functions should -usually honor that and return non-nil." - :group 'with-editor - :type 'hook) -(put 'with-editor-finish-query-functions 'permanent-local t) - -(defcustom with-editor-cancel-query-functions nil - "List of functions called to query before canceling session. - -The buffer in question is current while the functions are called. -If any of them returns nil, then the session is not canceled and -the buffer is not killed. The user should then fix the issue and -try again. The functions are called with one argument. If it is -non-nil then that indicates that the user used a prefix argument -to force canceling the session despite issues. Functions should -usually honor that and return non-nil." - :group 'with-editor - :type 'hook) -(put 'with-editor-cancel-query-functions 'permanent-local t) - -(defcustom with-editor-mode-lighter " WE" - "The mode-line lighter of the With-Editor mode." - :group 'with-editor - :type '(choice (const :tag "No lighter" "") string)) - -(defvar with-editor-server-window-alist nil - "Alist of filename patterns vs corresponding `server-window'. - -Each element looks like (REGEXP . FUNCTION). Files matching -REGEXP are selected using FUNCTION instead of the default in -`server-window'. - -Note that when a package adds an entry here then it probably -has a reason to disrespect `server-window' and it likely is -not a good idea to change such entries.") - -;;; Mode Commands - -(defvar with-editor-pre-finish-hook nil) -(defvar with-editor-pre-cancel-hook nil) -(defvar with-editor-post-cancel-hook nil) -(defvar with-editor-post-cancel-hook-1 nil) -(defvar with-editor-cancel-alist nil) -(put 'with-editor-pre-finish-hook 'permanent-local t) -(put 'with-editor-pre-cancel-hook 'permanent-local t) -(put 'with-editor-post-cancel-hook 'permanent-local t) - -(defvar with-editor-show-usage t) -(defvar with-editor-cancel-message nil) -(defvar with-editor-previous-winconf nil) -(make-variable-buffer-local 'with-editor-show-usage) -(make-variable-buffer-local 'with-editor-cancel-message) -(make-variable-buffer-local 'with-editor-previous-winconf) -(put 'with-editor-cancel-message 'permanent-local t) -(put 'with-editor-previous-winconf 'permanent-local t) - -(defvar-local with-editor--pid nil "For internal use.") -(put 'with-editor--pid 'permanent-local t) - -(defun with-editor-finish (force) - "Finish the current edit session." - (interactive "P") - (when (run-hook-with-args-until-failure - 'with-editor-finish-query-functions force) - (run-hooks 'with-editor-pre-finish-hook) - (with-editor-return nil))) - -(defun with-editor-cancel (force) - "Cancel the current edit session." - (interactive "P") - (when (run-hook-with-args-until-failure - 'with-editor-cancel-query-functions force) - (let ((message with-editor-cancel-message)) - (when (functionp message) - (setq message (funcall message))) - (let ((with-editor-post-cancel-hook-1 - (ignore-errors (delq t with-editor-post-cancel-hook))) - (with-editor-cancel-alist nil)) - (run-hooks 'with-editor-pre-cancel-hook) - (with-editor-return t) - (accept-process-output nil 0.1) - (run-hooks 'with-editor-post-cancel-hook-1)) - (message (or message "Canceled by user"))))) - -(defun with-editor-return (cancel) - (let ((winconf with-editor-previous-winconf) - (clients server-buffer-clients) - (dir default-directory) - (pid with-editor--pid)) - (remove-hook 'kill-buffer-query-functions - 'with-editor-kill-buffer-noop t) - (cond (cancel - (save-buffer) - (if clients - (dolist (client clients) - (ignore-errors - (server-send-string client "-error Canceled by user")) - (delete-process client)) - (kill-buffer))) - (t - (save-buffer) - (if clients (server-edit) (kill-buffer)))) - (when pid - (let ((default-directory dir)) - (process-file "kill" nil nil nil - "-s" (if cancel "USR2" "USR1") pid))) - (when (and winconf (eq (window-configuration-frame winconf) - (selected-frame))) - (set-window-configuration winconf)))) - -;;; Mode - -(defvar with-editor-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\C-c\C-c" 'with-editor-finish) - (define-key map [remap server-edit] 'with-editor-finish) - (define-key map "\C-c\C-k" 'with-editor-cancel) - (define-key map [remap kill-buffer] 'with-editor-cancel) - (define-key map [remap ido-kill-buffer] 'with-editor-cancel) - (define-key map [remap iswitchb-kill-buffer] 'with-editor-cancel) - map)) - -(define-minor-mode with-editor-mode - "Edit a file as the $EDITOR of an external process." - :lighter with-editor-mode-lighter - ;; Protect the user from killing the buffer without using - ;; either `with-editor-finish' or `with-editor-cancel', - ;; and from removing the key bindings for these commands. - (unless with-editor-mode - (error "With-Editor mode cannot be turned off")) - (add-hook 'kill-buffer-query-functions - 'with-editor-kill-buffer-noop nil t) - ;; `server-excecute' displays a message which is not - ;; correct when using this mode. - (when with-editor-show-usage - (with-editor-usage-message))) - -(put 'with-editor-mode 'permanent-local t) - -(defun with-editor-kill-buffer-noop () - (message (substitute-command-keys "\ -Don't kill this buffer. Instead cancel using \\[with-editor-cancel]"))) - -(defun with-editor-usage-message () - ;; Run after `server-execute', which is run using - ;; a timer which starts immediately. - (run-with-timer - 0.01 nil `(lambda () - (with-current-buffer ,(current-buffer) - (message (substitute-command-keys "\ -Type \\[with-editor-finish] to finish, \ -or \\[with-editor-cancel] to cancel")))))) - -;;; Wrappers - -(defvar with-editor--envvar nil "For internal use.") - -(defmacro with-editor (&rest body) - "Use the Emacsclient as $EDITOR while evaluating BODY. -Modify the `process-environment' for processes started in BODY, -instructing them to use the Emacsclient as $EDITOR. If optional -ENVVAR is provided then bind that environment variable instead. -\n(fn [ENVVAR] BODY...)" - (declare (indent defun)) - `(let ((with-editor--envvar ,(if (stringp (car body)) - (pop body) - '(or with-editor--envvar "EDITOR"))) - (process-environment process-environment)) - (if (or (not with-editor-emacsclient-executable) - (file-remote-p default-directory)) - (setenv with-editor--envvar with-editor-sleeping-editor) - ;; Make sure server-use-tcp's value is valid. - (unless (featurep 'make-network-process '(:family local)) - (setq server-use-tcp t)) - ;; Make sure the server is running. - (unless server-process - (when (server-running-p server-name) - (setq server-name (format "server%s" (emacs-pid))) - (when (server-running-p server-name) - (server-force-delete server-name))) - (server-start)) - ;; Tell $EDITOR to use the Emacsclient. - (setenv with-editor--envvar - (concat with-editor-emacsclient-executable - ;; Tell the process where the server file is. - (and (not server-use-tcp) - (concat " --socket-name=" - (expand-file-name server-name - server-socket-dir))))) - (when server-use-tcp - (setenv "EMACS_SERVER_FILE" - (expand-file-name server-name server-auth-dir))) - ;; As last resort fallback to the looping editor. - (setenv "ALTERNATE_EDITOR" with-editor-sleeping-editor)) - ,@body)) - -(defun with-editor-server-window () - (or (and buffer-file-name - (cdr (--first (string-match-p (car it) buffer-file-name) - with-editor-server-window-alist))) - server-window)) - -(defadvice server-switch-buffer (around with-editor activate) - "Honor `with-editor-server-window-alist' (which see)." - (let ((server-window (with-current-buffer - (or next-buffer (current-buffer)) - (with-editor-server-window)))) - ad-do-it)) - -(defadvice start-file-process (around with-editor activate) - "When called inside a `with-editor' form and the Emacsclient -cannot be used, then give the process the filter function -`with-editor-process-filter'. To avoid overriding the filter -being added here you should use `with-editor-set-process-filter' -instead of `set-process-filter' inside `with-editor' forms. - -When the `default-directory' is located on a remote machine, -then also manipulate PROGRAM and PROGRAM-ARGS in order to set -the appropriate editor environment variable." - ;; (fn NAME BUFFER PROGRAM &rest PROGRAM-ARGS) - (if (not with-editor--envvar) - ad-do-it - (when (file-remote-p default-directory) - (let ((prog (ad-get-arg 2)) - (args (ad-get-args 3))) - (unless (equal program "env") - (push prog args) - (setq prog "env")) - (push (concat with-editor--envvar "=" with-editor-sleeping-editor) args) - (ad-set-arg 2 prog) - (ad-set-args 3 args))) - (let ((process ad-do-it)) - (set-process-filter process 'with-editor-process-filter) - (process-put process 'default-dir default-directory) - process))) - -(defun with-editor-set-process-filter (process filter) - "Like `set-process-filter' but keep `with-editor-process-filter'. -Give PROCESS the new FILTER but keep `with-editor-process-filter' -if that was added earlier by the adviced `start-file-process'. - -Do so by wrapping the two filter functions using a lambda, which -becomes the actual filter. It calls `with-editor-process-filter' -first, passing t as NO-STANDARD-FILTER. Then it calls FILTER, -which may or may not insert the text into the PROCESS' buffer." - (set-process-filter - process - (if (eq (process-filter process) 'with-editor-process-filter) - `(lambda (proc str) - (,filter proc str) - (with-editor-process-filter proc str t)) - filter))) - -(defun with-editor-output-filter (string) - (save-match-data - (if (string-match "^WITH-EDITOR: \\([0-9]+\\) OPEN \\(.+?\\)\r?$" string) - (let ((pid (match-string 1 string)) - (file (match-string 2 string))) - (with-current-buffer - (find-file-noselect - (if (file-name-absolute-p file) - (if (tramp-tramp-file-p default-directory) - (with-parsed-tramp-file-name default-directory nil - (tramp-make-tramp-file-name method user host file hop)) - file) - (expand-file-name file))) - (with-editor-mode 1) - (setq with-editor--pid pid) - (run-hooks 'with-editor-filter-visit-hook) - (funcall (or (with-editor-server-window) 'switch-to-buffer) - (current-buffer)) - (kill-local-variable 'server-window)) - nil) - string))) - -(defun with-editor-process-filter - (process string &optional no-default-filter) - "Listen for edit requests by child processes." - (let ((default-directory (process-get process 'default-dir))) - (with-editor-output-filter string)) - (unless no-default-filter - (internal-default-process-filter process string))) - -;;; Augmentations - -(cl-defun with-editor-export-editor (&optional (envvar "EDITOR")) - "Teach subsequent commands to use current Emacs instance as editor. - -Set and export the environment variable ENVVAR, by default -\"EDITOR\". The value is automatically generated to teach -commands use the current Emacs instance as \"the editor\". - -This works in `shell-mode', `term-mode' and `eshell-mode'." - (interactive (list (with-editor-read-envvar))) - (cond - ((derived-mode-p 'comint-mode 'term-mode) - (let* ((process (get-buffer-process (current-buffer))) - (filter (process-filter process))) - (set-process-filter process 'ignore) - (goto-char (process-mark process)) - (process-send-string - process (format "export %s=%s\n" envvar - (shell-quote-argument with-editor-sleeping-editor))) - (while (accept-process-output process 0.1)) - (set-process-filter process filter) - (if (derived-mode-p 'term-mode) - (with-editor-set-process-filter process 'with-editor-emulate-terminal) - (add-hook 'comint-output-filter-functions 'with-editor-output-filter - nil t)))) - ((derived-mode-p 'eshell-mode) - (add-to-list 'eshell-preoutput-filter-functions - 'with-editor-output-filter) - (setenv envvar with-editor-sleeping-editor)) - (t - (error "Cannot export environment variables in this buffer"))) - (message "Successfully exported %s" envvar)) - -(defun with-editor-export-git-editor () - "Like `with-editor-export-editor' but always set `$GIT_EDITOR'." - (interactive) - (with-editor-export-editor "GIT_EDITOR")) - -(defun with-editor-export-hg-editor () - "Like `with-editor-export-editor' but always set `$HG_EDITOR'." - (interactive) - (with-editor-export-editor "HG_EDITOR")) - -(defun with-editor-emulate-terminal (process string) - "Like `term-emulate-terminal' but also handle edit requests." - (when (with-editor-output-filter string) - (term-emulate-terminal process string))) - -(defvar with-editor-envvars '("EDITOR" "GIT_EDITOR" "HG_EDITOR")) - -(cl-defun with-editor-read-envvar - (&optional (prompt "Set environment variable") - (default "EDITOR")) - (let ((reply (completing-read (if default - (format "%s (%s): " prompt default) - (concat prompt ": ")) - with-editor-envvars nil nil nil nil default))) - (if (string= reply "") (user-error "Nothing selected") reply))) - -(define-minor-mode shell-command-with-editor-mode - "Teach `shell-command' to use current Emacs instance as editor. - -Teach `shell-command', and all commands that ultimately call that -command, to use the current Emacs instance as editor by executing -\"EDITOR=CLIENT COMMAND&\" instead of just \"COMMAND&\". - -CLIENT is automatically generated; EDITOR=CLIENT instructs -COMMAND to use to the current Emacs instance as \"the editor\", -assuming no other variable overrides the effect of \"$EDITOR\". -CLIENT may be the path to an appropriate emacsclient executable -with arguments, or a script which also works over Tramp. - -Alternatively you can use the `with-editor-async-shell-command', -which also allows the use of another variable instead of -\"EDITOR\"." - :global t) - -(defun with-editor-async-shell-command - (command &optional output-buffer error-buffer envvar) - "Like `async-shell-command' but with `$EDITOR' set. - -Execute string \"ENVVAR=CLIENT COMMAND\" in an inferior shell; -display output, if any. With a prefix argument prompt for an -environment variable, otherwise the default \"EDITOR\" variable -is used. With a negative prefix argument additionally insert -the COMMAND's output at point. - -CLIENT is automatically generated; ENVVAR=CLIENT instructs -COMMAND to use to the current Emacs instance as \"the editor\", -assuming it respects ENVVAR as an \"EDITOR\"-like variable. -CLIENT maybe the path to an appropriate emacsclient executable -with arguments, or a script which also works over Tramp. - -Also see `async-shell-command' and `shell-command'." - (interactive (with-editor-shell-command-read-args "Async shell command: " t)) - (let ((with-editor--envvar envvar)) - (with-editor - (async-shell-command command output-buffer error-buffer)))) - -(defun with-editor-shell-command - (command &optional output-buffer error-buffer envvar) - "Like `shell-command' or `with-editor-async-shell-command'. -If COMMAND ends with \"&\" behave like the latter, -else like the former." - (interactive (with-editor-shell-command-read-args "Shell command: ")) - (if (string-match "&[ \t]*\\'" command) - (with-editor-async-shell-command - command output-buffer error-buffer envvar) - (shell-command command output-buffer error-buffer))) - -(defun with-editor-shell-command-read-args (prompt &optional async) - (let ((command (read-shell-command - prompt nil nil - (--when-let (or (buffer-file-name) - (and (eq major-mode 'dired-mode) - (dired-get-filename nil t))) - (file-relative-name it))))) - (list command - (if (or async (setq async (string-match-p "&[ \t]*\\'" command))) - (< (prefix-numeric-value current-prefix-arg) 0) - current-prefix-arg) - shell-command-default-error-buffer - (and async current-prefix-arg (with-editor-read-envvar))))) - -(defadvice shell-command (around with-editor activate) - (cond ((or (not (or with-editor--envvar shell-command-with-editor-mode)) - (not (string-match-p "&$" (ad-get-arg 0)))) - ad-do-it) - ((and with-editor-emacsclient-executable - (not (file-remote-p default-directory))) - (with-editor ad-do-it)) - (t - (ad-set-arg - 0 (format "%s=%s %s" - (or with-editor--envvar "EDITOR") - (shell-quote-argument with-editor-sleeping-editor) - (ad-get-arg 0))) - (let ((process ad-do-it)) - (set-process-filter - process (lambda (proc str) - (comint-output-filter proc str) - (with-editor-process-filter proc str t))) - process)))) - -;;; with-editor.el ends soon - -(defun with-editor-debug () - "Debug configuration issues. -See `with-editor.info' for instructions." - (interactive) - (with-current-buffer (get-buffer-create "*with-editor-debug*") - (pop-to-buffer (current-buffer)) - (erase-buffer) - (ignore-errors (with-editor)) - (insert - (format "with-editor: %s\n" (locate-library "with-editor.el")) - (format "emacs: %s (%s)\n" - (expand-file-name invocation-name invocation-directory) - emacs-version) - "system:\n" - (format " system-type: %s\n" system-type) - (format " system-configuration: %s\n" system-configuration) - (format " system-configuration-options: %s\n" system-configuration-options) - "server:\n" - (format " server-running-p: %s\n" (server-running-p)) - (format " server-process: %S\n" server-process) - (format " server-use-tcp: %s\n" server-use-tcp) - (format " server-name: %s\n" server-name) - (format " server-socket-dir: %s\n" server-socket-dir)) - (if (file-accessible-directory-p server-socket-dir) - (--each (directory-files server-socket-dir nil "^[^.]") - (insert (format " %s\n" it))) - (insert (format " %s: not an accessible directory\n" - (if server-use-tcp "WARNING" "ERROR")))) - (insert (format " server-auth-dir: %s\n" server-auth-dir)) - (if (file-accessible-directory-p server-auth-dir) - (--each (directory-files server-auth-dir nil "^[^.]") - (insert (format " %s\n" it))) - (insert (format " %s: not an accessible directory\n" - (if server-use-tcp "ERROR" "WARNING")))) - (let ((val with-editor-emacsclient-executable) - (def (default-value 'with-editor-emacsclient-executable)) - (fun (let ((warning-minimum-level :error) - (warning-minimum-log-level :error)) - (with-editor-locate-emacsclient)))) - (insert "magit-emacsclient-executable:\n" - (format " value: %s (%s)\n" val - (and val (with-editor-emacsclient-version val))) - (format " default: %s (%s)\n" def - (and def (with-editor-emacsclient-version def))) - (format " funcall: %s (%s)\n" fun - (and fun (with-editor-emacsclient-version fun))))) - (insert "path:\n" - (format " $PATH: %S\n" (getenv "PATH")) - (format " exec-path: %s\n" exec-path)) - (insert (format " with-editor-emacsclient-path:\n")) - (--each (with-editor-emacsclient-path) - (insert (format " %s (%s)\n" it (car (file-attributes it)))) - (when (file-directory-p it) - (dolist (exec (directory-files it nil "emacsclient")) - (insert (format " %s (%s)\n" exec - (with-editor-emacsclient-version exec)))))))) - -(defconst with-editor-font-lock-keywords - '(("(\\(with-\\(?:git-\\)?editor\\)\\_>" (1 'font-lock-keyword-face)))) -(font-lock-add-keywords 'emacs-lisp-mode with-editor-font-lock-keywords) - -(provide 'with-editor) -;; Local Variables: -;; indent-tabs-mode: nil -;; End: -;;; with-editor.el ends here diff --git a/elpa/with-editor-20150701.1246/with-editor.info b/elpa/with-editor-20150701.1246/with-editor.info deleted file mode 100644 index ecab503f..00000000 --- a/elpa/with-editor-20150701.1246/with-editor.info +++ /dev/null @@ -1,323 +0,0 @@ -This is with-editor.info, produced by makeinfo version 5.2 from -with-editor.texi. - -The library ‘with-editor’ makes it easy to use the Emacsclient as the -‘$EDITOR’ of child processes, making sure they know how to call home. -For remote processes a substitute is provided, which communicates with -Emacs on standard output instead of using a socket as the Emacsclient -does. - - This library was written because Magit has to be able to do the above -to allow the user to edit commit messages gracefully and to edit rebase -sequences, which wouldn’t be possible at all otherwise. - - Because other packages can benefit from such functionality, this -library is made available as a separate package. It also defines some -additional functionality which makes it useful even for end-users, who -don’t use Magit or another package which uses it internally. - - Copyright (C) 2015 Jonas Bernoulli - - You can redistribute this document 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 document 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. -INFO-DIR-SECTION Emacs -START-INFO-DIR-ENTRY -* With-Editor: (with-editor). Using the Emacsclient as $EDITOR. -END-INFO-DIR-ENTRY - - -File: with-editor.info, Node: Top, Next: Using the With-Editor package, Up: (dir) - -With-Editor User Manual -*********************** - -The library ‘with-editor’ makes it easy to use the Emacsclient as the -‘$EDITOR’ of child processes, making sure they know how to call home. -For remote processes a substitute is provided, which communicates with -Emacs on standard output instead of using a socket as the Emacsclient -does. - - This library was written because Magit has to be able to do the above -to allow the user to edit commit messages gracefully and to edit rebase -sequences, which wouldn’t be possible at all otherwise. - - Because other packages can benefit from such functionality, this -library is made available as a separate package. It also defines some -additional functionality which makes it useful even for end-users, who -don’t use Magit or another package which uses it internally. - - Copyright (C) 2015 Jonas Bernoulli - - You can redistribute this document 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 document 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. - -* Menu: - -* Using the With-Editor package:: -* Using With-Editor as a library:: -* Debugging:: - -— The Detailed Node Listing — - -Using the With-Editor package - -* Configuring With-Editor:: -* Using With-Editor commands:: - - - -File: with-editor.info, Node: Using the With-Editor package, Next: Using With-Editor as a library, Prev: Top, Up: Top - -1 Using the With-Editor package -******************************* - -The ‘With-Editor’ package is used internally by Magit when editing -commit messages and rebase sequences. It also provides some commands -and features which are useful by themselves, even if you don’t use -Magit. - - For information about using this library in you own package, see -*note Using With-Editor as a library: Using With-Editor as a library. - -* Menu: - -* Configuring With-Editor:: -* Using With-Editor commands:: - - -File: with-editor.info, Node: Configuring With-Editor, Next: Using With-Editor commands, Up: Using the With-Editor package - -1.1 Configuring With-Editor -=========================== - -With-Editor tries very hard to locate a suitable emacsclient executable, -so ideally you should never have to customize the option -‘with-editor-emacsclient-executable’. When it fails to do so, then the -most likely reason is that someone found yet another way to package -Emacs (most likely on OS X) without putting the executable on ‘$PATH’, -and we have to add another kludge to find it anyway. - - -- User Option: with-editor-emacsclient-executable - - The emacsclient executable used as the editor by child process of - this Emacs instance. By using this executable, child processes can - call home to their parent process. - - This option is automatically set at startup by looking in - ‘exec-path’, and other places where the executable could be - installed, to find the emacsclient executable most suitable for the - current emacs instance. - - You should *not* customize this option permanently. If you have to - do it, then you should consider that a temporary kludge and inform - the Magit maintainer as described in *note Debugging: Debugging. - - If With-Editor fails to find a suitable emacsclient on you system, - then this should be fixed for all users at once, by teaching - ‘with-editor-locate-emacsclient’ how to so on your system and - system like yours. Doing it this way has the advantage, that you - won’t have do it again every time you update Emacs, and that other - users who have installed Emacs the same way as you have, won’t have - to go through the same trouble. - - Note that there also is a nuclear option; setting this variable to - ‘nil’ causes the "sleeping editor" described below to be used even - for local child processes. Obviously we don’t recommend that you - use this except in "emergencies", i.e. before we had a change to - add a kludge appropriate for you setup. - - -- Function: with-editor-locate-emacsclient - - The function used to set the initial value of the option - ‘with-editor-emacsclient-executable’. There’s a lot of voodoo - here. - - The emacsclient cannot be used when using Tramp to run a process on a -remote machine. (Theoretically it could, but that would be hard to -setup, very fragile, and rather insecure). - - With-Editor provides an alternative "editor" which can be used by -remote processes in much the same way as local processes use an -emacsclient executable. This alternative is known as the "sleeping -editor" because it is implemented as a shell script which sleeps until -it receives a signal. - - -- User Option: with-editor-sleeping-editor - - The sleeping editor is a shell script used as the editor of child - processes when the emacsclient executable cannot be used. - - This fallback is used for asynchronous process started inside the - macro ‘with-editor’, when the process runs on a remote machine or - for local processes when ‘with-editor-emacsclient-executable’ is - ‘nil’. - - Where the latter uses a socket to communicate with Emacs’ server, - this substitute prints edit requests to its standard output on - which a process filter listens for such requests. As such it is - not a complete substitute for a proper Emacsclient, it can only be - used as ‘$EDITOR’ of child process of the current Emacs instance. - - It is unlikely that you should ever have to customize this option. - - -File: with-editor.info, Node: Using With-Editor commands, Prev: Configuring With-Editor, Up: Using the With-Editor package - -1.2 Using With-Editor commands -============================== - -This section describes how to use the with-editor library _outside_ of -Magit. You don’t need to know any of this just to create commits using -Magit. - - The commands ‘with-editor-async-shell-command’ and -‘with-editor-shell-command’ are intended as drop in replacements for -‘async-shell-command’ and ‘shell-command’. They automatically export -‘$EDITOR’ making sure the executed command uses the current Emacs -instance as "the editor". With a prefix argument these commands prompt -for an alternative environment variable such as ‘$GIT_EDITOR’. - - -- Command: with-editor-async-shell-command - - Like ‘async-shell-command’, but the command is run with the current - Emacs instance exported as ‘$EDITOR’. - - -- Command: with-editor-shell-command - - Like ‘async-shell-command’, but the command is run with the current - Emacs instance exported as ‘$EDITOR’. This only has an effect if - the command is run asynchronously, i.e. when the command ends with - ‘&’. - - To always use these variants add this to you init file: - - (define-key (current-global-map) - [remap async-shell-command] 'with-editor-async-shell-command) - (define-key (current-global-map) - [remap shell-command] 'with-editor-shell-command) - - Alternatively use the global ‘shell-command-with-editor-mode’. - - -- Variable: shell-command-with-editor-mode - - When this mode is active, then ‘$EDITOR’ is exported whenever - ultimately ‘shell-command’ is called to asynchronously run some - shell command. This affects most variants of that command, whether - they are defined in Emacs or in some third-party package. - - The command ‘with-editor-export-editor’ exports ‘$EDITOR’ or another -such environment variable in ‘shell-mode’, ‘term-mode’ and ‘eshell-mode’ -buffers. Use this Emacs command before executing a shell command which -needs the editor set, or always arrange for the current Emacs instance -to be used as editor by adding it to the appropriate mode hooks: - - (add-hook 'shell-mode-hook 'with-editor-export-editor) - (add-hook 'term-mode-hook 'with-editor-export-editor) - (add-hook 'eshell-mode-hook 'with-editor-export-editor) - - Some variants of this function exist; these two forms are equivalent: - - (add-hook 'shell-mode-hook - (apply-partially 'with-editor-export-editor "GIT_EDITOR")) - (add-hook 'shell-mode-hook 'with-editor-export-git-editor) - - -- Command: with-editor-export-editor - - When invoked in a ‘shell-mode’, ‘term-mode’, or ‘eshell-mode’ - buffer, this command teaches shell commands to use the current - Emacs instance as the editor, by exporting ‘$EDITOR’. - - -- Command: with-editor-export-git-editor - - Like ‘with-editor-export-editor’ but exports ‘$GIT_EDITOR’. - - -- Command: with-editor-export-hg-editor - - Like ‘with-editor-export-editor’ but exports ‘$HG_EDITOR’. - - -File: with-editor.info, Node: Using With-Editor as a library, Next: Debugging, Prev: Using the With-Editor package, Up: Top - -2 Using With-Editor as a library -******************************** - -This section describes how to use the with-editor library _outside_ of -Magit to teach another package how to have its child processes call -home, just like Magit does. You don’t need to know any of this just to -create commits using Magit. You can also ignore this if you use -with-editor outside of Magit, but only as an end-user. - - For information about interactive use and options which affect both -interactive and non-interactive use, see *note Using the With-Editor -package: Using the With-Editor package. - - -- Macro: with-editor &rest body - - This macro arranges for the emacsclient or the sleeping editor to - be used as the editor of child processes, effectively teaching them - to call home to the current emacs instance when they require that - the user edits a file. - - This is essentially done by establishing a local binding for - ‘process-environment’ and changing the value of the ‘$EDITOR’ - environment variable. This affects all processes started by forms - inside BODY. - - -- Function: with-editor-set-process-filter process filter - - This function is like ‘set-process-filter’ but ensures that adding - the new FILTER does not remove the ‘with-editor-process-filter’. - This is done by wrapping the two filter functions using a lambda, - which becomes the actual filter. It calls - ‘with-editor-process-filter’ first, passing ‘t’ as - NO-STANDARD-FILTER. Then it calls FILTER. - - -File: with-editor.info, Node: Debugging, Prev: Using With-Editor as a library, Up: Top - -3 Debugging -*********** - -With-Editor tries very hard to locate a suitable emacsclient executable, -and then sets option ‘with-editor-emacsclient-executable’ accordingly. -In very rare cases this fails. When it does fail, then the most likely -reason is that someone found yet another way to package Emacs (most -likely on OS X) without putting the executable on ‘$PATH’, and we have -to add another kludge to find it anyway. - - If you are having problems using ‘with-editor’, e.g. you cannot -commit in Magit, then please open a new issue at - and provide information about -your Emacs installation. Most importantly how did you install Emacs and -what is the output of ‘M-x with-editor-debug’? - - - -Tag Table: -Node: Top1540 -Node: Using the With-Editor package3227 -Node: Configuring With-Editor3843 -Node: Using With-Editor commands7450 -Node: Using With-Editor as a library10614 -Node: Debugging12280 - -End Tag Table - - -Local Variables: -coding: utf-8 -End: diff --git a/elpa/with-editor-20151223.1341/dir b/elpa/with-editor-20151223.1341/dir new file mode 100644 index 00000000..93a7ef74 --- /dev/null +++ b/elpa/with-editor-20151223.1341/dir @@ -0,0 +1,18 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "?" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Emacs +* With-Editor: (with-editor). Using the Emacsclient as $EDITOR. diff --git a/elpa/with-editor-20151223.1341/with-editor-autoloads.el b/elpa/with-editor-20151223.1341/with-editor-autoloads.el new file mode 100644 index 00000000..7deaeb53 --- /dev/null +++ b/elpa/with-editor-20151223.1341/with-editor-autoloads.el @@ -0,0 +1,16 @@ +;;; with-editor-autoloads.el --- automatically extracted autoloads +;; +;;; Code: +(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +;;;### (autoloads nil nil ("with-editor-pkg.el" "with-editor.el") +;;;;;; (22140 6971 36516 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; End: +;;; with-editor-autoloads.el ends here diff --git a/elpa/with-editor-20151223.1341/with-editor-pkg.el b/elpa/with-editor-20151223.1341/with-editor-pkg.el new file mode 100644 index 00000000..97a98cde --- /dev/null +++ b/elpa/with-editor-20151223.1341/with-editor-pkg.el @@ -0,0 +1,9 @@ +(define-package "with-editor" "20151223.1341" "Use the Emacsclient as $EDITOR" + '((emacs "24.4") + (async "20150909.2257") + (dash "20151021.113")) + :url "https://github.com/magit/magit" :keywords + '("tools")) +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/with-editor-20151223.1341/with-editor.el b/elpa/with-editor-20151223.1341/with-editor.el new file mode 100644 index 00000000..c137837c --- /dev/null +++ b/elpa/with-editor-20151223.1341/with-editor.el @@ -0,0 +1,724 @@ +;;; with-editor.el --- Use the Emacsclient as $EDITOR -*- lexical-binding: t -*- + +;; Copyright (C) 2014-2015 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Package-Requires: ((emacs "24.4") (async "20150909.2257") (dash "20151021.113")) +;; Keywords: tools +;; Homepage: https://github.com/magit/magit + +;; This file is not part of GNU Emacs. + +;; This file 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. + +;; This file 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 file. If not, see . + +;;; Commentary: + +;; Use the Emacsclient as `$EDITOR' of child processes, making sure +;; they know how to call home. For remote processes a substitute is +;; provided, which communicates with Emacs on stdout instead of using +;; a socket as the Emacsclient does. + +;; The commands `with-editor-async-shell-command' and +;; `with-editor-shell-command' are intended as drop in replacements +;; for `async-shell-command' and `shell-command'. They automatically +;; export `$EDITOR' making sure the executed command uses the current +;; Emacs instance as "the editor". With a prefix argument these +;; commands prompt for an alternative environment variable such as +;; `$GIT_EDITOR'. To always use these variants add this to your init +;; file: +;; +;; (define-key (current-global-map) +;; [remap async-shell-command] 'with-editor-async-shell-command) +;; (define-key (current-global-map) +;; [remap shell-command] 'with-editor-shell-command) + +;; Alternatively use the global `shell-command-with-editor-mode', +;; which always sets `$EDITOR' for all Emacs commands which ultimately +;; use `shell-command' to asynchronously run some shell command. + +;; The command `with-editor-export-editor' exports `$EDITOR' or +;; another such environment variable in `shell-mode', `term-mode' and +;; `eshell-mode' buffers. Use this Emacs command before executing a +;; shell command which needs the editor set, or always arrange for the +;; current Emacs instance to be used as editor by adding it to the +;; appropriate mode hooks: +;; +;; (add-hook 'shell-mode-hook 'with-editor-export-editor) +;; (add-hook 'term-mode-hook 'with-editor-export-editor) +;; (add-hook 'eshell-mode-hook 'with-editor-export-editor) + +;; Some variants of this function exist, these two forms are +;; equivalent: +;; +;; (add-hook 'shell-mode-hook +;; (apply-partially 'with-editor-export-editor "GIT_EDITOR")) +;; (add-hook 'shell-mode-hook 'with-editor-export-git-editor) + +;; This library can also be used by other packages which need to use +;; the current Emacs instance as editor. In fact this library was +;; written for Magit and its `git-commit-mode' and `git-rebase-mode'. +;; Consult `git-rebase.el' and the related code in `magit-sequence.el' +;; for a simple example. + +;;; Code: + +(require 'cl-lib) +(require 'dash) +(require 'server) +(require 'tramp) +(require 'tramp-sh nil t) + +(and (require 'async-bytecomp nil t) + (memq 'magit (bound-and-true-p async-bytecomp-allowed-packages)) + (fboundp 'async-bytecomp-package-mode) + (async-bytecomp-package-mode 1)) + +(eval-when-compile + (progn (require 'dired nil t) + (require 'eshell nil t) + (require 'term nil t) + (require 'warnings nil t))) +(declare-function dired-get-filename 'dired) +(declare-function term-emulate-terminal 'term) +(defvar eshell-preoutput-filter-functions) + +;;; Options + +(defgroup with-editor nil + "Use the Emacsclient as $EDITOR." + :group 'external + :group 'server) + +(defun with-editor-locate-emacsclient () + "Search for a suitable Emacsclient executable." + (--if-let (with-editor-locate-emacsclient-1 (with-editor-emacsclient-path) 3) + it + (display-warning 'with-editor (format "\ +Cannot determine a suitable Emacsclient + +Determining an Emacsclient executable suitable for the +current Emacs instance failed. For more information +please see https://github.com/magit/magit/wiki/Emacsclient.")) + nil)) + +(defun with-editor-locate-emacsclient-1 (path depth) + (let* ((version-lst (-take depth (split-string emacs-version "\\."))) + (version-reg (concat "^" (mapconcat #'identity version-lst "\\.")))) + (or (locate-file-internal + "emacsclient" path + (cl-mapcan + (lambda (v) (cl-mapcar (lambda (e) (concat v e)) exec-suffixes)) + (nconc (cl-mapcon (lambda (v) + (setq v (mapconcat #'identity (reverse v) ".")) + (list v (concat "-" v) (concat ".emacs" v))) + (reverse version-lst)) + (list ""))) + (lambda (exec) + (ignore-errors + (string-match-p version-reg + (with-editor-emacsclient-version exec))))) + (and (> depth 1) + (with-editor-locate-emacsclient-1 path (1- depth)))))) + +(defun with-editor-emacsclient-version (exec) + (-when-let (1st-line (car (process-lines exec "--version"))) + (cadr (split-string 1st-line)))) + +(defun with-editor-emacsclient-path () + (let ((path exec-path)) + (when invocation-directory + (push (directory-file-name invocation-directory) path) + (let* ((linkname (expand-file-name invocation-name invocation-directory)) + (truename (file-chase-links linkname))) + (unless (equal truename linkname) + (push (directory-file-name (file-name-directory truename)) path))) + (when (eq system-type 'darwin) + (let ((dir (expand-file-name "bin" invocation-directory))) + (when (file-directory-p dir) + (push dir path))) + (when (string-match-p "Cellar" invocation-directory) + (let ((dir (expand-file-name "../../../bin" invocation-directory))) + (when (file-directory-p dir) + (push dir path)))))) + (cl-remove-duplicates path :test 'equal))) + +(defcustom with-editor-emacsclient-executable (with-editor-locate-emacsclient) + "The Emacsclient executable used by the `with-editor' macro." + :group 'with-editor + :type '(choice (string :tag "Executable") + (const :tag "Don't use Emacsclient" nil))) + +(defcustom with-editor-sleeping-editor "\ +sh -c '\ +echo \"WITH-EDITOR: $$ OPEN $0\"; \ +sleep 604800 & sleep=$!; \ +trap \"kill $sleep; exit 0\" USR1; \ +trap \"kill $sleep; exit 1\" USR2; \ +wait $sleep'" + "The sleeping editor, used when the Emacsclient cannot be used. + +This fallback is used for asynchronous process started inside the +macro `with-editor', when the process runs on a remote machine or +for local processes when `with-editor-emacsclient-executable' is +nil (i.e. when no suitable Emacsclient was found, or the user +decided not to use it). + +Where the latter uses a socket to communicate with Emacs' server, +this substitute prints edit requests to its standard output on +which a process filter listens for such requests. As such it is +not a complete substitute for a proper Emacsclient, it can only +be used as $EDITOR of child process of the current Emacs instance." + :group 'with-editor + :type 'string) + +(defcustom with-editor-finish-query-functions nil + "List of functions called to query before finishing session. + +The buffer in question is current while the functions are called. +If any of them returns nil, then the session is not finished and +the buffer is not killed. The user should then fix the issue and +try again. The functions are called with one argument. If it is +non-nil then that indicates that the user used a prefix argument +to force finishing the session despite issues. Functions should +usually honor that and return non-nil." + :group 'with-editor + :type 'hook) +(put 'with-editor-finish-query-functions 'permanent-local t) + +(defcustom with-editor-cancel-query-functions nil + "List of functions called to query before canceling session. + +The buffer in question is current while the functions are called. +If any of them returns nil, then the session is not canceled and +the buffer is not killed. The user should then fix the issue and +try again. The functions are called with one argument. If it is +non-nil then that indicates that the user used a prefix argument +to force canceling the session despite issues. Functions should +usually honor that and return non-nil." + :group 'with-editor + :type 'hook) +(put 'with-editor-cancel-query-functions 'permanent-local t) + +(defcustom with-editor-mode-lighter " WE" + "The mode-line lighter of the With-Editor mode." + :group 'with-editor + :type '(choice (const :tag "No lighter" "") string)) + +(defvar with-editor-server-window-alist nil + "Alist of filename patterns vs corresponding `server-window'. + +Each element looks like (REGEXP . FUNCTION). Files matching +REGEXP are selected using FUNCTION instead of the default in +`server-window'. + +Note that when a package adds an entry here then it probably +has a reason to disrespect `server-window' and it likely is +not a good idea to change such entries.") + +;;; Mode Commands + +(defvar with-editor-pre-finish-hook nil) +(defvar with-editor-pre-cancel-hook nil) +(defvar with-editor-post-finish-hook nil) +(defvar with-editor-post-finish-hook-1 nil) +(defvar with-editor-post-cancel-hook nil) +(defvar with-editor-post-cancel-hook-1 nil) +(defvar with-editor-cancel-alist nil) +(put 'with-editor-pre-finish-hook 'permanent-local t) +(put 'with-editor-pre-cancel-hook 'permanent-local t) +(put 'with-editor-post-finish-hook 'permanent-local t) +(put 'with-editor-post-cancel-hook 'permanent-local t) + +(defvar with-editor-show-usage t) +(defvar with-editor-cancel-message nil) +(defvar with-editor-previous-winconf nil) +(make-variable-buffer-local 'with-editor-show-usage) +(make-variable-buffer-local 'with-editor-cancel-message) +(make-variable-buffer-local 'with-editor-previous-winconf) +(put 'with-editor-cancel-message 'permanent-local t) +(put 'with-editor-previous-winconf 'permanent-local t) + +(defvar-local with-editor--pid nil "For internal use.") +(put 'with-editor--pid 'permanent-local t) + +(defun with-editor-finish (force) + "Finish the current edit session." + (interactive "P") + (when (run-hook-with-args-until-failure + 'with-editor-finish-query-functions force) + (let ((with-editor-post-finish-hook-1 + (ignore-errors (delq t with-editor-post-finish-hook)))) + (run-hooks 'with-editor-pre-finish-hook) + (with-editor-return nil) + (accept-process-output nil 0.1) + (run-hooks 'with-editor-post-finish-hook-1)))) + +(defun with-editor-cancel (force) + "Cancel the current edit session." + (interactive "P") + (when (run-hook-with-args-until-failure + 'with-editor-cancel-query-functions force) + (let ((message with-editor-cancel-message)) + (when (functionp message) + (setq message (funcall message))) + (let ((with-editor-post-cancel-hook-1 + (ignore-errors (delq t with-editor-post-cancel-hook))) + (with-editor-cancel-alist nil)) + (run-hooks 'with-editor-pre-cancel-hook) + (with-editor-return t) + (accept-process-output nil 0.1) + (run-hooks 'with-editor-post-cancel-hook-1)) + (message (or message "Canceled by user"))))) + +(defun with-editor-return (cancel) + (let ((winconf with-editor-previous-winconf) + (clients server-buffer-clients) + (dir default-directory) + (pid with-editor--pid)) + (remove-hook 'kill-buffer-query-functions + 'with-editor-kill-buffer-noop t) + (cond (cancel + (save-buffer) + (if clients + (dolist (client clients) + (ignore-errors + (server-send-string client "-error Canceled by user")) + (delete-process client)) + ;; Fallback for when emacs was used as $EDITOR instead + ;; of emacsclient or the sleeping editor. See #2258. + (ignore-errors (delete-file buffer-file-name)) + (kill-buffer))) + (t + (save-buffer) + (if clients + ;; Don't use `server-edit' because we do not want to show + ;; another buffer belonging to another client. See #2197. + (server-done) + (kill-buffer)))) + (when pid + (let ((default-directory dir)) + (process-file "kill" nil nil nil + "-s" (if cancel "USR2" "USR1") pid))) + (when (and winconf (eq (window-configuration-frame winconf) + (selected-frame))) + (set-window-configuration winconf)))) + +;;; Mode + +(defvar with-editor-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\C-c\C-c" 'with-editor-finish) + (define-key map [remap server-edit] 'with-editor-finish) + (define-key map "\C-c\C-k" 'with-editor-cancel) + (define-key map [remap kill-buffer] 'with-editor-cancel) + (define-key map [remap ido-kill-buffer] 'with-editor-cancel) + (define-key map [remap iswitchb-kill-buffer] 'with-editor-cancel) + map)) + +(define-minor-mode with-editor-mode + "Edit a file as the $EDITOR of an external process." + :lighter with-editor-mode-lighter + ;; Protect the user from killing the buffer without using + ;; either `with-editor-finish' or `with-editor-cancel', + ;; and from removing the key bindings for these commands. + (unless with-editor-mode + (error "With-Editor mode cannot be turned off")) + (add-hook 'kill-buffer-query-functions + 'with-editor-kill-buffer-noop nil t) + ;; `server-execute' displays a message which is not + ;; correct when using this mode. + (when with-editor-show-usage + (with-editor-usage-message))) + +(put 'with-editor-mode 'permanent-local t) + +(defun with-editor-kill-buffer-noop () + (message (substitute-command-keys "\ +Don't kill this buffer. Instead cancel using \\[with-editor-cancel]"))) + +(defun with-editor-usage-message () + ;; Run after `server-execute', which is run using + ;; a timer which starts immediately. + (run-with-timer + 0.01 nil `(lambda () + (with-current-buffer ,(current-buffer) + (message (substitute-command-keys "\ +Type \\[with-editor-finish] to finish, \ +or \\[with-editor-cancel] to cancel")))))) + +;;; Wrappers + +(defvar with-editor--envvar nil "For internal use.") + +(defmacro with-editor (&rest body) + "Use the Emacsclient as $EDITOR while evaluating BODY. +Modify the `process-environment' for processes started in BODY, +instructing them to use the Emacsclient as $EDITOR. If optional +ENVVAR is provided then bind that environment variable instead. +\n(fn [ENVVAR] BODY...)" + (declare (indent defun) (debug (body))) + `(let ((with-editor--envvar ,(if (stringp (car body)) + (pop body) + '(or with-editor--envvar "EDITOR"))) + (process-environment process-environment)) + (if (or (not with-editor-emacsclient-executable) + (file-remote-p default-directory)) + (setenv with-editor--envvar with-editor-sleeping-editor) + ;; Make sure server-use-tcp's value is valid. + (unless (featurep 'make-network-process '(:family local)) + (setq server-use-tcp t)) + ;; Make sure the server is running. + (unless server-process + (when (server-running-p server-name) + (setq server-name (format "server%s" (emacs-pid))) + (when (server-running-p server-name) + (server-force-delete server-name))) + (server-start)) + ;; Tell $EDITOR to use the Emacsclient. + (setenv with-editor--envvar + (concat (shell-quote-argument with-editor-emacsclient-executable) + ;; Tell the process where the server file is. + (and (not server-use-tcp) + (concat " --socket-name=" + (shell-quote-argument + (expand-file-name server-name + server-socket-dir)))))) + (when server-use-tcp + (setenv "EMACS_SERVER_FILE" + (expand-file-name server-name server-auth-dir))) + ;; As last resort fallback to the sleeping editor. + (setenv "ALTERNATE_EDITOR" with-editor-sleeping-editor)) + ,@body)) + +(defun with-editor-server-window () + (or (and buffer-file-name + (cdr (--first (string-match-p (car it) buffer-file-name) + with-editor-server-window-alist))) + server-window)) + +(defun server-switch-buffer--with-editor-server-window-alist + (fn &optional next-buffer killed-one filepos) + "Honor `with-editor-server-window-alist' (which see)." + (let ((server-window (with-current-buffer + (or next-buffer (current-buffer)) + (when with-editor-mode + (setq with-editor-previous-winconf + (current-window-configuration))) + (with-editor-server-window)))) + (funcall fn next-buffer killed-one filepos))) + +(advice-add 'server-switch-buffer :around + 'server-switch-buffer--with-editor-server-window-alist) + +(defun start-file-process--with-editor-process-filter + (fn name buffer program &rest program-args) + "When called inside a `with-editor' form and the Emacsclient +cannot be used, then give the process the filter function +`with-editor-process-filter'. To avoid overriding the filter +being added here you should use `with-editor-set-process-filter' +instead of `set-process-filter' inside `with-editor' forms. + +When the `default-directory' is located on a remote machine, +then also manipulate PROGRAM and PROGRAM-ARGS in order to set +the appropriate editor environment variable." + (if (not with-editor--envvar) + (apply fn name buffer program program-args) + (when (file-remote-p default-directory) + (unless (equal program "env") + (push program program-args) + (setq program "env")) + (push (concat with-editor--envvar "=" with-editor-sleeping-editor) + program-args)) + (let ((process (apply fn name buffer program program-args))) + (set-process-filter process 'with-editor-process-filter) + (process-put process 'default-dir default-directory) + process))) + +(advice-add 'start-file-process :around + 'start-file-process--with-editor-process-filter) + +(defun with-editor-set-process-filter (process filter) + "Like `set-process-filter' but keep `with-editor-process-filter'. +Give PROCESS the new FILTER but keep `with-editor-process-filter' +if that was added earlier by the adviced `start-file-process'. + +Do so by wrapping the two filter functions using a lambda, which +becomes the actual filter. It calls `with-editor-process-filter' +first, passing t as NO-STANDARD-FILTER. Then it calls FILTER, +which may or may not insert the text into the PROCESS' buffer." + (set-process-filter + process + (if (eq (process-filter process) 'with-editor-process-filter) + `(lambda (proc str) + (,filter proc str) + (with-editor-process-filter proc str t)) + filter))) + +(defvar with-editor-filter-visit-hook nil) + +(defun with-editor-output-filter (string) + (save-match-data + (if (string-match "^WITH-EDITOR: \\([0-9]+\\) OPEN \\(.+?\\)\r?$" string) + (let ((pid (match-string 1 string)) + (file (match-string 2 string))) + (with-current-buffer + (find-file-noselect + (if (file-name-absolute-p file) + (if (tramp-tramp-file-p default-directory) + (with-parsed-tramp-file-name default-directory nil + (tramp-make-tramp-file-name method user host file hop)) + file) + (expand-file-name file))) + (with-editor-mode 1) + (setq with-editor--pid pid) + (run-hooks 'with-editor-filter-visit-hook) + (funcall (or (with-editor-server-window) 'switch-to-buffer) + (current-buffer)) + (kill-local-variable 'server-window)) + nil) + string))) + +(defun with-editor-process-filter + (process string &optional no-default-filter) + "Listen for edit requests by child processes." + (let ((default-directory (process-get process 'default-dir))) + (with-editor-output-filter string)) + (unless no-default-filter + (internal-default-process-filter process string))) + +;;; Augmentations + +(cl-defun with-editor-export-editor (&optional (envvar "EDITOR")) + "Teach subsequent commands to use current Emacs instance as editor. + +Set and export the environment variable ENVVAR, by default +\"EDITOR\". The value is automatically generated to teach +commands use the current Emacs instance as \"the editor\". + +This works in `shell-mode', `term-mode' and `eshell-mode'." + (interactive (list (with-editor-read-envvar))) + (cond + ((derived-mode-p 'comint-mode 'term-mode) + (let* ((process (get-buffer-process (current-buffer))) + (filter (process-filter process))) + (set-process-filter process 'ignore) + (goto-char (process-mark process)) + (process-send-string + process (format "export %s=%s\n" envvar + (shell-quote-argument with-editor-sleeping-editor))) + (while (accept-process-output process 0.1)) + (set-process-filter process filter) + (if (derived-mode-p 'term-mode) + (with-editor-set-process-filter process 'with-editor-emulate-terminal) + (add-hook 'comint-output-filter-functions 'with-editor-output-filter + nil t)))) + ((derived-mode-p 'eshell-mode) + (add-to-list 'eshell-preoutput-filter-functions + 'with-editor-output-filter) + (setenv envvar with-editor-sleeping-editor)) + (t + (error "Cannot export environment variables in this buffer"))) + (message "Successfully exported %s" envvar)) + +(defun with-editor-export-git-editor () + "Like `with-editor-export-editor' but always set `$GIT_EDITOR'." + (interactive) + (with-editor-export-editor "GIT_EDITOR")) + +(defun with-editor-export-hg-editor () + "Like `with-editor-export-editor' but always set `$HG_EDITOR'." + (interactive) + (with-editor-export-editor "HG_EDITOR")) + +(defun with-editor-emulate-terminal (process string) + "Like `term-emulate-terminal' but also handle edit requests." + (when (with-editor-output-filter string) + (term-emulate-terminal process string))) + +(defvar with-editor-envvars '("EDITOR" "GIT_EDITOR" "HG_EDITOR")) + +(cl-defun with-editor-read-envvar + (&optional (prompt "Set environment variable") + (default "EDITOR")) + (let ((reply (completing-read (if default + (format "%s (%s): " prompt default) + (concat prompt ": ")) + with-editor-envvars nil nil nil nil default))) + (if (string= reply "") (user-error "Nothing selected") reply))) + +(define-minor-mode shell-command-with-editor-mode + "Teach `shell-command' to use current Emacs instance as editor. + +Teach `shell-command', and all commands that ultimately call that +command, to use the current Emacs instance as editor by executing +\"EDITOR=CLIENT COMMAND&\" instead of just \"COMMAND&\". + +CLIENT is automatically generated; EDITOR=CLIENT instructs +COMMAND to use to the current Emacs instance as \"the editor\", +assuming no other variable overrides the effect of \"$EDITOR\". +CLIENT may be the path to an appropriate emacsclient executable +with arguments, or a script which also works over Tramp. + +Alternatively you can use the `with-editor-async-shell-command', +which also allows the use of another variable instead of +\"EDITOR\"." + :global t) + +(defun with-editor-async-shell-command + (command &optional output-buffer error-buffer envvar) + "Like `async-shell-command' but with `$EDITOR' set. + +Execute string \"ENVVAR=CLIENT COMMAND\" in an inferior shell; +display output, if any. With a prefix argument prompt for an +environment variable, otherwise the default \"EDITOR\" variable +is used. With a negative prefix argument additionally insert +the COMMAND's output at point. + +CLIENT is automatically generated; ENVVAR=CLIENT instructs +COMMAND to use to the current Emacs instance as \"the editor\", +assuming it respects ENVVAR as an \"EDITOR\"-like variable. +CLIENT maybe the path to an appropriate emacsclient executable +with arguments, or a script which also works over Tramp. + +Also see `async-shell-command' and `shell-command'." + (interactive (with-editor-shell-command-read-args "Async shell command: " t)) + (let ((with-editor--envvar envvar)) + (with-editor + (async-shell-command command output-buffer error-buffer)))) + +(defun with-editor-shell-command + (command &optional output-buffer error-buffer envvar) + "Like `shell-command' or `with-editor-async-shell-command'. +If COMMAND ends with \"&\" behave like the latter, +else like the former." + (interactive (with-editor-shell-command-read-args "Shell command: ")) + (if (string-match "&[ \t]*\\'" command) + (with-editor-async-shell-command + command output-buffer error-buffer envvar) + (shell-command command output-buffer error-buffer))) + +(defun with-editor-shell-command-read-args (prompt &optional async) + (let ((command (read-shell-command + prompt nil nil + (--when-let (or buffer-file-name + (and (eq major-mode 'dired-mode) + (dired-get-filename nil t))) + (file-relative-name it))))) + (list command + (if (or async (setq async (string-match-p "&[ \t]*\\'" command))) + (< (prefix-numeric-value current-prefix-arg) 0) + current-prefix-arg) + shell-command-default-error-buffer + (and async current-prefix-arg (with-editor-read-envvar))))) + +(defun shell-command--shell-command-with-editor-mode + (fn command &optional output-buffer error-buffer) + (cond ((or (not (or with-editor--envvar shell-command-with-editor-mode)) + (not (string-match-p "&\\'" command))) + (funcall fn command output-buffer error-buffer)) + ((and with-editor-emacsclient-executable + (not (file-remote-p default-directory))) + (with-editor (funcall fn command output-buffer error-buffer))) + (t + (apply fn (format "%s=%s %s" + (or with-editor--envvar "EDITOR") + (shell-quote-argument with-editor-sleeping-editor) + command) + output-buffer error-buffer) + (ignore-errors + (let ((process (get-buffer-process + (or output-buffer + (get-buffer "*Async Shell Command*"))))) + (set-process-filter + process (lambda (proc str) + (comint-output-filter proc str) + (with-editor-process-filter proc str t))) + process))))) + +(advice-add 'shell-command :around + 'shell-command--shell-command-with-editor-mode) + +;;; with-editor.el ends soon + +(defun with-editor-debug () + "Debug configuration issues. +See `with-editor.info' for instructions." + (interactive) + (with-current-buffer (get-buffer-create "*with-editor-debug*") + (pop-to-buffer (current-buffer)) + (erase-buffer) + (ignore-errors (with-editor)) + (insert + (format "with-editor: %s\n" (locate-library "with-editor.el")) + (format "emacs: %s (%s)\n" + (expand-file-name invocation-name invocation-directory) + emacs-version) + "system:\n" + (format " system-type: %s\n" system-type) + (format " system-configuration: %s\n" system-configuration) + (format " system-configuration-options: %s\n" system-configuration-options) + "server:\n" + (format " server-running-p: %s\n" (server-running-p)) + (format " server-process: %S\n" server-process) + (format " server-use-tcp: %s\n" server-use-tcp) + (format " server-name: %s\n" server-name) + (format " server-socket-dir: %s\n" server-socket-dir)) + (if (and server-socket-dir (file-accessible-directory-p server-socket-dir)) + (--each (directory-files server-socket-dir nil "^[^.]") + (insert (format " %s\n" it))) + (insert (format " %s: not an accessible directory\n" + (if server-use-tcp "WARNING" "ERROR")))) + (insert (format " server-auth-dir: %s\n" server-auth-dir)) + (if (file-accessible-directory-p server-auth-dir) + (--each (directory-files server-auth-dir nil "^[^.]") + (insert (format " %s\n" it))) + (insert (format " %s: not an accessible directory\n" + (if server-use-tcp "ERROR" "WARNING")))) + (let ((val with-editor-emacsclient-executable) + (def (default-value 'with-editor-emacsclient-executable)) + (fun (let ((warning-minimum-level :error) + (warning-minimum-log-level :error)) + (with-editor-locate-emacsclient)))) + (insert "magit-emacsclient-executable:\n" + (format " value: %s (%s)\n" val + (and val (with-editor-emacsclient-version val))) + (format " default: %s (%s)\n" def + (and def (with-editor-emacsclient-version def))) + (format " funcall: %s (%s)\n" fun + (and fun (with-editor-emacsclient-version fun))))) + (insert "path:\n" + (format " $PATH: %S\n" (getenv "PATH")) + (format " exec-path: %s\n" exec-path)) + (insert (format " with-editor-emacsclient-path:\n")) + (--each (with-editor-emacsclient-path) + (insert (format " %s (%s)\n" it (car (file-attributes it)))) + (when (file-directory-p it) + (dolist (exec (directory-files it t "emacsclient")) + (insert (format " %s (%s)\n" exec + (with-editor-emacsclient-version exec)))))))) + +(defconst with-editor-font-lock-keywords + '(("(\\(with-\\(?:git-\\)?editor\\)\\_>" (1 'font-lock-keyword-face)))) +(font-lock-add-keywords 'emacs-lisp-mode with-editor-font-lock-keywords) + +(provide 'with-editor) +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; with-editor.el ends here diff --git a/elpa/with-editor-20151223.1341/with-editor.info b/elpa/with-editor-20151223.1341/with-editor.info new file mode 100644 index 00000000..ea246fa9 --- /dev/null +++ b/elpa/with-editor-20151223.1341/with-editor.info @@ -0,0 +1,323 @@ +This is with-editor.info, produced by makeinfo version 5.2 from +with-editor.texi. + +The library ‘with-editor’ makes it easy to use the Emacsclient as the +‘$EDITOR’ of child processes, making sure they know how to call home. +For remote processes a substitute is provided, which communicates with +Emacs on standard output instead of using a socket as the Emacsclient +does. + + This library was written because Magit has to be able to do the above +to allow the user to edit commit messages gracefully and to edit rebase +sequences, which wouldn’t be possible at all otherwise. + + Because other packages can benefit from such functionality, this +library is made available as a separate package. It also defines some +additional functionality which makes it useful even for end-users, who +don’t use Magit or another package which uses it internally. + + Copyright (C) 2015 Jonas Bernoulli + + You can redistribute this document 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 document 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. +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* With-Editor: (with-editor). Using the Emacsclient as $EDITOR. +END-INFO-DIR-ENTRY + + +File: with-editor.info, Node: Top, Next: Using the With-Editor package, Up: (dir) + +With-Editor User Manual +*********************** + +The library ‘with-editor’ makes it easy to use the Emacsclient as the +‘$EDITOR’ of child processes, making sure they know how to call home. +For remote processes a substitute is provided, which communicates with +Emacs on standard output instead of using a socket as the Emacsclient +does. + + This library was written because Magit has to be able to do the above +to allow the user to edit commit messages gracefully and to edit rebase +sequences, which wouldn’t be possible at all otherwise. + + Because other packages can benefit from such functionality, this +library is made available as a separate package. It also defines some +additional functionality which makes it useful even for end-users, who +don’t use Magit or another package which uses it internally. + + Copyright (C) 2015 Jonas Bernoulli + + You can redistribute this document 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 document 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. + +* Menu: + +* Using the With-Editor package:: +* Using With-Editor as a library:: +* Debugging:: + +— The Detailed Node Listing — + +Using the With-Editor package + +* Configuring With-Editor:: +* Using With-Editor commands:: + + + +File: with-editor.info, Node: Using the With-Editor package, Next: Using With-Editor as a library, Prev: Top, Up: Top + +1 Using the With-Editor package +******************************* + +The ‘With-Editor’ package is used internally by Magit when editing +commit messages and rebase sequences. It also provides some commands +and features which are useful by themselves, even if you don’t use +Magit. + + For information about using this library in you own package, see +*note Using With-Editor as a library: Using With-Editor as a library. + +* Menu: + +* Configuring With-Editor:: +* Using With-Editor commands:: + + +File: with-editor.info, Node: Configuring With-Editor, Next: Using With-Editor commands, Up: Using the With-Editor package + +1.1 Configuring With-Editor +=========================== + +With-Editor tries very hard to locate a suitable emacsclient executable, +so ideally you should never have to customize the option +‘with-editor-emacsclient-executable’. When it fails to do so, then the +most likely reason is that someone found yet another way to package +Emacs (most likely on OS X) without putting the executable on ‘$PATH’, +and we have to add another kludge to find it anyway. + + -- User Option: with-editor-emacsclient-executable + + The emacsclient executable used as the editor by child process of + this Emacs instance. By using this executable, child processes can + call home to their parent process. + + This option is automatically set at startup by looking in + ‘exec-path’, and other places where the executable could be + installed, to find the emacsclient executable most suitable for the + current emacs instance. + + You should *not* customize this option permanently. If you have to + do it, then you should consider that a temporary kludge and inform + the Magit maintainer as described in *note Debugging: Debugging. + + If With-Editor fails to find a suitable emacsclient on you system, + then this should be fixed for all users at once, by teaching + ‘with-editor-locate-emacsclient’ how to so on your system and + system like yours. Doing it this way has the advantage, that you + won’t have do it again every time you update Emacs, and that other + users who have installed Emacs the same way as you have, won’t have + to go through the same trouble. + + Note that there also is a nuclear option; setting this variable to + ‘nil’ causes the "sleeping editor" described below to be used even + for local child processes. Obviously we don’t recommend that you + use this except in "emergencies", i.e. before we had a change to + add a kludge appropriate for you setup. + + -- Function: with-editor-locate-emacsclient + + The function used to set the initial value of the option + ‘with-editor-emacsclient-executable’. There’s a lot of voodoo + here. + + The emacsclient cannot be used when using Tramp to run a process on a +remote machine. (Theoretically it could, but that would be hard to +setup, very fragile, and rather insecure). + + With-Editor provides an alternative "editor" which can be used by +remote processes in much the same way as local processes use an +emacsclient executable. This alternative is known as the "sleeping +editor" because it is implemented as a shell script which sleeps until +it receives a signal. + + -- User Option: with-editor-sleeping-editor + + The sleeping editor is a shell script used as the editor of child + processes when the emacsclient executable cannot be used. + + This fallback is used for asynchronous process started inside the + macro ‘with-editor’, when the process runs on a remote machine or + for local processes when ‘with-editor-emacsclient-executable’ is + ‘nil’. + + Where the latter uses a socket to communicate with Emacs’ server, + this substitute prints edit requests to its standard output on + which a process filter listens for such requests. As such it is + not a complete substitute for a proper Emacsclient, it can only be + used as ‘$EDITOR’ of child process of the current Emacs instance. + + It is unlikely that you should ever have to customize this option. + + +File: with-editor.info, Node: Using With-Editor commands, Prev: Configuring With-Editor, Up: Using the With-Editor package + +1.2 Using With-Editor commands +============================== + +This section describes how to use the ‘with-editor’ library _outside_ of +Magit. You don’t need to know any of this just to create commits using +Magit. + + The commands ‘with-editor-async-shell-command’ and +‘with-editor-shell-command’ are intended as drop in replacements for +‘async-shell-command’ and ‘shell-command’. They automatically export +‘$EDITOR’ making sure the executed command uses the current Emacs +instance as "the editor". With a prefix argument these commands prompt +for an alternative environment variable such as ‘$GIT_EDITOR’. + + -- Command: with-editor-async-shell-command + + Like ‘async-shell-command’, but the command is run with the current + Emacs instance exported as ‘$EDITOR’. + + -- Command: with-editor-shell-command + + Like ‘async-shell-command’, but the command is run with the current + Emacs instance exported as ‘$EDITOR’. This only has an effect if + the command is run asynchronously, i.e. when the command ends with + ‘&’. + + To always use these variants add this to you init file: + + (define-key (current-global-map) + [remap async-shell-command] 'with-editor-async-shell-command) + (define-key (current-global-map) + [remap shell-command] 'with-editor-shell-command) + + Alternatively use the global ‘shell-command-with-editor-mode’. + + -- Variable: shell-command-with-editor-mode + + When this mode is active, then ‘$EDITOR’ is exported whenever + ultimately ‘shell-command’ is called to asynchronously run some + shell command. This affects most variants of that command, whether + they are defined in Emacs or in some third-party package. + + The command ‘with-editor-export-editor’ exports ‘$EDITOR’ or another +such environment variable in ‘shell-mode’, ‘term-mode’ and ‘eshell-mode’ +buffers. Use this Emacs command before executing a shell command which +needs the editor set, or always arrange for the current Emacs instance +to be used as editor by adding it to the appropriate mode hooks: + + (add-hook 'shell-mode-hook 'with-editor-export-editor) + (add-hook 'term-mode-hook 'with-editor-export-editor) + (add-hook 'eshell-mode-hook 'with-editor-export-editor) + + Some variants of this function exist; these two forms are equivalent: + + (add-hook 'shell-mode-hook + (apply-partially 'with-editor-export-editor "GIT_EDITOR")) + (add-hook 'shell-mode-hook 'with-editor-export-git-editor) + + -- Command: with-editor-export-editor + + When invoked in a ‘shell-mode’, ‘term-mode’, or ‘eshell-mode’ + buffer, this command teaches shell commands to use the current + Emacs instance as the editor, by exporting ‘$EDITOR’. + + -- Command: with-editor-export-git-editor + + Like ‘with-editor-export-editor’ but exports ‘$GIT_EDITOR’. + + -- Command: with-editor-export-hg-editor + + Like ‘with-editor-export-editor’ but exports ‘$HG_EDITOR’. + + +File: with-editor.info, Node: Using With-Editor as a library, Next: Debugging, Prev: Using the With-Editor package, Up: Top + +2 Using With-Editor as a library +******************************** + +This section describes how to use the with-editor library _outside_ of +Magit to teach another package how to have its child processes call +home, just like Magit does. You don’t need to know any of this just to +create commits using Magit. You can also ignore this if you use +‘with-editor’ outside of Magit, but only as an end-user. + + For information about interactive use and options which affect both +interactive and non-interactive use, see *note Using the With-Editor +package: Using the With-Editor package. + + -- Macro: with-editor &rest body + + This macro arranges for the emacsclient or the sleeping editor to + be used as the editor of child processes, effectively teaching them + to call home to the current emacs instance when they require that + the user edits a file. + + This is essentially done by establishing a local binding for + ‘process-environment’ and changing the value of the ‘$EDITOR’ + environment variable. This affects all processes started by forms + inside BODY. + + -- Function: with-editor-set-process-filter process filter + + This function is like ‘set-process-filter’ but ensures that adding + the new FILTER does not remove the ‘with-editor-process-filter’. + This is done by wrapping the two filter functions using a lambda, + which becomes the actual filter. It calls + ‘with-editor-process-filter’ first, passing ‘t’ as + NO-STANDARD-FILTER. Then it calls FILTER. + + +File: with-editor.info, Node: Debugging, Prev: Using With-Editor as a library, Up: Top + +3 Debugging +*********** + +With-Editor tries very hard to locate a suitable emacsclient executable, +and then sets option ‘with-editor-emacsclient-executable’ accordingly. +In very rare cases this fails. When it does fail, then the most likely +reason is that someone found yet another way to package Emacs (most +likely on OS X) without putting the executable on ‘$PATH’, and we have +to add another kludge to find it anyway. + + If you are having problems using ‘with-editor’, e.g. you cannot +commit in Magit, then please open a new issue at + and provide information about +your Emacs installation. Most importantly how did you install Emacs and +what is the output of ‘M-x with-editor-debug’? + + + +Tag Table: +Node: Top1540 +Node: Using the With-Editor package3227 +Node: Configuring With-Editor3843 +Node: Using With-Editor commands7450 +Node: Using With-Editor as a library10613 +Node: Debugging12285 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/with-editor-readme.txt b/elpa/with-editor-readme.txt new file mode 100644 index 00000000..7c6c5597 --- /dev/null +++ b/elpa/with-editor-readme.txt @@ -0,0 +1,46 @@ +Use the Emacsclient as `$EDITOR' of child processes, making sure +they know how to call home. For remote processes a substitute is +provided, which communicates with Emacs on stdout instead of using +a socket as the Emacsclient does. + +The commands `with-editor-async-shell-command' and +`with-editor-shell-command' are intended as drop in replacements +for `async-shell-command' and `shell-command'. They automatically +export `$EDITOR' making sure the executed command uses the current +Emacs instance as "the editor". With a prefix argument these +commands prompt for an alternative environment variable such as +`$GIT_EDITOR'. To always use these variants add this to your init +file: + + (define-key (current-global-map) + [remap async-shell-command] 'with-editor-async-shell-command) + (define-key (current-global-map) + [remap shell-command] 'with-editor-shell-command) + +Alternatively use the global `shell-command-with-editor-mode', +which always sets `$EDITOR' for all Emacs commands which ultimately +use `shell-command' to asynchronously run some shell command. + +The command `with-editor-export-editor' exports `$EDITOR' or +another such environment variable in `shell-mode', `term-mode' and +`eshell-mode' buffers. Use this Emacs command before executing a +shell command which needs the editor set, or always arrange for the +current Emacs instance to be used as editor by adding it to the +appropriate mode hooks: + + (add-hook 'shell-mode-hook 'with-editor-export-editor) + (add-hook 'term-mode-hook 'with-editor-export-editor) + (add-hook 'eshell-mode-hook 'with-editor-export-editor) + +Some variants of this function exist, these two forms are +equivalent: + + (add-hook 'shell-mode-hook + (apply-partially 'with-editor-export-editor "GIT_EDITOR")) + (add-hook 'shell-mode-hook 'with-editor-export-git-editor) + +This library can also be used by other packages which need to use +the current Emacs instance as editor. In fact this library was +written for Magit and its `git-commit-mode' and `git-rebase-mode'. +Consult `git-rebase.el' and the related code in `magit-sequence.el' +for a simple example.