pax_global_header00006660000000000000000000000064122515617350014521gustar00rootroot0000000000000052 comment=0e3aa4a32931deb15d268649b6c08fc8c195266a git-cola-1.9.3/000077500000000000000000000000001225156173500132325ustar00rootroot00000000000000git-cola-1.9.3/.gitignore000066400000000000000000000002011225156173500152130ustar00rootroot00000000000000/git-cola.app /build /config.mak /dist /Meta /share/locale /test/tmp /tags .DS_Store .noseids *.gz *.py[cod] *.qm *.swp *.zip *~ git-cola-1.9.3/.mailmap000066400000000000000000000001211225156173500146450ustar00rootroot00000000000000David Martínez Martí David Aguilar git-cola-1.9.3/CONTRIBUTING.md000066400000000000000000000124271225156173500154710ustar00rootroot00000000000000# CONTRIBUTING GUIDELINES Here are some guidelines for people who want to contribute their code to this software. ## Make separate commits for logically separate changes. ## Be picky about whitespace This project is very picky about code style. The style here is the standard Python PEP-8 style: http://www.python.org/dev/peps/pep-0008/ * We use 4-space indents. * We use variable_names_with_underscores. No camelCase. The only exception is when overriding Qt functions. * Do not introduce trailing whitespace. The "Diff" viewer displays trailing whitespace in red, or you can use "git diff --check". * Generally, follow the same style as the existing code. ## Describe your changes well. The first line of the commit message should be a short description (50 characters is the soft limit, see DISCUSSION in git-commit(1)), and should skip the full stop. It is also conventional in most cases to prefix the first line with "area: " where the area is a filename or identifier for the general area of the code being modified, e.g. * push: allow pushing to multiple remotes * grep: allow passing in command-line arguments If in doubt which identifier to use, run "git log --no-merges" on the files you are modifying to see the current conventions. The body should provide a meaningful commit message, which: * explains the problem the change tries to solve, iow, what is wrong with the current code without the change. * justifies the way the change solves the problem, iow, why the result with the change is better. * alternate solutions considered but discarded, if any. Describe your changes in imperative mood, e.g. "make xyzzy do frotz" instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy to do frotz", as if you are giving orders to the codebase to change its behaviour. Try to make sure your explanation can be understood without external resources. Instead of giving a URL to a mailing list archive, summarize the relevant points of the discussion. If you like, you can put extra tags at the end: * "Reported-by:" is used to credit someone who found the bug that the patch attempts to fix. * "Acked-by:" says that the person who is more familiar with the area the patch attempts to modify liked the patch. * "Reviewed-by:", unlike the other tags, can only be offered by the reviewer and means that she is completely satisfied that the patch is ready for application. It is usually offered only after a detailed review. * "Tested-by:" is used to indicate that the person applied the patch and found it to have the desired effect. You can also create your own tag or use one that's in common usage such as "Thanks-to:", "Based-on-patch-by:", or "Helped-by:". ## Sign your work To improve tracking of who did what, we've borrowed the "sign-off" procedure from the Linux kernel project on patches that are being emailed around. Although core Git is a lot smaller project it is a good discipline to follow it. The sign-off is a simple line at the end of the explanation for the patch, which certifies that you wrote it or otherwise have the right to pass it on as a open-source patch. The rules are pretty simple: if you can certify the below: Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. then you just add a line saying Signed-off-by: Random J Developer This line can be automatically added by Git if you run the git-commit command with the -s option. Notice that you can place your own Signed-off-by: line when forwarding somebody else's patch with the above rules for D-C-O. Indeed you are encouraged to do so. Do not forget to place an in-body "From: " line at the beginning to properly attribute the change to its true author (see (2) above). Also notice that a real name is used in the Signed-off-by: line. Please don't hide your real name. ## Fork the repo on Github and create a pull request. git-cola-1.9.3/COPYING000066400000000000000000000431031225156173500142660ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. 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 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. git-cola-1.9.3/COPYRIGHT000066400000000000000000000001511225156173500145220ustar00rootroot00000000000000Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 David Aguilar and contributors git-cola-1.9.3/Makefile000066400000000000000000000072741225156173500147040ustar00rootroot00000000000000# The default target of this Makefile is... all:: # The external commands used by this Makefile are... CTAGS = ctags CP = cp FIND = find GIT = git GZIP = gzip LN = ln MKDIR_P = mkdir -p NOSETESTS = nosetests PYTHON = python RM = rm -f RM_R = rm -fr RMDIR = rmdir TAR = tar # These values can be overridden on the command-line or via config.mak prefix = $(HOME) bindir = $(prefix)/bin coladir = $(prefix)/share/git-cola/lib darwin_python = /System/Library/Frameworks/Python.framework/Resources/Python.app/Contents/MacOS/Python # DESTDIR = cola_base := git-cola cola_app_base= $(cola_base).app cola_app = $(CURDIR)/$(cola_app_base) cola_version = $(shell $(PYTHON) bin/git-cola version --brief) cola_dist := $(cola_base)-$(cola_version) test_flags = all_test_flags = --with-doctest --exclude=sphinxtogithub $(test_flags) # User customizations -include config.mak setup_args = --prefix=$(prefix) setup_args += --quiet setup_args += --force setup_args += --install-scripts=$(bindir) setup_args += --record=build/MANIFEST setup_args += --install-lib=$(coladir) ifdef DESTDIR setup_args += --root=$(DESTDIR) export DESTDIR endif all:: $(PYTHON) setup.py build install: all $(PYTHON) setup.py install $(setup_args) (cd $(DESTDIR)$(bindir) && \ ! test -e cola && $(LN) -s git-cola cola) || true $(RM_R) $(DESTDIR)$(coladir)/git_cola* $(RM_R) git_cola.egg-info # Maintainer's dist target dist: $(GIT) archive --format=tar --prefix=$(cola_dist)/ HEAD^{tree} | \ $(GZIP) -f -9 - >$(cola_dist).tar.gz doc: $(MAKE) -C share/doc/git-cola prefix=$(prefix) all html: $(MAKE) -C share/doc/git-cola prefix=$(prefix) html install-doc: $(MAKE) -C share/doc/git-cola prefix=$(prefix) install install-html: $(MAKE) -C share/doc/git-cola prefix=$(prefix) install-html uninstall: $(RM) $(DESTDIR)$(prefix)/bin/git-cola $(RM) $(DESTDIR)$(prefix)/bin/git-dag $(RM) $(DESTDIR)$(prefix)/bin/cola $(RM) $(DESTDIR)$(prefix)/share/applications/git-cola.desktop $(RM) $(DESTDIR)$(prefix)/share/applications/git-dag.desktop $(RM_R) $(DESTDIR)$(prefix)/share/git-cola $(RM_R) $(DESTDIR)$(prefix)/share/doc/git-cola $(RM) $(DESTDIR)$(prefix)/share/locale/*/LC_MESSAGES/git-cola.mo $(RMDIR) $(DESTDIR)$(prefix)/share/locale/*/LC_MESSAGES 2>/dev/null || true $(RMDIR) $(DESTDIR)$(prefix)/share/locale/* 2>/dev/null || true $(RMDIR) $(DESTDIR)$(prefix)/share/locale 2>/dev/null || true $(RMDIR) $(DESTDIR)$(prefix)/share/doc 2>/dev/null || true $(RMDIR) $(DESTDIR)$(prefix)/share/applications 2>/dev/null || true $(RMDIR) $(DESTDIR)$(prefix)/share 2>/dev/null || true $(RMDIR) $(DESTDIR)$(prefix)/bin 2>/dev/null || true $(RMDIR) $(DESTDIR)$(prefix) 2>/dev/null || true test: all $(NOSETESTS) $(all_test_flags) coverage: $(NOSETESTS) --with-coverage --cover-package=cola $(all_test_flags) clean: $(MAKE) -C share/doc/git-cola clean $(FIND) . -name .noseids -print0 | xargs -0 rm -f $(FIND) . -name '*.py[co]' -print0 | xargs -0 rm -f $(RM_R) build dist tmp tags git-cola.app $(RM_R) share/locale tags: $(FIND) . -name '*.py' -print0 | xargs -0 $(CTAGS) -f tags pot: $(PYTHON) setup.py build_pot -N -d . mo: $(PYTHON) setup.py build_mo -f git-cola.app: $(MKDIR_P) $(cola_app)/Contents/MacOS $(MKDIR_P) $(cola_app)/Contents/Resources $(CP) contrib/darwin/Info.plist darwin/PkgInfo $(cola_app)/Contents $(CP) contrib/darwin/git-cola $(cola_app)/Contents/MacOS $(CP) contrib/darwin/git-cola.icns $(cola_app)/Contents/Resources $(MAKE) prefix=$(cola_app)/Contents/Resources install install-doc $(LN) -sf $(darwin_python) $(cola_app)/Contents/Resources/git-cola app-tarball: git-cola.app $(TAR) czf $(cola_dist).app.tar.gz $(cola_app_base) .PHONY: all install doc install-doc install-html test clean tags .PHONY: git-cola.app app-tarball git-cola-1.9.3/README.md000066400000000000000000000100521225156173500145070ustar00rootroot00000000000000# git-cola: The highly caffeinated git GUI git-cola is a powerful Git GUI with a slick and intuitive user interface. Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 David Aguilar and contributors This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ## SCREENSHOTS Screenshots are available on the [git-cola screenshots page](http://git-cola.github.io/screenshots.html). ## DOWNLOAD apt-get install git-cola python-pyinotify New releases are available on the [git-cola download page](http://git-cola.github.io/downloads.html). ## FORK git clone git://github.com/git-cola/git-cola.git [git-cola on github](https://github.com/git-cola/git-cola) [git-cola google group](http://groups.google.com/group/git-cola/) # NUTRITIONAL FACTS ## ACTIVE INGREDIENTS * [git](http://git-scm.com/) 1.6.3 or newer * [Python](http://python.org/) 2.5 through 2.7 * [PyQt4](http://www.riverbankcomputing.co.uk/software/pyqt/download) 4.4 or newer * [argparse](https://pypi.python.org/pypi/argparse) 1.1 or newer argparse is part of the stdlib in Python 2.7; install argparse separately if you are running on Python 2.6 or below. ## ADDITIVES [pyinotify](https://github.com/seb-m/pyinotify) 0.7.1 or newer enables inotify support on Linux. # BREWING INSTRUCTIONS Normally you can just do "make install" to install *git-cola* in your `$HOME` directory (`$HOME/bin`, `$HOME/share`, etc). If you want to do a global install you can do make prefix=/usr install You don't need to `make` to run it, though. *git-cola* is designed to run directly out of its source tree. bin/git-cola bin/git-dag ## LINUX Linux is it! Your distro has probably already packaged git-cola. If not, please file a bug against your distribution ;-) ### arch yaourt -S git-cola ### debian, ubuntu apt-get install git-cola ### fedora yum install git-cola ### gentoo emerge git-cola ### opensuse Use the [one-click install link](http://software.opensuse.org/package/git-cola). ## MAC OS X [Homebrew](http://mxcl.github.com/homebrew/) is the easiest way to install git-cola, *Qt4* and *PyQt4*. brew install git-cola Once brew has installed git-cola you can build a `git-cola.app` application bundle from source and copy it to `/Applications`. make git-cola.app ## WINDOWS INSTALLATION Download the latest stable Git, Python 2.x, and Py2x-PyQt4 installers * [msysGit](http://msysgit.github.com/) * [Python](http://python.org/download/) * [PyQt](http://www.riverbankcomputing.co.uk/software/pyqt/download/) * [git-cola Installer](https://github.com/git-cola/git-cola/downloads) Once these are installed you can run *git-cola* from the Start menu or by double-clicking on the `git-cola.pyw` script. If you are developing *git-cola* on Windows you can use `python.exe` to run *git-cola* directly from source. python.exe bin/git-cola If you want to build the `git-cola Installer` yourself run the provided script contrib/win32/create-installer.sh You have to make sure that the file /share/InnoSetup/ISCC.exe exists. That is normally the case when you run the *msysGit bash* and not the *Git for Windows bash* (look [here](http://msysgit.github.com/) for the differences). ## GOODIES *git-cola* ships with an interactive rebase editor called *git-xbase*. *git-xbase* can be used to reorder and choose commits and can be launched independently of the main *git-cola* interface, e.g.: GIT_SEQUENCE_EDITOR=$PWD/share/git-cola/bin/git-xbase git rebase -i master git-cola-1.9.3/bin/000077500000000000000000000000001225156173500140025ustar00rootroot00000000000000git-cola-1.9.3/bin/git-cola000077500000000000000000000242001225156173500154250ustar00rootroot00000000000000#!/usr/bin/env python # -*- python-mode -*- """git-cola: The highly caffeinated Git GUI """ __copyright__ = """ Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 David Aguilar and contributors This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. 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. """ import os import sys import subprocess from argparse import ArgumentParser from os.path import abspath from os.path import dirname from os.path import realpath def setup_environment(): """Provides access to the cola modules""" # Try to detect where it is run from and set prefix and the search path. # It is assumed that the user installed Cola using the --prefix= option prefix = dirname(dirname(realpath(abspath(__file__)))) # Look for modules in the source or install trees cola_mod = os.path.join(prefix, 'cola', '__init__.py') if os.path.exists(cola_mod): # Source tree sys.path.insert(1, prefix) else: # Install tree install_lib = os.path.join(prefix, 'share', 'git-cola', 'lib') sys.path.insert(1, install_lib) setup_environment() from cola import core from cola import cmds from cola.app import add_common_arguments from cola.app import application_init from cola.app import application_start def main(): # we're using argparse with subparser, but argparse # does not allow us to assign a default subparser # when none has been specified. We fake it by injecting # 'cola' into the command-line so that parse_args() # routes them to the 'cola' parser by default. if (len(sys.argv) < 2 or sys.argv[1].startswith('-') and sys.argv[1] not in ('-h', '--help')): sys.argv.insert(1, 'cola') args = parse_args() return args.func(args) def parse_args(): parser = ArgumentParser() subparser = parser.add_subparsers(title='valid commands') add_cola_command(subparser) add_archive_command(subparser) add_branch_command(subparser) add_browse_command(subparser) add_config_command(subparser) add_dag_command(subparser) add_diff_command(subparser) add_fetch_command(subparser) add_grep_command(subparser) add_merge_command(subparser) add_pull_command(subparser) add_push_command(subparser) add_rebase_command(subparser) add_remote_command(subparser) add_search_command(subparser) add_stash_command(subparser) add_tag_command(subparser) add_version_command(subparser) return parser.parse_args() def add_command(parent, name, description, func): parser = parent.add_parser(name, help=description) parser.set_defaults(func=func) add_common_arguments(parser) return parser def add_cola_command(subparser): parser = add_command(subparser, 'cola', 'start git-cola', cmd_cola) parser.add_argument('--amend', default=False, action='store_true', help='start in amend mode') def add_archive_command(parent): parser = add_command(parent, 'archive', 'save an archive', cmd_archive) parser.add_argument('ref', metavar='', nargs='?', default=None, help='SHA-1 to archive') def add_branch_command(subparser): add_command(subparser, 'branch', 'create a branch', cmd_branch) def add_browse_command(subparser): add_command(subparser, 'browse', 'browse repository', cmd_browse) add_command(subparser, 'classic', 'browse repository', cmd_browse) def add_config_command(subparser): add_command(subparser, 'config', 'edit configuration', cmd_config) def add_dag_command(subparser): parser = add_command(subparser, 'dag', 'start git-dag', cmd_dag) parser.add_argument('-c', '--count', metavar='', type=int, default=1000, help='number of commits to display') parser.add_argument('args', nargs='*', metavar='', help='git log arguments') def add_diff_command(subparser): parser = add_command(subparser, 'diff', 'view diffs', cmd_diff) parser.add_argument('args', nargs='*', metavar='', help='git diff arguments') def add_fetch_command(subparser): add_command(subparser, 'fetch', 'fetch remotes', cmd_fetch) def add_grep_command(subparser): parser = add_command(subparser, 'grep', 'grep source', cmd_grep) parser.add_argument('args', nargs='*', metavar='', help='git grep arguments') def add_merge_command(subparser): add_command(subparser, 'merge', 'merge branches', cmd_merge) def add_pull_command(subparser): parser = add_command(subparser, 'pull', 'pull remote branches', cmd_pull) parser.add_argument('--rebase', default=False, action='store_true', help='rebase local branch when pulling') def add_push_command(subparser): add_command(subparser, 'push', 'push remote branches', cmd_push) def add_rebase_command(subparser): parser = add_command(subparser, 'rebase', 'interactive rebase', cmd_rebase) parser.add_argument('branch', metavar='', help='New upstream branch') def add_remote_command(subparser): add_command(subparser, 'remote', 'edit remotes', cmd_remote) def add_search_command(subparser): add_command(subparser, 'search', 'search commits', cmd_search) def add_stash_command(subparser): add_command(subparser, 'stash', 'stash and unstash changes', cmd_stash) def add_tag_command(subparser): parser = add_command(subparser, 'tag', 'create tags', cmd_tag) parser.add_argument('name', metavar='', nargs='?', default=None, help='tag name') parser.add_argument('ref', metavar='', nargs='?', default=None, help='SHA-1 to tag') parser.add_argument('-s', '--sign', default=False, action='store_true', help='annotated and GPG-signed tag') def add_version_command(subparser): parser = add_command(subparser, 'version', 'print the version', cmd_version) parser.add_argument('--brief', action='store_true', default=False, help='print the version number only') # entry points def cmd_cola(args): context = application_init(args) from cola.widgets.main import MainView view = MainView(context.model) if args.amend: cmds.do(cmds.AmendMode, True) return application_start(context, view) def cmd_archive(args): context = application_init(args, update=True) if args.ref is None: args.ref = context.model.currentbranch from cola.widgets.archive import GitArchiveDialog view = GitArchiveDialog(args.ref) return application_start(context, view) def cmd_branch(args): context = application_init(args, update=True) from cola.widgets.createbranch import create_new_branch view = create_new_branch() return application_start(context, view) def cmd_browse(args): context = application_init(args) from cola.widgets.browse import worktree_browser view = worktree_browser(update=False) return application_start(context, view) def cmd_config(args): context = application_init(args) from cola.widgets.prefs import preferences view = preferences() return application_start(context, view) def cmd_dag(args): context = application_init(args) from cola.widgets.dag import git_dag view = git_dag(context.model, args=args) return application_start(context, view) def cmd_diff(args): context = application_init(args) from cola.difftool import diff_expression expr = subprocess.list2cmdline(map(core.decode, args.args)) view = diff_expression(None, expr, create_widget=True) return application_start(context, view) def cmd_fetch(args): # TODO: the calls to update_status() can be done asynchronously # by hooking into the message_updated notification. context = application_init(args) from cola.widgets import remote context.model.update_status() view = remote.fetch() return application_start(context, view) def cmd_grep(args): context = application_init(args) from cola.widgets import grep text = subprocess.list2cmdline(map(core.decode, args.args)) view = grep.run_grep(text=text, parent=None) return application_start(context, view) def cmd_merge(args): context = application_init(args, update=True) from cola.widgets.merge import MergeView view = MergeView(context.model, parent=None) return application_start(context, view) def cmd_version(args): from cola import version version.print_version(brief=args.brief) return 0 def cmd_pull(args): context = application_init(args, update=True) from cola.widgets import remote view = remote.pull() if args.rebase: view.set_rebase(True) return application_start(context, view) def cmd_push(args): context = application_init(args, update=True) from cola.widgets import remote view = remote.push() return application_start(context, view) def cmd_rebase(args): status, out, err = cmds.do(cmds.Rebase, args.branch) if out: core.stdout(out) if err: core.stderr(err) return status def cmd_remote(args): context = application_init(args) from cola.widgets import editremotes view = editremotes.edit() return application_start(context, view) def cmd_search(args): context = application_init(args) from cola.widgets.search import search view = search() return application_start(context, view) def cmd_stash(args): context = application_init(args) from cola.widgets.stash import stash view = stash() return application_start(context, view) def cmd_tag(args): context = application_init(args) from cola.widgets.createtag import create_tag view = create_tag(name=args.name, ref=args.ref, sign=args.sign) return application_start(context, view) if __name__ == '__main__': sys.exit(main()) git-cola-1.9.3/bin/git-dag000077500000000000000000000043501225156173500152460ustar00rootroot00000000000000#!/usr/bin/env python # -*- python-mode -*- """git-dag: An advanced git DAG visualizer """ __copyright__ = """ Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 David Aguilar and contributors This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. 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. """ import os import sys from argparse import ArgumentParser from os.path import abspath from os.path import dirname from os.path import realpath def setup_environment(): """Provides access to the cola modules""" # Try to detect where it is run from and set prefix and the search path. # It is assumed that the user installed Cola using the --prefix= option prefix = dirname(dirname(realpath(abspath(__file__)))) # Look for modules in the source or install trees cola_mod = os.path.join(prefix, 'cola', '__init__.py') if os.path.exists(cola_mod): # Source tree sys.path.insert(1, prefix) else: # Install tree install_lib = os.path.join(prefix, 'share', 'git-cola', 'lib') sys.path.insert(1, install_lib) setup_environment() from cola.app import add_common_arguments from cola.app import application_init from cola.app import application_start def main(): args = parse_args() return args.func(args) def parse_args(): parser = ArgumentParser() parser.set_defaults(func=dag) add_common_arguments(parser) parser.add_argument('-c', '--count', metavar='', type=int, default=1000, help='number of commits to display') parser.add_argument('args', nargs='*', metavar='', help='git log arguments') return parser.parse_args() def dag(args): context = application_init(args) from cola.widgets.dag import git_dag view = git_dag(context.model, args=args) return application_start(context, view) if __name__ == '__main__': sys.exit(main()) git-cola-1.9.3/cola/000077500000000000000000000000001225156173500141505ustar00rootroot00000000000000git-cola-1.9.3/cola/__init__.py000066400000000000000000000000001225156173500162470ustar00rootroot00000000000000git-cola-1.9.3/cola/_version.py000066400000000000000000000000611225156173500163430ustar00rootroot00000000000000# The current git-cola version VERSION = '1.9.3' git-cola-1.9.3/cola/app.py000066400000000000000000000217341225156173500153110ustar00rootroot00000000000000# Copyright (C) 2009, 2010, 2011, 2012, 2013 # David Aguilar """Provides the main() routine and ColaApplicaiton""" import glob import os import signal import sys # Make homebrew work by default if sys.platform == 'darwin': from distutils import sysconfig python_version = sysconfig.get_python_version() homebrew_mods = '/usr/local/lib/python%s/site-packages' % python_version if os.path.isdir(homebrew_mods): sys.path.append(homebrew_mods) try: from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import SIGNAL except ImportError: sys.stderr.write('Sorry, you do not seem to have PyQt4 installed.\n') sys.stderr.write('Please install it before using git-cola.\n') sys.stderr.write('e.g.: sudo apt-get install python-qt4\n') sys.exit(-1) # Import cola modules from cola import core from cola import compat from cola import git from cola import inotify from cola import i18n from cola import qtcompat from cola import qtutils from cola import resources from cola import utils from cola import version from cola.decorators import memoize from cola.interaction import Interaction from cola.models import main from cola.widgets import cfgactions from cola.widgets import startup def setup_environment(): # Spoof an X11 display for SSH os.environ.setdefault('DISPLAY', ':0') # Setup the path so that git finds us when we run 'git cola' path_entries = core.getenv('PATH', '').split(os.pathsep) bindir = os.path.dirname(core.abspath(__file__)) path_entries.insert(0, bindir) path = os.pathsep.join(path_entries) compat.setenv('PATH', path) # We don't ever want a pager compat.setenv('GIT_PAGER', '') # Setup *SSH_ASKPASS git_askpass = core.getenv('GIT_ASKPASS') ssh_askpass = core.getenv('SSH_ASKPASS') if git_askpass: askpass = git_askpass elif ssh_askpass: askpass = ssh_askpass elif sys.platform == 'darwin': askpass = resources.share('bin', 'ssh-askpass-darwin') else: askpass = resources.share('bin', 'ssh-askpass') compat.setenv('GIT_ASKPASS', askpass) compat.setenv('SSH_ASKPASS', askpass) # --- >8 --- >8 --- # Git v1.7.10 Release Notes # ========================= # # Compatibility Notes # ------------------- # # * From this release on, the "git merge" command in an interactive # session will start an editor when it automatically resolves the # merge for the user to explain the resulting commit, just like the # "git commit" command does when it wasn't given a commit message. # # If you have a script that runs "git merge" and keeps its standard # input and output attached to the user's terminal, and if you do not # want the user to explain the resulting merge commits, you can # export GIT_MERGE_AUTOEDIT environment variable set to "no", like # this: # # #!/bin/sh # GIT_MERGE_AUTOEDIT=no # export GIT_MERGE_AUTOEDIT # # to disable this behavior (if you want your users to explain their # merge commits, you do not have to do anything). Alternatively, you # can give the "--no-edit" option to individual invocations of the # "git merge" command if you know everybody who uses your script has # Git v1.7.8 or newer. # --- >8 --- >8 --- # Longer-term: Use `git merge --no-commit` so that we always # have a chance to explain our merges. compat.setenv('GIT_MERGE_AUTOEDIT', 'no') @memoize def instance(argv): return QtGui.QApplication(list(argv)) # style note: we use camelCase here since we're masquerading a Qt class class ColaApplication(object): """The main cola application ColaApplication handles i18n of user-visible data """ def __init__(self, argv, locale=None, gui=True): cfgactions.install() i18n.install(locale) qtcompat.install() qtutils.install() # Add the default style dir so that we find our icons icon_dir = resources.icon_dir() qtcompat.add_search_path(os.path.basename(icon_dir), icon_dir) if gui: self._app = instance(tuple(argv)) self._app.setWindowIcon(qtutils.git_icon()) else: self._app = QtCore.QCoreApplication(argv) self._app.setStyleSheet(""" QMainWindow::separator { width: 3px; height: 3px; } QMainWindow::separator:hover { background: white; } """) def activeWindow(self): """Wrap activeWindow()""" return self._app.activeWindow() def desktop(self): return self._app.desktop() def exec_(self): """Wrap exec_()""" return self._app.exec_() def process_args(args): if args.version: # Accept 'git cola --version' or 'git cola version' version.print_version() sys.exit(0) if args.git_path: # Adds git to the PATH. This is needed on Windows. path_entries = core.getenv('PATH', '').split(os.pathsep) path_entries.insert(0, os.path.dirname(core.decode(args.git_path))) compat.setenv('PATH', os.pathsep.join(path_entries)) # Bail out if --repo is not a directory repo = core.decode(args.repo) if repo.startswith('file:'): repo = repo[len('file:'):] repo = core.realpath(repo) if not core.isdir(repo): sys.stderr.write("fatal: '%s' is not a directory. " 'Consider supplying -r .\n' % repo) sys.exit(-1) # We do everything relative to the repo root os.chdir(args.repo) return repo def application_init(args, update=False): """Parses the command-line arguments and starts git-cola """ setup_environment() process_args(args) # Ensure that we're working in a valid git repository. # If not, try to find one. When found, chdir there. app = new_application() model = new_model(app, args.repo, prompt=args.prompt) if update: model.update_status() return ApplicationContext(args, app, model) def application_start(context, view): # Make sure that we start out on top view.show() view.raise_() # Scan for the first time task = _start_update_thread(context.model) # Start the inotify thread inotify.start() msg_timer = QtCore.QTimer() msg_timer.setSingleShot(True) msg_timer.connect(msg_timer, SIGNAL('timeout()'), _send_msg) msg_timer.start(0) # Start the event loop result = context.app.exec_() # All done, cleanup inotify.stop() QtCore.QThreadPool.globalInstance().waitForDone() del task pattern = utils.tmp_file_pattern() for filename in glob.glob(pattern): os.unlink(filename) return result def add_common_arguments(parser): # We also accept 'git cola version' parser.add_argument('--version', default=False, action='store_true', help='prints the version') # Specifies a git repository to open parser.add_argument('-r', '--repo', metavar='', default=os.getcwd(), help='specifies the path to a git repository') # Specifies that we should prompt for a repository at startup parser.add_argument('--prompt', action='store_true', default=False, help='prompts for a repository') # Used on Windows for adding 'git' to the path parser.add_argument('-g', '--git-path', metavar='', default=None, help='specifies the path to the git binary') def new_application(): # Allow Ctrl-C to exit signal.signal(signal.SIGINT, signal.SIG_DFL) # Initialize the app return ColaApplication(sys.argv) def new_model(app, repo, prompt=False): model = main.model() valid = model.set_worktree(repo) and not prompt while not valid: startup_dlg = startup.StartupDialog(app.activeWindow()) gitdir = startup_dlg.find_git_repo() if not gitdir: sys.exit(-1) valid = model.set_worktree(gitdir) # Finally, go to the root of the git repo os.chdir(model.git.worktree()) return model def _start_update_thread(model): """Update the model in the background git-cola should startup as quickly as possible. """ class UpdateTask(QtCore.QRunnable): def run(self): model.update_status(update_index=True) # Hold onto a reference to prevent PyQt from dereferencing task = UpdateTask() QtCore.QThreadPool.globalInstance().start(task) return task def _send_msg(): if git.GIT_COLA_TRACE == 'trace': msg = ('info: Trace enabled. ' 'Many of commands reported with "trace" use git\'s stable ' '"plumbing" API and are not intended for typical ' 'day-to-day use. Here be dragons') Interaction.log(msg) class ApplicationContext(object): def __init__(self, args, app, model): self.args = args self.app = app self.model = model git-cola-1.9.3/cola/bookmarks.py000066400000000000000000000104441225156173500165150ustar00rootroot00000000000000"""Provides BookmarksDialog.""" import sys from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import core from cola import qtutils from cola import settings from cola.i18n import N_ from cola.interaction import Interaction from cola.widgets import defs from cola.widgets import standard def manage_bookmarks(): dlg = BookmarksDialog(qtutils.active_window()) dlg.show() dlg.exec_() return dlg class BookmarksDialog(standard.Dialog): def __init__(self, parent): standard.Dialog.__init__(self, parent) self.model = settings.Settings() self.resize(494, 238) self.setWindowTitle(N_('Bookmarks')) self.setWindowModality(Qt.WindowModal) self.layt = QtGui.QVBoxLayout(self) self.layt.setMargin(defs.margin) self.layt.setSpacing(defs.spacing) self.bookmarks = QtGui.QListWidget(self) self.bookmarks.setAlternatingRowColors(True) self.bookmarks.setSelectionMode(QtGui.QAbstractItemView .ExtendedSelection) self.layt.addWidget(self.bookmarks) self.button_layout = QtGui.QHBoxLayout() self.open_button = QtGui.QPushButton(self) self.open_button.setText(N_('Open')) self.open_button.setIcon(qtutils.open_icon()) self.open_button.setEnabled(False) self.button_layout.addWidget(self.open_button) self.add_button = QtGui.QPushButton(self) self.add_button.setText(N_('Add')) self.add_button.setIcon(qtutils.icon('add.svg')) self.button_layout.addWidget(self.add_button) self.delete_button = QtGui.QPushButton(self) self.delete_button.setText(N_('Delete')) self.delete_button.setIcon(qtutils.discard_icon()) self.delete_button.setEnabled(False) self.button_layout.addWidget(self.delete_button) self.button_layout.addStretch() self.save_button = QtGui.QPushButton(self) self.save_button.setText(N_('Save')) self.save_button.setIcon(qtutils.save_icon()) self.save_button.setEnabled(False) self.button_layout.addWidget(self.save_button) self.close_button = QtGui.QPushButton(self) self.close_button.setText(N_('Close')) self.button_layout.addWidget(self.close_button) self.layt.addLayout(self.button_layout) self.connect(self.bookmarks, SIGNAL('itemSelectionChanged()'), self.item_selection_changed) qtutils.connect_button(self.open_button, self.open_repo) qtutils.connect_button(self.add_button, self.add) qtutils.connect_button(self.delete_button, self.delete) qtutils.connect_button(self.save_button, self.save) qtutils.connect_button(self.close_button, self.accept) self.update_bookmarks() def update_bookmarks(self): self.bookmarks.clear() self.bookmarks.addItems(self.model.bookmarks) def selection(self): return qtutils.selection_list(self.bookmarks, self.model.bookmarks) def item_selection_changed(self): has_selection = bool(self.selection()) self.open_button.setEnabled(has_selection) self.delete_button.setEnabled(has_selection) def save(self): """Saves the bookmarks settings and exits""" self.model.save() Interaction.information(N_('Bookmarks Saved'), N_('Successfully saved bookmarks')) self.save_button.setEnabled(False) def add(self): path, ok = qtutils.prompt(N_('Path to git repository'), title=N_('Enter Git Repository'), text=core.getcwd()) if not ok: return self.model.bookmarks.append(path) self.update_bookmarks() self.save() def open_repo(self): """Opens a new git-cola session on a bookmark""" for repo in self.selection(): core.fork([sys.executable, sys.argv[0], '--repo', repo]) def delete(self): """Removes a bookmark from the bookmarks list""" selection = self.selection() if not selection: return for repo in selection: self.model.remove_bookmark(repo) self.update_bookmarks() self.save_button.setEnabled(True) git-cola-1.9.3/cola/cmds.py000066400000000000000000001065341225156173500154610ustar00rootroot00000000000000import os import sys from fnmatch import fnmatch from cStringIO import StringIO from cola import compat from cola import core from cola import gitcfg from cola import gitcmds from cola import utils from cola import difftool from cola import resources from cola.compat import set from cola.diffparse import DiffParser from cola.git import STDOUT from cola.i18n import N_ from cola.interaction import Interaction from cola.models import main from cola.models import prefs from cola.models import selection _config = gitcfg.instance() class UsageError(StandardError): """Exception class for usage errors.""" def __init__(self, title, message): StandardError.__init__(self, message) self.title = title self.msg = message class BaseCommand(object): """Base class for all commands; provides the command pattern""" DISABLED = False def __init__(self): self.undoable = False def is_undoable(self): """Can this be undone?""" return self.undoable @staticmethod def name(cls): return 'Unknown' def do(self): raise NotImplementedError('%s.do() is unimplemented' % self.__class__.__name__) def undo(self): raise NotImplementedError('%s.undo() is unimplemented' % self.__class__.__name__) class Command(BaseCommand): """Base class for commands that modify the main model""" def __init__(self): """Initialize the command and stash away values for use in do()""" # These are commonly used so let's make it easier to write new commands. BaseCommand.__init__(self) self.model = main.model() self.old_diff_text = self.model.diff_text self.old_filename = self.model.filename self.old_mode = self.model.mode self.new_diff_text = self.old_diff_text self.new_filename = self.old_filename self.new_mode = self.old_mode def do(self): """Perform the operation.""" self.model.set_filename(self.new_filename) self.model.set_mode(self.new_mode) self.model.set_diff_text(self.new_diff_text) def undo(self): """Undo the operation.""" self.model.set_diff_text(self.old_diff_text) self.model.set_filename(self.old_filename) self.model.set_mode(self.old_mode) class AmendMode(Command): """Try to amend a commit.""" SHORTCUT = 'Ctrl+M' LAST_MESSAGE = None @staticmethod def name(): return N_('Amend') def __init__(self, amend): Command.__init__(self) self.undoable = True self.skip = False self.amending = amend self.old_commitmsg = self.model.commitmsg self.old_mode = self.model.mode if self.amending: self.new_mode = self.model.mode_amend self.new_commitmsg = self.model.prev_commitmsg() AmendMode.LAST_MESSAGE = self.model.commitmsg return # else, amend unchecked, regular commit self.new_mode = self.model.mode_none self.new_diff_text = '' self.new_commitmsg = self.model.commitmsg # If we're going back into new-commit-mode then search the # undo stack for a previous amend-commit-mode and grab the # commit message at that point in time. if AmendMode.LAST_MESSAGE is not None: self.new_commitmsg = AmendMode.LAST_MESSAGE AmendMode.LAST_MESSAGE = None def do(self): """Leave/enter amend mode.""" """Attempt to enter amend mode. Do not allow this when merging.""" if self.amending: if self.model.is_merging: self.skip = True self.model.set_mode(self.old_mode) Interaction.information( N_('Cannot Amend'), N_('You are in the middle of a merge.\n' 'Cannot amend while merging.')) return self.skip = False Command.do(self) self.model.set_commitmsg(self.new_commitmsg) self.model.update_file_status() def undo(self): if self.skip: return self.model.set_commitmsg(self.old_commitmsg) Command.undo(self) self.model.update_file_status() class ApplyDiffSelection(Command): def __init__(self, staged, selected, offset, selection_text, apply_to_worktree): Command.__init__(self) self.staged = staged self.selected = selected self.offset = offset self.selection_text = selection_text self.apply_to_worktree = apply_to_worktree def do(self): # The normal worktree vs index scenario parser = DiffParser(self.model, filename=self.model.filename, cached=self.staged, reverse=self.apply_to_worktree) status, out, err = \ parser.process_diff_selection(self.selected, self.offset, self.selection_text, apply_to_worktree=self.apply_to_worktree) Interaction.log_status(status, out, err) self.model.update_file_status(update_index=True) class ApplyPatches(Command): def __init__(self, patches): Command.__init__(self) patches.sort() self.patches = patches def do(self): diff_text = '' num_patches = len(self.patches) orig_head = self.model.git.rev_parse('HEAD')[STDOUT] for idx, patch in enumerate(self.patches): status, out, err = self.model.git.am(patch) # Log the git-am command Interaction.log_status(status, out, err) if num_patches > 1: diff = self.model.git.diff('HEAD^!', stat=True)[STDOUT] diff_text += (N_('PATCH %(current)d/%(count)d') % dict(current=idx+1, count=num_patches)) diff_text += ' - %s:\n%s\n\n' % (os.path.basename(patch), diff) diff_text += N_('Summary:') + '\n' diff_text += self.model.git.diff(orig_head, stat=True)[STDOUT] # Display a diffstat self.model.set_diff_text(diff_text) self.model.update_file_status() basenames = '\n'.join([os.path.basename(p) for p in self.patches]) Interaction.information( N_('Patch(es) Applied'), (N_('%d patch(es) applied.') + '\n\n%s') % (len(self.patches), basenames)) class Archive(BaseCommand): def __init__(self, ref, fmt, prefix, filename): BaseCommand.__init__(self) self.ref = ref self.fmt = fmt self.prefix = prefix self.filename = filename def do(self): fp = core.xopen(self.filename, 'wb') cmd = ['git', 'archive', '--format='+self.fmt] if self.fmt in ('tgz', 'tar.gz'): cmd.append('-9') if self.prefix: cmd.append('--prefix=' + self.prefix) cmd.append(self.ref) proc = core.start_command(cmd, stdout=fp) out, err = proc.communicate() fp.close() status = proc.returncode Interaction.log_status(status, out or '', err or '') class Checkout(Command): """ A command object for git-checkout. 'argv' is handed off directly to git. """ def __init__(self, argv, checkout_branch=False): Command.__init__(self) self.argv = argv self.checkout_branch = checkout_branch self.new_diff_text = '' def do(self): status, out, err = self.model.git.checkout(*self.argv) Interaction.log_status(status, out, err) if self.checkout_branch: self.model.update_status() else: self.model.update_file_status() class CheckoutBranch(Checkout): """Checkout a branch.""" def __init__(self, branch): args = [branch] Checkout.__init__(self, args, checkout_branch=True) class CherryPick(Command): """Cherry pick commits into the current branch.""" def __init__(self, commits): Command.__init__(self) self.commits = commits def do(self): self.model.cherry_pick_list(self.commits) self.model.update_file_status() class ResetMode(Command): """Reset the mode and clear the model's diff text.""" def __init__(self): Command.__init__(self) self.new_mode = self.model.mode_none self.new_diff_text = '' def do(self): Command.do(self) self.model.update_file_status() class Commit(ResetMode): """Attempt to create a new commit.""" SHORTCUT = 'Ctrl+Return' def __init__(self, amend, msg): ResetMode.__init__(self) self.amend = amend self.msg = msg self.old_commitmsg = self.model.commitmsg self.new_commitmsg = '' def do(self): tmpfile = utils.tmp_filename('commit-message') status, out, err = self.model.commit_with_msg(self.msg, tmpfile, amend=self.amend) if status == 0: ResetMode.do(self) self.model.set_commitmsg(self.new_commitmsg) msg = N_('Created commit: %s') % out else: msg = N_('Commit failed: %s') % out Interaction.log_status(status, msg, err) return status, out, err class Ignore(Command): """Add files to .gitignore""" def __init__(self, filenames): Command.__init__(self) self.filenames = filenames def do(self): new_additions = '' for fname in self.filenames: new_additions = new_additions + fname + '\n' for_status = new_additions if new_additions: if core.exists('.gitignore'): current_list = core.read('.gitignore') new_additions = new_additions + current_list core.write('.gitignore', new_additions) Interaction.log_status( 0, 'Added to .gitignore:\n%s' % for_status, '') self.model.update_file_status() class Delete(Command): """Delete files.""" def __init__(self, filenames): Command.__init__(self) self.filenames = filenames # We could git-hash-object stuff and provide undo-ability # as an option. Heh. def do(self): rescan = False for filename in self.filenames: if filename: try: os.remove(filename) rescan=True except: Interaction.information( N_('Error'), N_('Deleting "%s" failed') % filename) if rescan: self.model.update_file_status() class DeleteBranch(Command): """Delete a git branch.""" def __init__(self, branch): Command.__init__(self) self.branch = branch def do(self): status, out, err = self.model.delete_branch(self.branch) Interaction.log_status(status, out, err) class DeleteRemoteBranch(Command): """Delete a remote git branch.""" def __init__(self, remote, branch): Command.__init__(self) self.remote = remote self.branch = branch def do(self): status, out, err = self.model.git.push(self.remote, self.branch, delete=True) Interaction.log_status(status, out, err) self.model.update_status() if status == 0: Interaction.information( N_('Remote Branch Deleted'), N_('"%(branch)s" has been deleted from "%(remote)s".') % dict(branch=self.branch, remote=self.remote)) else: command = 'git push' message = (N_('"%(command)s" returned exit status %(status)d') % dict(command=command, status=status)) Interaction.critical(N_('Error Deleting Remote Branch'), message, out + err) class Diff(Command): """Perform a diff and set the model's current text.""" def __init__(self, filenames, cached=False): Command.__init__(self) # Guard against the list of files being empty if not filenames: return opts = {} if cached: opts['ref'] = self.model.head self.new_filename = filenames[0] self.old_filename = self.model.filename self.new_mode = self.model.mode_worktree self.new_diff_text = gitcmds.diff_helper(filename=self.new_filename, cached=cached, **opts) class Diffstat(Command): """Perform a diffstat and set the model's diff text.""" def __init__(self): Command.__init__(self) diff = self.model.git.diff(self.model.head, unified=_config.get('diff.context', 3), no_ext_diff=True, no_color=True, M=True, stat=True)[STDOUT] self.new_diff_text = diff self.new_mode = self.model.mode_worktree class DiffStaged(Diff): """Perform a staged diff on a file.""" def __init__(self, filenames): Diff.__init__(self, filenames, cached=True) self.new_mode = self.model.mode_index class DiffStagedSummary(Command): def __init__(self): Command.__init__(self) diff = self.model.git.diff(self.model.head, cached=True, no_color=True, no_ext_diff=True, patch_with_stat=True, M=True)[STDOUT] self.new_diff_text = diff self.new_mode = self.model.mode_index class Difftool(Command): """Run git-difftool limited by path.""" def __init__(self, staged, filenames): Command.__init__(self) self.staged = staged self.filenames = filenames def do(self): difftool.launch_with_head(self.filenames, self.staged, self.model.head) class Edit(Command): """Edit a file using the configured gui.editor.""" SHORTCUT = 'Ctrl+E' @staticmethod def name(): return N_('Edit') def __init__(self, filenames, line_number=None): Command.__init__(self) self.filenames = filenames self.line_number = line_number def do(self): if not self.filenames: return filename = self.filenames[0] if not core.exists(filename): return editor = prefs.editor() opts = [] if self.line_number is None: opts = self.filenames else: # Single-file w/ line-numbers (likely from grep) editor_opts = { '*vim*': ['+'+self.line_number, filename], '*emacs*': ['+'+self.line_number, filename], '*textpad*': ['%s(%s,0)' % (filename, self.line_number)], '*notepad++*': ['-n'+self.line_number, filename], } opts = self.filenames for pattern, opt in editor_opts.items(): if fnmatch(editor, pattern): opts = opt break try: core.fork(utils.shell_split(editor) + opts) except Exception as e: message = (N_('Cannot exec "%s": please configure your editor') % editor) Interaction.critical(N_('Error Editing File'), message, str(e)) class FormatPatch(Command): """Output a patch series given all revisions and a selected subset.""" def __init__(self, to_export, revs): Command.__init__(self) self.to_export = to_export self.revs = revs def do(self): status, out, err = gitcmds.format_patchsets(self.to_export, self.revs) Interaction.log_status(status, out, err) class LaunchDifftool(BaseCommand): SHORTCUT = 'Ctrl+D' @staticmethod def name(): return N_('Launch Diff Tool') def __init__(self): BaseCommand.__init__(self) def do(self): s = selection.selection() if s.unmerged: paths = s.unmerged if utils.is_win32(): core.fork(['git', 'mergetool', '--no-prompt', '--'] + paths) else: core.fork(['xterm', '-e', 'git', 'mergetool', '--no-prompt', '--'] + paths) else: difftool.run() class LaunchEditor(Edit): SHORTCUT = 'Ctrl+E' @staticmethod def name(): return N_('Launch Editor') def __init__(self): s = selection.selection() allfiles = s.staged + s.unmerged + s.modified + s.untracked Edit.__init__(self, allfiles) class LoadCommitMessageFromFile(Command): """Loads a commit message from a path.""" def __init__(self, path): Command.__init__(self) self.undoable = True self.path = path self.old_commitmsg = self.model.commitmsg self.old_directory = self.model.directory def do(self): path = self.path if not path or not core.isfile(path): raise UsageError(N_('Error: Cannot find commit template'), N_('%s: No such file or directory.') % path) self.model.set_directory(os.path.dirname(path)) self.model.set_commitmsg(core.read(path)) def undo(self): self.model.set_commitmsg(self.old_commitmsg) self.model.set_directory(self.old_directory) class LoadCommitMessageFromTemplate(LoadCommitMessageFromFile): """Loads the commit message template specified by commit.template.""" def __init__(self): template = _config.get('commit.template') LoadCommitMessageFromFile.__init__(self, template) def do(self): if self.path is None: raise UsageError( N_('Error: Unconfigured commit template'), N_('A commit template has not been configured.\n' 'Use "git config" to define "commit.template"\n' 'so that it points to a commit template.')) return LoadCommitMessageFromFile.do(self) class LoadCommitMessageFromSHA1(Command): """Load a previous commit message""" def __init__(self, sha1, prefix=''): Command.__init__(self) self.sha1 = sha1 self.old_commitmsg = self.model.commitmsg self.new_commitmsg = prefix + self.model.prev_commitmsg(sha1) self.undoable = True def do(self): self.model.set_commitmsg(self.new_commitmsg) def undo(self): self.model.set_commitmsg(self.old_commitmsg) class LoadFixupMessage(LoadCommitMessageFromSHA1): """Load a fixup message""" def __init__(self, sha1): LoadCommitMessageFromSHA1.__init__(self, sha1, prefix='fixup! ') class Merge(Command): def __init__(self, revision, no_commit, squash): Command.__init__(self) self.revision = revision self.no_commit = no_commit self.squash = squash def do(self): squash = self.squash revision = self.revision no_commit = self.no_commit msg = gitcmds.merge_message(revision) status, out, err = self.model.git.merge('-m', msg, revision, no_commit=no_commit, squash=squash) Interaction.log_status(status, out, err) self.model.update_status() class OpenDefaultApp(BaseCommand): """Open a file using the OS default.""" SHORTCUT = 'Space' @staticmethod def name(): return N_('Open Using Default Application') def __init__(self, filenames): BaseCommand.__init__(self) if utils.is_darwin(): launcher = 'open' else: launcher = 'xdg-open' self.launcher = launcher self.filenames = filenames def do(self): if not self.filenames: return core.fork([self.launcher] + self.filenames) class OpenParentDir(OpenDefaultApp): """Open parent directories using the OS default.""" SHORTCUT = 'Shift+Space' @staticmethod def name(): return N_('Open Parent Directory') def __init__(self, filenames): OpenDefaultApp.__init__(self, filenames) def do(self): if not self.filenames: return dirs = set(map(os.path.dirname, self.filenames)) core.fork([self.launcher] + dirs) class OpenRepo(Command): """Launches git-cola on a repo.""" def __init__(self, repo_path): Command.__init__(self) self.repo_path = repo_path def do(self): self.model.set_directory(self.repo_path) core.fork([sys.executable, sys.argv[0], '--repo', self.repo_path]) class Clone(Command): """Clones a repository and optionally spawns a new cola session.""" def __init__(self, url, new_directory, spawn=True): Command.__init__(self) self.url = url self.new_directory = new_directory self.spawn = spawn def do(self): status, out, err = self.model.git.clone(self.url, self.new_directory) if status != 0: Interaction.information( N_('Error: could not clone "%s"') % self.url, (N_('git clone returned exit code %s') % status) + ((out+err) and ('\n\n' + out + err) or '')) return False if self.spawn: core.fork([sys.executable, sys.argv[0], '--repo', self.new_directory]) return True class GitXBaseContext(object): def __init__(self, **kwargs): self.extras = kwargs def __enter__(self): compat.setenv('GIT_SEQUENCE_EDITOR', resources.share('bin', 'git-xbase')) for var, value in self.extras.items(): compat.setenv(var, value) return self def __exit__(self, exc_type, exc_val, exc_tb): compat.unsetenv('GIT_SEQUENCE_EDITOR') for var in self.extras: compat.unsetenv(var) class Rebase(Command): def __init__(self, branch): Command.__init__(self) self.branch = branch def do(self): branch = self.branch if not branch: return status = 1 out = '' err = '' with GitXBaseContext( GIT_EDITOR=prefs.editor(), GIT_XBASE_TITLE=N_('Rebase onto %s') % branch, GIT_XBASE_ACTION=N_('Rebase')): status, out, err = self.model.git.rebase(branch, interactive=True, autosquash=True) Interaction.log_status(status, out, err) self.model.update_status() return status, out, err class RebaseEditTodo(Command): def do(self): with GitXBaseContext( GIT_XBASE_TITLE=N_('Edit Rebase'), GIT_XBASE_ACTION=N_('Save')): status, out, err = self.model.git.rebase(edit_todo=True) Interaction.log_status(status, out, err) self.model.update_status() class RebaseContinue(Command): def do(self): status, out, err = self.model.git.rebase('--continue') Interaction.log_status(status, out, err) self.model.update_status() class RebaseSkip(Command): def do(self): status, out, err = self.model.git.rebase(skip=True) Interaction.log_status(status, out, err) self.model.update_status() class RebaseAbort(Command): def do(self): status, out, err = self.model.git.rebase(abort=True) Interaction.log_status(status, out, err) self.model.update_status() class Rescan(Command): """Rescan for changes""" def do(self): self.model.update_status() class Refresh(Command): """Update refs and refresh the index""" SHORTCUT = 'Ctrl+R' @staticmethod def name(): return N_('Refresh') def do(self): self.model.update_status(update_index=True) class RunConfigAction(Command): """Run a user-configured action, typically from the "Tools" menu""" def __init__(self, action_name): Command.__init__(self) self.action_name = action_name self.model = main.model() def do(self): for env in ('FILENAME', 'REVISION', 'ARGS'): try: compat.unsetenv(env) except KeyError: pass rev = None args = None opts = _config.get_guitool_opts(self.action_name) cmd = opts.get('cmd') if 'title' not in opts: opts['title'] = cmd if 'prompt' not in opts or opts.get('prompt') is True: prompt = N_('Run "%s"?') % cmd opts['prompt'] = prompt if opts.get('needsfile'): filename = selection.filename() if not filename: Interaction.information( N_('Please select a file'), N_('"%s" requires a selected file.') % cmd) return False compat.setenv('FILENAME', filename) if opts.get('revprompt') or opts.get('argprompt'): while True: ok = Interaction.confirm_config_action(cmd, opts) if not ok: return False rev = opts.get('revision') args = opts.get('args') if opts.get('revprompt') and not rev: title = N_('Invalid Revision') msg = N_('The revision expression cannot be empty.') Interaction.critical(title, msg) continue break elif opts.get('confirm'): title = os.path.expandvars(opts.get('title')) prompt = os.path.expandvars(opts.get('prompt')) if Interaction.question(title, prompt): return if rev: compat.setenv('REVISION', rev) if args: compat.setenv('ARGS', args) title = os.path.expandvars(cmd) Interaction.log(N_('Running command: %s') % title) cmd = ['sh', '-c', cmd] if opts.get('noconsole'): status, out, err = core.run_command(cmd) else: status, out, err = Interaction.run_command(title, cmd) Interaction.log_status(status, out and (N_('Output: %s') % out) or '', err and (N_('Errors: %s') % err) or '') if not opts.get('norescan'): self.model.update_status() return status class SetDiffText(Command): def __init__(self, text): Command.__init__(self) self.undoable = True self.new_diff_text = text class ShowUntracked(Command): """Show an untracked file.""" def __init__(self, filenames): Command.__init__(self) self.filenames = filenames self.new_mode = self.model.mode_untracked self.new_diff_text = '' if filenames: self.new_diff_text = self.diff_text_for(filenames[0]) def diff_text_for(self, filename): size = _config.get('cola.readsize', 1024 * 2) try: result = core.read(filename, size=size) except: result = '' if len(result) == size: result += '...' return result class SignOff(Command): SHORTCUT = 'Ctrl+I' @staticmethod def name(): return N_('Sign Off') def __init__(self): Command.__init__(self) self.undoable = True self.old_commitmsg = self.model.commitmsg def do(self): signoff = self.signoff() if signoff in self.model.commitmsg: return self.model.set_commitmsg(self.model.commitmsg + '\n' + signoff) def undo(self): self.model.set_commitmsg(self.old_commitmsg) def signoff(self): try: import pwd user = pwd.getpwuid(os.getuid()).pw_name except ImportError: user = os.getenv('USER', N_('unknown')) name = _config.get('user.name', user) email = _config.get('user.email', '%s@%s' % (user, core.node())) return '\nSigned-off-by: %s <%s>' % (name, email) class Stage(Command): """Stage a set of paths.""" SHORTCUT = 'Ctrl+S' @staticmethod def name(): return N_('Stage') def __init__(self, paths): Command.__init__(self) self.paths = paths def do(self): msg = N_('Staging: %s') % (', '.join(self.paths)) Interaction.log(msg) # Prevent external updates while we are staging files. # We update file stats at the end of this operation # so there's no harm in ignoring updates from other threads # (e.g. inotify). with CommandDisabled(UpdateFileStatus): self.model.stage_paths(self.paths) class StageModified(Stage): """Stage all modified files.""" SHORTCUT = 'Ctrl+S' @staticmethod def name(): return N_('Stage Modified') def __init__(self): Stage.__init__(self, None) self.paths = self.model.modified class StageUnmerged(Stage): """Stage all modified files.""" SHORTCUT = 'Ctrl+S' @staticmethod def name(): return N_('Stage Unmerged') def __init__(self): Stage.__init__(self, None) self.paths = self.model.unmerged class StageUntracked(Stage): """Stage all untracked files.""" SHORTCUT = 'Ctrl+S' @staticmethod def name(): return N_('Stage Untracked') def __init__(self): Stage.__init__(self, None) self.paths = self.model.untracked class Tag(Command): """Create a tag object.""" def __init__(self, name, revision, sign=False, message=''): Command.__init__(self) self._name = name self._message = message self._revision = revision self._sign = sign def do(self): log_msg = (N_('Tagging "%(revision)s" as "%(name)s"') % dict(revision=self._revision, name=self._name)) opts = {} if self._message: opts['F'] = utils.tmp_filename('tag-message') core.write(opts['F'], self._message) if self._sign: log_msg += ' (%s)' % N_('GPG-signed') opts['s'] = True status, output, err = self.model.git.tag(self._name, self._revision, **opts) else: opts['a'] = bool(self._message) status, output, err = self.model.git.tag(self._name, self._revision, **opts) if 'F' in opts: os.unlink(opts['F']) if output: log_msg += '\n' + (N_('Output: %s') % output) Interaction.log_status(status, log_msg, err) if status == 0: self.model.update_status() class Unstage(Command): """Unstage a set of paths.""" SHORTCUT = 'Ctrl+S' @staticmethod def name(): return N_('Unstage') def __init__(self, paths): Command.__init__(self) self.paths = paths def do(self): msg = N_('Unstaging: %s') % (', '.join(self.paths)) Interaction.log(msg) with CommandDisabled(UpdateFileStatus): self.model.unstage_paths(self.paths) class UnstageAll(Command): """Unstage all files; resets the index.""" def do(self): self.model.unstage_all() class UnstageSelected(Unstage): """Unstage selected files.""" def __init__(self): Unstage.__init__(self, selection.selection_model().staged) class Untrack(Command): """Unstage a set of paths.""" def __init__(self, paths): Command.__init__(self) self.paths = paths def do(self): msg = N_('Untracking: %s') % (', '.join(self.paths)) Interaction.log(msg) with CommandDisabled(UpdateFileStatus): status, out, err = self.model.untrack_paths(self.paths) Interaction.log_status(status, out, err) class UntrackedSummary(Command): """List possible .gitignore rules as the diff text.""" def __init__(self): Command.__init__(self) untracked = self.model.untracked suffix = len(untracked) > 1 and 's' or '' io = StringIO() io.write('# %s untracked file%s\n' % (len(untracked), suffix)) if untracked: io.write('# possible .gitignore rule%s:\n' % suffix) for u in untracked: io.write('/'+core.encode(u)+'\n') self.new_diff_text = core.decode(io.getvalue()) self.new_mode = self.model.mode_untracked class UpdateFileStatus(Command): """Rescans for changes.""" def do(self): self.model.update_file_status() class VisualizeAll(Command): """Visualize all branches.""" def do(self): browser = utils.shell_split(prefs.history_browser()) core.fork(browser + ['--all']) class VisualizeCurrent(Command): """Visualize all branches.""" def do(self): browser = utils.shell_split(prefs.history_browser()) core.fork(browser + [self.model.currentbranch]) class VisualizePaths(Command): """Path-limited visualization.""" def __init__(self, paths): Command.__init__(self) browser = utils.shell_split(prefs.history_browser()) if paths: self.argv = browser + paths else: self.argv = browser def do(self): core.fork(self.argv) class VisualizeRevision(Command): """Visualize a specific revision.""" def __init__(self, revision, paths=None): Command.__init__(self) self.revision = revision self.paths = paths def do(self): argv = utils.shell_split(prefs.history_browser()) if self.revision: argv.append(self.revision) if self.paths: argv.append('--') argv.extend(self.paths) try: core.fork(argv) except Exception as e: _, details = utils.format_exception(e) title = N_('Error Launching History Browser') msg = (N_('Cannot exec "%s": please configure a history browser') % ' '.join(argv)) Interaction.critical(title, message=msg, details=details) def run(cls, *args, **opts): """ Returns a callback that runs a command If the caller of run() provides args or opts then those are used instead of the ones provided by the invoker of the callback. """ def runner(*local_args, **local_opts): if args or opts: do(cls, *args, **opts) else: do(cls, *local_args, **local_opts) return runner class CommandDisabled(object): """Context manager to temporarily disable a command from running""" def __init__(self, cmdclass): self.cmdclass = cmdclass def __enter__(self): self.cmdclass.DISABLED = True return self def __exit__(self, exc_type, exc_val, exc_tb): self.cmdclass.DISABLED = False def do(cls, *args, **opts): """Run a command in-place""" return do_cmd(cls(*args, **opts)) def do_cmd(cmd): if hasattr(cmd, 'DISABLED') and cmd.DISABLED: return None try: return cmd.do() except StandardError, e: msg, details = utils.format_exception(e) Interaction.critical(N_('Error'), message=msg, details=details) return None git-cola-1.9.3/cola/compat.py000066400000000000000000000016561225156173500160150ustar00rootroot00000000000000import os from cola import core try: set = set except NameError: from sets import Set as set set = set try: import simplejson as json except ImportError: import json try: import hashlib except ImportError: import md5 class hashlib(object): @staticmethod def new(*args): return md5.new() @classmethod def md5(cls, value=''): obj = md5.new() obj.update(value) return obj def setenv(key, value): """Compatibility wrapper for setting environment variables Why? win32 requires putenv(). UNIX only requires os.environ. """ os.environ[key] = core.encode(value) os.putenv(key, core.encode(value)) def unsetenv(key): """Compatibility wrapper for unsetting environment variables""" try: del os.environment[key] except: pass if hasattr(os, 'unsetenv'): os.unsetenv(key) git-cola-1.9.3/cola/core.py000066400000000000000000000144421225156173500154570ustar00rootroot00000000000000"""This module provides core functions for handling unicode and UNIX quirks The @interruptable functions retry when system calls are interrupted, e.g. when python raises an IOError or OSError with errno == EINTR. """ import os import sys import itertools import platform import subprocess from cola.decorators import interruptable # Some files are not in UTF-8; some other aren't in any codification. # Remember that GIT doesn't care about encodings (saves binary data) _encoding_tests = [ 'utf-8', 'iso-8859-15', 'windows1252', 'ascii', # <-- add encodings here ] def decode(enc, encoding=None): """decode(encoded_string) returns an unencoded unicode string """ if type(enc) is unicode: return enc if encoding is None: encoding_tests = _encoding_tests else: encoding_tests = itertools.chain([encoding], _encoding_tests) for encoding in encoding_tests: try: return enc.decode(encoding) except: pass # this shouldn't ever happen... FIXME return unicode(enc) def encode(string, encoding=None): """encode(unencoded_string) returns a string encoded in utf-8 """ if type(string) is not unicode: return string return string.encode(encoding or 'utf-8', 'replace') def read(filename, size=-1, encoding=None): """Read filename and return contents""" with xopen(filename, 'r') as fh: return fread(fh, size=size, encoding=encoding) def write(path, contents, encoding=None): """Writes a unicode string to a file""" with xopen(path, 'wb') as fh: return fwrite(fh, contents, encoding=encoding) @interruptable def fread(fh, size=-1, encoding=None): """Read from a filehandle and retry when interrupted""" return decode(fh.read(size), encoding=encoding) @interruptable def fwrite(fh, content, encoding=None): """Write to a filehandle and retry when interrupted""" return fh.write(encode(content, encoding=encoding)) @interruptable def wait(proc): """Wait on a subprocess and retry when interrupted""" return proc.wait() @interruptable def readline(fh, encoding=None): return decode(fh.readline(), encoding=encoding) @interruptable def start_command(cmd, cwd=None, shell=False, add_env=None, universal_newlines=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE): """Start the given command, and return a subprocess object. This provides a simpler interface to the subprocess module. """ env = None if add_env is not None: env = os.environ.copy() env.update(add_env) cmd = [encode(c) for c in cmd] return subprocess.Popen(cmd, bufsize=1, stdin=stdin, stdout=stdout, stderr=stderr, cwd=cwd, shell=shell, env=env, universal_newlines=universal_newlines) @interruptable def communicate(proc): return proc.communicate() def run_command(cmd, *args, **kwargs): """Run the given command to completion, and return its results. This provides a simpler interface to the subprocess module. The results are formatted as a 3-tuple: (exit_code, output, errors) The other arguments are passed on to start_command(). """ process = start_command(cmd, *args, **kwargs) (output, errors) = communicate(process) output = decode(output) errors = decode(errors) exit_code = process.returncode return (exit_code, output, errors) @interruptable def _fork_posix(args): """Launch a process in the background.""" encoded_args = [encode(arg) for arg in args] return subprocess.Popen(encoded_args).pid def _fork_win32(args): """Launch a background process using crazy win32 voodoo.""" # This is probably wrong, but it works. Windows.. wow. if args[0] == 'git-dag': # win32 can't exec python scripts args = [sys.executable] + args enc_args = [encode(arg) for arg in args] abspath = _win32_abspath(enc_args[0]) if abspath: # e.g. fork(['git', 'difftool', '--no-prompt', '--', 'path']) enc_args[0] = abspath else: # e.g. fork(['gitk', '--all']) cmdstr = subprocess.list2cmdline(enc_args) sh_exe = _win32_abspath('sh') enc_args = [sh_exe, '-c', cmdstr] DETACHED_PROCESS = 0x00000008 # Amazing! return subprocess.Popen(enc_args, creationflags=DETACHED_PROCESS).pid def _win32_abspath(exe): """Return the absolute path to an .exe if it exists""" if exists(exe): return exe if not exe.endswith('.exe'): exe += '.exe' if exists(exe): return exe for path in getenv('PATH', '').split(os.pathsep): abspath = os.path.join(path, exe) if exists(abspath): return abspath return None # Portability wrappers if sys.platform == 'win32' or sys.platform == 'cygwin': fork = _fork_win32 else: fork = _fork_posix def wrap(action, fn, decorator=None): """Wrap arguments with `action`, optionally decorate the result""" if decorator is None: decorator = lambda x: x def wrapped(*args, **kwargs): return decorator(fn(action(*args, **kwargs))) return wrapped def decorate(decorator, fn): """Decorate the result of `fn` with `action`""" def decorated(*args, **kwargs): return decorator(fn(*args, **kwargs)) return decorated def getenv(name, default=None): return decode(os.getenv(encode(name), default)) def xopen(path, mode='r', encoding=None): return open(encode(path, encoding=encoding), mode) def stdout(msg): sys.stdout.write(encode(msg) + '\n') def stderr(msg): sys.stderr.write(encode(msg) + '\n') @interruptable def node(): return platform.node() abspath = wrap(encode, os.path.abspath, decorator=decode) exists = wrap(encode, os.path.exists) expanduser = wrap(encode, os.path.expanduser, decorator=decode) getcwd = decorate(decode, os.getcwd) isdir = wrap(encode, os.path.isdir) isfile = wrap(encode, os.path.isfile) islink = wrap(encode, os.path.islink) makedirs = wrap(encode, os.makedirs) try: readlink = wrap(encode, os.readlink, decorator=decode) except AttributeError: readlink = lambda p: p realpath = wrap(encode, os.path.realpath, decorator=decode) stat = wrap(encode, os.stat) unlink = wrap(encode, os.unlink) git-cola-1.9.3/cola/decorators.py000066400000000000000000000036171225156173500166760ustar00rootroot00000000000000__all__ = ('decorator', 'memoize', 'interruptable') import errno def decorator(caller, func=None): """ Create a new decorator decorator(caller) converts a caller function into a decorator; decorator(caller, func) decorates a function using a caller. """ if func is None: # return a decorator def _decorator(f, *args, **opts): def _caller(*args, **opts): return caller(f, *args, **opts) return _caller return _decorator else: # return a decorated function def _decorated(*args, **opts): return caller(func, *args, **opts) return _decorated def memoize(func): """ A decorator for memoizing function calls http://en.wikipedia.org/wiki/Memoization """ func.cache = {} return decorator(_memoize, func) def _memoize(func, *args, **opts): """Implements memoized cache lookups""" if opts: # frozenset is used to ensure hashability key = args, frozenset(opts.items()) else: key = args cache = func.cache # attribute added by memoize try: result = cache[key] except KeyError: result = cache[key] = func(*args, **opts) return result @decorator def interruptable(func, *args, **opts): """Handle interruptable system calls OSX and others are known to interrupt system calls http://en.wikipedia.org/wiki/PCLSRing http://en.wikipedia.org/wiki/Unix_philosophy#Worse_is_better The @interruptable decorator handles this situation """ while True: try: result = func(*args, **opts) except IOError, e: if e.errno == errno.EINTR: continue raise e except OSError, e: if e.errno in (errno.EINTR, errno.EINVAL): continue raise e else: break return result git-cola-1.9.3/cola/diffparse.py000066400000000000000000000255371225156173500165010ustar00rootroot00000000000000import os import re from cola import core from cola import gitcmds from cola import gitcfg from cola import utils class Range(object): def __init__(self, begin, end): self.begin = self._parse(begin) self.end = self._parse(end) def _parse(self, range_str): if ',' in range_str: begin, end = range_str.split(',') return [int(begin), int(end)] else: return [int(range_str), int(range_str)] def make(self): return '@@ -%s +%s @@' % (self._span(self.begin), self._span(self.end)) def set_begin_count(self, count): self._set_count(self.begin, count) def set_end_count(self, count): self._set_count(self.end, count) def _set_count(self, which, count): if count != which[1]: which[1] = count if count == 1 and which[0] == 0: # the file would be empty in the diff, but we're only # partially applying it, and thus it's not a +0,0 diff # anymore. which[0] = 1 def _span(self, seq): a = seq[0] b = seq[1] if a == b and a == 1: return '%d' % a else: return '%d,%d' % (a, b) class DiffSource(object): def get(self, head, amending, filename, cached, reverse): return gitcmds.diff_helper(head=head, amending=amending, filename=filename, with_diff_header=True, cached=cached, reverse=reverse) class DiffParser(object): """Handles parsing diff for use by the interactive index editor.""" HEADER_RE = re.compile(r'^@@ -([0-9,]+) \+([0-9,]+) @@.*') def __init__(self, model, filename='', cached=True, reverse=False, diff_source=None): self._idx = -1 self._diffs = [] self._diff_spans = [] self._diff_offsets = [] self._ranges = [] self.config = gitcfg.instance() self.head = model.head self.amending = model.amending() self.start = None self.end = None self.offset = None self.diff_sel = [] self.selected = [] self.filename = filename self.diff_source = diff_source or DiffSource() (header, diff) = self.diff_source.get(self.head, self.amending, filename, cached, cached or reverse) self.model = model self.diff = diff self.header = header self.parse_diff(diff) # Always index into the non-reversed diff self.fwd_header, self.fwd_diff = \ self.diff_source.get(self.head, self.amending, filename, cached, False) def write_diff(self,filename,which,selected=False,noop=False): """Writes a new diff corresponding to the user's selection.""" if not noop and which < len(self.diff_sel): diff = self.diff_sel[which] encoding = self.config.file_encoding(self.filename) core.write(filename, self.header + '\n' + diff + '\n', encoding=encoding) return True else: return False def ranges(self): """Return the diff header ranges""" return self._ranges def diffs(self): """Returns the list of diffs.""" return self._diffs def diff_subset(self, diff, start, end): """Processes the diffs and returns a selected subset from that diff. """ adds = 0 deletes = 0 existing = 0 newdiff = [] local_offset = 0 offset = self._diff_spans[diff][0] ADD = '+' DEL = '-' NOP = ' ' for line in self._diffs[diff]: line_start = offset + local_offset local_offset += len(line) + 1 #\n line_end = offset + local_offset # |line1 |line2 |line3 | # |--selection--| # '-start '-end # selection has head of diff (line3) has_head = start <= line_start and end > line_start and end <= line_end # selection has all of diff (line2) has_all = start <= line_start and end >= line_end # selection has tail of diff (line1) has_tail = start >= line_start and start < line_end - 1 action = line[0:1] if has_head or has_all or has_tail: newdiff.append(line) if action == ADD: adds += 1 elif action == DEL: deletes += 1 elif action == NOP: existing += 1 else: # Don't add new lines unless selected if action == ADD: continue elif action == DEL: # Don't remove lines unless selected newdiff.append(' ' + line[1:]) existing += 1 elif action == NOP: newdiff.append(line) existing += 1 else: newdiff.append(line) diff_range = self._ranges[diff] begin_count = existing + deletes end_count = existing + adds diff_range.set_begin_count(begin_count) diff_range.set_end_count(end_count) newdiff[0] = diff_range.make() return (self.header + '\n' + '\n'.join(newdiff) + '\n') def spans(self): """Returns the line spans of each hunk.""" return self._diff_spans def offsets(self): """Returns the offsets.""" return self._diff_offsets def set_diff_to_offset(self, offset): """Sets the diff selection to be the hunk at a particular offset.""" self.offset = offset self.diff_sel, self.selected = self.diff_for_offset(offset) def set_diffs_to_range(self, start, end): """Sets the diff selection to be a range of hunks.""" self.start = start self.end = end self.diff_sel, self.selected = self.diffs_for_range(start,end) def diff_for_offset(self, offset): """Returns the hunks for a particular offset.""" for idx, diff_offset in enumerate(self._diff_offsets): if offset < diff_offset: return (['\n'.join(self._diffs[idx])], [idx]) return ([],[]) def diffs_for_range(self, start, end): """Returns the hunks for a selected range.""" diffs = [] indices = [] for idx, span in enumerate(self._diff_spans): has_end_of_diff = start >= span[0] and start < span[1] has_all_of_diff = start <= span[0] and end >= span[1] has_head_of_diff = end >= span[0] and end <= span[1] selected_diff =(has_end_of_diff or has_all_of_diff or has_head_of_diff) if selected_diff: diff = '\n'.join(self._diffs[idx]) diffs.append(diff) indices.append(idx) return diffs, indices def parse_diff(self, diff): """Parses a diff and extracts headers, offsets, hunks, etc. """ total_offset = 0 self._idx = -1 for line in diff.split('\n'): match = self.HEADER_RE.match(line) if match: self._ranges.append(Range(match.group(1), match.group(2))) self._diffs.append([line]) line_len = len(line) + 1 #\n self._diff_spans.append([total_offset, total_offset + line_len]) total_offset += line_len self._diff_offsets.append(total_offset) self._idx += 1 continue if self._idx < 0: errmsg = 'Malformed diff?: %s' % diff raise AssertionError(errmsg) line_len = len(line) + 1 total_offset += line_len self._diffs[self._idx].append(line) self._diff_spans[-1][-1] += line_len self._diff_offsets[self._idx] += line_len def process_diff_selection(self, selected, offset, selection, apply_to_worktree=False): """Processes a diff selection and applies changes to git.""" if selection: # qt destroys \r\n and makes it \n with no way of going back. # boo! we work around that here. # I think this was win32-specific. We might want to do # this on win32 only (TODO verify) if selection not in self.fwd_diff: special_selection = selection.replace('\n', '\r\n') if special_selection in self.fwd_diff: selection = special_selection else: return 0, '' start = self.fwd_diff.index(selection) end = start + len(selection) self.set_diffs_to_range(start, end) else: self.set_diff_to_offset(offset) selected = False output = '' error = '' status = 0 # Process diff selection only if selected: encoding = self.config.file_encoding(self.filename) for idx in self.selected: contents = self.diff_subset(idx, start, end) if not contents: continue tmpfile = utils.tmp_filename('selection') core.write(tmpfile, contents, encoding=encoding) if apply_to_worktree: stat, out, err = self.model.apply_diff_to_worktree(tmpfile) output += out error += err status = max(status, stat) else: stat, out, err = self.model.apply_diff(tmpfile) output += out error += err status = max(status, stat) os.unlink(tmpfile) # Process a complete hunk else: for idx, diff in enumerate(self.diff_sel): tmpfile = utils.tmp_filename('patch%02d' % idx) if not self.write_diff(tmpfile,idx): continue if apply_to_worktree: stat, out, err = self.model.apply_diff_to_worktree(tmpfile) output += out error += err status = max(status, stat) else: stat, out, err = self.model.apply_diff(tmpfile) output += out error += err status = max(status, stat) os.unlink(tmpfile) return status, output, error git-cola-1.9.3/cola/difftool.py000066400000000000000000000121761225156173500163370ustar00rootroot00000000000000from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import core from cola import utils from cola import qtutils from cola import gitcmds from cola.i18n import N_ from cola.models import main from cola.models import selection from cola.widgets import completion from cola.widgets import defs from cola.widgets import standard def run(): files = selection.selected_group() if not files: return s = selection.selection() model = main.model() launch_with_head(files, bool(s.staged), model.head) def launch_with_head(filenames, staged, head): args = [] if staged: args.append('--cached') if head != 'HEAD': args.append(head) args.append('--') args.extend(filenames) launch(args) def launch(args): """Launches 'git difftool' with args""" difftool_args = ['git', 'difftool', '--no-prompt'] difftool_args.extend(args) core.fork(difftool_args) def diff_commits(parent, a, b): dlg = FileDiffDialog(parent, a=a, b=b) dlg.show() dlg.raise_() return dlg.exec_() == QtGui.QDialog.Accepted def diff_expression(parent, expr, create_widget=False, hide_expr=False): dlg = FileDiffDialog(parent, expr=expr, hide_expr=hide_expr) if create_widget: return dlg dlg.show() dlg.raise_() return dlg.exec_() == QtGui.QDialog.Accepted class FileDiffDialog(QtGui.QDialog): def __init__(self, parent, a=None, b=None, expr=None, title=None, hide_expr=False): QtGui.QDialog.__init__(self, parent) self.setAttribute(Qt.WA_MacMetalStyle) self.a = a self.b = b self.expr = expr if title is None: title = N_('git-cola diff') self.setWindowTitle(title) self.setWindowModality(QtCore.Qt.WindowModal) self._expr = completion.GitRefLineEdit(parent=self) if expr is not None: self._expr.setText(expr) if expr is None or hide_expr: self._expr.hide() self._tree = standard.TreeWidget(self) self._tree.setSelectionMode(self._tree.ExtendedSelection) self._tree.setHeaderHidden(True) self._diff_btn = QtGui.QPushButton(N_('Compare')) self._diff_btn.setIcon(qtutils.ok_icon()) self._diff_btn.setEnabled(False) self._close_btn = QtGui.QPushButton(N_('Close')) self._close_btn.setIcon(qtutils.close_icon()) self._button_layt = QtGui.QHBoxLayout() self._button_layt.setMargin(0) self._button_layt.addStretch() self._button_layt.addWidget(self._diff_btn) self._button_layt.addWidget(self._close_btn) self._layt = QtGui.QVBoxLayout() self._layt.setMargin(defs.margin) self._layt.setSpacing(defs.spacing) self._layt.addWidget(self._expr) self._layt.addWidget(self._tree) self._layt.addLayout(self._button_layt) self.setLayout(self._layt) self.connect(self._tree, SIGNAL('itemSelectionChanged()'), self._tree_selection_changed) self.connect(self._tree, SIGNAL('itemDoubleClicked(QTreeWidgetItem*,int)'), self._tree_double_clicked) self.connect(self._expr, SIGNAL('textChanged(QString)'), self.text_changed) self.connect(self._expr, SIGNAL('returnPressed()'), self.refresh) qtutils.connect_button(self._diff_btn, self.diff) qtutils.connect_button(self._close_btn, self.close) qtutils.add_close_action(self) self.resize(720, 420) self.refresh() def text_changed(self, txt): self.expr = unicode(txt) self.refresh() def refresh(self): if self.expr is not None: self.diff_arg = utils.shell_split(self.expr) elif self.b is None: self.diff_arg = [self.a] else: self.diff_arg = [self.a, self.b] self.refresh_filenames() def refresh_filenames(self): self._tree.clear() if self.a and self.b is None: filenames = gitcmds.diff_index_filenames(self.a) else: filenames = gitcmds.diff(self.diff_arg) if not filenames: return icon = qtutils.file_icon() items = [] for filename in filenames: item = QtGui.QTreeWidgetItem() item.setIcon(0, icon) item.setText(0, filename) item.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(filename)) items.append(item) self._tree.addTopLevelItems(items) def _tree_selection_changed(self): self._diff_btn.setEnabled(bool(self._tree.selectedItems())) def _tree_double_clicked(self, item, column): path = item.data(0, QtCore.Qt.UserRole).toPyObject() launch(self.diff_arg + ['--', unicode(path)]) def diff(self): items = self._tree.selectedItems() if not items: return paths = [i.data(0, QtCore.Qt.UserRole).toPyObject() for i in items] for path in paths: launch(self.diff_arg + ['--', unicode(path)]) git-cola-1.9.3/cola/git.py000066400000000000000000000166731225156173500153220ustar00rootroot00000000000000import os import sys import subprocess import threading from os.path import join from cola import core from cola.decorators import memoize from cola.interaction import Interaction INDEX_LOCK = threading.Lock() GIT_COLA_TRACE = core.getenv('GIT_COLA_TRACE', '') STATUS = 0 STDOUT = 1 STDERR = 2 def dashify(s): return s.replace('_', '-') def is_git_dir(d): """From git's setup.c:is_git_directory().""" if (core.isdir(d) and core.isdir(join(d, 'objects')) and core.isdir(join(d, 'refs'))): headref = join(d, 'HEAD') return (core.isfile(headref) or (core.islink(headref) and core.readlink(headref).startswith('refs'))) return is_git_file(d) def is_git_file(f): return core.isfile(f) and '.git' == os.path.basename(f) def is_git_worktree(d): return is_git_dir(join(d, '.git')) def read_git_file(path): if path is None: return None if is_git_file(path): data = core.read(path).strip() if data.startswith('gitdir: '): return data[len('gitdir: '):] return None class Git(object): """ The Git class manages communication with the Git binary """ def __init__(self): self._git_cwd = None #: The working directory used by execute() self._worktree = None self._git_file_path = None self.set_worktree(core.getcwd()) def set_worktree(self, path): self._git_dir = path self._git_file_path = None self._worktree = None self.worktree() def worktree(self): if self._worktree: return self._worktree self.git_dir() if self._git_dir: curdir = self._git_dir else: curdir = core.getcwd() if is_git_dir(join(curdir, '.git')): return curdir # Handle bare repositories if (len(os.path.basename(curdir)) > 4 and curdir.endswith('.git')): return curdir if 'GIT_WORK_TREE' in os.environ: self._worktree = core.getenv('GIT_WORK_TREE') if not self._worktree or not core.isdir(self._worktree): if self._git_dir: gitparent = join(core.abspath(self._git_dir), '..') self._worktree = core.abspath(gitparent) self.set_cwd(self._worktree) return self._worktree def is_valid(self): return self._git_dir and is_git_dir(self._git_dir) def git_path(self, *paths): if self._git_file_path is None: return join(self.git_dir(), *paths) else: return join(self._git_file_path, *paths) def git_dir(self): if self.is_valid(): return self._git_dir if 'GIT_DIR' in os.environ: self._git_dir = core.getenv('GIT_DIR') if self._git_dir: curpath = core.abspath(self._git_dir) else: curpath = core.abspath(core.getcwd()) # Search for a .git directory while curpath: if is_git_dir(curpath): self._git_dir = curpath break gitpath = join(curpath, '.git') if is_git_dir(gitpath): self._git_dir = gitpath break curpath, dummy = os.path.split(curpath) if not dummy: break self._git_file_path = read_git_file(self._git_dir) return self._git_dir def set_cwd(self, path): """Sets the current directory.""" self._git_cwd = path def __getattr__(self, name): if name[:1] == '_': raise AttributeError(name) return lambda *args, **kwargs: self._call_process(name, *args, **kwargs) @staticmethod def execute(command, _cwd=None, _stdin=None, _raw=False, _decode=True, _encoding=None): """ Execute a command and returns its output :param command: argument list to execute. :param _cwd: working directory, defaults to the current directory. :param _decode: whether to decode output, defaults to True. :param _encoding: default encoding, defaults to None (utf-8). :param _raw: do not strip trailing whitespace. :param _stdin: optional stdin filehandle. :returns (status, out, err): exit status, stdout, stderr """ # Allow the user to have the command executed in their working dir. if not _cwd: _cwd = core.getcwd() extra = {} if sys.platform == 'win32': command = map(replace_carot, command) extra['shell'] = True # Start the process # Guard against thread-unsafe .git/index.lock files INDEX_LOCK.acquire() status, out, err = core.run_command(command, cwd=_cwd, stdin=_stdin, **extra) # Let the next thread in INDEX_LOCK.release() if _decode: out = core.decode(out, encoding=_encoding) err = core.decode(err, encoding=_encoding) if not _raw: out = out.rstrip('\n') cola_trace = GIT_COLA_TRACE if cola_trace == 'trace': msg = 'trace: ' + subprocess.list2cmdline(command) Interaction.log_status(status, msg, '') elif cola_trace == 'full': if out: core.stderr("%s -> %d: '%s' '%s'" % (' '.join(command), status, out, err)) else: core.stderr("%s -> %d" % (' '.join(command), status)) elif cola_trace: core.stderr(' '.join(command)) # Allow access to the command's status code return (status, out, err) def transform_kwargs(self, **kwargs): """Transform kwargs into git command line options""" args = [] for k, v in kwargs.items(): if len(k) == 1: if v is True: args.append("-%s" % k) elif type(v) is not bool: args.append("-%s%s" % (k, v)) else: if v is True: args.append("--%s" % dashify(k)) elif type(v) is not bool: args.append("--%s=%s" % (dashify(k), v)) return args def _call_process(self, cmd, *args, **kwargs): # Handle optional arguments prior to calling transform_kwargs # otherwise they'll end up in args, which is bad. _kwargs = dict(_cwd=self._git_cwd) execute_kwargs = ('_cwd', '_stdin', '_decode', '_encoding', '_raw') for kwarg in execute_kwargs: if kwarg in kwargs: _kwargs[kwarg] = kwargs.pop(kwarg) # Prepare the argument list opt_args = self.transform_kwargs(**kwargs) call = ['git', dashify(cmd)] + opt_args call.extend(args) return self.execute(call, **_kwargs) def replace_carot(cmd_arg): """ Guard against the windows command shell. In the Windows shell, a carat character (^) may be used for line continuation. To guard against this, escape the carat by using two of them. http://technet.microsoft.com/en-us/library/cc723564.aspx """ return cmd_arg.replace('^', '^^') @memoize def instance(): """Return the Git singleton""" return Git() git = instance() """ Git command singleton >>> from cola.git import git >>> from cola.git import STDOUT >>> 'git' == git.version()[STDOUT][:3].lower() True """ git-cola-1.9.3/cola/gitcfg.py000066400000000000000000000211151225156173500157650ustar00rootroot00000000000000import copy import fnmatch from os.path import join from cola import core from cola import git from cola import observable from cola.decorators import memoize from cola.git import STDOUT @memoize def instance(): """Return a static GitConfig instance.""" return GitConfig() _USER_CONFIG = core.expanduser(join('~', '.gitconfig')) _USER_XDG_CONFIG = core.expanduser( join(core.getenv('XDG_CONFIG_HOME', join('~', '.config')), 'git', 'config')) def _stat_info(): # Try /etc/gitconfig as a fallback for the system config paths = (('system', '/etc/gitconfig'), ('user', _USER_XDG_CONFIG), ('user', _USER_CONFIG), ('repo', git.instance().git_path('config'))) statinfo = [] for category, path in paths: try: statinfo.append((category, path, core.stat(path).st_mtime)) except OSError: continue return statinfo def _cache_key(): # Try /etc/gitconfig as a fallback for the system config paths = ('/etc/gitconfig', _USER_XDG_CONFIG, _USER_CONFIG, git.instance().git_path('config')) mtimes = [] for path in paths: try: mtimes.append(core.stat(path).st_mtime) except OSError: continue return mtimes class GitConfig(observable.Observable): """Encapsulate access to git-config values.""" message_user_config_changed = 'user_config_changed' message_repo_config_changed = 'repo_config_changed' def __init__(self): observable.Observable.__init__(self) self.git = git.instance() self._map = {} self._system = {} self._user = {} self._repo = {} self._all = {} self._cache_key = None self._configs = [] self._config_files = {} self._value_cache = {} self._attr_cache = {} self._find_config_files() def reset(self): self._map.clear() self._system.clear() self._user.clear() self._repo.clear() self._all.clear() self._cache_key = None self._configs = [] self._config_files.clear() self._value_cache = {} self._attr_cache = {} self._find_config_files() def user(self): return copy.deepcopy(self._user) def repo(self): return copy.deepcopy(self._repo) def all(self): return copy.deepcopy(self._all) def _find_config_files(self): """ Classify git config files into 'system', 'user', and 'repo'. Populates self._configs with a list of the files in reverse-precedence order. self._config_files is populated with {category: path} where category is one of 'system', 'user', or 'repo'. """ # Try the git config in git's installation prefix statinfo = _stat_info() self._configs = map(lambda x: x[1], statinfo) self._config_files = {} for (cat, path, mtime) in statinfo: self._config_files[cat] = path def update(self): """Read config values from git.""" if self._cached(): return self._read_configs() def _cached(self): """ Return True when the cache matches. Updates the cache and returns False when the cache does not match. """ cache_key = _cache_key() if self._cache_key is None or cache_key != self._cache_key: self._cache_key = cache_key return False return True def _read_configs(self): """Read git config value into the system, user and repo dicts.""" self._map.clear() self._system.clear() self._user.clear() self._repo.clear() self._all.clear() if 'system' in self._config_files: self._system.update( self.read_config(self._config_files['system'])) if 'user' in self._config_files: self._user.update( self.read_config(self._config_files['user'])) if 'repo' in self._config_files: self._repo.update( self.read_config(self._config_files['repo'])) for dct in (self._system, self._user, self._repo): self._all.update(dct) def read_config(self, path): """Return git config data from a path as a dictionary.""" dest = {} args = ('--null', '--file', path, '--list') config_lines = self.git.config(*args)[STDOUT].split('\0') for line in config_lines: try: k, v = line.split('\n', 1) except ValueError: # the user has an invalid entry in their git config if not line: continue k = line v = 'true' if v in ('true', 'yes'): v = True elif v in ('false', 'no'): v = False else: try: v = int(v) except ValueError: pass self._map[k.lower()] = k dest[k] = v return dest def _get(self, src, key, default): self.update() try: return src[key] except KeyError: pass key = self._map.get(key.lower(), key) try: return src[key] except KeyError: return src.get(key.lower(), default) def get(self, key, default=None): """Return the string value for a config key.""" return self._get(self._all, key, default) def get_user(self, key, default=None): return self._get(self._user, key, default) def get_repo(self, key, default=None): return self._get(self._repo, key, default) def python_to_git(self, value): if type(value) is bool: if value: return 'true' else: return 'false' if type(value) is int: return unicode(value) return value def set_user(self, key, value): msg = self.message_user_config_changed self.git.config('--global', key, self.python_to_git(value)) self.update() self.notify_observers(msg, key, value) def set_repo(self, key, value): msg = self.message_repo_config_changed self.git.config(key, self.python_to_git(value)) self.update() self.notify_observers(msg, key, value) def find(self, pat): pat = pat.lower() match = fnmatch.fnmatch result = {} self.update() for key, val in self._all.items(): if match(key, pat): result[key] = val return result def get_cached(self, key, default=None): cache = self._value_cache try: value = cache[key] except KeyError: value = cache[key] = self.get(key, default=default) return value def gui_encoding(self): return self.get_cached('gui.encoding', default='utf-8') def is_per_file_attrs_enabled(self): return self.get_cached('cola.fileattributes', default=False) def file_encoding(self, path): if not self.is_per_file_attrs_enabled(): return None cache = self._attr_cache try: value = cache[path] except KeyError: value = cache[path] = self._file_encoding(path) return value def _file_encoding(self, path): """Return the file encoding for a path""" status, out, err = self.git.check_attr('encoding', '--', path) if status != 0: return None header = '%s: encoding: ' % path if out.startswith(header): encoding = out[len(header):].strip() if (encoding != 'unspecified' and encoding != 'unset' and encoding != 'set'): return encoding return None guitool_opts = ('cmd', 'needsfile', 'noconsole', 'norescan', 'confirm', 'argprompt', 'revprompt', 'revunmerged', 'title', 'prompt') def get_guitool_opts(self, name): """Return the guitool. namespace as a dict""" keyprefix = 'guitool.' + name + '.' opts = {} for cfg in self.guitool_opts: value = self.get(keyprefix + cfg) if value is None: continue opts[cfg] = value return opts def get_guitool_names(self): guitools = self.find('guitool.*.cmd') prefix = len('guitool.') suffix = len('.cmd') return sorted([name[prefix:-suffix] for (name, cmd) in guitools.items()]) git-cola-1.9.3/cola/gitcmds.py000066400000000000000000000435131225156173500161620ustar00rootroot00000000000000"""Provides commands and queries for Git.""" import re from cStringIO import StringIO from cola import core from cola import gitcfg from cola import utils from cola import version from cola.compat import set from cola.git import git from cola.git import STDOUT from cola.i18n import N_ config = gitcfg.instance() class InvalidRepositoryError(StandardError): pass def default_remote(config=None): """Return the remote tracked by the current branch.""" if config is None: config = gitcfg.instance() return config.get('branch.%s.remote' % current_branch()) def diff_index_filenames(ref): """Return a of filenames that have been modified relative to the index""" out = git.diff_index(ref, name_only=True, z=True)[STDOUT] return _parse_diff_filenames(out) def diff_filenames(*args): """Return a list of filenames that have been modified""" out = git.diff_tree(name_only=True, no_commit_id=True, r=True, z=True, *args)[STDOUT] return _parse_diff_filenames(out) def diff(args): """Return a list of filenames for the given diff arguments :param args: list of arguments to pass to "git diff --name-only" """ out = git.diff(name_only=True, z=True, *args)[STDOUT] return _parse_diff_filenames(out) def _parse_diff_filenames(out): if out: return out[:-1].split('\0') else: return [] def all_files(): """Return the names of all files in the repository""" out = git.ls_files(z=True)[STDOUT] if out: return out[:-1].split('\0') else: return [] class _current_branch: """Cache for current_branch()""" key = None value = None def clear_cache(): _current_branch.key = None def current_branch(): """Return the current branch""" head = git.git_path('HEAD') try: key = core.stat(head).st_mtime if _current_branch.key == key: return _current_branch.value except OSError: pass status, data, err = git.rev_parse('HEAD', symbolic_full_name=True) if status != 0: # git init -- read .git/HEAD. We could do this unconditionally... data = _read_git_head(head) for refs_prefix in ('refs/heads/', 'refs/remotes/', 'refs/tags/'): if data.startswith(refs_prefix): value = data[len(refs_prefix):] _current_branch.key = key _current_branch.value = value return value # Detached head return data def _read_git_head(head, default='master', git=git): """Pure-python .git/HEAD reader""" # Legacy .git/HEAD symlinks if core.islink(head): refs_heads = core.realpath(git.git_path('refs', 'heads')) path = core.abspath(head).replace('\\', '/') if path.startswith(refs_heads + '/'): return path[len(refs_heads)+1:] # Common .git/HEAD "ref: refs/heads/master" file elif core.isfile(head): data = core.read(head).rstrip() ref_prefix = 'ref: ' if data.startswith(ref_prefix): return data[len(ref_prefix):] # Detached head return data return default def branch_list(remote=False): """ Return a list of local or remote branches This explicitly removes HEAD from the list of remote branches. """ if remote: return for_each_ref_basename('refs/remotes') else: return for_each_ref_basename('refs/heads') def for_each_ref_basename(refs, git=git): """Return refs starting with 'refs'.""" out = git.for_each_ref(refs, format='%(refname)')[STDOUT] output = out.splitlines() non_heads = filter(lambda x: not x.endswith('/HEAD'), output) return map(lambda x: x[len(refs) + 1:], non_heads) def all_refs(split=False, git=git): """Return a tuple of (local branches, remote branches, tags).""" local_branches = [] remote_branches = [] tags = [] triple = lambda x, y: (x, len(x) + 1, y) query = (triple('refs/tags', tags), triple('refs/heads', local_branches), triple('refs/remotes', remote_branches)) out = git.for_each_ref(format='%(refname)')[STDOUT] for ref in out.splitlines(): for prefix, prefix_len, dst in query: if ref.startswith(prefix) and not ref.endswith('/HEAD'): dst.append(ref[prefix_len:]) continue if split: return local_branches, remote_branches, tags else: return local_branches + remote_branches + tags def tracked_branch(branch=None, config=None): """Return the remote branch associated with 'branch'.""" if config is None: config = gitcfg.instance() if branch is None: branch = current_branch() if branch is None: return None remote = config.get('branch.%s.remote' % branch) if not remote: return None merge_ref = config.get('branch.%s.merge' % branch) if not merge_ref: return None refs_heads = 'refs/heads/' if merge_ref.startswith(refs_heads): return remote + '/' + merge_ref[len(refs_heads):] return None def untracked_files(git=git): """Returns a sorted list of untracked files.""" out = git.ls_files(z=True, others=True, exclude_standard=True)[STDOUT] if out: return out[:-1].split('\0') return [] def tag_list(): """Return a list of tags.""" tags = for_each_ref_basename('refs/tags') tags.reverse() return tags def log(git, *args, **kwargs): return git.log(no_color=True, no_ext_diff=True, *args, **kwargs)[STDOUT] def commit_diff(sha1, git=git): return log(git, '-1', sha1, '--') + '\n\n' + sha1_diff(git, sha1) _diff_overrides = {} def update_diff_overrides(space_at_eol, space_change, all_space, function_context): _diff_overrides['ignore_space_at_eol'] = space_at_eol _diff_overrides['ignore_space_change'] = space_change _diff_overrides['ignore_all_space'] = all_space _diff_overrides['function_context'] = function_context def common_diff_opts(config=config): submodule = version.check('diff-submodule', version.git_version()) opts = { 'patience': True, 'submodule': submodule, 'no_color': True, 'no_ext_diff': True, 'unified': config.get('gui.diffcontext', 3), '_raw': True, } opts.update(_diff_overrides) return opts def sha1_diff(git, sha1): return git.diff(sha1+'^!', **common_diff_opts())[STDOUT] def diff_info(sha1, git=git): decoded = log(git, '-1', sha1, '--', pretty='format:%b').strip() if decoded: decoded += '\n\n' return decoded + sha1_diff(git, sha1) def diff_helper(commit=None, ref=None, endref=None, filename=None, cached=True, head=None, amending=False, with_diff_header=False, suppress_header=True, reverse=False, git=git): "Invokes git diff on a filepath." if commit: ref, endref = commit+'^', commit argv = [] if ref and endref: argv.append('%s..%s' % (ref, endref)) elif ref: for r in utils.shell_split(ref.strip()): argv.append(r) elif head and amending and cached: argv.append(head) encoding = None if filename: argv.append('--') if type(filename) is list: argv.extend(filename) else: argv.append(filename) encoding = config.file_encoding(filename) if filename is not None: deleted = cached and not core.exists(filename) else: deleted = False status, out, err = git.diff(R=reverse, M=True, cached=cached, _encoding=encoding, *argv, **common_diff_opts()) if status != 0: # git init if with_diff_header: return ('', '') else: return '' return extract_diff_header(status, deleted, with_diff_header, suppress_header, out) def extract_diff_header(status, deleted, with_diff_header, suppress_header, diffoutput): encode = core.encode headers = [] if diffoutput.startswith('Submodule'): if with_diff_header: return ('', diffoutput) else: return diffoutput start = False del_tag = 'deleted file mode ' output = StringIO() diff = diffoutput.split('\n') for line in diff: if not start and '@@' == line[:2] and '@@' in line[2:]: start = True if start or (deleted and del_tag in line): output.write(encode(line) + '\n') else: if with_diff_header: headers.append(line) elif not suppress_header: output.write(encode(line) + '\n') result = core.decode(output.getvalue()) output.close() if with_diff_header: return('\n'.join(headers), result) else: return result def format_patchsets(to_export, revs, output='patches'): """ Group contiguous revision selection into patchsets Exists to handle multi-selection. Multiple disparate ranges in the revision selection are grouped into continuous lists. """ outs = [] errs = [] cur_rev = to_export[0] cur_master_idx = revs.index(cur_rev) patches_to_export = [[cur_rev]] patchset_idx = 0 # Group the patches into continuous sets for idx, rev in enumerate(to_export[1:]): # Limit the search to the current neighborhood for efficiency master_idx = revs[cur_master_idx:].index(rev) master_idx += cur_master_idx if master_idx == cur_master_idx + 1: patches_to_export[ patchset_idx ].append(rev) cur_master_idx += 1 continue else: patches_to_export.append([ rev ]) cur_master_idx = master_idx patchset_idx += 1 # Export each patchsets status = 0 for patchset in patches_to_export: stat, out, err = export_patchset(patchset[0], patchset[-1], output='patches', n=len(patchset) > 1, thread=True, patch_with_stat=True) outs.append(out) if err: errs.append(err) status = max(stat, status) return (status, '\n'.join(outs), '\n'.join(errs)) def export_patchset(start, end, output='patches', **kwargs): """Export patches from start^ to end.""" return git.format_patch('-o', output, start + '^..' + end, **kwargs) def unstage_paths(args, head='HEAD'): status, out, err = git.reset(head, '--', *set(args)) if status == 128: # handle git init: we have to use 'git rm --cached' # detect this condition by checking if the file is still staged return untrack_paths(args, head=head) else: return (status, out, err) def untrack_paths(args, head='HEAD'): if not args: return (-1, N_('Nothing to do'), '') return git.update_index('--', force_remove=True, *set(args)) def worktree_state(head='HEAD'): """Return a tuple of files in various states of being Can be staged, unstaged, untracked, unmerged, or changed upstream. """ state = worktree_state_dict(head=head) return(state.get('staged', []), state.get('modified', []), state.get('unmerged', []), state.get('untracked', []), state.get('upstream_changed', [])) def worktree_state_dict(head='HEAD', update_index=False, display_untracked=True): """Return a dict of files in various states of being :rtype: dict, keys are staged, unstaged, untracked, unmerged, changed_upstream, and submodule. """ if update_index: git.update_index(refresh=True) staged, unmerged, staged_submods = diff_index(head) modified, modified_submods = diff_worktree() untracked = display_untracked and untracked_files() or [] # Remove unmerged paths from the modified list unmerged_set = set(unmerged) modified_set = set(modified) modified_unmerged = modified_set.intersection(unmerged_set) for path in modified_unmerged: modified.remove(path) # All submodules submodules = staged_submods.union(modified_submods) # Only include the submodule in the staged list once it has # been staged. Otherwise, we'll see the submodule as being # both modified and staged. modified_submods = modified_submods.difference(staged_submods) # Add submodules to the staged and unstaged lists staged.extend(list(staged_submods)) modified.extend(list(modified_submods)) # Look for upstream modified files if this is a tracking branch upstream_changed = diff_upstream(head) # Keep stuff sorted staged.sort() modified.sort() unmerged.sort() untracked.sort() upstream_changed.sort() return {'staged': staged, 'modified': modified, 'unmerged': unmerged, 'untracked': untracked, 'upstream_changed': upstream_changed, 'submodules': submodules} def diff_index(head, cached=True): submodules = set() staged = [] unmerged = [] status, out, err = git.diff_index(head, '--', cached=cached, z=True) if status != 0: # handle git init return all_files(), unmerged, submodules while out: rest, out = out.split('\0', 1) name, out = out.split('\0', 1) status = rest[-1] if '160000' in rest[1:14]: submodules.add(name) elif status in 'DAMT': staged.append(name) elif status == 'U': unmerged.append(name) return staged, unmerged, submodules def diff_worktree(): modified = [] submodules = set() status, out, err = git.diff_files(z=True) if status != 0: # handle git init out = git.ls_files(modified=True, z=True)[STDOUT] if out: modified = out[:-1].split('\0') return modified, submodules while out: rest, out = out.split('\0', 1) name, out = out.split('\0', 1) status = rest[-1] if '160000' in rest[1:14]: submodules.add(name) elif status in 'DAMT': modified.append(name) return modified, submodules def diff_upstream(head): tracked = tracked_branch() if not tracked: return [] base = merge_base(head, tracked) return diff_filenames(base, tracked) def _branch_status(branch): """ Returns a tuple of staged, unstaged, untracked, and unmerged files This shows only the changes that were introduced in branch """ staged = diff_filenames(branch) return {'staged': staged, 'upstream_changed': staged} def merge_base(head, ref): """Given `ref`, return $(git merge-base ref HEAD)..ref.""" return git.merge_base(head, ref)[STDOUT] def merge_base_parent(branch): tracked = tracked_branch(branch=branch) if tracked: return tracked return 'HEAD' def parse_ls_tree(rev): """Return a list of(mode, type, sha1, path) tuples.""" output = [] lines = git.ls_tree(rev, r=True)[STDOUT].splitlines() regex = re.compile(r'^(\d+)\W(\w+)\W(\w+)[ \t]+(.*)$') for line in lines: match = regex.match(line) if match: mode = match.group(1) objtype = match.group(2) sha1 = match.group(3) filename = match.group(4) output.append((mode, objtype, sha1, filename,) ) return output # A regex for matching the output of git(log|rev-list) --pretty=oneline REV_LIST_REGEX = re.compile(r'^([0-9a-f]{40}) (.*)$') def parse_rev_list(raw_revs): """Parse `git log --pretty=online` output into (SHA-1, summary) pairs.""" revs = [] for line in raw_revs.splitlines(): match = REV_LIST_REGEX.match(line) if match: rev_id = match.group(1) summary = match.group(2) revs.append((rev_id, summary,)) return revs def log_helper(all=False, extra_args=None): """Return parallel arrays containing the SHA-1s and summaries.""" revs = [] summaries = [] args = [] if extra_args: args = extra_args output = log(git, pretty='oneline', all=all, *args) for line in output.splitlines(): match = REV_LIST_REGEX.match(line) if match: revs.append(match.group(1)) summaries.append(match.group(2)) return (revs, summaries) def rev_list_range(start, end): """Return a (SHA-1, summary) pairs between start and end.""" revrange = '%s..%s' % (start, end) out = git.rev_list(revrange, pretty='oneline')[STDOUT] return parse_rev_list(out) def commit_message_path(): """Return the path to .git/GIT_COLA_MSG""" path = git.git_path("GIT_COLA_MSG") if core.exists(path): return path return None def merge_message_path(): """Return the path to .git/MERGE_MSG or .git/SQUASH_MSG.""" for basename in ('MERGE_MSG', 'SQUASH_MSG'): path = git.git_path(basename) if core.exists(path): return path return None def abort_merge(): """Abort a merge by reading the tree at HEAD.""" # Reset the worktree git.read_tree('HEAD', reset=True, u=True, v=True) # remove MERGE_HEAD merge_head = git.git_path('MERGE_HEAD') if core.exists(merge_head): core.unlink(merge_head) # remove MERGE_MESSAGE, etc. merge_msg_path = merge_message_path() while merge_msg_path: core.unlink(merge_msg_path) merge_msg_path = merge_message_path() def merge_message(revision): """Return a merge message for FETCH_HEAD.""" fetch_head = git.git_path('FETCH_HEAD') if core.exists(fetch_head): return git.fmt_merge_msg('--file', fetch_head)[STDOUT] return "Merge branch '%s'" % revision git-cola-1.9.3/cola/gravatar.py000066400000000000000000000072051225156173500163350ustar00rootroot00000000000000import time import urllib from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4 import QtNetwork from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import resources from cola.compat import hashlib class Gravatar(object): @staticmethod def url_for_email(email, imgsize): email_hash = hashlib.md5(email).hexdigest() default_url = 'http://git-cola.github.io/images/git-64x64.jpg' encoded_url = urllib.quote(default_url, '') query = '?s=%d&d=%s' % (imgsize, encoded_url) url = 'http://gravatar.com/avatar/' + email_hash + query return url class GravatarLabel(QtGui.QLabel): def __init__(self, parent=None): QtGui.QLabel.__init__(self, parent) self.email = None self.response = None self.timeout = 0 self.imgsize = 48 self.pixmaps = {} self.network = QtNetwork.QNetworkAccessManager() self.connect(self.network, SIGNAL('finished(QNetworkReply*)'), self.network_finished) def set_email(self, email): if email in self.pixmaps: self.setPixmap(self.pixmaps[email]) return if (self.timeout > 0 and (int(time.time()) - self.timeout) < (5 * 60)): self.set_pixmap_from_response() return if email == self.email and self.response is not None: self.set_pixmap_from_response() return self.email = email self.request(email) def request(self, email): url = Gravatar.url_for_email(email, self.imgsize) self.network.get(QtNetwork.QNetworkRequest(QtCore.QUrl(url))) def default_pixmap_as_bytes(self): xres = self.imgsize pixmap = QtGui.QPixmap(resources.icon('git.svg')) pixmap = pixmap.scaledToHeight(xres, Qt.SmoothTransformation) byte_array = QtCore.QByteArray() buf = QtCore.QBuffer(byte_array) buf.open(QtCore.QIODevice.WriteOnly) pixmap.save(buf, 'PNG') buf.close() return byte_array def network_finished(self, reply): email = self.email header = QtCore.QByteArray('Location') raw_header = reply.rawHeader(header) if raw_header: location = unicode(QtCore.QString(raw_header)).strip() request_location = unicode( Gravatar.url_for_email(self.email, self.imgsize)) relocated = location != request_location else: relocated = False if reply.error() == QtNetwork.QNetworkReply.NoError: if relocated: # We could do get_url(urllib.unquote(location)) to # download the default image. # Save bandwidth by using a pixmap. self.response = self.default_pixmap_as_bytes() else: self.response = reply.readAll() self.timeout = 0 else: self.response = self.default_pixmap_as_bytes() self.timeout = int(time.time()) pixmap = self.set_pixmap_from_response() # If the email has not changed (e.g. no other requests) # then we know that this pixmap corresponds to this specific # email address. We can't blindly trust self.email else # we may add cache entries for thee wrong email address. url = Gravatar.url_for_email(email, self.imgsize) if url == unicode(reply.url().toString()): self.pixmaps[email] = pixmap def set_pixmap_from_response(self): pixmap = QtGui.QPixmap() pixmap.loadFromData(self.response) self.setPixmap(pixmap) return pixmap git-cola-1.9.3/cola/guicmds.py000066400000000000000000000170411225156173500161600ustar00rootroot00000000000000import os import re from PyQt4 import QtGui from cola import cmds from cola import core from cola import difftool from cola import gitcmds from cola import qtutils from cola.git import git from cola.i18n import N_ from cola.interaction import Interaction from cola.models import main from cola.widgets import completion from cola.widgets.browse import BrowseDialog from cola.widgets.grep import run_grep from cola.widgets.selectcommits import select_commits def delete_branch(): """Launch the 'Delete Branch' dialog.""" branch = choose_branch(N_('Delete Branch'), N_('Delete')) if not branch: return cmds.do(cmds.DeleteBranch, branch) def delete_remote_branch(): """Launch the 'Delete Remote Branch' dialog.""" branch = choose_remote_branch(N_('Delete Remote Branch'), N_('Delete')) if not branch: return rgx = re.compile(r'^(?P[^/]+)/(?P.+)$') match = rgx.match(branch) if match: remote = match.group('remote') branch = match.group('branch') cmds.do(cmds.DeleteRemoteBranch, remote, branch) def browse_current(): """Launch the 'Browse Current Branch' dialog.""" branch = gitcmds.current_branch() BrowseDialog.browse(branch) def browse_other(): """Prompt for a branch and inspect content at that point in time.""" # Prompt for a branch to browse branch = choose_ref(N_('Browse Commits...'), N_('Browse')) if not branch: return BrowseDialog.browse(branch) def checkout_branch(): """Launch the 'Checkout Branch' dialog.""" branch = choose_branch(N_('Checkout Branch'), N_('Checkout')) if not branch: return cmds.do(cmds.CheckoutBranch, branch) def cherry_pick(): """Launch the 'Cherry-Pick' dialog.""" revs, summaries = gitcmds.log_helper(all=True) commits = select_commits(N_('Cherry-Pick Commit'), revs, summaries, multiselect=False) if not commits: return cmds.do(cmds.CherryPick, commits) def new_repo(): """Prompt for a new directory and create a new Git repository :returns str: repository path or None if no repository was created. """ dlg = QtGui.QFileDialog() dlg.setFileMode(QtGui.QFileDialog.Directory) dlg.setOption(QtGui.QFileDialog.ShowDirsOnly) dlg.show() dlg.raise_() if dlg.exec_() != QtGui.QFileDialog.Accepted: return None paths = dlg.selectedFiles() if not paths: return None path = unicode(paths[0]) if not path: return None # Avoid needlessly calling `git init`. if git.is_git_dir(path): # We could prompt here and confirm that they really didn't # mean to open an existing repository, but I think # treating it like an "Open" is a sensible DWIM answer. return path status, out, err = core.run_command(['git', 'init', path]) if status == 0: return path else: title = N_('Error Creating Repository') msg = (N_('"%(command)s" returned exit status %(status)d') % dict(command='git init %s' % path, status=status)) details = N_('Output:\n%s') % out if err: details += '\n\n' details += N_('Errors: %s') % err qtutils.critical(title, msg, details) return None def open_new_repo(): dirname = new_repo() if not dirname: return cmds.do(cmds.OpenRepo, dirname) def clone_repo(spawn=True): """ Present GUI controls for cloning a repository A new cola session is invoked when 'spawn' is True. """ url, ok = qtutils.prompt(N_('Path or URL to clone (Env. $VARS okay)')) url = os.path.expandvars(url) if not ok or not url: return None try: # Pick a suitable basename by parsing the URL newurl = url.replace('\\', '/').rstrip('/') default = newurl.rsplit('/', 1)[-1] if default == '.git': # The end of the URL is /.git, so assume it's a file path default = os.path.basename(os.path.dirname(newurl)) if default.endswith('.git'): # The URL points to a bare repo default = default[:-4] if url == '.': # The URL is the current repo default = os.path.basename(core.getcwd()) if not default: raise except: Interaction.information( N_('Error Cloning'), N_('Could not parse Git URL: "%s"') % url) Interaction.log(N_('Could not parse Git URL: "%s"') % url) return None # Prompt the user for a directory to use as the parent directory msg = N_('Select a parent directory for the new clone') dirname = qtutils.opendir_dialog(msg, main.model().getcwd()) if not dirname: return None count = 1 destdir = os.path.join(dirname, default) olddestdir = destdir if core.exists(destdir): # An existing path can be specified msg = (N_('"%s" already exists, cola will create a new directory') % destdir) Interaction.information('Directory Exists', msg) # Make sure the new destdir doesn't exist while core.exists(destdir): destdir = olddestdir + str(count) count += 1 if cmds.do(cmds.Clone, url, destdir, spawn=spawn): return destdir return None def export_patches(): """Run 'git format-patch' on a list of commits.""" revs, summaries = gitcmds.log_helper() to_export = select_commits(N_('Export Patches'), revs, summaries) if not to_export: return to_export.reverse() revs.reverse() cmds.do(cmds.FormatPatch, to_export, revs) def diff_expression(): """Diff using an arbitrary expression.""" tracked = gitcmds.tracked_branch() current = gitcmds.current_branch() if tracked and current: ref = tracked + '..' + current else: ref = 'origin/master..' difftool.diff_expression(qtutils.active_window(), ref) def grep(): """Prompt and use 'git grep' to find the content.""" widget = run_grep(parent=qtutils.active_window()) widget.show() widget.raise_() return widget def open_repo(): """Spawn a new cola session.""" dirname = qtutils.opendir_dialog(N_('Open Git Repository...'), main.model().getcwd()) if not dirname: return cmds.do(cmds.OpenRepo, dirname) def load_commitmsg(): """Load a commit message from a file.""" filename = qtutils.open_dialog(N_('Load Commit Message'), main.model().getcwd()) if filename: cmds.do(cmds.LoadCommitMessageFromFile, filename) def choose_from_dialog(get, title, button_text, default): parent = qtutils.active_window() return get(title, button_text, parent, default=default) def choose_ref(title, button_text, default=None): return choose_from_dialog(completion.GitRefDialog.get, title, button_text, default) def choose_branch(title, button_text, default=None): return choose_from_dialog(completion.GitBranchDialog.get, title, button_text, default) def choose_remote_branch(title, button_text, default=None): return choose_from_dialog(completion.GitRemoteBranchDialog.get, title, button_text, default) def review_branch(): """Diff against an arbitrary revision, branch, tag, etc.""" branch = choose_ref(N_('Select Branch to Review'), N_('Review')) if not branch: return merge_base = gitcmds.merge_base_parent(branch) difftool.diff_commits(qtutils.active_window(), merge_base, branch) git-cola-1.9.3/cola/i18n.py000066400000000000000000000044461225156173500153110ustar00rootroot00000000000000"""i18n and l10n support for git-cola""" import gettext as _gettext import os import sys from cola import compat from cola import core from cola import resources _null_translation = _gettext.NullTranslations() _translation = _null_translation def gettext(s): txt = _translation.ugettext(s) if txt[-6:-4] == '@@': # handle @@verb / @@noun txt = txt[:-6] return txt def ngettext(s, p, n): return _translation.ungettext(s, p, n) def N_(s): return gettext(s) def install(locale): global _translation if sys.platform == 'win32': _check_win32_locale() if locale: compat.setenv('LANG', locale) compat.setenv('LC_MESSAGES', locale) _install_custom_language() _gettext.textdomain('messages') _translation = _gettext.translation('git-cola', localedir=_get_locale_dir(), fallback=True) def uninstall(): global _translation _translation = _null_translation def _get_locale_dir(): return resources.prefix('share', 'locale') def _install_custom_language(): """Allow a custom language to be set in ~/.config/git-cola/language""" lang_file = resources.config_home('language') if not core.exists(lang_file): return try: lang = core.read(lang_file).strip() except: return if lang: compat.setenv('LANGUAGE', lang) def _check_win32_locale(): for i in ('LANGUAGE','LC_ALL','LC_MESSAGES','LANG'): if os.environ.get(i): break else: lang = None import locale try: import ctypes except ImportError: # use only user's default locale lang = locale.getdefaultlocale()[0] else: # using ctypes to determine all locales lcid_user = ctypes.windll.kernel32.GetUserDefaultLCID() lcid_system = ctypes.windll.kernel32.GetSystemDefaultLCID() if lcid_user != lcid_system: lcid = [lcid_user, lcid_system] else: lcid = [lcid_user] lang = [locale.windows_locale.get(i) for i in lcid] lang = ':'.join([i for i in lang if i]) # set lang code for gettext if lang: compat.setenv('LANGUAGE', lang) git-cola-1.9.3/cola/inotify.py000066400000000000000000000204671225156173500162140ustar00rootroot00000000000000# Copyright (c) 2008 David Aguilar """Provides an inotify plugin for Linux and other systems with pyinotify""" import os from threading import Timer from threading import Lock try: import pyinotify from pyinotify import ProcessEvent from pyinotify import WatchManager from pyinotify import Notifier from pyinotify import EventsCodes AVAILABLE = True except ImportError: ProcessEvent = object AVAILABLE = False from cola import utils if utils.is_win32(): try: import win32file import win32con import pywintypes import win32event AVAILABLE = True except ImportError: ProcessEvent = object AVAILABLE = False from PyQt4 import QtCore from cola import gitcfg from cola import cmds from cola import core from cola.compat import set from cola.git import STDOUT from cola.i18n import N_ from cola.interaction import Interaction from cola.models import main _thread = None def start(): global _thread cfg = gitcfg.instance() if not cfg.get('cola.inotify', True): msg = N_('inotify is disabled because "cola.inotify" is false') Interaction.log(msg) return if not AVAILABLE: if utils.is_win32(): msg = N_('file notification: disabled\n' 'Note: install pywin32 to enable.\n') elif utils.is_linux(): msg = N_('inotify: disabled\n' 'Note: install python-pyinotify to enable inotify.\n') else: return if utils.is_debian(): msg += N_('On Debian systems ' 'try: sudo aptitude install python-pyinotify') Interaction.log(msg) return # Start the notification thread _thread = GitNotifier() _thread.start() if utils.is_win32(): msg = N_('File notification enabled.') else: msg = N_('inotify enabled.') Interaction.log(msg) def stop(): if not has_inotify(): return _thread.stop(True) _thread.wait() def has_inotify(): """Return True if pyinotify is available.""" return AVAILABLE and _thread and _thread.isRunning() class Handler(): """Queues filesystem events for broadcast""" def __init__(self): """Create an event handler""" ## Timer used to prevent notification floods self._timer = None ## Lock to protect files and timer from threading issues self._lock = Lock() def broadcast(self): """Broadcasts a list of all files touched since last broadcast""" with self._lock: cmds.do(cmds.UpdateFileStatus) self._timer = None def handle(self, path): """Queues up filesystem events for broadcast""" with self._lock: if self._timer is None: self._timer = Timer(0.888, self.broadcast) self._timer.start() class FileSysEvent(ProcessEvent): """Generated by GitNotifier in response to inotify events""" def __init__(self): """Maintain event state""" ProcessEvent.__init__(self) ## Takes care of Queueing events for broadcast self._handler = Handler() def process_default(self, event): """Queues up inotify events for broadcast""" if event.name: return path = os.path.join(event.path, event.name) if os.path.exists(path): path = os.path.relpath(path) self._handler.handle(path) class GitNotifier(QtCore.QThread): """Polls inotify for changes and generates FileSysEvents""" def __init__(self, timeout=333): """Set up the pyinotify thread""" QtCore.QThread.__init__(self) ## Git command object self._git = main.model().git ## pyinotify timeout self._timeout = timeout ## Path to monitor self._path = self._git.worktree() ## Signals thread termination self._running = True ## Directories to watching self._dirs_seen = set() ## The inotify watch manager instantiated in run() self._wmgr = None ## Events to capture if utils.is_linux(): self._mask = (EventsCodes.ALL_FLAGS['IN_ATTRIB'] | EventsCodes.ALL_FLAGS['IN_CLOSE_WRITE'] | EventsCodes.ALL_FLAGS['IN_DELETE'] | EventsCodes.ALL_FLAGS['IN_MODIFY'] | EventsCodes.ALL_FLAGS['IN_MOVED_TO']) def stop(self, stopped): """Tells the GitNotifier to stop""" self._timeout = 0 self._running = not stopped def _watch_directory(self, directory): """Set up a directory for monitoring by inotify""" if not self._wmgr: return directory = core.realpath(directory) if not core.exists(directory): return if directory not in self._dirs_seen: self._wmgr.add_watch(directory, self._mask) self._dirs_seen.add(directory) def _is_pyinotify_08x(self): """Is this pyinotify 0.8.x? The pyinotify API changed between 0.7.x and 0.8.x. This allows us to maintain backwards compatibility. """ if hasattr(pyinotify, '__version__'): if pyinotify.__version__[:3] == '0.8': return True return False def run(self): """Create the inotify WatchManager and generate FileSysEvents""" if utils.is_win32(): self.run_win32() return # Only capture events that git cares about self._wmgr = WatchManager() if self._is_pyinotify_08x(): notifier = Notifier(self._wmgr, FileSysEvent(), timeout=self._timeout) else: notifier = Notifier(self._wmgr, FileSysEvent()) self._watch_directory(self._path) # Register files/directories known to git for filename in self._git.ls_files()[STDOUT].splitlines(): filename = core.realpath(filename) directory = os.path.dirname(filename) self._watch_directory(directory) # self._running signals app termination. The timeout is a tradeoff # between fast notification response and waiting too long to exit. while self._running: if self._is_pyinotify_08x(): check = notifier.check_events() else: check = notifier.check_events(timeout=self._timeout) if not self._running: break if check: notifier.read_events() notifier.process_events() notifier.stop() def run_win32(self): """Generate notifications using pywin32""" hdir = win32file.CreateFile( self._path, 0x0001, win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, None, win32con.OPEN_EXISTING, win32con.FILE_FLAG_BACKUP_SEMANTICS | win32con.FILE_FLAG_OVERLAPPED, None) flags = (win32con.FILE_NOTIFY_CHANGE_FILE_NAME | win32con.FILE_NOTIFY_CHANGE_DIR_NAME | win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES | win32con.FILE_NOTIFY_CHANGE_SIZE | win32con.FILE_NOTIFY_CHANGE_LAST_WRITE | win32con.FILE_NOTIFY_CHANGE_SECURITY) buf = win32file.AllocateReadBuffer(8192) overlapped = pywintypes.OVERLAPPED() overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None) handler = Handler() while self._running: win32file.ReadDirectoryChangesW(hdir, buf, True, flags, overlapped) rc = win32event.WaitForSingleObject(overlapped.hEvent, self._timeout) if rc != win32event.WAIT_OBJECT_0: continue nbytes = win32file.GetOverlappedResult(hdir, overlapped, True) if not nbytes: continue results = win32file.FILE_NOTIFY_INFORMATION(buf, nbytes) for action, path in results: if not self._running: break path = path.replace('\\', '/') if (not path.startswith('.git/') and '/.git/' not in path and os.path.isfile(path)): handler.handle(path) git-cola-1.9.3/cola/interaction.py000066400000000000000000000046241225156173500170470ustar00rootroot00000000000000import os import subprocess from cola import core from cola.i18n import N_ class Interaction(object): """Prompts the user and answers questions""" VERBOSE = bool(os.getenv('GIT_COLA_VERBOSE')) @staticmethod def information(title, message=None, details=None, informative_text=None): if message is None: message = title scope = {} scope['title'] = title scope['title_dashes'] = '-' * len(title) scope['message'] = message scope['details'] = details and '\n'+details or '' scope['informative_text'] = (informative_text and '\n'+informative_text or '') print(""" %(title)s %(title_dashes)s %(message)s%(details)s%(informative_text)s""" % scope) @classmethod def critical(cls, title, message=None, details=None): """Show a warning with the provided title and message.""" cls.information(title, message=message, details=details) @classmethod def confirm(cls, title, text, informative_text, ok_text, icon=None, default=True): cls.information(title, message=text, informative_text=informative_text) if default: prompt = '%s? [Y/n]:' % ok_text else: prompt = '%s? [y/N]: ' % ok_text answer = raw_input(prompt) if answer == '': return default return answer.lower().startswith('y') @classmethod def question(cls, title, message, default=True): return cls.confirm(title, message, '', ok_text=N_('Continue'), default=default) @classmethod def run_command(cls, title, cmd): cls.log('$ ' + subprocess.list2cmdline(cmd)) status, out, err = core.run_command(cmd) cls.log_status(status, out, err) @classmethod def confirm_config_action(cls, name, opts): return cls.confirm(N_('Run %s?') % name, N_('Run the "%s" command?') % name, ok_text=N_('Run')) @classmethod def log_status(cls, status, out, err=None): msg = ( (out and ((N_('Output: %s') % out) + '\n') or '') + (err and ((N_('Errors: %s') % err) + '\n') or '') + N_('Exit code: %s') % status ) cls.log(msg) @classmethod def log(cls, message): if cls.VERBOSE: core.stdout(message) git-cola-1.9.3/cola/models/000077500000000000000000000000001225156173500154335ustar00rootroot00000000000000git-cola-1.9.3/cola/models/__init__.py000066400000000000000000000000001225156173500175320ustar00rootroot00000000000000git-cola-1.9.3/cola/models/browse.py000066400000000000000000000340731225156173500173150ustar00rootroot00000000000000import time from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import gitcfg from cola import core from cola import utils from cola import qtutils from cola import version from cola import resources from cola.compat import set from cola.git import STDOUT from cola.i18n import N_ from cola.models import main # Custom event type for GitRepoInfoEvents INFO_EVENT_TYPE = QtCore.QEvent.User + 42 class Columns(object): """Defines columns in the worktree browser""" NAME = 'Name' STATUS = 'Status' AGE = 'Age' MESSAGE = 'Message' AUTHOR = 'Author' ALL = (NAME, STATUS, AGE, MESSAGE, AUTHOR) @classmethod def text(cls, column): if column == cls.NAME: return N_('Name') elif column == cls.STATUS: return N_('Status') elif column == cls.AGE: return N_('Age') elif column == cls.MESSAGE: return N_('Message') elif column == cls.AUTHOR: return N_('Author') else: raise NotImplemented('Mapping required for "%s"' % column) class GitRepoModel(QtGui.QStandardItemModel): """Provides an interface into a git repository for browsing purposes.""" def __init__(self, parent): QtGui.QStandardItemModel.__init__(self, parent) self._interesting_paths = self._get_paths() self._known_paths = set() self.connect(self, SIGNAL('updated'), self._updated_callback) model = main.model() model.add_observer(model.message_updated, self._model_updated) self._dir_rows = {} self.setColumnCount(len(Columns.ALL)) for idx, header in enumerate(Columns.ALL): text = Columns.text(header) self.setHeaderData(idx, Qt.Horizontal, QtCore.QVariant(text)) self._direntries = {'': self.invisibleRootItem()} self._initialize() def _create_column(self, col, path): """Creates a StandardItem for use in a treeview cell.""" # GitRepoNameItem is the only one that returns a custom type(), # so we use to infer selections. if col == Columns.NAME: return GitRepoNameItem(path) return GitRepoItem(col, path) def _create_row(self, path): """Return a list of items representing a row.""" return [self._create_column(c, path) for c in Columns.ALL] def _add_file(self, parent, path, insert=False): """Add a file entry to the model.""" # Create model items row_items = self._create_row(path) # Use a standard file icon for the name field row_items[0].setIcon(qtutils.file_icon()) if not insert: # Add file paths at the end of the list parent.appendRow(row_items) self.entry(path).update_name() self._known_paths.add(path) return # Entries exist so try to find an a good insertion point done = False for idx in xrange(parent.rowCount()): child = parent.child(idx, 0) if child.rowCount() > 0: continue if path < child.path: parent.insertRow(idx, row_items) done = True break # No adequate place found so simply append if not done: parent.appendRow(row_items) self.entry(path).update_name() self._known_paths.add(path) def add_directory(self, parent, path): """Add a directory entry to the model.""" # Create model items row_items = self._create_row(path) # Use a standard directory icon row_items[0].setIcon(qtutils.dir_icon()) # Insert directories before file paths row = self._dir_rows.setdefault(parent, 0) parent.insertRow(row, row_items) self._dir_rows[parent] += 1 # Update the 'name' column for this entry self.entry(path).update_name() self._known_paths.add(path) return row_items[0] def path_is_interesting(self, path): """Return True if path has a status.""" return path in self._interesting_paths def _get_paths(self): """Return paths of interest; e.g. paths with a status.""" model = main.model() paths = set(model.staged + model.unstaged) return utils.add_parents(paths) def _model_updated(self): """Observes model changes and updates paths accordingly.""" self.emit(SIGNAL('updated')) def _updated_callback(self): old_paths = self._interesting_paths new_paths = self._get_paths() for path in new_paths.union(old_paths): if path not in self._known_paths: continue self.entry(path).update() self._interesting_paths = new_paths def _initialize(self): """Iterate over the cola model and create GitRepoItems.""" for path in main.model().everything(): self.add_file(path) def add_file(self, path, insert=False): """Add a file to the model.""" dirname = utils.dirname(path) if dirname in self._direntries: parent = self._direntries[dirname] else: parent = self._create_dir_entry(dirname, self._direntries) self._direntries[dirname] = parent self._add_file(parent, path, insert=insert) def _create_dir_entry(self, dirname, direntries): """ Create a directory entry for the model. This ensures that directories are always listed before files. """ entries = dirname.split('/') curdir = [] parent = self.invisibleRootItem() curdir_append = curdir.append self_add_directory = self.add_directory for entry in entries: curdir_append(entry) path = '/'.join(curdir) if path in direntries: parent = direntries[path] else: grandparent = parent parent = self_add_directory(grandparent, path) direntries[path] = parent return parent def entry(self, path): """Return the GitRepoEntry for a path.""" return GitRepoEntryManager.entry(path) class GitRepoEntryManager(object): """ Provides access to static instances of GitRepoEntry and model data. """ static_entries = {} @classmethod def entry(cls, path, _static_entries=static_entries): """Return a static instance of a GitRepoEntry.""" try: e = _static_entries[path] except KeyError: e = _static_entries[path] = GitRepoEntry(path) return e class TaskRunner(object): """Manages QRunnable task instances to avoid python's garbage collector When PyQt stops referencing a QRunnable instance Python cleans it up which leads to segfaults, e.g. the dreaded "C++ object has gone away". This class keeps track of tasks and cleans up references to them as they complete. """ singleton = None @classmethod def instance(cls): if cls.singleton is None: cls.singleton = TaskRunner() return cls.singleton def __init__(self): self.tasks = set() self.threadpool = QtCore.QThreadPool.globalInstance() self.notifier = QtCore.QObject() self.notifier.connect(self.notifier, SIGNAL('task_done'), self.task_done) def run(self, task): self.tasks.add(task) self.threadpool.start(task) def task_done(self, task): if task in self.tasks: self.tasks.remove(task) def cleanup_task(self, task): self.notifier.emit(SIGNAL('task_done'), task) class GitRepoEntry(QtCore.QObject): """ Provides asynchronous lookup of repository data for a path. Emits signal names matching those defined in Columns. """ def __init__(self, path): QtCore.QObject.__init__(self) self.path = path def update_name(self): """Emits a signal corresponding to the entry's name.""" # 'name' is cheap to calculate so simply emit a signal self.emit(SIGNAL(Columns.NAME), utils.basename(self.path)) if '/' not in self.path: self.update() def update(self): """Starts a GitRepoInfoTask to calculate info for entries.""" # GitRepoInfoTask handles expensive lookups task = GitRepoInfoTask(self.path) TaskRunner.instance().run(task) def event(self, e): """Receive GitRepoInfoEvents and emit corresponding Qt signals.""" if e.type() == INFO_EVENT_TYPE: e.accept() self.emit(SIGNAL(e.signal), *e.data) return True return QtCore.QObject.event(self, e) # Support older versions of PyQt if version.check('pyqt_qrunnable', QtCore.PYQT_VERSION_STR): QRunnable = QtCore.QRunnable else: class QRunnable(object): pass class GitRepoInfoTask(QRunnable): """Handles expensive git lookups for a path.""" def __init__(self, path): QRunnable.__init__(self) self.path = path self._cfg = gitcfg.instance() self._data = {} def data(self, key): """ Return git data for a path. Supported keys are 'date', 'message', and 'author' """ if not self._data: log_line = main.model().git.log('-1', '--', self.path, M=True, all=False, no_color=True, pretty='format:%ar%x01%s%x01%an' )[STDOUT] if log_line: log_line = log_line date, message, author = log_line.split(chr(0x01), 2) self._data['date'] = date self._data['message'] = message self._data['author'] = author else: self._data['date'] = self.date() self._data['message'] = '-' self._data['author'] = self._cfg.get('user.name', 'unknown') return self._data[key] def name(self): """Calculate the name for an entry.""" return utils.basename(self.path) def date(self): """ Returns a relative date for a file path. This is typically used for new entries that do not have 'git log' information. """ st = core.stat(self.path) elapsed = time.time() - st.st_mtime minutes = int(elapsed / 60.) if minutes < 60: return N_('%d minutes ago') % minutes hours = int(elapsed / 60. / 60.) if hours < 24: return N_('%d hours ago') % hours return N_('%d days ago') % int(elapsed / 60. / 60. / 24.) def status(self): """Return the status for the entry's path.""" model = main.model() unmerged = utils.add_parents(set(model.unmerged)) modified = utils.add_parents(set(model.modified)) staged = utils.add_parents(set(model.staged)) untracked = utils.add_parents(set(model.untracked)) upstream_changed = utils.add_parents(set(model.upstream_changed)) if self.path in unmerged: return (resources.icon('modified.png'), N_('Unmerged')) if self.path in modified and self.path in staged: return (resources.icon('partial.png'), N_('Partially Staged')) if self.path in modified: return (resources.icon('modified.png'), N_('Modified')) if self.path in staged: return (resources.icon('staged.png'), N_('Staged')) if self.path in upstream_changed: return (resources.icon('upstream.png'), N_('Changed Upstream')) if self.path in untracked: return (None, '?') return (None, '') def run(self): """Perform expensive lookups and post corresponding events.""" app = QtGui.QApplication.instance() entry = GitRepoEntryManager.entry(self.path) app.postEvent(entry, GitRepoInfoEvent(Columns.MESSAGE, self.data('message'))) app.postEvent(entry, GitRepoInfoEvent(Columns.AGE, self.data('date'))) app.postEvent(entry, GitRepoInfoEvent(Columns.AUTHOR, self.data('author'))) app.postEvent(entry, GitRepoInfoEvent(Columns.STATUS, self.status())) TaskRunner.instance().cleanup_task(self) class GitRepoInfoEvent(QtCore.QEvent): """Transport mechanism for communicating from a GitRepoInfoTask.""" def __init__(self, signal, *data): QtCore.QEvent.__init__(self, QtCore.QEvent.User + 1) self.signal = signal self.data = data def type(self): return INFO_EVENT_TYPE class GitRepoItem(QtGui.QStandardItem): """ Represents a cell in a treeview. Many GitRepoItems map to a single repository path. Each GitRepoItem manages a different cell in the tree view. One is created for each column -- Name, Status, Age, etc. """ def __init__(self, column, path): QtGui.QStandardItem.__init__(self) self.setEditable(False) self.setDragEnabled(False) entry = GitRepoEntryManager.entry(path) if column == Columns.STATUS: QtCore.QObject.connect(entry, SIGNAL(column), self.set_status) else: QtCore.QObject.connect(entry, SIGNAL(column), self.setText) def set_status(self, data): icon, txt = data if icon: self.setIcon(QtGui.QIcon(icon)) else: self.setIcon(QtGui.QIcon()) self.setText(txt) class GitRepoNameItem(GitRepoItem): """Subclass GitRepoItem to provide a custom type().""" TYPE = QtGui.QStandardItem.UserType + 1 def __init__(self, path): GitRepoItem.__init__(self, Columns.NAME, path) self.path = path def type(self): """ Indicate that this item is of a special user-defined type. 'name' is the only column that registers a user-defined type. This is done to allow filtering out other columns when determining which paths are selected. """ return GitRepoNameItem.TYPE git-cola-1.9.3/cola/models/dag.py000066400000000000000000000162431225156173500165460ustar00rootroot00000000000000import subprocess from cola import core from cola import utils from cola.git import git from cola.observable import Observable # put summary at the end b/c it can contain # any number of funky characters, including the separator logfmt = 'format:%H%x01%P%x01%d%x01%an%x01%ad%x01%ae%x01%s' logsep = chr(0x01) class CommitFactory(object): root_generation = 0 commits = {} @classmethod def reset(cls): cls.commits.clear() cls.root_generation = 0 @classmethod def new(cls, sha1=None, log_entry=None): if not sha1 and log_entry: sha1 = log_entry[:40] try: commit = cls.commits[sha1] if log_entry and not commit.parsed: commit.parse(log_entry) cls.root_generation = max(commit.generation, cls.root_generation) except KeyError: commit = Commit(sha1=sha1, log_entry=log_entry) if not log_entry: cls.root_generation += 1 commit.generation = max(commit.generation, cls.root_generation) cls.commits[sha1] = commit return commit class DAG(Observable): ref_updated = 'ref_updated' count_updated = 'count_updated' def __init__(self, ref, count): Observable.__init__(self) self.ref = ref self.count = count self.overrides = {} def set_ref(self, ref): changed = ref != self.ref if changed: self.ref = ref self.notify_observers(self.ref_updated) return changed def set_count(self, count): changed = count != self.count if changed: self.count = count self.notify_observers(self.count_updated) return changed def set_arguments(self, args): if args is None: return if self.set_count(args.count): self.overrides['count'] = args.count if args.args: ref = subprocess.list2cmdline(map(core.decode, args.args)) if self.set_ref(ref): self.overrides['ref'] = ref def overridden(self, opt): return opt in self.overrides def paths(self): all_refs = utils.shell_split(self.ref) if '--' in all_refs: all_refs = all_refs[all_refs.index('--'):] return [p for p in all_refs if p and core.exists(p)] class Commit(object): root_generation = 0 __slots__ = ('sha1', 'summary', 'parents', 'children', 'tags', 'author', 'authdate', 'email', 'generation', 'parsed') def __init__(self, sha1=None, log_entry=None): self.sha1 = sha1 self.summary = None self.parents = [] self.children = [] self.tags = set() self.email = None self.author = None self.authdate = None self.parsed = False self.generation = CommitFactory.root_generation if log_entry: self.parse(log_entry) def parse(self, log_entry, sep=logsep): self.sha1 = log_entry[:40] (parents, tags, author, authdate, email, summary) = \ log_entry[41:].split(sep, 6) self.summary = summary and summary or '' self.author = author and author or '' self.authdate = authdate or '' self.email = email and email or '' if parents: generation = None for parent_sha1 in parents.split(' '): parent = CommitFactory.new(sha1=parent_sha1) parent.children.append(self) if generation is None: generation = parent.generation+1 self.parents.append(parent) generation = max(parent.generation+1, generation) self.generation = generation if tags: for tag in tags[2:-1].split(', '): if tag.startswith('tag: '): tag = tag[5:] # tag: refs/ elif tag.startswith('refs/remotes/'): tag = tag[13:] # refs/remotes/ elif tag.startswith('refs/heads/'): tag = tag[11:] # refs/heads/ if tag.endswith('/HEAD'): continue self.tags.add(tag) self.parsed = True return self def __str__(self): return self.sha1 def __repr__(self): return ("{\n" " sha1: " + self.sha1 + "\n" " summary: " + self.summary + "\n" " author: " + self.author + "\n" " authdate: " + self.authdate + "\n" " parents: [" + ', '.join([p.sha1 for p in self.parents]) + "]\n" " tags: [" + ', '.join(self.tags) + "]\n" "}") def is_fork(self): ''' Returns True if the node is a fork''' return len(self.children) > 1 def is_merge(self): ''' Returns True if the node is a fork''' return len(self.parents) > 1 class RepoReader(object): def __init__(self, dag, git=git): self.dag = dag self.git = git self._proc = None self._objects = {} self._cmd = ['git', 'log', '--topo-order', '--reverse', '--pretty='+logfmt] self._cached = False """Indicates that all data has been read""" self._idx = -1 """Index into the cached commits""" self._topo_list = [] """List of commits objects in topological order""" cached = property(lambda self: self._cached) """Return True when no commits remain to be read""" def __len__(self): return len(self._topo_list) def reset(self): CommitFactory.reset() if self._proc: self._topo_list = [] self._proc.kill() self._proc = None self._cached = False def __iter__(self): if self._cached: return self self.reset() return self def next(self): if self._cached: try: self._idx += 1 return self._topo_list[self._idx] except IndexError: self._idx = -1 raise StopIteration if self._proc is None: ref_args = utils.shell_split(self.dag.ref) cmd = self._cmd + ['-%d' % self.dag.count] + ref_args self._proc = core.start_command(cmd) self._topo_list = [] log_entry = core.readline(self._proc.stdout).rstrip() if not log_entry: self._cached = True self._proc.wait() self._proc = None raise StopIteration sha1 = log_entry[:40] try: return self._objects[sha1] except KeyError: c = CommitFactory.new(log_entry=log_entry) self._objects[c.sha1] = c self._topo_list.append(c) return c def __getitem__(self, sha1): return self._objects[sha1] def items(self): return self._objects.items() git-cola-1.9.3/cola/models/main.py000066400000000000000000000403611225156173500167350ustar00rootroot00000000000000# Copyright (c) 2008 David Aguilar """This module provides the central cola model. """ import os import copy from cola import core from cola import git from cola import gitcfg from cola import gitcmds from cola.compat import set from cola.git import STDOUT from cola.observable import Observable from cola.decorators import memoize from cola.models.selection import selection_model from cola.models import prefs # Static GitConfig instance _config = gitcfg.instance() @memoize def model(): """Returns the main model singleton""" return MainModel() class MainModel(Observable): """Provides a friendly wrapper for doing common git operations.""" # Observable messages message_about_to_update = 'about_to_update' message_commit_message_changed = 'commit_message_changed' message_diff_text_changed = 'diff_text_changed' message_directory_changed = 'directory_changed' message_filename_changed = 'filename_changed' message_mode_about_to_change = 'mode_about_to_change' message_mode_changed = 'mode_changed' message_updated = 'updated' # States mode_none = 'none' # Default: nothing's happened, do nothing mode_worktree = 'worktree' # Comparing index to worktree mode_untracked = 'untracked' # Dealing with an untracked file mode_index = 'index' # Comparing index to last commit mode_amend = 'amend' # Amending a commit # Modes where we can checkout files from the $head modes_undoable = set((mode_amend, mode_index, mode_worktree)) # Modes where we can partially stage files modes_stageable = set((mode_amend, mode_worktree, mode_untracked)) # Modes where we can partially unstage files modes_unstageable = set((mode_amend, mode_index)) unstaged = property(lambda self: self.modified + self.unmerged + self.untracked) """An aggregate of the modified, unmerged, and untracked file lists.""" def __init__(self, cwd=None): """Reads git repository settings and sets several methods so that they refer to the git module. This object encapsulates cola's interaction with git.""" Observable.__init__(self) # Initialize the git command object self.git = git.instance() self.head = 'HEAD' self.diff_text = '' self.mode = self.mode_none self.filename = None self.is_merging = False self.is_rebasing = False self.currentbranch = '' self.directory = '' self.project = '' self.remotes = [] self.commitmsg = '' self.modified = [] self.staged = [] self.untracked = [] self.unmerged = [] self.upstream_changed = [] self.submodules = set() self.local_branches = [] self.remote_branches = [] self.tags = [] if cwd: self.set_worktree(cwd) def unstageable(self): return self.mode in self.modes_unstageable def amending(self): return self.mode == self.mode_amend def undoable(self): """Whether we can checkout files from the $head.""" return self.mode in self.modes_undoable def stageable(self): """Whether staging should be allowed.""" return self.mode in self.modes_stageable def all_branches(self): return (self.local_branches + self.remote_branches) def set_worktree(self, worktree): self.git.set_worktree(worktree) is_valid = self.git.is_valid() if is_valid: self.project = os.path.basename(self.git.worktree()) return is_valid def set_commitmsg(self, msg): self.commitmsg = msg self.notify_observers(self.message_commit_message_changed, msg) def save_commitmsg(self, msg): path = self.git.git_path('GIT_COLA_MSG') core.write(path, msg) def set_diff_text(self, txt): self.diff_text = txt self.notify_observers(self.message_diff_text_changed, txt) def set_directory(self, path): self.directory = path self.notify_observers(self.message_directory_changed, path) def set_filename(self, filename): self.filename = filename self.notify_observers(self.message_filename_changed, filename) def set_mode(self, mode): if self.amending(): if mode != self.mode_none: return if self.is_merging and mode == self.mode_amend: mode = self.mode if mode == self.mode_amend: head = 'HEAD^' else: head = 'HEAD' self.notify_observers(self.message_mode_about_to_change, mode) self.head = head self.mode = mode self.notify_observers(self.message_mode_changed, mode) def apply_diff(self, filename): return self.git.apply(filename, index=True, cached=True) def apply_diff_to_worktree(self, filename): return self.git.apply(filename) def prev_commitmsg(self, *args): """Queries git for the latest commit message.""" return self.git.log('-1', no_color=True, pretty='format:%s%n%n%b', *args)[STDOUT] def update_file_status(self, update_index=False): self.notify_observers(self.message_about_to_update) self._update_files(update_index=update_index) self.notify_observers(self.message_updated) def update_status(self, update_index=False): # Give observers a chance to respond self.notify_observers(self.message_about_to_update) self._update_merge_rebase_status() self._update_files(update_index=update_index) self._update_refs() self._update_branches_and_tags() self._update_branch_heads() self.notify_observers(self.message_updated) def _update_files(self, update_index=False): display_untracked = prefs.display_untracked() state = gitcmds.worktree_state_dict(head=self.head, update_index=update_index, display_untracked=display_untracked) self.staged = state.get('staged', []) self.modified = state.get('modified', []) self.unmerged = state.get('unmerged', []) self.untracked = state.get('untracked', []) self.submodules = state.get('submodules', set()) self.upstream_changed = state.get('upstream_changed', []) sel = selection_model() if self.is_empty(): sel.reset() else: sel.update(self) if selection_model().is_empty(): self.set_diff_text('') def is_empty(self): return not(bool(self.staged or self.modified or self.unmerged or self.untracked)) def _update_refs(self): self.remotes = self.git.remote()[STDOUT].splitlines() def _update_branch_heads(self): # Set these early since they are used to calculate 'upstream_changed'. self.currentbranch = gitcmds.current_branch() def _update_branches_and_tags(self): local_branches, remote_branches, tags = gitcmds.all_refs(split=True) self.local_branches = local_branches self.remote_branches = remote_branches self.tags = tags def _update_merge_rebase_status(self): self.is_merging = core.exists(self.git.git_path('MERGE_HEAD')) self.is_rebasing = core.exists(self.git.git_path('rebase-merge')) if self.is_merging and self.mode == self.mode_amend: self.set_mode(self.mode_none) def delete_branch(self, branch): return self.git.branch(branch, D=True) def _sliced_op(self, input_items, map_fn): """Slice input_items and call map_fn over every slice This exists because of "errno: Argument list too long" """ # This comment appeared near the top of include/linux/binfmts.h # in the Linux source tree: # # /* # * MAX_ARG_PAGES defines the number of pages allocated for arguments # * and envelope for the new program. 32 should suffice, this gives # * a maximum env+arg of 128kB w/4KB pages! # */ # #define MAX_ARG_PAGES 32 # # 'size' is a heuristic to keep things highly performant by minimizing # the number of slices. If we wanted it to run as few commands as # possible we could call "getconf ARG_MAX" and make a better guess, # but it's probably not worth the complexity (and the extra call to # getconf that we can't do on Windows anyways). # # In my testing, getconf ARG_MAX on Mac OS X Mountain Lion reported # 262144 and Debian/Linux-x86_64 reported 2097152. # # The hard-coded max_arg_len value is safely below both of these # real-world values. max_arg_len = 32 * 4 * 1024 avg_filename_len = 300 size = max_arg_len / avg_filename_len status = 0 outs = [] errs = [] items = copy.copy(input_items) while items: stat, out, err = map_fn(items[:size]) status = max(stat, status) outs.append(out) errs.append(err) items = items[size:] return (status, '\n'.join(outs), '\n'.join(errs)) def _sliced_add(self, input_items): lambda_fn = lambda x: self.git.add('--', force=True, verbose=True, *x) return self._sliced_op(input_items, lambda_fn) def stage_modified(self): status, out, err = self._sliced_add(self.modified) self.update_file_status() return (status, out, err) def stage_untracked(self): status, out, err = self._sliced_add(self.untracked) self.update_file_status() return (status, out, err) def reset(self, *items): lambda_fn = lambda x: self.git.reset('--', *x) status, out, err = self._sliced_op(items, lambda_fn) self.update_file_status() return (status, out, err) def unstage_all(self): """Unstage all files, even while amending""" status, out, err = self.git.reset(self.head, '--', '.') self.update_file_status() return (status, out, err) def stage_all(self): status, out, err = self.git.add(v=True, u=True) self.update_file_status() return (status, out, err) def config_set(self, key, value, local=True): # git config category.key value strval = unicode(value) if type(value) is bool: # git uses "true" and "false" strval = strval.lower() if local: argv = [key, strval] else: argv = ['--global', key, strval] return self.git.config(*argv) def config_dict(self, local=True): """parses the lines from git config --list into a dictionary""" kwargs = { 'list': True, 'global': not local, # global is a python keyword } config_lines = self.git.config(**kwargs)[STDOUT].splitlines() newdict = {} for line in config_lines: try: k, v = line.split('=', 1) except: # value-less entry in .gitconfig continue k = k.replace('.','_') # git -> model if v == 'true' or v == 'false': v = bool(eval(v.title())) try: v = int(eval(v)) except: pass newdict[k]=v return newdict def commit_with_msg(self, msg, tmpfile, amend=False): """Creates a git commit.""" if not msg.endswith('\n'): msg += '\n' # Create the commit message file core.write(tmpfile, msg) # Run 'git commit' status, out, err = self.git.commit(F=tmpfile, v=True, amend=amend) core.unlink(tmpfile) return (status, out, err) def remote_url(self, name, action): if action == 'push': url = self.git.config('remote.%s.pushurl' % name, get=True)[STDOUT] if url: return url return self.git.config('remote.%s.url' % name, get=True)[STDOUT] def remote_args(self, remote, local_branch='', remote_branch='', ffwd=True, tags=False, rebase=False, push=False): # Swap the branches in push mode (reverse of fetch) if push: tmp = local_branch local_branch = remote_branch remote_branch = tmp if ffwd: branch_arg = '%s:%s' % (remote_branch, local_branch) else: branch_arg = '+%s:%s' % (remote_branch, local_branch) args = [remote] if local_branch and remote_branch: args.append(branch_arg) elif local_branch: args.append(local_branch) elif remote_branch: args.append(remote_branch) kwargs = { 'verbose': True, 'tags': tags, 'rebase': rebase, } return (args, kwargs) def run_remote_action(self, action, remote, push=False, **kwargs): args, kwargs = self.remote_args(remote, push=push, **kwargs) return action(*args, **kwargs) def fetch(self, remote, **opts): return self.run_remote_action(self.git.fetch, remote, **opts) def push(self, remote, **opts): return self.run_remote_action(self.git.push, remote, push=True, **opts) def pull(self, remote, **opts): return self.run_remote_action(self.git.pull, remote, push=True, **opts) def create_branch(self, name, base, track=False, force=False): """Create a branch named 'name' from revision 'base' Pass track=True to create a local tracking branch. """ return self.git.branch(name, base, track=track, force=force) def cherry_pick_list(self, revs, **kwargs): """Cherry-picks each revision into the current branch. Returns a list of command output strings (1 per cherry pick)""" if not revs: return [] outs = [] errs = [] status = 0 for rev in revs: stat, out, err = self.git.cherry_pick(rev) status = max(stat, status) outs.append(out) errs.append(err) return (status, '\n'.join(outs), '\n'.join(errs)) def pad(self, pstr, num=22): topad = num-len(pstr) if topad > 0: return pstr + ' '*topad else: return pstr def is_commit_published(self): head = self.git.rev_parse('HEAD')[STDOUT] return bool(self.git.branch(r=True, contains=head)[STDOUT]) def everything(self): """Returns a sorted list of all files, including untracked files.""" ls_files = self.git.ls_files(z=True, cached=True, others=True, exclude_standard=True)[STDOUT] return sorted([f for f in ls_files.split('\0') if f]) def stage_paths(self, paths): """Stages add/removals to git.""" if not paths: self.stage_all() return add = [] remove = [] for path in set(paths): if core.exists(path): add.append(path) else: remove.append(path) self.notify_observers(self.message_about_to_update) # `git add -u` doesn't work on untracked files if add: self._sliced_add(add) # If a path doesn't exist then that means it should be removed # from the index. We use `git add -u` for that. if remove: while remove: self.git.add('--', u=True, *remove[:42]) remove = remove[42:] self._update_files() self.notify_observers(self.message_updated) def unstage_paths(self, paths): if not paths: self.unstage_all() return gitcmds.unstage_paths(paths, head=self.head) self.update_file_status() def untrack_paths(self, paths): status, out, err = gitcmds.untrack_paths(paths, head=self.head) self.update_file_status() return status, out, err def getcwd(self): """If we've chosen a directory then use it, otherwise os.getcwd().""" if self.directory: return self.directory return core.getcwd() git-cola-1.9.3/cola/models/prefs.py000066400000000000000000000044071225156173500171310ustar00rootroot00000000000000from cola import gitcfg from cola import observable FONTDIFF = 'cola.fontdiff' DIFFCONTEXT = 'gui.diffcontext' DIFFTOOL = 'diff.tool' DISPLAY_UNTRACKED = 'gui.displayuntracked' EDITOR = 'gui.editor' LINEBREAK = 'cola.linebreak' TABWIDTH = 'cola.tabwidth' TEXTWIDTH = 'cola.textwidth' HISTORY_BROWSER = 'gui.historybrowser' MERGE_SUMMARY = 'merge.summary' MERGE_DIFFSTAT = 'merge.diffstat' MERGE_KEEPBACKUP = 'merge.keepbackup' MERGE_VERBOSITY = 'merge.verbosity' MERGETOOL = 'merge.tool' SAVEWINDOWSETTINGS = 'cola.savewindowsettings' USER_EMAIL = 'user.email' USER_NAME = 'user.name' def config(): return gitcfg.instance() def display_untracked(): return config().get(DISPLAY_UNTRACKED, True) def editor(): app = config().get(EDITOR, 'gvim') return {'vim': 'gvim'}.get(app, app) def history_browser(): return config().get(HISTORY_BROWSER, 'gitk') def linebreak(): return config().get(LINEBREAK, True) def tabwidth(): return config().get(TABWIDTH, 8) def textwidth(): return config().get(TEXTWIDTH, 72) class PreferencesModel(observable.Observable): message_config_updated = 'config_updated' def __init__(self): observable.Observable.__init__(self) self.config = gitcfg.instance() def set_config(self, source, config, value): if source == 'repo': self.config.set_repo(config, value) else: self.config.set_user(config, value) message = self.message_config_updated self.notify_observers(message, source, config, value) def get_config(self, source, config): if source == 'repo': return self.config.get_repo(config) else: return self.config.get(config) class SetConfig(object): def __init__(self, model, source, config, value): self.source = source self.config = config self.value = value self.old_value = None self.model = model def is_undoable(self): return True def do(self): self.old_value = self.model.get_config(self.source, self.config) self.model.set_config(self.source, self.config, self.value) def undo(self): if self.old_value is None: return self.model.set_config(self.source, self.config, self.old_value) git-cola-1.9.3/cola/models/selection.py000066400000000000000000000065741225156173500200060ustar00rootroot00000000000000"""Provides a selection model to handle selection.""" import collections from cola.compat import set from cola.observable import Observable from cola.decorators import memoize State = collections.namedtuple('State', 'staged unmerged modified untracked') @memoize def selection_model(): """Provides access to a static SelectionModel instance.""" return SelectionModel() def selection(): """Return the current selection.""" return selection_model().selection() def single_selection(): """Scan across staged, modified, etc. and return a single item.""" return selection_model().single_selection() def selected_group(): return selection_model().group() def filename(): return selection_model().filename() def pick(s): if s.staged: files = s.staged elif s.unmerged: files = s.unmerged elif s.modified: files = s.modified elif s.untracked: files = s.untracked else: files = [] return files def _filter(a, b): b_set = set(b) a_copy = list(a) last = len(a_copy) - 1 for idx, i in enumerate(reversed(a)): if i not in b_set: a.pop(last - idx) class SelectionModel(Observable): """Provides information about selected file paths.""" # Notification message sent out when selection changes message_selection_changed = 'selection_changed' # These properties wrap the individual selection items # to provide higher-level pseudo-selections. unstaged = property(lambda self: self.unmerged + self.modified + self.untracked) def __init__(self): Observable.__init__(self) self.staged = [] self.unmerged = [] self.modified = [] self.untracked = [] def reset(self): self.staged = [] self.unmerged = [] self.modified = [] self.untracked = [] def is_empty(self): return not(bool(self.staged or self.unmerged or self.modified or self.untracked)) def set_selection(self, s): """Set the new selection.""" self.staged = s.staged self.unmerged = s.unmerged self.modified = s.modified self.untracked = s.untracked self.notify_observers(self.message_selection_changed) def update(self, other): _filter(self.staged, other.staged) _filter(self.unmerged, other.unmerged) _filter(self.modified, other.modified) _filter(self.untracked, other.untracked) self.notify_observers(self.message_selection_changed) def selection(self): return State(self.staged, self.unmerged, self.modified, self.untracked) def single_selection(self): st = None m = None um = None ut = None if self.staged: st = self.staged[0] elif self.modified: m = self.modified[0] elif self.unmerged: um = self.unmerged[0] elif self.untracked: ut = self.untracked[0] return State(st, um, m, ut) def filename(self): paths = [p for p in self.single_selection() if p is not None] if paths: return paths[0] else: return None def group(self): """A list of selected files in various states of being""" return pick(self.selection()) git-cola-1.9.3/cola/models/stash.py000066400000000000000000000041001225156173500171220ustar00rootroot00000000000000from cola import observable from cola.git import git from cola.git import STDOUT from cola.interaction import Interaction from cola.models import main class StashModel(observable.Observable): def __init__(self): observable.Observable.__init__(self) def stash_list(self): return git.stash('list')[STDOUT].splitlines() def has_stashable_changes(self): model = main.model() return bool(model.modified + model.staged) def stash_info(self, revids=False, names=False): """Parses "git stash list" and returns a list of stashes.""" stashes = self.stash_list() revids = [s[:s.index(':')] for s in stashes] names = [s.split(': ', 2)[-1] for s in stashes] return stashes, revids, names def stash_diff(self, rev): diffstat = git.stash('show', rev)[STDOUT] diff = git.stash('show', '-p', rev)[STDOUT] return diffstat + '\n\n' + diff class ApplyStash(object): def __init__(self, selection, index): self.selection = selection self.index = index def is_undoable(self): return False def do(self): if self.index: args = ['apply', '--index', self.selection] else: args = ['apply', self.selection] status, out, err = git.stash(*args) Interaction.log_status(status, out, err) class DropStash(object): def __init__(self, stash_sha1): self.stash_sha1 = stash_sha1 def is_undoable(self): return False def do(self): status, out, err = git.stash('drop', self.stash_sha1) Interaction.log_status(status, out, err) class SaveStash(object): def __init__(self, stash_name, keep_index): self.stash_name = stash_name self.keep_index = keep_index def is_undoable(self): return False def do(self): if self.keep_index: args = ['save', '--keep-index', self.stash_name] else: args = ['save', self.stash_name] status, out, err = git.stash(*args) Interaction.log_status(status, out, err) git-cola-1.9.3/cola/observable.py000066400000000000000000000017141225156173500166510ustar00rootroot00000000000000# Copyright (c) 2008 David Aguilar """This module provides the Observable class""" from cola.compat import set class Observable(object): """Handles subject/observer notifications.""" def __init__(self): self.notification_enabled = True self.observers = {} def add_observer(self, message, observer): """Add an observer for a specific message.""" observers = self.observers.setdefault(message, set()) observers.add(observer) def remove_observer(self, observer): """Remove an observer.""" for message, observers in self.observers.items(): if observer in observers: observers.remove(observer) def notify_observers(self, message, *args, **opts): """Pythonic signals and slots.""" if not self.notification_enabled: return observers = self.observers.get(message, ()) for method in observers: method(*args, **opts) git-cola-1.9.3/cola/qtcompat.py000066400000000000000000000023311225156173500163510ustar00rootroot00000000000000from PyQt4 import QtGui from PyQt4 import QtCore def install(): if not hasattr(QtGui.QHBoxLayout, 'setContentsMargins'): QtGui.QHBoxLayout.setContentsMargins = lambda *args: True if not hasattr(QtGui.QVBoxLayout, 'setContentsMargins'): QtGui.QVBoxLayout.setContentsMargins = lambda *args: True if not hasattr(QtGui.QKeySequence, 'Preferences'): QtGui.QKeySequence.Preferences = 'Ctrl+O' if not hasattr(QtGui.QGraphicsItem, 'mapRectToScene'): QtGui.QGraphicsItem.mapRectToScene = _map_rect_to_scene if not hasattr(QtCore.QCoreApplication, 'setStyleSheet'): QtCore.QCoreApplication.setStyleSheet = lambda *args: None def add_search_path(prefix, path): if hasattr(QtCore.QDir, 'addSearchPath'): QtCore.QDir.addSearchPath(prefix, path) def set_common_dock_options(window): if not hasattr(window, 'setDockOptions'): return nested = QtGui.QMainWindow.AllowNestedDocks tabbed = QtGui.QMainWindow.AllowTabbedDocks animated = QtGui.QMainWindow.AnimatedDocks window.setDockOptions(nested | tabbed | animated) def _map_rect_to_scene(self, rect): """Only available in newer PyQt4 versions""" return self.sceneTransform().mapRect(rect) git-cola-1.9.3/cola/qtutils.py000066400000000000000000000604441225156173500162370ustar00rootroot00000000000000# Copyright (c) 2008 David Aguilar """This module provides miscellaneous Qt utility functions. """ import os import re from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import core from cola import gitcfg from cola import utils from cola import settings from cola import resources from cola.compat import set from cola.decorators import memoize from cola.i18n import N_ from cola.interaction import Interaction from cola.models.prefs import FONTDIFF from cola.widgets import defs def connect_action(action, fn): action.connect(action, SIGNAL('triggered()'), fn) def connect_action_bool(action, fn): action.connect(action, SIGNAL('triggered(bool)'), fn) def connect_button(button, fn): button.connect(button, SIGNAL('clicked()'), fn) def connect_toggle(toggle, fn): toggle.connect(toggle, SIGNAL('toggled(bool)'), fn) def active_window(): return QtGui.QApplication.activeWindow() def prompt(msg, title=None, text=''): """Presents the user with an input widget and returns the input.""" if title is None: title = msg result = QtGui.QInputDialog.getText(active_window(), msg, title, QtGui.QLineEdit.Normal, text) return (unicode(result[0]), result[1]) def create_listwidget_item(text, filename): """Creates a QListWidgetItem with text and the icon at filename.""" item = QtGui.QListWidgetItem() item.setIcon(QtGui.QIcon(filename)) item.setText(text) return item def create_treewidget_item(text, filename): """Creates a QTreeWidgetItem with text and the icon at filename.""" icon = cached_icon_from_path(filename) item = QtGui.QTreeWidgetItem() item.setIcon(0, icon) item.setText(0, text) return item @memoize def cached_icon_from_path(filename): return QtGui.QIcon(filename) def confirm(title, text, informative_text, ok_text, icon=None, default=True): """Confirm that an action should take place""" if icon is None: icon = ok_icon() elif icon and isinstance(icon, basestring): icon = QtGui.QIcon(icon) msgbox = QtGui.QMessageBox(active_window()) msgbox.setWindowTitle(title) msgbox.setText(text) msgbox.setInformativeText(informative_text) ok = msgbox.addButton(ok_text, QtGui.QMessageBox.ActionRole) ok.setIcon(icon) cancel = msgbox.addButton(QtGui.QMessageBox.Cancel) if default: msgbox.setDefaultButton(ok) else: msgbox.setDefaultButton(cancel) msgbox.exec_() return msgbox.clickedButton() == ok def critical(title, message=None, details=None): """Show a warning with the provided title and message.""" if message is None: message = title mbox = QtGui.QMessageBox(active_window()) mbox.setWindowTitle(title) mbox.setTextFormat(QtCore.Qt.PlainText) mbox.setText(message) mbox.setIcon(QtGui.QMessageBox.Critical) mbox.setStandardButtons(QtGui.QMessageBox.Close) mbox.setDefaultButton(QtGui.QMessageBox.Close) if details: mbox.setDetailedText(details) mbox.exec_() def information(title, message=None, details=None, informative_text=None): """Show information with the provided title and message.""" if message is None: message = title mbox = QtGui.QMessageBox(active_window()) mbox.setStandardButtons(QtGui.QMessageBox.Close) mbox.setDefaultButton(QtGui.QMessageBox.Close) mbox.setWindowTitle(title) mbox.setWindowModality(QtCore.Qt.WindowModal) mbox.setTextFormat(QtCore.Qt.PlainText) mbox.setText(message) if informative_text: mbox.setInformativeText(informative_text) if details: mbox.setDetailedText(details) # Render git.svg into a 1-inch wide pixmap pixmap = QtGui.QPixmap(resources.icon('git.svg')) xres = pixmap.physicalDpiX() pixmap = pixmap.scaledToHeight(xres, QtCore.Qt.SmoothTransformation) mbox.setIconPixmap(pixmap) mbox.exec_() def question(title, msg, default=True): """Launches a QMessageBox question with the provided title and message. Passing "default=False" will make "No" the default choice.""" yes = QtGui.QMessageBox.Yes no = QtGui.QMessageBox.No buttons = yes | no if default: default = yes else: default = no result = (QtGui.QMessageBox .question(active_window(), title, msg, buttons, default)) return result == QtGui.QMessageBox.Yes def selected_treeitem(tree_widget): """Returns a(id_number, is_selected) for a QTreeWidget.""" id_number = None selected = False item = tree_widget.currentItem() if item: id_number = item.data(0, QtCore.Qt.UserRole).toInt()[0] selected = True return(id_number, selected) def selected_row(list_widget): """Returns a(row_number, is_selected) tuple for a QListWidget.""" items = list_widget.selectedItems() if not items: return (-1, False) item = items[0] return (list_widget.row(item), True) def selection_list(listwidget, items): """Returns an array of model items that correspond to the selected QListWidget indices.""" selected = [] itemcount = listwidget.count() widgetitems = [ listwidget.item(idx) for idx in range(itemcount) ] for item, widgetitem in zip(items, widgetitems): if widgetitem.isSelected(): selected.append(item) return selected def tree_selection(treeitem, items): """Returns model items that correspond to selected widget indices""" itemcount = treeitem.childCount() widgetitems = [ treeitem.child(idx) for idx in range(itemcount) ] selected = [] for item, widgetitem in zip(items[:len(widgetitems)], widgetitems): if widgetitem.isSelected(): selected.append(item) return selected def selected_item(list_widget, items): """Returns the selected item in a QListWidget.""" widget_items = list_widget.selectedItems() if not widget_items: return None widget_item = widget_items[0] row = list_widget.row(widget_item) if row < len(items): return items[row] else: return None def selected_items(list_widget, items): """Returns the selected item in a QListWidget.""" selection = [] widget_items = list_widget.selectedItems() if not widget_items: return selection for widget_item in widget_items: row = list_widget.row(widget_item) if row < len(items): selection.append(items[row]) return selection def open_dialog(title, filename=None): """Creates an Open File dialog and returns a filename.""" return unicode(QtGui.QFileDialog .getOpenFileName(active_window(), title, filename)) def opendir_dialog(title, path): """Prompts for a directory path""" flags = (QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontResolveSymlinks) return unicode(QtGui.QFileDialog .getExistingDirectory(active_window(), title, path, flags)) def save_as(filename, title='Save As...'): """Creates a Save File dialog and returns a filename.""" return unicode(QtGui.QFileDialog .getSaveFileName(active_window(), title, filename)) def icon(basename): """Given a basename returns a QIcon from the corresponding cola icon.""" return QtGui.QIcon(resources.icon(basename)) def set_clipboard(text): """Sets the copy/paste buffer to text.""" if not text: return clipboard = QtGui.QApplication.instance().clipboard() clipboard.setText(text, QtGui.QClipboard.Clipboard) clipboard.setText(text, QtGui.QClipboard.Selection) def add_action_bool(widget, text, fn, checked, *shortcuts): action = _add_action(widget, text, fn, connect_action_bool, *shortcuts) action.setCheckable(True) action.setChecked(checked) return action def add_action(widget, text, fn, *shortcuts): return _add_action(widget, text, fn, connect_action, *shortcuts) def _add_action(widget, text, fn, connect, *shortcuts): action = QtGui.QAction(text, widget) connect(action, fn) if shortcuts: shortcuts = list(set(shortcuts)) action.setShortcuts(shortcuts) action.setShortcutContext(Qt.WidgetWithChildrenShortcut) widget.addAction(action) return action def set_selected_item(widget, idx): """Sets a the currently selected item to the item at index idx.""" if type(widget) is QtGui.QTreeWidget: item = widget.topLevelItem(idx) if item: widget.setItemSelected(item, True) widget.setCurrentItem(item) def add_items(widget, items): """Adds items to a widget.""" for item in items: widget.addItem(item) def set_items(widget, items): """Clear the existing widget contents and set the new items.""" widget.clear() add_items(widget, items) def icon_file(filename, staged=False, untracked=False): """Returns a file path representing a corresponding file path.""" if staged: if core.exists(filename): ifile = resources.icon('staged-item.png') else: ifile = resources.icon('removed.png') elif untracked: ifile = resources.icon('untracked.png') else: ifile = utils.file_icon(filename) return ifile def icon_for_file(filename, staged=False, untracked=False): """Returns a QIcon for a particular file path.""" ifile = icon_file(filename, staged=staged, untracked=untracked) return icon(ifile) def create_treeitem(filename, staged=False, untracked=False, check=True): """Given a filename, return a QListWidgetItem suitable for adding to a QListWidget. "staged" and "untracked" controls whether to use the appropriate icons.""" if check: ifile = icon_file(filename, staged=staged, untracked=untracked) else: ifile = resources.icon('staged.png') return create_treewidget_item(filename, ifile) def update_file_icons(widget, items, staged=True, untracked=False, offset=0): """Populate a QListWidget with custom icon items.""" for idx, model_item in enumerate(items): item = widget.item(idx+offset) if item: item.setIcon(icon_for_file(model_item, staged, untracked)) @memoize def cached_icon(key): """Maintain a cache of standard icons and return cache entries.""" style = QtGui.QApplication.instance().style() return style.standardIcon(key) def dir_icon(): """Return a standard icon for a directory.""" return cached_icon(QtGui.QStyle.SP_DirIcon) def file_icon(): """Return a standard icon for a file.""" return cached_icon(QtGui.QStyle.SP_FileIcon) def apply_icon(): """Return a standard Apply icon""" return cached_icon(QtGui.QStyle.SP_DialogApplyButton) def new_icon(): return cached_icon(QtGui.QStyle.SP_FileDialogNewFolder) def save_icon(): """Return a standard Save icon""" return cached_icon(QtGui.QStyle.SP_DialogSaveButton) def ok_icon(): """Return a standard Ok icon""" return cached_icon(QtGui.QStyle.SP_DialogOkButton) def open_icon(): """Return a standard open directory icon""" return cached_icon(QtGui.QStyle.SP_DirOpenIcon) def help_icon(): """Return a standard open directory icon""" return cached_icon(QtGui.QStyle.SP_DialogHelpButton) def open_file_icon(): return icon('open.svg') def options_icon(): """Return a standard open directory icon""" return icon('options.svg') def dir_close_icon(): """Return a standard closed directory icon""" return cached_icon(QtGui.QStyle.SP_DirClosedIcon) def titlebar_close_icon(): """Return a dock widget close icon""" return cached_icon(QtGui.QStyle.SP_TitleBarCloseButton) def titlebar_normal_icon(): """Return a dock widget close icon""" return cached_icon(QtGui.QStyle.SP_TitleBarNormalButton) def git_icon(): return icon('git.svg') def reload_icon(): """Returna standard Refresh icon""" return cached_icon(QtGui.QStyle.SP_BrowserReload) def discard_icon(): """Return a standard Discard icon""" return cached_icon(QtGui.QStyle.SP_DialogDiscardButton) def close_icon(): """Return a standard Close icon""" return cached_icon(QtGui.QStyle.SP_DialogCloseButton) def add_close_action(widget): """Adds close action and shortcuts to a widget.""" return add_action(widget, N_('Close...'), widget.close, QtGui.QKeySequence.Close, 'Ctrl+Q') def center_on_screen(widget): """Move widget to the center of the default screen""" desktop = QtGui.QApplication.instance().desktop() rect = desktop.screenGeometry(QtGui.QCursor().pos()) cy = rect.height()/2 cx = rect.width()/2 widget.move(cx - widget.width()/2, cy - widget.height()/2) def save_state(widget, handler=None): if handler is None: handler = settings.Settings() if gitcfg.instance().get('cola.savewindowsettings', True): handler.save_gui_state(widget) def export_window_state(widget, state, version): # Save the window state windowstate = widget.saveState(version) state['windowstate'] = unicode(windowstate.toBase64().data()) return state def apply_window_state(widget, state, version): # Restore the dockwidget, etc. window state try: windowstate = state['windowstate'] return widget.restoreState(QtCore.QByteArray.fromBase64(str(windowstate)), version) except KeyError: return False def apply_state(widget): state = settings.Settings().get_gui_state(widget) return bool(state) and widget.apply_state(state) @memoize def theme_icon(name): """Grab an icon from the current theme with a fallback Support older versions of Qt by catching AttributeError and falling back to our default icons. """ try: base, ext = os.path.splitext(name) qicon = QtGui.QIcon.fromTheme(base) if not qicon.isNull(): return qicon except AttributeError: pass return icon(name) def default_monospace_font(): font = QtGui.QFont() family = 'Monospace' if utils.is_darwin(): family = 'Monaco' font.setFamily(family) return font def diff_font_str(): font_str = gitcfg.instance().get(FONTDIFF) if font_str is None: font = default_monospace_font() font_str = unicode(font.toString()) return font_str def diff_font(): font_str = diff_font_str() font = QtGui.QFont() font.fromString(font_str) return font def create_button(text='', layout=None, tooltip=None, icon=None): """Create a button, set its title, and add it to the parent.""" button = QtGui.QPushButton() button.setCursor(Qt.PointingHandCursor) if text: button.setText(text) if icon: button.setIcon(icon) if tooltip is not None: button.setToolTip(tooltip) if layout is not None: layout.addWidget(button) return button def create_action_button(tooltip, icon): button = QtGui.QPushButton() button.setCursor(QtCore.Qt.PointingHandCursor) button.setFlat(True) button.setIcon(icon) button.setFixedSize(QtCore.QSize(16, 16)) button.setToolTip(tooltip) return button class DockTitleBarWidget(QtGui.QWidget): def __init__(self, parent, title, stretch=True): QtGui.QWidget.__init__(self, parent) self.label = label = QtGui.QLabel() font = label.font() font.setCapitalization(QtGui.QFont.SmallCaps) label.setFont(font) label.setText(title) self.setCursor(QtCore.Qt.OpenHandCursor) self.close_button = create_action_button( N_('Close'), titlebar_close_icon()) self.toggle_button = create_action_button( N_('Detach'), titlebar_normal_icon()) self.corner_layout = QtGui.QHBoxLayout() self.corner_layout.setMargin(defs.no_margin) self.corner_layout.setSpacing(defs.spacing) self.main_layout = QtGui.QHBoxLayout() self.main_layout.setMargin(defs.small_margin) self.main_layout.setSpacing(defs.spacing) self.main_layout.addWidget(label) self.main_layout.addSpacing(defs.spacing) if stretch: self.main_layout.addStretch() self.main_layout.addLayout(self.corner_layout) self.main_layout.addSpacing(defs.spacing) self.main_layout.addWidget(self.toggle_button) self.main_layout.addWidget(self.close_button) self.setLayout(self.main_layout) connect_button(self.toggle_button, self.toggle_floating) connect_button(self.close_button, self.toggle_visibility) def toggle_floating(self): self.parent().setFloating(not self.parent().isFloating()) self.update_tooltips() def toggle_visibility(self): self.parent().toggleViewAction().trigger() def set_title(self, title): self.label.setText(title) def add_corner_widget(self, widget): self.corner_layout.addWidget(widget) def update_tooltips(self): if self.parent().isFloating(): tooltip = N_('Attach') else: tooltip = N_('Detach') self.toggle_button.setToolTip(tooltip) def create_dock(title, parent, stretch=True): """Create a dock widget and set it up accordingly.""" dock = QtGui.QDockWidget(parent) dock.setWindowTitle(title) dock.setObjectName(title) titlebar = DockTitleBarWidget(dock, title, stretch=stretch) dock.setTitleBarWidget(titlebar) if hasattr(parent, 'dockwidgets'): parent.dockwidgets.append(dock) return dock def create_menu(title, parent): """Create a menu and set its title.""" qmenu = QtGui.QMenu(parent) qmenu.setTitle(title) return qmenu def create_toolbutton(text=None, layout=None, tooltip=None, icon=None): button = QtGui.QToolButton() button.setAutoRaise(True) button.setAutoFillBackground(True) button.setCursor(Qt.PointingHandCursor) if icon: button.setIcon(icon) if text: button.setText(text) button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) if tooltip: button.setToolTip(tooltip) if layout is not None: layout.addWidget(button) return button # Syntax highlighting def TERMINAL(pattern): """ Denotes that a pattern is the final pattern that should be matched. If this pattern matches no other formats will be applied, even if they would have matched. """ return '__TERMINAL__:%s' % pattern # Cache the results of re.compile so that we don't keep # rebuilding the same regexes whenever stylesheets change _RGX_CACHE = {} def rgba(r, g, b, a=255): c = QtGui.QColor() c.setRgb(r, g, b) c.setAlpha(a) return c default_colors = { 'color_text': rgba(0x00, 0x00, 0x00), 'color_add': rgba(0xcd, 0xff, 0xe0), 'color_remove': rgba(0xff, 0xd0, 0xd0), 'color_header': rgba(0xbb, 0xbb, 0xbb), } class GenericSyntaxHighligher(QtGui.QSyntaxHighlighter): def __init__(self, doc, *args, **kwargs): QtGui.QSyntaxHighlighter.__init__(self, doc) for attr, val in default_colors.items(): setattr(self, attr, val) self._rules = [] self.enabled = True self.generate_rules() def generate_rules(self): pass def set_enabled(self, enabled): self.enabled = enabled def create_rules(self, *rules): if len(rules) % 2: raise Exception('create_rules requires an even ' 'number of arguments.') for idx, rule in enumerate(rules): if idx % 2: continue formats = rules[idx+1] terminal = rule.startswith(TERMINAL('')) if terminal: rule = rule[len(TERMINAL('')):] try: regex = _RGX_CACHE[rule] except KeyError: regex = _RGX_CACHE[rule] = re.compile(rule) self._rules.append((regex, formats, terminal,)) def formats(self, line): matched = [] for regex, fmts, terminal in self._rules: match = regex.match(line) if not match: continue matched.append([match, fmts]) if terminal: return matched return matched def mkformat(self, fg=None, bg=None, bold=False): fmt = QtGui.QTextCharFormat() if fg: fmt.setForeground(fg) if bg: fmt.setBackground(bg) if bold: fmt.setFontWeight(QtGui.QFont.Bold) return fmt def highlightBlock(self, qstr): if not self.enabled: return ascii = unicode(qstr) if not ascii: return formats = self.formats(ascii) if not formats: return for match, fmts in formats: start = match.start() groups = match.groups() # No groups in the regex, assume this is a single rule # that spans the entire line if not groups: self.setFormat(0, len(ascii), fmts) continue # Groups exist, rule is a tuple corresponding to group for grpidx, group in enumerate(groups): # allow empty matches if not group: continue # allow None as a no-op format length = len(group) if fmts[grpidx]: self.setFormat(start, start+length, fmts[grpidx]) start += length def set_colors(self, colordict): for attr, val in colordict.items(): setattr(self, attr, val) class DiffSyntaxHighlighter(GenericSyntaxHighligher): """Implements the diff syntax highlighting This class is used by widgets that display diffs. """ def __init__(self, doc, whitespace=True): self.whitespace = whitespace GenericSyntaxHighligher.__init__(self, doc) def generate_rules(self): diff_head = self.mkformat(fg=self.color_header) diff_head_bold = self.mkformat(fg=self.color_header, bold=True) diff_add = self.mkformat(fg=self.color_text, bg=self.color_add) diff_remove = self.mkformat(fg=self.color_text, bg=self.color_remove) if self.whitespace: bad_ws = self.mkformat(fg=Qt.black, bg=Qt.red) # We specify the whitespace rule last so that it is # applied after the diff addition/removal rules. # The rules for the header diff_old_rgx = TERMINAL(r'^--- ') diff_new_rgx = TERMINAL(r'^\+\+\+ ') diff_ctx_rgx = TERMINAL(r'^@@ ') diff_hd1_rgx = TERMINAL(r'^diff --git a/.*b/.*') diff_hd2_rgx = TERMINAL(r'^index \S+\.\.\S+') diff_hd3_rgx = TERMINAL(r'^new file mode') diff_hd4_rgx = TERMINAL(r'^deleted file mode') diff_add_rgx = TERMINAL(r'^\+') diff_rmv_rgx = TERMINAL(r'^-') diff_bar_rgx = TERMINAL(r'^([ ]+.*)(\|[ ]+\d+[ ]+[+-]+)$') diff_sts_rgx = (r'(.+\|.+?)(\d+)(.+?)([\+]*?)([-]*?)$') diff_sum_rgx = (r'(\s+\d+ files changed[^\d]*)' r'(:?\d+ insertions[^\d]*)' r'(:?\d+ deletions.*)$') self.create_rules(diff_old_rgx, diff_head, diff_new_rgx, diff_head, diff_ctx_rgx, diff_head_bold, diff_bar_rgx, (diff_head_bold, diff_head), diff_hd1_rgx, diff_head, diff_hd2_rgx, diff_head, diff_hd3_rgx, diff_head, diff_hd4_rgx, diff_head, diff_add_rgx, diff_add, diff_rmv_rgx, diff_remove, diff_sts_rgx, (None, diff_head, None, diff_head, diff_head), diff_sum_rgx, (diff_head, diff_head, diff_head)) if self.whitespace: self.create_rules('(..*?)(\s+)$', (None, bad_ws)) def install(): Interaction.critical = staticmethod(critical) Interaction.confirm = staticmethod(confirm) Interaction.question = staticmethod(question) Interaction.information = staticmethod(information) git-cola-1.9.3/cola/resources.py000066400000000000000000000033421225156173500165360ustar00rootroot00000000000000"""Provides the prefix() function for finding cola resources""" import os import webbrowser from os.path import dirname from cola import core _modpath = core.abspath(__file__) if os.path.join('share', 'git-cola', 'lib') in _modpath: # this is the release tree # __file__ = '$prefix/share/git-cola/lib/cola/__file__.py' _lib_dir = dirname(dirname(_modpath)) _prefix = dirname(dirname(dirname(_lib_dir))) else: # this is the source tree # __file__ = '$prefix/cola/__file__.py' _prefix = dirname(dirname(_modpath)) def prefix(*args): """Return a path relative to cola's installation prefix""" return os.path.join(_prefix, *args) def doc(*args): """Return a path relative to cola's /usr/share/doc/ directory""" return os.path.join(_prefix, 'share', 'doc', 'git-cola', *args) def html_docs(): """Return the path to the cola html documentation.""" # index.html only exists after the install-docs target is run, # so fallback to git-cola.txt. htmldocs = doc('html', 'index.html') if core.exists(htmldocs): return htmldocs return doc('git-cola.txt') def show_html_docs(): url = html_docs() webbrowser.open_new_tab(url) def share(*args): """Return a path relative to cola's /usr/share/ directory""" return prefix('share', 'git-cola', *args) def icon(basename): """Return the full path to an icon file given a basename.""" return 'icons:'+basename def icon_dir(): """Return the path to the style dir within the cola install tree.""" return share('icons') def config_home(*args): config = core.getenv('XDG_CONFIG_HOME', os.path.join(core.expanduser('~'), '.config')) return os.path.join(config, 'git-cola', *args) git-cola-1.9.3/cola/settings.py000066400000000000000000000077031225156173500163710ustar00rootroot00000000000000# Copyright (c) 2008 David Aguilar """This handles saving complex settings such as bookmarks, etc. """ import os import sys from cola import core from cola import git from cola import resources from cola.compat import json def mkdict(obj): if type(obj) is dict: return obj else: return {} def mklist(obj): if type(obj) is list: return obj else: return [] class Settings(object): _file = resources.config_home('settings') bookmarks = property(lambda self: mklist(self.values['bookmarks'])) gui_state = property(lambda self: mkdict(self.values['gui_state'])) recent = property(lambda self: mklist(self.values['recent'])) def __init__(self, verify=git.is_git_worktree): """Load existing settings if they exist""" self.values = { 'bookmarks': [], 'gui_state': {}, 'recent': [], } self.verify = verify self.load() self.remove_missing() def remove_missing(self): missing_bookmarks = [] missing_recent = [] for bookmark in self.bookmarks: if not self.verify(bookmark): missing_bookmarks.append(bookmark) for bookmark in missing_bookmarks: try: self.bookmarks.remove(bookmark) except: pass for recent in self.recent: if not self.verify(recent): missing_recent.append(recent) for recent in missing_recent: try: self.recent.remove(recent) except: pass def add_bookmark(self, bookmark): """Adds a bookmark to the saved settings""" if bookmark not in self.bookmarks: self.bookmarks.append(bookmark) def remove_bookmark(self, bookmark): """Removes a bookmark from the saved settings""" if bookmark in self.bookmarks: self.bookmarks.remove(bookmark) def add_recent(self, entry): if entry in self.recent: self.recent.remove(entry) self.recent.insert(0, entry) if len(self.recent) > 8: self.recent.pop() def path(self): return self._file def save(self): path = self.path() try: parent = os.path.dirname(path) if not core.isdir(parent): core.makedirs(parent) with core.xopen(path, 'wb') as fp: json.dump(self.values, fp, indent=4) except: sys.stderr.write('git-cola: error writing "%s"\n' % path) def load(self): self.values.update(self._load()) def _load(self): path = self.path() if not core.exists(path): return self._load_dot_cola() try: fp = core.xopen(path, 'rb') return mkdict(json.load(fp)) except: # bad json return {} def reload_recent(self): values = self._load() self.values['recent'] = mklist(values.get('recent', [])) def _load_dot_cola(self): values = {} path = os.path.join(core.expanduser('~'), '.cola') if not core.exists(path): return {} try: with core.xopen(path, 'r') as fp: json_values = json.load(fp) except: # bad json return {} # Keep only the entries we care about for key in self.values: try: values[key] = json_values[key] except KeyError: pass return values def save_gui_state(self, gui): """Saves settings for a cola view""" name = gui.name() self.gui_state[name] = mkdict(gui.export_state()) self.save() def get_gui_state(self, gui): """Returns the state for a gui""" try: state = mkdict(self.gui_state[gui.name()]) except KeyError: state = self.gui_state[gui.name()] = {} return state git-cola-1.9.3/cola/textwrap.py000066400000000000000000000201321225156173500163760ustar00rootroot00000000000000"""Text wrapping and filling. """ # Copyright (C) 1999-2001 Gregory P. Ward. # Copyright (C) 2002, 2003 Python Software Foundation. # Copyright (C) 2013, David Aguilar # Written by Greg Ward # Simplified for git-cola by David Aguilar import re class TextWrapper(object): """ Object for wrapping/filling text. The public interface consists of the wrap() and fill() methods; the other methods are just there for subclasses to override in order to tweak the default behaviour. If you want to completely replace the main wrapping algorithm, you'll probably have to override _wrap_chunks(). Several instance attributes control various aspects of wrapping: width (default: 70) The preferred width of wrapped lines. tabwidth (default: 8) The width of a tab used when calculating line length. break_on_hyphens (default: true) Allow breaking hyphenated words. If true, wrapping will occur preferably on whitespaces and right after hyphens part of compound words. drop_whitespace (default: true) Drop leading and trailing whitespace from lines. """ # This funky little regex is just the trick for splitting # text up into word-wrappable chunks. E.g. # "Hello there -- you goof-ball, use the -b option!" # splits into # Hello/ /there/ /--/ /you/ /goof-/ball,/ /use/ /the/ /-b/ /option! # (after stripping out empty strings). wordsep_re = re.compile( r'(\s+|' # any whitespace r'[^\s\w]*\w+[^0-9\W]-(?=\w+[^0-9\W])|' # hyphenated words r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash # This less funky little regex just split on recognized spaces. E.g. # "Hello there -- you goof-ball, use the -b option!" # splits into # Hello/ /there/ /--/ /you/ /goof-ball,/ /use/ /the/ /-b/ /option!/ wordsep_simple_re = re.compile(r'(\s+)') def __init__(self, width=70, tabwidth=8, break_on_hyphens=True, drop_whitespace=True): self.width = width self.tabwidth = tabwidth self.break_on_hyphens = break_on_hyphens self.drop_whitespace = drop_whitespace # recompile the regexes for Unicode mode -- done in this clumsy way for # backwards compatibility because it's rather common to monkey-patch # the TextWrapper class' wordsep_re attribute. self.wordsep_re_uni = re.compile(self.wordsep_re.pattern, re.U) self.wordsep_simple_re_uni = re.compile( self.wordsep_simple_re.pattern, re.U) def _split(self, text): """_split(text : string) -> [string] Split the text to wrap into indivisible chunks. Chunks are not quite the same as words; see _wrap_chunks() for full details. As an example, the text Look, goof-ball -- use the -b option! breaks into the following chunks: 'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ', 'use', ' ', 'the', ' ', '-b', ' ', 'option!' if break_on_hyphens is True, or in: 'Look,', ' ', 'goof-ball', ' ', '--', ' ', 'use', ' ', 'the', ' ', '-b', ' ', option!' otherwise. """ if isinstance(text, unicode): if self.break_on_hyphens: pat = self.wordsep_re_uni else: pat = self.wordsep_simple_re_uni else: if self.break_on_hyphens: pat = self.wordsep_re else: pat = self.wordsep_simple_re chunks = pat.split(text) chunks = filter(None, chunks) # remove empty chunks return chunks def _wrap_chunks(self, chunks): """_wrap_chunks(chunks : [string]) -> [string] Wrap a sequence of text chunks and return a list of lines of length 'self.width' or less. Some lines may be longer than this. Chunks correspond roughly to words and the whitespace between them: each chunk is indivisible, but a line break can come between any two chunks. Chunks should not have internal whitespace; ie. a chunk is either all whitespace or a "word". Whitespace chunks will be removed from the beginning and end of lines, but apart from that whitespace is preserved. """ lines = [] # Arrange in reverse order so items can be efficiently popped # from a stack of chucks. chunks.reverse() while chunks: # Start the list of chunks that will make up the current line. # cur_len is just the length of all the chunks in cur_line. cur_line = [] cur_len = 0 # Maximum width for this line. width = self.width # First chunk on line is a space -- drop it, unless this # is the very beginning of the text (ie. no lines started yet). if self.drop_whitespace and chunks[-1] == ' ' and lines: chunks.pop() while chunks: l = self.chunklen(chunks[-1]) # Can at least squeeze this chunk onto the current line. if cur_len + l <= width: cur_line.append(chunks.pop()) cur_len += l # Nope, this line is full. else: break # The current line is full, and the next chunk is too big to # fit on *any* line (not just this one). if chunks and self.chunklen(chunks[-1]) > width: if not cur_line: cur_line.append(chunks.pop()) # If the last chunk on this line is all a space, drop it. if self.drop_whitespace and cur_line and cur_line[-1] == ' ': cur_line.pop() # Avoid whitespace at the beginining of the line. if (self.drop_whitespace and cur_line and cur_line[0] in (' ', ' ')): cur_line.pop(0) # Convert current line back to a string and store it in list # of all lines (return value). if cur_line: lines.append(''.join(cur_line)) return lines def chunklen(self, word): """Return length of a word taking tabs into account >>> w = TextWrapper(tabwidth=8) >>> w.chunklen("\\t\\t\\t\\tX") 33 """ return len(word.replace('\t', '')) + word.count('\t') * self.tabwidth # -- Public interface ---------------------------------------------- def wrap(self, text): """wrap(text : string) -> [string] Reformat the single paragraph in 'text' so it fits in lines of no more than 'self.width' columns, and return a list of wrapped lines. Tabs in 'text' are expanded with string.expandtabs(), and all other whitespace characters (including newline) are converted to space. """ chunks = self._split(text) return self._wrap_chunks(chunks) def fill(self, text): """fill(text : string) -> string Reformat the single paragraph in 'text' to fit in lines of no more than 'self.width' columns, and return a new string containing the entire wrapped paragraph. """ return "\n".join(self.wrap(text)) def word_wrap(text, tabwidth, limit): r"""Wrap long lines to the specified limit >>> text = 'a bb ccc dddd\neeeee' >>> word_wrap(text, 8, 2) 'a\nbb\nccc\ndddd\neeeee' >>> word_wrap(text, 8, 4) 'a bb\nccc\ndddd\neeeee' >>> text = 'a bb ccc dddd\n\teeeee' >>> word_wrap(text, 8, 4) 'a bb\nccc\ndddd\n\t\neeeee' """ lines = [] # Acked-by:, Signed-off-by:, Helped-by:, etc. special_tag_rgx = re.compile('^[a-zA-Z_-]+:') w = TextWrapper(width=limit, tabwidth=tabwidth, break_on_hyphens=True, drop_whitespace=True) for line in text.split('\n'): if special_tag_rgx.match(line): lines.append(line) else: lines.append(w.fill(line)) return '\n'.join(lines) git-cola-1.9.3/cola/utils.py000066400000000000000000000201201225156173500156550ustar00rootroot00000000000000# Copyright (c) 2008 David Aguilar """This module provides miscellaneous utility functions.""" import mimetypes import os import random import re import shlex import sys import time import traceback from cola import core from cola import resources from cola.compat import hashlib random.seed(hash(time.time())) KNOWN_FILE_MIME_TYPES = { 'text': 'script.png', 'image': 'image.png', 'python': 'script.png', 'ruby': 'script.png', 'shell': 'script.png', 'perl': 'script.png', 'octet': 'binary.png', } KNOWN_FILE_EXTENSION = { '.java': 'script.png', '.groovy': 'script.png', '.cpp': 'script.png', '.c': 'script.png', '.h': 'script.png', '.cxx': 'script.png', } def add_parents(path_entry_set): """Iterate over each item in the set and add its parent directories.""" for path in list(path_entry_set): while '//' in path: path = path.replace('//', '/') if path not in path_entry_set: path_entry_set.add(path) if '/' in path: parent_dir = dirname(path) while parent_dir and parent_dir not in path_entry_set: path_entry_set.add(parent_dir) parent_dir = dirname(parent_dir) return path_entry_set def ident_file_type(filename): """Returns an icon based on the contents of filename.""" if core.exists(filename): filemimetype = mimetypes.guess_type(filename) if filemimetype[0] != None: for filetype, iconname in KNOWN_FILE_MIME_TYPES.iteritems(): if filetype in filemimetype[0].lower(): return iconname filename = filename.lower() for fileext, iconname in KNOWN_FILE_EXTENSION.iteritems(): if filename.endswith(fileext): return iconname return 'generic.png' else: return 'removed.png' # Fallback for modified files of an unknown type return 'generic.png' def file_icon(filename): """ Returns the full path to an icon file corresponding to filename"s contents. """ return resources.icon(ident_file_type(filename)) def format_exception(e): exc_type, exc_value, exc_tb = sys.exc_info() details = traceback.format_exception(exc_type, exc_value, exc_tb) details = '\n'.join(details) if hasattr(e, 'msg'): msg = e.msg else: msg = str(e) return (msg, details) def sublist(a,b): """Subtracts list b from list a and returns the resulting list.""" # conceptually, c = a - b c = [] for item in a: if item not in b: c.append(item) return c __grep_cache = {} def grep(pattern, items, squash=True): """Greps a list for items that match a pattern and return a list of matching items. If only one item matches, return just that item. """ isdict = type(items) is dict if pattern in __grep_cache: regex = __grep_cache[pattern] else: regex = __grep_cache[pattern] = re.compile(pattern) matched = [] matchdict = {} for item in items: match = regex.match(item) if not match: continue groups = match.groups() if not groups: subitems = match.group(0) else: if len(groups) == 1: subitems = groups[0] else: subitems = list(groups) if isdict: matchdict[item] = items[item] else: matched.append(subitems) if isdict: return matchdict else: if squash and len(matched) == 1: return matched[0] else: return matched def basename(path): """ An os.path.basename() implementation that always uses '/' Avoid os.path.basename because git's output always uses '/' regardless of platform. """ return path.rsplit('/', 1)[-1] def strip_one(path): """Strip one level of directory >>> strip_one('/usr/bin/git') 'bin/git' >>> strip_one('local/bin/git') 'bin/git' >>> strip_one('bin/git') 'git' >>> strip_one('git') 'git' """ return path.strip('/').split('/', 1)[-1] def dirname(path): """ An os.path.dirname() implementation that always uses '/' Avoid os.path.dirname because git's output always uses '/' regardless of platform. """ while '//' in path: path = path.replace('//', '/') path_dirname = path.rsplit('/', 1)[0] if path_dirname == path: return '' return path.rsplit('/', 1)[0] def strip_prefix(prefix, string): """Return string, without the prefix. Blow up if string doesn't start with prefix.""" assert string.startswith(prefix) return string[len(prefix):] def sanitize(s): """Removes shell metacharacters from a string.""" for c in """ \t!@#$%^&*()\\;,<>"'[]{}~|""": s = s.replace(c, '_') return s def tablength(word, tabwidth): """Return length of a word taking tabs into account >>> tablength("\\t\\t\\t\\tX", 8) 33 """ return len(word.replace('\t', '')) + word.count('\t') * tabwidth def _shell_split(s): """Split string apart into utf-8 encoded words using shell syntax""" try: return shlex.split(core.encode(s)) except ValueError: return [core.encode(s)] def shell_split(s): """Returns a unicode list instead of encoded strings""" return [core.decode(arg) for arg in _shell_split(s)] def tmp_dir(): # Allow TMPDIR/TMP with a fallback to /tmp return core.getenv('TMP', core.getenv('TMPDIR', '/tmp')) def tmp_file_pattern(): return os.path.join(tmp_dir(), 'git-cola-%s-.*' % os.getpid()) def tmp_filename(prefix): randstr = ''.join([chr(random.randint(ord('a'), ord('z'))) for i in range(7)]) prefix = prefix.replace('/', '-').replace('\\', '-') basename = 'git-cola-%s-%s-%s' % (os.getpid(), randstr, prefix) return os.path.join(tmp_dir(), basename) def is_linux(): """Is this a linux machine?""" return sys.platform.startswith('linux') def is_debian(): """Is it debian?""" return os.path.exists('/usr/bin/apt-get') def is_darwin(): """Return True on OSX.""" return sys.platform == 'darwin' def is_win32(): """Return True on win32""" return sys.platform == 'win32' or sys.platform == 'cygwin' def checksum(path): """Return a cheap md5 hexdigest for a path.""" md5 = hashlib.new('md5') md5.update(core.read(path)) return md5.hexdigest() class ProgressIndicator(object): """Simple progress indicator. Displayed as a spinning character by default, but can be customized by passing custom messages that overrides the spinning character. """ States = ("|", "/", "-", "\\") def __init__(self, prefix="", f=sys.stdout): """Create a new ProgressIndicator, bound to the given file object.""" self.n = 0 # Simple progress counter self.f = f # Progress is written to this file object self.prev_len = 0 # Length of previous msg (to be overwritten) self.prefix = prefix # Prefix prepended to each progress message self.prefix_lens = [] # Stack of prefix string lengths def pushprefix(self, prefix): """Append the given prefix onto the prefix stack.""" self.prefix_lens.append(len(self.prefix)) self.prefix += prefix def popprefix(self): """Remove the last prefix from the prefix stack.""" prev_len = self.prefix_lens.pop() self.prefix = self.prefix[:prev_len] def __call__(self, msg = None, lf=False): """Indicate progress, possibly with a custom message.""" if msg is None: msg = self.States[self.n % len(self.States)] msg = self.prefix + msg print >> self.f, "\r%-*s" % (self.prev_len, msg), self.prev_len = len(msg.expandtabs()) if lf: print >> self.f self.prev_len = 0 self.n += 1 def finish (self, msg="done", noprefix=False): """Finalize progress indication with the given message.""" if noprefix: self.prefix = "" self(msg, True) git-cola-1.9.3/cola/version.py000066400000000000000000000037351225156173500162170ustar00rootroot00000000000000# Copyright (c) David Aguilar """Provide git-cola's version number""" import os import sys if __name__ == '__main__': srcdir = os.path.dirname(os.path.dirname(__file__)) sys.path.insert(1, srcdir) from cola.git import git from cola.git import STDOUT from cola.decorators import memoize from cola._version import VERSION # minimum version requirements _versions = { # git-diff learned --patience in 1.6.2 # git-mergetool learned --no-prompt in 1.6.2 # git-difftool moved out of contrib in git 1.6.3 'git': '1.6.3', 'python': '2.4', 'pyqt': '4.4', 'pyqt_qrunnable': '4.4', 'diff-submodule': '1.6.6', } def get(key): """Returns an entry from the known versions table""" return _versions.get(key) def version(): """Returns the current version""" return VERSION @memoize def check_version(min_ver, ver): """Check whether ver is greater or equal to min_ver """ min_ver_list = version_to_list(min_ver) ver_list = version_to_list(ver) return min_ver_list <= ver_list @memoize def check(key, ver): """Checks if a version is greater than the known version for """ return check_version(get(key), ver) def version_to_list(version): """Convert a version string to a list of numbers or strings """ ver_list = [] for p in version.split('.'): try: n = int(p) except ValueError: n = p ver_list.append(n) return ver_list @memoize def git_version_str(): """Returns the current GIT version""" return git.version()[STDOUT].strip() @memoize def git_version(): """Returns the current GIT version""" parts = git_version_str().split() if parts and len(parts) >= 3: return parts[2] else: # minimum supported version return '1.6.3' def print_version(brief=False): if brief: print('%s' % version()) else: print('cola version %s' % version()) if __name__ == '__main__': print(version()) git-cola-1.9.3/cola/widgets/000077500000000000000000000000001225156173500156165ustar00rootroot00000000000000git-cola-1.9.3/cola/widgets/__init__.py000066400000000000000000000000001225156173500177150ustar00rootroot00000000000000git-cola-1.9.3/cola/widgets/about.py000066400000000000000000000100431225156173500173000ustar00rootroot00000000000000from PyQt4 import QtGui from PyQt4.QtCore import Qt from cola import core from cola import resources from cola import qtutils from cola import version from cola.i18n import N_ from cola.widgets import defs from cola.widgets.text import MonoTextView def launch_about_dialog(): """Launches the Help -> About dialog""" view = AboutView(qtutils.active_window()) view.set_version(version.version()) view.show() COPYRIGHT = """git-cola: The highly caffeinated git GUI v$VERSION Copyright (C) 2007-2012, David Aguilar and contributors This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. """ class AboutView(QtGui.QDialog): """Provides the git-cola 'About' dialog. """ def __init__(self, parent=None): QtGui.QDialog.__init__(self, parent) self.setWindowTitle(N_('About git-cola')) self.setWindowModality(Qt.WindowModal) self.label = QtGui.QLabel() self.pixmap = QtGui.QPixmap('icons:logo-top.png') #self.label.setStyleSheet('QWidget {background: #000; }') self.label.setPixmap(self.pixmap) self.label.setAlignment(Qt.AlignRight | Qt.AlignTop) palette = self.label.palette() palette.setColor(QtGui.QPalette.Window, Qt.black) self.label.setAutoFillBackground(True) self.label.setPalette(palette) self.text = MonoTextView(self) self.text.setReadOnly(True) self.text.setPlainText(COPYRIGHT) self.close_button = QtGui.QPushButton() self.close_button.setText(N_('Close')) self.close_button.setDefault(True) self.button_layout = QtGui.QHBoxLayout() self.button_layout.addStretch() self.button_layout.addWidget(self.close_button) self.main_layout = QtGui.QVBoxLayout() self.main_layout.setMargin(0) self.main_layout.setSpacing(defs.spacing) self.main_layout.addWidget(self.label) self.main_layout.addWidget(self.text) self.main_layout.addLayout(self.button_layout) self.setLayout(self.main_layout) self.resize(666, 420) qtutils.connect_button(self.close_button, self.accept) def set_version(self, version): """Sets the version field in the 'about' dialog""" self.text.setPlainText(self.text.toPlainText().replace('$VERSION', version)) def show_shortcuts(): try: from PyQt4 import QtWebKit except ImportError: # redhat disabled QtWebKit in their qt build but don't punish the # users qtutils.critical(N_('This PyQt4 does not include QtWebKit.\n' 'The keyboard shortcuts feature is unavailable.')) return try: html = show_shortcuts.html except AttributeError: hotkeys = resources.doc(N_('hotkeys.html')) html = show_shortcuts.html = core.read(hotkeys) try: widget = show_shortcuts.widget except AttributeError: parent = qtutils.active_window() widget = show_shortcuts.widget = QtGui.QDialog(parent) widget.setWindowModality(Qt.WindowModal) web = QtWebKit.QWebView(parent) web.setHtml(html) layout = QtGui.QHBoxLayout() layout.setMargin(0) layout.setSpacing(0) layout.addWidget(web) widget.setWindowTitle(N_('Shortcuts')) widget.setLayout(layout) widget.resize(800, min(parent.height(), 600)) qtutils.add_action(widget, N_('Close'), widget.accept, Qt.Key_Question, Qt.Key_Enter, Qt.Key_Return) widget.show() return widget git-cola-1.9.3/cola/widgets/action.py000066400000000000000000000057641225156173500174610ustar00rootroot00000000000000"""The "Actions" widget""" from PyQt4 import QtCore from PyQt4 import QtGui from cola import cmds from cola.i18n import N_ from cola.models.selection import selection_model from cola.widgets import defs from cola.widgets import remote from cola.widgets import stash from cola.qtutils import create_button from cola.qtutils import connect_button class QFlowLayoutWidget(QtGui.QWidget): _horizontal = QtGui.QBoxLayout.LeftToRight _vertical = QtGui.QBoxLayout.TopToBottom def __init__(self, parent): QtGui.QWidget.__init__(self, parent) self._direction = self._vertical self._layout = layout = QtGui.QBoxLayout(self._direction) layout.setSpacing(defs.spacing) layout.setMargin(defs.margin) self.setLayout(layout) policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) self.setSizePolicy(policy) self.setMinimumSize(QtCore.QSize(1, 1)) self.aspect_ratio = 0.8 def resizeEvent(self, event): size = event.size() if size.width() * self.aspect_ratio < size.height(): dxn = self._vertical else: dxn = self._horizontal if dxn != self._direction: self._direction = dxn self.layout().setDirection(dxn) class ActionButtons(QFlowLayoutWidget): def __init__(self, parent=None): QFlowLayoutWidget.__init__(self, parent) layout = self.layout() self.stage_button = create_button(text=N_('Stage'), layout=layout) self.unstage_button = create_button(text=N_('Unstage'), layout=layout) self.refresh_button = create_button(text=N_('Refresh'), layout=layout) self.fetch_button = create_button(text=N_('Fetch...'), layout=layout) self.push_button = create_button(text=N_('Push...'), layout=layout) self.pull_button = create_button(text=N_('Pull...'), layout=layout) self.stash_button = create_button(text=N_('Stash...'), layout=layout) self.aspect_ratio = 0.4 layout.addStretch() self.setMinimumHeight(30) # Add callbacks connect_button(self.refresh_button, cmds.run(cmds.Refresh)) connect_button(self.fetch_button, remote.fetch) connect_button(self.push_button, remote.push) connect_button(self.pull_button, remote.pull) connect_button(self.stash_button, stash.stash) connect_button(self.stage_button, self.stage) connect_button(self.unstage_button, self.unstage) def stage(self): """Stage selected files, or all files if no selection exists.""" paths = selection_model().unstaged if not paths: cmds.do(cmds.StageModified) else: cmds.do(cmds.Stage, paths) def unstage(self): """Unstage selected files, or all files if no selection exists.""" paths = selection_model().staged if not paths: cmds.do(cmds.UnstageAll) else: cmds.do(cmds.Unstage, paths) git-cola-1.9.3/cola/widgets/archive.py000066400000000000000000000211241225156173500176110ustar00rootroot00000000000000import os from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import cmds from cola import core from cola import qtutils from cola.git import git from cola.git import STDOUT from cola.i18n import N_ from cola.widgets import defs class ExpandableGroupBox(QtGui.QGroupBox): def __init__(self, parent=None): QtGui.QGroupBox.__init__(self, parent) self.setFlat(True) self.expanded = True self.click_pos = None self.arrow_icon_size = 16 def set_expanded(self, expanded): if expanded == self.expanded: self.emit(SIGNAL('expanded(bool)'), expanded) return self.expanded = expanded for widget in self.findChildren(QtGui.QWidget): widget.setHidden(not expanded) self.emit(SIGNAL('expanded(bool)'), expanded) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: option = QtGui.QStyleOptionGroupBox() self.initStyleOption(option) icon_size = self.arrow_icon_size button_area = QtCore.QRect(0, 0, icon_size, icon_size) offset = self.arrow_icon_size + defs.spacing adjusted = option.rect.adjusted(0, 0, -offset, 0) top_left = adjusted.topLeft() button_area.moveTopLeft(QtCore.QPoint(top_left)) self.click_pos = event.pos() QtGui.QGroupBox.mousePressEvent(self, event) def mouseReleaseEvent(self, event): if (event.button() == Qt.LeftButton and self.click_pos == event.pos()): self.set_expanded(not self.expanded) QtGui.QGroupBox.mouseReleaseEvent(self, event) def paintEvent(self, event): painter = QtGui.QStylePainter(self) option = QtGui.QStyleOptionGroupBox() self.initStyleOption(option) painter.save() painter.translate(self.arrow_icon_size + defs.spacing, 0) painter.drawText(option.rect, Qt.AlignLeft, self.title()) painter.restore() style = QtGui.QStyle point = option.rect.adjusted(0, -4, 0, 0).topLeft() icon_size = self.arrow_icon_size option.rect = QtCore.QRect(point.x(), point.y(), icon_size, icon_size) if self.expanded: painter.drawPrimitive(style.PE_IndicatorArrowDown, option) else: painter.drawPrimitive(style.PE_IndicatorArrowRight, option) class GitArchiveDialog(QtGui.QDialog): @staticmethod def save(ref, shortref, parent=None): dlg = GitArchiveDialog(ref, shortref, parent) if dlg.exec_() != dlg.Accepted: return None return dlg def __init__(self, ref, shortref=None, parent=None): QtGui.QDialog.__init__(self, parent) self.setWindowModality(Qt.WindowModal) # input self.ref = ref if shortref is None: shortref = ref # outputs self.fmt = None filename = '%s-%s' % (os.path.basename(os.getcwd()), shortref) self.prefix = filename + '/' self.filename = filename # widgets self.setWindowTitle(N_('Save Archive')) self.filetext = QtGui.QLineEdit() self.filetext.setText(self.filename) self.browse = QtGui.QToolButton() self.browse.setAutoRaise(True) style = self.style() self.browse.setIcon(style.standardIcon(QtGui.QStyle.SP_DirIcon)) self.format_strings = ( git.archive('--list')[STDOUT].rstrip().splitlines()) self.format_combo = QtGui.QComboBox() self.format_combo.setEditable(False) self.format_combo.addItems(self.format_strings) self.cancel = QtGui.QPushButton() self.cancel.setText(N_('Cancel')) self.save = QtGui.QPushButton() self.save.setText(N_('Save')) self.save.setDefault(True) self.prefix_label = QtGui.QLabel() self.prefix_label.setText(N_('Prefix')) self.prefix_text = QtGui.QLineEdit() self.prefix_text.setText(self.prefix) self.prefix_group = ExpandableGroupBox() self.prefix_group.setTitle(N_('Advanced')) # layouts self.filelayt = QtGui.QHBoxLayout() self.filelayt.setMargin(0) self.filelayt.setSpacing(defs.spacing) self.filelayt.addWidget(self.browse) self.filelayt.addWidget(self.filetext) self.filelayt.addWidget(self.format_combo) self.prefixlayt = QtGui.QHBoxLayout() self.prefixlayt.setMargin(defs.margin) self.prefixlayt.setSpacing(defs.spacing) self.prefixlayt.addWidget(self.prefix_label) self.prefixlayt.addWidget(self.prefix_text) self.prefix_group.setLayout(self.prefixlayt) self.prefix_group.set_expanded(False) self.btnlayt = QtGui.QHBoxLayout() self.btnlayt.setMargin(0) self.btnlayt.setSpacing(defs.spacing) self.btnlayt.addStretch() self.btnlayt.addWidget(self.cancel) self.btnlayt.addWidget(self.save) self.mainlayt = QtGui.QVBoxLayout() self.mainlayt.setMargin(defs.margin) self.mainlayt.setSpacing(0) self.mainlayt.addLayout(self.filelayt) self.mainlayt.addWidget(self.prefix_group) self.mainlayt.addStretch() self.mainlayt.addLayout(self.btnlayt) self.setLayout(self.mainlayt) self.resize(555, 0) # initial setup; done before connecting to avoid # signal/slot side-effects if 'tar.gz' in self.format_strings: idx = self.format_strings.index('tar.gz') elif 'zip' in self.format_strings: idx = self.format_strings.index('zip') else: idx = 0 self.format_combo.setCurrentIndex(idx) self.update_filetext_for_format(idx) # connections self.connect(self.filetext, SIGNAL('textChanged(QString)'), self.filetext_changed) self.connect(self.prefix_text, SIGNAL('textChanged(QString)'), self.prefix_text_changed) self.connect(self.format_combo, SIGNAL('currentIndexChanged(int)'), self.update_filetext_for_format) self.connect(self.prefix_group, SIGNAL('expanded(bool)'), self.prefix_group_expanded) self.connect(self, SIGNAL('accepted()'), self.archive_saved) qtutils.connect_button(self.browse, self.choose_filename) qtutils.connect_button(self.cancel, self.reject) qtutils.connect_button(self.save, self.save_archive) def archive_saved(self): cmds.do(cmds.Archive, self.ref, self.fmt, self.prefix, self.filename) qtutils.information(N_('File Saved'), N_('File saved to "%s"') % self.filename) def save_archive(self): filename = self.filename if not filename: return if core.exists(filename): title = N_('Overwrite File?') msg = N_('The file "%s" exists and will be overwritten.') % filename info_txt = N_('Overwrite "%s"?') % filename ok_txt = N_('Overwrite') icon = qtutils.save_icon() if not qtutils.confirm(title, msg, info_txt, ok_txt, default=False, icon=icon): return self.accept() def choose_filename(self): filename = qtutils.save_as(self.filename) if not filename: return self.filetext.setText(filename) self.update_filetext_for_format(self.format_combo.currentIndex()) def filetext_changed(self, qstr): self.filename = unicode(qstr) self.save.setEnabled(bool(self.filename)) prefix = self.strip_exts(os.path.basename(self.filename)) + '/' self.prefix_text.setText(prefix) def prefix_text_changed(self, qstr): self.prefix = unicode(qstr) def strip_exts(self, text): for format_string in self.format_strings: ext = '.'+format_string if text.endswith(ext): return text[:-len(ext)] return text def update_filetext_for_format(self, idx): self.fmt = self.format_strings[idx] text = self.strip_exts(unicode(self.filetext.text())) self.filename = '%s.%s' % (text, self.fmt) self.filetext.setText(self.filename) self.filetext.setFocus() if '/' in text: start = text.rindex('/') + 1 else: start = 0 self.filetext.setSelection(start, len(text) - start) def prefix_group_expanded(self, expanded): if expanded: self.prefix_text.setFocus() else: self.filetext.setFocus() git-cola-1.9.3/cola/widgets/browse.py000066400000000000000000000614311225156173500174760ustar00rootroot00000000000000import os from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import cmds from cola import core from cola import difftool from cola import gitcmds from cola import utils from cola import qtutils from cola.cmds import BaseCommand from cola.compat import set from cola.git import git from cola.i18n import N_ from cola.interaction import Interaction from cola.models import main from cola.models.browse import GitRepoModel from cola.models.browse import GitRepoEntryManager from cola.models.browse import GitRepoNameItem from cola.models.selection import State from cola.models.selection import selection_model from cola.widgets import defs from cola.widgets import standard from cola.widgets.selectcommits import select_commits def worktree_browser_widget(parent, update=True): """Return a widget for immediate use.""" view = Browser(parent, update=update) view.tree.setModel(GitRepoModel(view.tree)) view.ctl = BrowserController(view.tree) return view def worktree_browser(update=True): """Launch a new worktree browser session.""" view = worktree_browser_widget(None, update=update) view.show() return view class Browser(standard.Widget): def __init__(self, parent, update=True): standard.Widget.__init__(self, parent) self.tree = RepoTreeView(self) self.mainlayout = QtGui.QHBoxLayout() self.setLayout(self.mainlayout) self.mainlayout.setMargin(0) self.mainlayout.setSpacing(defs.spacing) self.mainlayout.addWidget(self.tree) self.resize(720, 420) self.connect(self, SIGNAL('updated'), self._updated_callback) self.model = main.model() self.model.add_observer(self.model.message_updated, self.model_updated) qtutils.add_close_action(self) if update: self.model_updated() # Read-only mode property mode = property(lambda self: self.model.mode) def model_updated(self): """Update the title with the current branch and directory name.""" self.emit(SIGNAL('updated')) def _updated_callback(self): branch = self.model.currentbranch curdir = os.getcwd() msg = N_('Repository: %s') % curdir msg += '\n' msg += N_('Branch: %s') % branch self.setToolTip(msg) title = N_('%s: %s - Browse') % (self.model.project, branch) if self.mode == self.model.mode_amend: title += ' (%s)' % N_('Amending') self.setWindowTitle(title) class RepoTreeView(standard.TreeView): """Provides a filesystem-like view of a git repository.""" def __init__(self, parent): standard.TreeView.__init__(self, parent) self.setRootIsDecorated(True) self.setSortingEnabled(False) self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) # Observe model updates model = main.model() model.add_observer(model.message_updated, self.update_actions) # The non-Qt cola application model self.connect(self, SIGNAL('expanded(QModelIndex)'), self.size_columns) self.connect(self, SIGNAL('collapsed(QModelIndex)'), self.size_columns) # Sync selection before the key press event changes the model index self.connect(self, SIGNAL('indexAboutToChange()'), self.sync_selection) self.action_history =\ self._create_action( N_('View History...'), N_('View history for selected path(s).'), self.view_history, 'Shift+Ctrl+H') self.action_stage =\ self._create_action(N_('Stage Selected'), N_('Stage selected path(s) for commit.'), self.stage_selected, cmds.Stage.SHORTCUT) self.action_unstage =\ self._create_action( N_('Unstage Selected'), N_('Remove selected path(s) from the staging area.'), self.unstage_selected, 'Ctrl+U') self.action_untrack =\ self._create_action(N_('Untrack Selected'), N_('Stop tracking path(s)'), self.untrack_selected) self.action_difftool =\ self._create_action(cmds.LaunchDifftool.name(), N_('Launch git-difftool on the current path.'), cmds.run(cmds.LaunchDifftool), cmds.LaunchDifftool.SHORTCUT) self.action_difftool_predecessor =\ self._create_action(N_('Diff Against Predecessor...'), N_('Launch git-difftool against previous versions.'), self.difftool_predecessor, 'Shift+Ctrl+D') self.action_revert =\ self._create_action(N_('Revert Uncommitted Changes...'), N_('Revert changes to selected path(s).'), self.revert, 'Ctrl+Z') self.action_editor =\ self._create_action(cmds.LaunchEditor.name(), N_('Edit selected path(s).'), cmds.run(cmds.LaunchEditor), cmds.LaunchDifftool.SHORTCUT) def size_columns(self): """Set the column widths.""" self.resizeColumnToContents(0) def update_actions(self): """Enable/disable actions.""" selection = self.selected_paths() selected = bool(selection) staged = bool(self.selected_staged_paths(selection=selection)) modified = bool(self.selected_modified_paths(selection=selection)) unstaged = bool(self.selected_unstaged_paths(selection=selection)) tracked = bool(self.selected_tracked_paths()) self.action_history.setEnabled(selected) self.action_stage.setEnabled(unstaged) self.action_unstage.setEnabled(staged) self.action_untrack.setEnabled(tracked) self.action_difftool.setEnabled(staged or modified) self.action_difftool_predecessor.setEnabled(tracked) self.action_revert.setEnabled(tracked) def contextMenuEvent(self, event): """Create a context menu.""" self.update_actions() menu = QtGui.QMenu(self) menu.addAction(self.action_editor) menu.addAction(self.action_stage) menu.addAction(self.action_unstage) menu.addSeparator() menu.addAction(self.action_history) menu.addAction(self.action_difftool) menu.addAction(self.action_difftool_predecessor) menu.addSeparator() menu.addAction(self.action_revert) menu.addAction(self.action_untrack) menu.exec_(self.mapToGlobal(event.pos())) def mousePressEvent(self, event): """Synchronize the selection on mouse-press.""" result = QtGui.QTreeView.mousePressEvent(self, event) self.sync_selection() return result def sync_selection(self): """Push selection into the selection model.""" staged = [] unmerged = [] modified = [] untracked = [] state = State(staged, unmerged, modified, untracked) paths = self.selected_paths() model = main.model() model_staged = utils.add_parents(set(model.staged)) model_modified = utils.add_parents(set(model.modified)) model_unmerged = utils.add_parents(set(model.unmerged)) model_untracked = utils.add_parents(set(model.untracked)) for path in paths: if path in model_unmerged: unmerged.append(path) elif path in model_untracked: untracked.append(path) elif path in model_staged: staged.append(path) elif path in model_modified: modified.append(path) else: staged.append(path) # Push the new selection into the model. selection_model().set_selection(state) return paths def selectionChanged(self, old_selection, new_selection): """Override selectionChanged to update available actions.""" result = QtGui.QTreeView.selectionChanged(self, old_selection, new_selection) self.update_actions() paths = self.sync_selection() if paths and self.model().path_is_interesting(paths[0]): cached = paths[0] in main.model().staged cmds.do(cmds.Diff, paths, cached) return result def setModel(self, model): """Set the concrete QAbstractItemModel instance.""" QtGui.QTreeView.setModel(self, model) self.size_columns() def item_from_index(self, model_index): """Return the name item corresponding to the model index.""" index = model_index.sibling(model_index.row(), 0) return self.model().itemFromIndex(index) def selected_paths(self): """Return the selected paths.""" items = map(self.model().itemFromIndex, self.selectedIndexes()) return [i.path for i in items if i.type() == GitRepoNameItem.TYPE] def selected_staged_paths(self, selection=None): """Return selected staged paths.""" if not selection: selection = self.selected_paths() staged = utils.add_parents(set(main.model().staged)) return [p for p in selection if p in staged] def selected_modified_paths(self, selection=None): """Return selected modified paths.""" if not selection: selection = self.selected_paths() model = main.model() modified = utils.add_parents(set(model.modified)) return [p for p in selection if p in modified] def selected_unstaged_paths(self, selection=None): """Return selected unstaged paths.""" if not selection: selection = self.selected_paths() model = main.model() modified = utils.add_parents(set(model.modified)) untracked = utils.add_parents(set(model.untracked)) unstaged = modified.union(untracked) return [p for p in selection if p in unstaged] def selected_tracked_paths(self, selection=None): """Return selected tracked paths.""" if not selection: selection = self.selected_paths() model = main.model() staged = set(self.selected_staged_paths()) modified = set(self.selected_modified_paths()) untracked = utils.add_parents(set(model.untracked)) tracked = staged.union(modified) return [p for p in selection if p not in untracked or p in tracked] def _create_action(self, name, tooltip, slot, shortcut=None): """Create an action with a shortcut, tooltip, and callback slot.""" action = QtGui.QAction(name, self) action.setStatusTip(tooltip) if shortcut is not None: if hasattr(Qt, 'WidgetWithChildrenShortcut'): action.setShortcutContext(Qt.WidgetWithChildrenShortcut) action.setShortcut(shortcut) self.addAction(action) qtutils.connect_action(action, slot) return action def view_history(self): """Signal that we should view history for paths.""" self.emit(SIGNAL('history(QStringList)'), self.selected_paths()) def stage_selected(self): """Signal that we should stage selected paths.""" cmds.do(cmds.Stage, self.selected_unstaged_paths()) def unstage_selected(self): """Signal that we should stage selected paths.""" cmds.do(cmds.Unstage, self.selected_staged_paths()) def untrack_selected(self): """untrack selected paths.""" cmds.do(cmds.Untrack, self.selected_tracked_paths()) def difftool_predecessor(self): """Diff paths against previous versions.""" paths = self.selected_tracked_paths() self.emit(SIGNAL('difftool_predecessor'), paths) def revert(self): """Signal that we should revert changes to a path.""" if not qtutils.confirm(N_('Revert Uncommitted Changes?'), N_('This operation drops uncommitted changes.\n' 'These changes cannot be recovered.'), N_('Revert the uncommitted changes?'), N_('Revert Uncommitted Changes'), default=True, icon=qtutils.icon('undo.svg')): return paths = self.selected_tracked_paths() cmds.do(cmds.Checkout, ['HEAD', '--'] + paths) def current_path(self): """Return the path for the current item.""" index = self.currentIndex() if not index.isValid(): return None return self.item_from_index(index).path class BrowserController(QtCore.QObject): def __init__(self, view=None): QtCore.QObject.__init__(self, view) self.model = main.model() self.view = view self.updated = set() self.connect(view, SIGNAL('history(QStringList)'), self.view_history) self.connect(view, SIGNAL('expanded(QModelIndex)'), self.query_model) self.connect(view, SIGNAL('difftool_predecessor'), self.difftool_predecessor) def view_history(self, entries): """Launch the configured history browser path-limited to entries.""" entries = map(unicode, entries) cmds.do(cmds.VisualizePaths, entries) def query_model(self, model_index): """Update information about a directory as it is expanded.""" item = self.view.item_from_index(model_index) path = item.path if path in self.updated: return self.updated.add(path) GitRepoEntryManager.entry(path).update() entry = GitRepoEntryManager.entry for row in xrange(item.rowCount()): path = item.child(row, 0).path entry(path).update() def difftool_predecessor(self, paths): """Prompt for an older commit and launch difftool against it.""" args = ['--'] + paths revs, summaries = gitcmds.log_helper(all=False, extra_args=args) commits = select_commits(N_('Select Previous Version'), revs, summaries, multiselect=False) if not commits: return commit = commits[0] difftool.launch([commit, '--'] + paths) class BrowseModel(object): def __init__(self, ref): self.ref = ref self.relpath = None self.filename = None class SaveBlob(BaseCommand): def __init__(self, model): self.model = model def do(self): model = self.model cmd = ['git', 'show', '%s:%s' % (model.ref, model.relpath)] with core.xopen(model.filename, 'wb') as fp: proc = core.start_command(cmd, stdout=fp) out, err = proc.communicate() status = proc.returncode msg = (N_('Saved "%(filename)s" from "%(ref)s" to "%(destination)s"') % dict(filename=model.relpath, ref=model.ref, destination=model.filename)) Interaction.log_status(status, msg, '') Interaction.information( N_('File Saved'), N_('File saved to "%s"') % model.filename) class BrowseDialog(QtGui.QDialog): @staticmethod def browse(ref): parent = qtutils.active_window() model = BrowseModel(ref) dlg = BrowseDialog(model, parent=parent) dlg_model = GitTreeModel(ref, dlg) dlg.setModel(dlg_model) dlg.setWindowTitle(N_('Browsing %s') % model.ref) if hasattr(parent, 'width'): dlg.resize(parent.width()*3/4, 333) else: dlg.resize(420, 333) dlg.show() dlg.raise_() if dlg.exec_() != dlg.Accepted: return None return dlg @staticmethod def select_file(ref): parent = qtutils.active_window() model = BrowseModel(ref) dlg = BrowseDialog(model, select_file=True, parent=parent) dlg_model = GitTreeModel(ref, dlg) dlg.setModel(dlg_model) dlg.setWindowTitle(N_('Select file from "%s"') % model.ref) dlg.resize(parent.width()*3/4, 333) dlg.show() dlg.raise_() if dlg.exec_() != dlg.Accepted: return None return model.filename @staticmethod def select_file_from_list(file_list, title=N_('Select File')): parent = qtutils.active_window() model = BrowseModel(None) dlg = BrowseDialog(model, select_file=True, parent=parent) dlg_model = GitFileTreeModel(dlg) dlg_model.add_files(file_list) dlg.setModel(dlg_model) dlg.expandAll() dlg.setWindowTitle(title) dlg.resize(parent.width()*3/4, 333) dlg.show() dlg.raise_() if dlg.exec_() != dlg.Accepted: return None return model.filename def __init__(self, model, select_file=False, parent=None): QtGui.QDialog.__init__(self, parent) self.setAttribute(Qt.WA_MacMetalStyle) self.setWindowModality(Qt.WindowModal) # updated for use by commands self.model = model # widgets self.tree = GitTreeWidget(model.ref, parent=self) self.close = QtGui.QPushButton(N_('Close')) self.save = QtGui.QPushButton(select_file and N_('Select') or N_('Save')) self.save.setDefault(True) self.save.setEnabled(False) # layouts self.btnlayt = QtGui.QHBoxLayout() self.btnlayt.addStretch() self.btnlayt.addWidget(self.close) self.btnlayt.addWidget(self.save) self.layt = QtGui.QVBoxLayout() self.layt.setMargin(defs.margin) self.layt.setSpacing(defs.spacing) self.layt.addWidget(self.tree) self.layt.addLayout(self.btnlayt) self.setLayout(self.layt) # connections if select_file: self.connect(self.tree, SIGNAL('path_chosen'), self.path_chosen) else: self.connect(self.tree, SIGNAL('path_chosen'), self.save_path) self.connect(self.tree, SIGNAL('selectionChanged()'), self.selection_changed) qtutils.connect_button(self.close, self.reject) qtutils.connect_button(self.save, self.save_blob) def expandAll(self): self.tree.expandAll() def setModel(self, model): self.tree.setModel(model) def path_chosen(self, path, close=True): """Update the model from the view""" model = self.model model.relpath = path model.filename = path if close: self.accept() def save_path(self, path): """Choose an output filename based on the selected path""" self.path_chosen(path, close=False) model = self.model filename = qtutils.save_as(model.filename) if not filename: return model.filename = filename cmds.do(SaveBlob, model) self.accept() def save_blob(self): """Save the currently selected file""" filenames = self.tree.selected_files() if not filenames: return self.path_chosen(filenames[0], close=True) def selection_changed(self): """Update actions based on the current selection""" filenames = self.tree.selected_files() self.save.setEnabled(bool(filenames)) class GitTreeWidget(standard.TreeView): def __init__(self, ref, parent=None): standard.TreeView.__init__(self, parent) self.setHeaderHidden(True) self.connect(self, SIGNAL('doubleClicked(const QModelIndex &)'), self.double_clicked) def double_clicked(self, index): item = self.model().itemFromIndex(index) if item is None: return if item.is_dir: return self.emit(SIGNAL('path_chosen'), item.path) def selected_files(self): items = map(self.model().itemFromIndex, self.selectedIndexes()) return [i.path for i in items if not i.is_dir] def selectionChanged(self, old_selection, new_selection): QtGui.QTreeView.selectionChanged(self, old_selection, new_selection) self.emit(SIGNAL('selectionChanged()')) def select_first_file(self): """Select the first filename in the tree""" model = self.model() idx = self.indexAt(QtCore.QPoint(0, 0)) item = model.itemFromIndex(idx) while idx and idx.isValid() and item and item.is_dir: idx = self.indexBelow(idx) item = model.itemFromIndex(idx) if idx and idx.isValid() and item: self.setCurrentIndex(idx) class GitFileTreeModel(QtGui.QStandardItemModel): """Presents a list of file paths as a hierarchical tree.""" def __init__(self, parent): QtGui.QStandardItemModel.__init__(self, parent) self.dir_entries = {'': self.invisibleRootItem()} self.dir_rows = {} def clear(self): QtGui.QStandardItemModel.clear(self) self.dir_rows = {} self.dir_entries = {'': self.invisibleRootItem()} def add_files(self, files): """Add a list of files""" add_file = self.add_file for f in files: add_file(f) def add_file(self, path): """Add a file to the model.""" dirname = utils.dirname(path) dir_entries = self.dir_entries try: parent = dir_entries[dirname] except KeyError: parent = dir_entries[dirname] = self.create_dir_entry(dirname) row_items = self.create_row(path, False) parent.appendRow(row_items) def add_directory(self, parent, path): """Add a directory entry to the model.""" # Create model items row_items = self.create_row(path, True) # Insert directories before file paths try: row = self.dir_rows[parent] except KeyError: row = self.dir_rows[parent] = 0 parent.insertRow(row, row_items) self.dir_rows[parent] += 1 self.dir_entries[path] = row_items[0] return row_items[0] def create_row(self, path, is_dir): """Return a list of items representing a row.""" return [GitTreeItem(path, is_dir)] def create_dir_entry(self, dirname): """ Create a directory entry for the model. This ensures that directories are always listed before files. """ entries = dirname.split('/') curdir = [] parent = self.invisibleRootItem() curdir_append = curdir.append self_add_directory = self.add_directory dir_entries = self.dir_entries for entry in entries: curdir_append(entry) path = '/'.join(curdir) try: parent = dir_entries[path] except KeyError: grandparent = parent parent = self_add_directory(grandparent, path) dir_entries[path] = parent return parent class GitTreeModel(GitFileTreeModel): def __init__(self, ref, parent): GitFileTreeModel.__init__(self, parent) self.ref = ref self._initialize() def _initialize(self): """Iterate over git-ls-tree and create GitTreeItems.""" status, out, err = git.ls_tree('--full-tree', '-r', '-t', '-z', self.ref) if status != 0: Interaction.log_status(status, out, err) return if not out: return for line in out[:-1].split('\0'): # .....6 ...4 ......................................40 # 040000 tree c127cde9a0c644a3a8fef449a244f47d5272dfa6 relative # 100644 blob 139e42bf4acaa4927ec9be1ec55a252b97d3f1e2 relative/path objtype = line[7] relpath = line[6 + 1 + 4 + 1 + 40 + 1:] if objtype == 't': parent = self.dir_entries[utils.dirname(relpath)] self.add_directory(parent, relpath) elif objtype == 'b': self.add_file(relpath) class GitTreeItem(QtGui.QStandardItem): """ Represents a cell in a treeview. Many GitRepoItems could map to a single repository path, but this tree only has a single column. Each GitRepoItem manages a different cell in the tree view. """ def __init__(self, path, is_dir): QtGui.QStandardItem.__init__(self) self.is_dir = is_dir self.path = path self.setEditable(False) self.setDragEnabled(False) self.setText(utils.basename(path)) if is_dir: self.setIcon(qtutils.dir_icon()) else: self.setIcon(qtutils.file_icon()) git-cola-1.9.3/cola/widgets/cfgactions.py000066400000000000000000000243401225156173500203130ustar00rootroot00000000000000import os from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import core from cola import gitcfg from cola import gitcmds from cola import qtutils from cola.i18n import N_ from cola.interaction import Interaction from cola.qtutils import create_button from cola.widgets import defs from cola.widgets import completion from cola.widgets import standard def install(): Interaction.run_command = staticmethod(run_command) Interaction.confirm_config_action = staticmethod(confirm_config_action) def get_config_actions(): cfg = gitcfg.instance() return cfg.get_guitool_names() def confirm_config_action(name, opts): dlg = ActionDialog(qtutils.active_window(), name, opts) dlg.show() if dlg.exec_() != QtGui.QDialog.Accepted: return False rev = unicode(dlg.revision()) if rev: opts['revision'] = rev args = unicode(dlg.args()) if args: opts['args'] = args return True def run_command(title, command): """Show a command widget""" view = GitCommandWidget(title, qtutils.active_window()) view.set_command(command) view.show() view.raise_() view.run() view.exec_() return (view.exitstatus, view.out, view.err) class GitCommandWidget(standard.Dialog): """Nice TextView that reads the output of a command syncronously""" # Keep us in scope otherwise PyQt kills the widget def __init__(self, title, parent=None): standard.Dialog.__init__(self, parent) self.resize(720, 420) self.setWindowTitle(title) self.setWindowModality(Qt.ApplicationModal) # Construct the process self.proc = QtCore.QProcess(self) self.exitstatus = 0 self.out = '' self.err = '' self._layout = QtGui.QVBoxLayout(self) self._layout.setContentsMargins(3, 3, 3, 3) # Create the text browser self.output_text = QtGui.QTextBrowser(self) self.output_text.setAcceptDrops(False) self.output_text.setTabChangesFocus(True) self.output_text.setUndoRedoEnabled(False) self.output_text.setReadOnly(True) self.output_text.setAcceptRichText(False) self._layout.addWidget(self.output_text) # Create abort / close buttons self.button_abort = QtGui.QPushButton(self) self.button_abort.setText(N_('Abort')) self.button_close = QtGui.QPushButton(self) self.button_close.setText(N_('Close')) # Put them in a horizontal layout at the bottom. self.button_box = QtGui.QDialogButtonBox(self) self.button_box.addButton(self.button_abort, QtGui.QDialogButtonBox.RejectRole) self.button_box.addButton(self.button_close, QtGui.QDialogButtonBox.AcceptRole) self._layout.addWidget(self.button_box) # Connect the signals to the process self.connect(self.proc, SIGNAL('readyReadStandardOutput()'), self.read_stdout) self.connect(self.proc, SIGNAL('readyReadStandardError()'), self.read_stderr) self.connect(self.proc, SIGNAL('finished(int)'), self.finishProc) self.connect(self.proc, SIGNAL('stateChanged(QProcess::ProcessState)'), self.stateChanged) # Start with abort disabled - will be enabled when the process is run. self.button_abort.setEnabled(False) qtutils.connect_button(self.button_abort, self.abortProc) qtutils.connect_button(self.button_close, self.close) def set_command(self, command): self.command = command def run(self): """Runs the process""" self.proc.start(self.command[0], QtCore.QStringList(self.command[1:])) def read_stdout(self): rawbytes = self.proc.readAllStandardOutput() data = '' for b in rawbytes: data += b text = core.decode(data) self.out += text self.append_text(text) def read_stderr(self): rawbytes = self.proc.readAllStandardError() data = '' for b in rawbytes: data += b text = core.decode(data) self.err += text self.append_text(text) def append_text(self, text): cursor = self.output_text.textCursor() cursor.movePosition(cursor.End) cursor.insertText(text) cursor.movePosition(cursor.End) self.output_text.setTextCursor(cursor) def abortProc(self): if self.proc.state() != QtCore.QProcess.NotRunning: # Terminate seems to do nothing in windows self.proc.terminate() # Kill the process. QtCore.QTimer.singleShot(1000, self.proc, QtCore.SLOT('kill()')) def closeEvent(self, event): if self.proc.state() != QtCore.QProcess.NotRunning: # The process is still running, make sure we really want to abort. title = N_('Abort Action') msg = N_('An action is still running.\n' 'Terminating it could result in data loss.') info_text = N_('Abort the action?') ok_text = N_('Abort Action') if qtutils.confirm(title, msg, info_text, ok_text, default=False, icon=qtutils.discard_icon()): self.abortProc() event.accept() else: event.ignore() else: event.accept() return standard.Dialog.closeEvent(self, event) def stateChanged(self, newstate): # State of process has changed - change the abort button state. if newstate == QtCore.QProcess.NotRunning: self.button_abort.setEnabled(False) else: self.button_abort.setEnabled(True) def finishProc(self, status ): self.exitstatus = status class ActionDialog(standard.Dialog): def __init__(self, parent, name, opts): standard.Dialog.__init__(self, parent) self.name = name self.opts = opts self.setWindowModality(Qt.ApplicationModal) self.layt = QtGui.QVBoxLayout() self.layt.setMargin(defs.margin) self.layt.setSpacing(defs.spacing) self.setLayout(self.layt) title = opts.get('title') if title: self.setWindowTitle(os.path.expandvars(title)) self.prompt = QtGui.QLabel() prompt = opts.get('prompt') if prompt: self.prompt.setText(os.path.expandvars(prompt)) self.layt.addWidget(self.prompt) self.argslabel = QtGui.QLabel() if 'argprompt' not in opts or opts.get('argprompt') is True: argprompt = N_('Arguments') else: argprompt = opts.get('argprompt') self.argslabel.setText(argprompt) self.argstxt = QtGui.QLineEdit() self.argslayt = QtGui.QHBoxLayout() self.argslayt.addWidget(self.argslabel) self.argslayt.addWidget(self.argstxt) self.layt.addLayout(self.argslayt) if not self.opts.get('argprompt'): self.argslabel.setMinimumSize(1, 1) self.argstxt.setMinimumSize(1, 1) self.argstxt.hide() self.argslabel.hide() revs = ( (N_('Local Branch'), gitcmds.branch_list(remote=False)), (N_('Tracking Branch'), gitcmds.branch_list(remote=True)), (N_('Tag'), gitcmds.tag_list()), ) if 'revprompt' not in opts or opts.get('revprompt') is True: revprompt = N_('Revision') else: revprompt = opts.get('revprompt') self.revselect = RevisionSelector(self, revs) self.revselect.set_revision_label(revprompt) self.layt.addWidget(self.revselect) if not opts.get('revprompt'): self.revselect.hide() # Close/Run buttons self.btnlayt = QtGui.QHBoxLayout() self.btnlayt.addStretch() self.closebtn = create_button(text=N_('Close'), layout=self.btnlayt) self.runbtn = create_button(text=N_('Run'), layout=self.btnlayt) self.runbtn.setDefault(True) self.layt.addLayout(self.btnlayt) # Widen the dialog by default self.resize(666, self.height()) qtutils.connect_button(self.closebtn, self.reject) qtutils.connect_button(self.runbtn, self.accept) def revision(self): return self.revselect.revision() def args(self): return self.argstxt.text() class RevisionSelector(QtGui.QWidget): def __init__(self, parent, revs): QtGui.QWidget.__init__(self, parent) self._revs = revs self._revdict = dict(revs) self._layt = QtGui.QVBoxLayout() self._layt.setMargin(0) self.setLayout(self._layt) self._rev_layt = QtGui.QHBoxLayout() self._rev_layt.setMargin(0) self._rev_label = QtGui.QLabel() self._rev_layt.addWidget(self._rev_label) self._revision = completion.GitRefLineEdit() self._rev_layt.addWidget(self._revision) self._layt.addLayout(self._rev_layt) self._radio_layt = QtGui.QHBoxLayout() self._radio_btns = {} # Create the radio buttons for label, rev_list in self._revs: radio = QtGui.QRadioButton() radio.setText(label) radio.setObjectName(label) qtutils.connect_button(radio, self._set_revision_list) self._radio_layt.addWidget(radio) self._radio_btns[label] = radio self._radio_layt.addStretch() self._layt.addLayout(self._radio_layt) self._rev_list = QtGui.QListWidget() self._layt.addWidget(self._rev_list) label, rev_list = self._revs[0] self._radio_btns[label].setChecked(True) qtutils.set_items(self._rev_list, rev_list) self.connect(self._rev_list, SIGNAL('itemSelectionChanged()'), self._rev_list_selection_changed) def revision(self): return self._revision.text() def set_revision_label(self, txt): self._rev_label.setText(txt) def _set_revision_list(self): sender = unicode(self.sender().objectName()) revs = self._revdict[sender] qtutils.set_items(self._rev_list, revs) def _rev_list_selection_changed(self): items = self._rev_list.selectedItems() if not items: return self._revision.setText(items[0].text()) git-cola-1.9.3/cola/widgets/combodlg.py000066400000000000000000000037771225156173500177740ustar00rootroot00000000000000from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import SIGNAL from cola.widgets import standard class ComboDialog(standard.Dialog): """A dialog for choosing branches.""" def __init__(self, parent=None, title='', items=None): standard.Dialog.__init__(self, parent=parent) self.setWindowTitle(title) self.resize(400, 73) self._main_layt = QtGui.QVBoxLayout(self) # Exposed self.items_widget = QtGui.QComboBox(self) self.items_widget.setEditable(True) self._main_layt.addWidget(self.items_widget) self.button_box = QtGui.QDialogButtonBox(self) self.button_box.setOrientation(QtCore.Qt.Horizontal) self.button_box.setStandardButtons(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) self._main_layt.addWidget(self.button_box) self.setTabOrder(self.items_widget, self.button_box) if items: self.items_widget.addItems(items) self.connect(self.button_box, SIGNAL('accepted()'), self.accept) self.connect(self.button_box, SIGNAL('rejected()'), self.reject) def idx(self): return self.items_widget.currentIndex() def value(self): return unicode(self.items_widget.currentText()) def selected(self): """Present the dialog and return the chosen item.""" geom = QtGui.QApplication.instance().desktop().screenGeometry() width = geom.width() height = geom.height() if self.parent(): x = self.parent().x() + self.parent().width()/2 - self.width()/2 y = self.parent().y() + self.parent().height()/3 - self.height()/2 self.move(x, y) self.show() if self.exec_() == QtGui.QDialog.Accepted: return self.value() else: return None if __name__ == "__main__": import sys app = QtGui.QApplication(sys.argv) combo = ComboDialog() combo.show() sys.exit(app.exec_()) git-cola-1.9.3/cola/widgets/commitmsg.py000066400000000000000000000522401225156173500201720ustar00rootroot00000000000000from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import cmds from cola import core from cola import gitcmds from cola import gitcfg from cola import textwrap from cola.cmds import Interaction from cola.gitcmds import commit_message_path from cola.i18n import N_ from cola.models.dag import DAG from cola.models.dag import RepoReader from cola.models.prefs import tabwidth from cola.models.prefs import textwidth from cola.models.prefs import linebreak from cola.qtutils import add_action from cola.qtutils import confirm from cola.qtutils import connect_action_bool from cola.qtutils import connect_button from cola.qtutils import create_toolbutton from cola.qtutils import diff_font from cola.qtutils import options_icon from cola.qtutils import save_icon from cola.widgets import defs from cola.widgets.selectcommits import select_commits from cola.widgets.spellcheck import SpellCheckTextEdit from cola.widgets.text import HintedLineEdit class CommitMessageEditor(QtGui.QWidget): def __init__(self, model, parent): QtGui.QWidget.__init__(self, parent) self.model = model self.notifying = False self.spellcheck_initialized = False self._linebreak = None self._textwidth = None self._tabwidth = None # Actions self.signoff_action = add_action(self, cmds.SignOff.name(), cmds.run(cmds.SignOff), cmds.SignOff.SHORTCUT) self.signoff_action.setToolTip(N_('Sign off on this commit')) self.commit_action = add_action(self, N_('Commit@@verb'), self.commit, cmds.Commit.SHORTCUT) self.commit_action.setToolTip(N_('Commit staged changes')) # Widgets self.summary = CommitSummaryLineEdit() self.summary.extra_actions.append(self.signoff_action) self.summary.extra_actions.append(self.commit_action) self.description = CommitMessageTextEdit() self.description.extra_actions.append(self.signoff_action) self.description.extra_actions.append(self.commit_action) commit_button_tooltip = N_('Commit staged changes\n' 'Shortcut: Ctrl+Enter') self.commit_button = create_toolbutton(text=N_('Commit@@verb'), tooltip=commit_button_tooltip, icon=save_icon()) self.actions_menu = QtGui.QMenu() self.actions_button = create_toolbutton(icon=options_icon(), tooltip=N_('Actions...')) self.actions_button.setMenu(self.actions_menu) self.actions_button.setPopupMode(QtGui.QToolButton.InstantPopup) self.actions_menu.addAction(self.signoff_action) self.actions_menu.addAction(self.commit_action) self.actions_menu.addSeparator() # Amend checkbox self.amend_action = self.actions_menu.addAction( N_('Amend Last Commit')) self.amend_action.setCheckable(True) self.amend_action.setShortcut(cmds.AmendMode.SHORTCUT) self.amend_action.setShortcutContext(Qt.ApplicationShortcut) # Spell checker self.check_spelling_action = self.actions_menu.addAction( N_('Check Spelling')) self.check_spelling_action.setCheckable(True) self.check_spelling_action.setChecked(False) # Line wrapping self.autowrap_action = self.actions_menu.addAction( N_('Auto-Wrap Lines')) self.autowrap_action.setCheckable(True) self.autowrap_action.setChecked(linebreak()) # Commit message self.actions_menu.addSeparator() self.load_commitmsg_menu = self.actions_menu.addMenu( N_('Load Previous Commit Message')) self.connect(self.load_commitmsg_menu, SIGNAL('aboutToShow()'), self.build_commitmsg_menu) self.fixup_commit_menu = self.actions_menu.addMenu( N_('Fixup Previous Commit')) self.connect(self.fixup_commit_menu, SIGNAL('aboutToShow()'), self.build_fixup_menu) self.toplayout = QtGui.QHBoxLayout() self.toplayout.setMargin(0) self.toplayout.setSpacing(defs.spacing) self.toplayout.addWidget(self.actions_button) self.toplayout.addWidget(self.summary) self.toplayout.addWidget(self.commit_button) self.mainlayout = QtGui.QVBoxLayout() self.mainlayout.setMargin(defs.margin) self.mainlayout.setSpacing(defs.spacing) self.mainlayout.addLayout(self.toplayout) self.mainlayout.addWidget(self.description) self.setLayout(self.mainlayout) connect_button(self.commit_button, self.commit) # Broadcast the amend mode connect_action_bool(self.amend_action, cmds.run(cmds.AmendMode)) connect_action_bool(self.check_spelling_action, self.toggle_check_spelling) # Handle the one-off autowrapping connect_action_bool(self.autowrap_action, self.set_linebreak) add_action(self.summary, N_('Move Down'), self.focus_description, Qt.Key_Down, Qt.Key_Return, Qt.Key_Enter) self.model.add_observer(self.model.message_commit_message_changed, self.set_commit_message) self.connect(self.summary, SIGNAL('cursorPosition(int,int)'), self.emit_position) self.connect(self.description, SIGNAL('cursorPosition(int,int)'), # description starts at line 2 lambda row, col: self.emit_position(row + 2, col)) # Keep model informed of changes self.connect(self.summary, SIGNAL('textChanged(QString)'), self.commit_summary_changed) self.connect(self.description, SIGNAL('textChanged()'), self.commit_message_changed) self.connect(self.description, SIGNAL('leave()'), self.focus_summary) self.setFont(diff_font()) self.summary.enable_hint(True) self.description.enable_hint(True) self.commit_button.setEnabled(False) self.commit_action.setEnabled(False) self.setFocusProxy(self.summary) self.set_tabwidth(tabwidth()) self.set_textwidth(textwidth()) self.set_linebreak(linebreak()) # Loading message commit_msg = '' commit_msg_path = commit_message_path() if commit_msg_path: commit_msg = core.read(commit_msg_path) self.set_commit_message(commit_msg) # Allow tab to jump from the summary to the description self.setTabOrder(self.summary, self.description) def set_initial_size(self): self.setMaximumHeight(133) QtCore.QTimer.singleShot(1, self.restore_size) def restore_size(self): self.setMaximumHeight(2 ** 13) def focus_summary(self): self.summary.setFocus() def focus_description(self): self.description.setFocus() def commit_message(self, raw=True): """Return the commit message as a unicode string""" summary = self.summary.value() if raw: description = self.description.value() else: description = self.formatted_description() if summary and description: return summary + '\n\n' + description elif summary: return summary elif description: return '\n\n' + description else: return '' def formatted_description(self): text = self.description.value() if not self._linebreak: return text return textwrap.word_wrap(text, self._tabwidth, self._textwidth) def commit_summary_changed(self, value): """Respond to changes to the `summary` field Newlines can enter the `summary` field when pasting, which is undesirable. Break the pasted value apart into the separate (summary, description) values and move the description over to the "extended description" field. """ value = unicode(value) if '\n' in value: summary, description = value.split('\n', 1) description = description.lstrip('\n') cur_description = self.description.value() if cur_description: description = description + '\n' + cur_description # this callback is triggered by changing `summary` # so disable signals for `summary` only. self.summary.blockSignals(True) self.summary.set_value(summary) self.summary.blockSignals(False) self.description.set_value(description) self.commit_message_changed() def commit_message_changed(self, value=None): """Update the model when values change""" self.notifying = True message = self.commit_message() self.model.set_commitmsg(message) self.refresh_palettes() self.notifying = False self.update_actions() def update_actions(self): commit_enabled = bool(self.summary.value()) self.commit_button.setEnabled(commit_enabled) self.commit_action.setEnabled(commit_enabled) def refresh_palettes(self): """Update the color palette for the hint text""" self.summary.refresh_palette() self.description.refresh_palette() def set_commit_message(self, message): """Set the commit message to match the observed model""" if self.notifying: # Calling self.model.set_commitmsg(message) causes us to # loop around so break the loop return # Parse the "summary" and "description" fields umsg = unicode(message) lines = umsg.splitlines() num_lines = len(lines) if num_lines == 0: # Message is empty summary = '' description = '' elif num_lines == 1: # Message has a summary only summary = lines[0] description = '' elif num_lines == 2: # Message has two lines; this is not a common case summary = lines[0] description = lines[1] else: # Summary and several description lines summary = lines[0] if lines[1]: # We usually skip this line but check just in case description_lines = lines[1:] else: description_lines = lines[2:] description = '\n'.join(description_lines) focus_summary = not summary focus_description = not description # Update summary if not summary and not self.summary.hasFocus(): summary = self.summary.hint() blocksignals = self.summary.blockSignals(True) self.summary.setText(summary) self.summary.setCursorPosition(0) self.summary.blockSignals(blocksignals) # Update description if not description and not self.description.hasFocus(): description = self.description.hint() blocksignals = self.description.blockSignals(True) self.description.setPlainText(description) self.description.blockSignals(blocksignals) # Update text color self.refresh_palettes() # Focus the empty summary or description if focus_summary: self.summary.setFocus() self.summary.emit_position() elif focus_description: self.description.setFocus() self.description.emit_position() else: self.summary.emit_position() self.update_actions() def set_tabwidth(self, width): self._tabwidth = width self.description.set_tabwidth(width) def set_textwidth(self, width): self._textwidth = width self.description.set_textwidth(width) def set_linebreak(self, brk): self._linebreak = brk self.description.set_linebreak(brk) blocksignals = self.autowrap_action.blockSignals(True) self.autowrap_action.setChecked(brk) self.autowrap_action.blockSignals(blocksignals) def setFont(self, font): """Pass the setFont() calls down to the text widgets""" self.summary.setFont(font) self.description.setFont(font) def set_mode(self, mode): can_amend = not self.model.is_merging checked = (mode == self.model.mode_amend) blocksignals = self.amend_action.blockSignals(True) self.amend_action.setEnabled(can_amend) self.amend_action.setChecked(checked) self.amend_action.blockSignals(blocksignals) def emit_position(self, row, col): self.emit(SIGNAL('cursorPosition(int,int)'), row, col) def commit(self): """Attempt to create a commit from the index and commit message.""" if not bool(self.summary.value()): # Describe a good commit message error_msg = N_('' 'Please supply a commit message.\n\n' 'A good commit message has the following format:\n\n' '- First line: Describe in one sentence what you did.\n' '- Second line: Blank\n' '- Remaining lines: Describe why this change is good.\n') Interaction.log(error_msg) Interaction.information(N_('Missing Commit Message'), error_msg) return msg = self.commit_message(raw=False) if not self.model.staged: error_msg = N_('' 'No changes to commit.\n\n' 'You must stage at least 1 file before you can commit.') if self.model.modified: informative_text = N_('Would you like to stage and ' 'commit all modified files?') if not confirm(N_('Stage and commit?'), error_msg, informative_text, N_('Stage and Commit'), default=True, icon=save_icon()): return else: Interaction.information(N_('Nothing to commit'), error_msg) return cmds.do(cmds.StageModified) # Warn that amending published commits is generally bad amend = self.amend_action.isChecked() if (amend and self.model.is_commit_published() and not confirm(N_('Rewrite Published Commit?'), N_('This commit has already been published.\n' 'This operation will rewrite published history.\n' 'You probably don\'t want to do this.'), N_('Amend the published commit?'), N_('Amend Commit'), default=False, icon=save_icon())): return status, out, err = cmds.do(cmds.Commit, amend, msg) if status != 0: Interaction.critical(N_('Commit failed'), N_('"git commit" returned exit code %s') % (status,), out + err) def build_fixup_menu(self): self.build_commits_menu(cmds.LoadFixupMessage, self.fixup_commit_menu, self.choose_fixup_commit, prefix='fixup! ') def build_commitmsg_menu(self): self.build_commits_menu(cmds.LoadCommitMessageFromSHA1, self.load_commitmsg_menu, self.choose_commit_message) def build_commits_menu(self, cmd, menu, chooser, prefix=''): dag = DAG('HEAD', 6) commits = RepoReader(dag) menu_commits = [] for idx, c in enumerate(commits): menu_commits.insert(0, c) if idx > 5: continue menu.clear() for c in menu_commits: menu.addAction(prefix + c.summary, cmds.run(cmd, c.sha1)) if len(commits) == 6: menu.addSeparator() menu.addAction(N_('More...'), chooser) def choose_commit(self, cmd): revs, summaries = gitcmds.log_helper() sha1s = select_commits(N_('Select Commit'), revs, summaries, multiselect=False) if not sha1s: return sha1 = sha1s[0] cmds.do(cmd, sha1) def choose_commit_message(self): self.choose_commit(cmds.LoadCommitMessageFromSHA1) def choose_fixup_commit(self): self.choose_commit(cmds.LoadFixupMessage) def toggle_check_spelling(self, enabled): spellcheck = self.description.spellcheck if enabled and not self.spellcheck_initialized: # Add our name to the dictionary self.spellcheck_initialized = True cfg = gitcfg.instance() user_name = cfg.get('user.name') if user_name: for part in user_name.split(): spellcheck.add_word(part) # Add our email address to the dictionary user_email = cfg.get('user.email') if user_email: for part in user_email.split('@'): for elt in part.split('.'): spellcheck.add_word(elt) # git jargon spellcheck.add_word('Acked') spellcheck.add_word('Signed') spellcheck.add_word('Closes') spellcheck.add_word('Fixes') self.description.highlighter.enable(enabled) class CommitSummaryLineEdit(HintedLineEdit): def __init__(self, parent=None): hint = N_('Commit summary') HintedLineEdit.__init__(self, hint, parent) self.extra_actions = [] def contextMenuEvent(self, event): menu = self.createStandardContextMenu() if self.extra_actions: menu.addSeparator() for action in self.extra_actions: menu.addAction(action) menu.exec_(self.mapToGlobal(event.pos())) class CommitMessageTextEdit(SpellCheckTextEdit): def __init__(self, parent=None): hint = N_('Extended description...') SpellCheckTextEdit.__init__(self, hint, parent) self.extra_actions = [] self.setMinimumSize(QtCore.QSize(1, 1)) self.action_emit_leave = add_action(self, 'Shift Tab', self.emit_leave, 'Shift+tab') self.installEventFilter(self) def eventFilter(self, obj, event): if event.type() == QtCore.QEvent.FocusIn: height = QtGui.QFontMetrics(self.font()).height() * 3 height += defs.spacing * 4 self.setMinimumSize(QtCore.QSize(1, height)) elif event.type() == QtCore.QEvent.FocusOut: self.setMinimumSize(QtCore.QSize(1, 1)) return False def contextMenuEvent(self, event): menu, spell_menu = self.context_menu() if self.extra_actions: menu.addSeparator() for action in self.extra_actions: menu.addAction(action) menu.exec_(self.mapToGlobal(event.pos())) def keyPressEvent(self, event): if event.key() == Qt.Key_Up: cursor = self.textCursor() position = cursor.position() if position == 0: # The cursor is at the beginning of the line. # If we have selection then simply reset the cursor. # Otherwise, emit a signal so that the parent can # change focus. if cursor.hasSelection(): cursor.setPosition(0) self.setTextCursor(cursor) else: self.emit_leave() event.accept() return text_before = unicode(self.toPlainText())[:position] lines_before = text_before.count('\n') if lines_before == 0: # If we're on the first line, but not at the # beginning, then move the cursor to the beginning # of the line. if event.modifiers() & Qt.ShiftModifier: mode = QtGui.QTextCursor.KeepAnchor else: mode = QtGui.QTextCursor.MoveAnchor cursor.setPosition(0, mode) self.setTextCursor(cursor) event.accept() return elif event.key() == Qt.Key_Down: cursor = self.textCursor() position = cursor.position() all_text = unicode(self.toPlainText()) text_after = all_text[position:] lines_after = text_after.count('\n') if lines_after == 0: if event.modifiers() & Qt.ShiftModifier: mode = QtGui.QTextCursor.KeepAnchor else: mode = QtGui.QTextCursor.MoveAnchor cursor.setPosition(len(all_text), mode) self.setTextCursor(cursor) event.accept() return SpellCheckTextEdit.keyPressEvent(self, event) def emit_leave(self): self.emit(SIGNAL('leave()')) git-cola-1.9.3/cola/widgets/compare.py000066400000000000000000000222211225156173500176150ustar00rootroot00000000000000"""Provides dialogs for comparing branches and commits.""" from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import SIGNAL from cola import qtutils from cola import difftool from cola import gitcmds from cola.i18n import N_ from cola.qtutils import connect_button from cola.widgets import defs from cola.widgets import standard class FileItem(QtGui.QTreeWidgetItem): def __init__(self, path, icon): QtGui.QTreeWidgetItem.__init__(self, [path]) self.path = path self.setIcon(0, icon) def compare_branches(): """Launches a dialog for comparing a pair of branches""" view = CompareBranchesDialog(qtutils.active_window()) view.show() return view class CompareBranchesDialog(standard.Dialog): def __init__(self, parent): standard.Dialog.__init__(self, parent=parent) self.BRANCH_POINT = N_('*** Branch Point ***') self.SANDBOX = N_('*** Sandbox ***') self.LOCAL = N_('Local') self.remote_branches = gitcmds.branch_list(remote=True) self.local_branches = gitcmds.branch_list(remote=False) self.setWindowTitle(N_('Branch Diff Viewer')) self.resize(658, 350) self.main_layt = QtGui.QVBoxLayout(self) self.main_layt.setMargin(defs.margin) self.main_layt.setSpacing(defs.spacing) self.splitter = QtGui.QSplitter(self) self.splitter.setOrientation(QtCore.Qt.Vertical) self.splitter.setHandleWidth(defs.handle_width) self.top_widget = QtGui.QWidget(self.splitter) self.top_grid_layt = QtGui.QGridLayout(self.top_widget) self.top_grid_layt.setMargin(0) self.top_grid_layt.setSpacing(defs.spacing) self.left_combo = QtGui.QComboBox(self.top_widget) self.left_combo.addItem(N_('Local')) self.left_combo.addItem(N_('Remote')) self.left_combo.setCurrentIndex(0) self.top_grid_layt.addWidget(self.left_combo, 0, 0, 1, 1) self.right_combo = QtGui.QComboBox(self.top_widget) self.right_combo.addItem(N_('Local')) self.right_combo.addItem(N_('Remote')) self.right_combo.setCurrentIndex(1) self.top_grid_layt.addWidget(self.right_combo, 0, 1, 1, 1) self.left_list = QtGui.QListWidget(self.top_widget) self.top_grid_layt.addWidget(self.left_list, 1, 0, 1, 1) self.right_list = QtGui.QListWidget(self.top_widget) self.top_grid_layt.addWidget(self.right_list, 1, 1, 1, 1) self.bottom_widget = QtGui.QWidget(self.splitter) self.bottom_grid_layt = QtGui.QGridLayout(self.bottom_widget) self.bottom_grid_layt.setMargin(0) self.bottom_grid_layt.setSpacing(defs.button_spacing) self.button_spacer = QtGui.QSpacerItem(1, 1, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.bottom_grid_layt.addItem(self.button_spacer, 1, 1, 1, 1) self.button_compare = QtGui.QPushButton(self.bottom_widget) self.button_compare.setText(N_('Compare')) self.bottom_grid_layt.addWidget(self.button_compare, 1, 2, 1, 1) self.button_close = QtGui.QPushButton(self.bottom_widget) self.button_close.setText(N_('Close')) self.bottom_grid_layt.addWidget(self.button_close, 1, 3, 1, 1) self.diff_files = standard.TreeWidget(self.bottom_widget) self.diff_files.headerItem().setText(0, N_('File Differences')) self.bottom_grid_layt.addWidget(self.diff_files, 0, 0, 1, 4) self.main_layt.addWidget(self.splitter) connect_button(self.button_close, self.accept) connect_button(self.button_compare, self.compare) self.connect(self.diff_files, SIGNAL('itemDoubleClicked(QTreeWidgetItem*,int)'), self.compare) self.connect(self.left_combo, SIGNAL('currentIndexChanged(int)'), lambda x: self.update_combo_boxes(left=True)) self.connect(self.right_combo, SIGNAL('currentIndexChanged(int)'), lambda x: self.update_combo_boxes(left=False)) self.connect(self.left_list, SIGNAL('itemSelectionChanged()'), self.update_diff_files) self.connect(self.right_list, SIGNAL('itemSelectionChanged()'), self.update_diff_files) self.update_combo_boxes(left=True) self.update_combo_boxes(left=False) # Pre-select the 0th elements item = self.left_list.item(0) if item: self.left_list.setCurrentItem(item) self.left_list.setItemSelected(item, True) item = self.right_list.item(0) if item: self.right_list.setCurrentItem(item) self.right_list.setItemSelected(item, True) def selection(self): left_item = self.left_list.currentItem() if left_item and left_item.isSelected(): left_item = unicode(left_item.text()) else: left_item = None right_item = self.right_list.currentItem() if right_item and right_item.isSelected(): right_item = unicode(right_item.text()) else: right_item = None return (left_item, right_item) def update_diff_files(self, *rest): """Updates the list of files whenever the selection changes""" # Left and Right refer to the comparison pair (l,r) left_item, right_item = self.selection() if (not left_item or not right_item or left_item == right_item): self.set_diff_files([]) return left_item = self.remote_ref(left_item) right_item = self.remote_ref(right_item) # If any of the selection includes sandbox then we # generate the same diff, regardless. This means we don't # support reverse diffs against sandbox aka worktree. if self.SANDBOX in (left_item, right_item): self.use_sandbox = True if left_item == self.SANDBOX: self.diff_arg = (right_item,) else: self.diff_arg = (left_item,) else: self.diff_arg = (left_item, right_item) self.use_sandbox = False # start and end as in 'git diff start end' self.start = left_item self.end = right_item if len(self.diff_arg) == 1: files = gitcmds.diff_index_filenames(self.diff_arg[0]) else: files = gitcmds.diff_filenames(*self.diff_arg) self.set_diff_files(files) def set_diff_files(self, files): mk = FileItem icon = qtutils.icon('script.png') self.diff_files.clear() self.diff_files.addTopLevelItems([mk(f, icon) for f in files]) def remote_ref(self, branch): """Returns the remote ref for 'git diff [local] [remote]' """ if branch == self.BRANCH_POINT: # Compare against the branch point so find the merge-base branch = gitcmds.current_branch() tracked_branch = gitcmds.tracked_branch() if tracked_branch: return gitcmds.merge_base(branch, tracked_branch) else: remote_branches = gitcmds.branch_list(remote=True) remote_branch = 'origin/%s' % branch if remote_branch in remote_branches: return gitcmds.merge_base(branch, remote_branch) elif 'origin/master' in remote_branches: return gitcmds.merge_base(branch, 'origin/master') else: return 'HEAD' else: # Compare against the remote branch return branch def update_combo_boxes(self, left=False): """Update listwidgets from the combobox selection Update either the left or right listwidgets to reflect the available items. """ if left: which = unicode(self.left_combo.currentText()) widget = self.left_list else: which = unicode(self.right_combo.currentText()) widget = self.right_list if not which: return # If we're looking at "local" stuff then provide the # sandbox as a valid choice. If we're looking at # "remote" stuff then also include the branch point. if which == self.LOCAL: new_list = ([self.SANDBOX]+ self.local_branches) else: new_list = ([self.BRANCH_POINT] + self.remote_branches) widget.clear() widget.addItems(new_list) if new_list: item = widget.item(0) widget.setCurrentItem(item) widget.setItemSelected(item, True) def compare(self, *args): """Shows the diff for a specific file """ tree_widget = self.diff_files item = tree_widget.currentItem() if item and item.isSelected(): self.compare_file(item.path) def compare_file(self, filename): """Initiates the difftool session""" if self.use_sandbox: arg = self.diff_arg else: arg = (self.start, self.end) difftool.launch(arg + ('--', filename)) git-cola-1.9.3/cola/widgets/completion.py000066400000000000000000000444511225156173500203510ustar00rootroot00000000000000import re import subprocess from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola.i18n import N_ from cola import qtutils from cola import utils from cola.compat import set from cola.models import main from cola.widgets import defs class CompletionLineEdit(QtGui.QLineEdit): def __init__(self, model, parent=None): QtGui.QLineEdit.__init__(self, parent) self.setFont(qtutils.diff_font()) # used to hide the completion popup after a drag-select self._drag = 0 self._keys_to_ignore = set([Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape]) completion_model = model(self) completer = Completer(completion_model, self) completer.setWidget(self) self._completer = completer self._delegate = HighlightDelegate(self) self.connect(self, SIGNAL('textChanged(QString)'), self._text_changed) completer.popup().setItemDelegate(self._delegate) self.connect(self._completer, SIGNAL('activated(QString)'), self._complete) def refresh(self): return self._completer.model().update() def popup(self): return self._completer.popup() def value(self): return unicode(self.text()) def _is_case_sensitive(self, text): return bool([char for char in text if char.isupper()]) def _text_changed(self, text): text = self._last_word() self._do_text_changed(text) def _do_text_changed(self, text): case_sensitive = self._is_case_sensitive(text) if case_sensitive: self._completer.setCaseSensitivity(Qt.CaseSensitive) else: self._completer.setCaseSensitivity(Qt.CaseInsensitive) self._delegate.set_highlight_text(text, case_sensitive) self._completer.set_match_text(text, case_sensitive) def update_matches(self): text = self._last_word() case_sensitive = self._is_case_sensitive(text) self._completer.model().update_matches(case_sensitive) def _complete(self, completion): """ This is the event handler for the QCompleter.activated(QString) signal, it is called when the user selects an item in the completer popup. """ completion = unicode(completion) if not completion: self._do_text_changed('') return words = self._words() if words and not self._ends_with_whitespace(): words.pop() words.append(completion) text = subprocess.list2cmdline(words) self.setText(text) self.emit(SIGNAL('changed()')) self._do_text_changed('') def _words(self): return utils.shell_split(unicode(self.text())) def _ends_with_whitespace(self): text = unicode(self.text()) return text.rstrip() != text def _last_word(self): if self._ends_with_whitespace(): return u'' words = self._words() if not words: return unicode(self.text()) if not words[-1]: return u'' return words[-1] def event(self, event): if event.type() == QtCore.QEvent.KeyPress: if (event.key() == Qt.Key_Tab and self.popup().isVisible()): event.ignore() return True if (event.key() in (Qt.Key_Return, Qt.Key_Enter) and not self.popup().isVisible()): self.emit(SIGNAL('returnPressed()')) event.accept() return True if event.type() == QtCore.QEvent.Hide: self.close_popup() return QtGui.QLineEdit.event(self, event) def do_completion(self): self._completer.popup().setCurrentIndex( self._completer.model().index(0,0)) self._completer.complete() def keyPressEvent(self, event): if self._completer.popup().isVisible(): if event.key() in self._keys_to_ignore: event.ignore() self._complete(self._last_word()) return elif (event.key() == Qt.Key_Down and self._completer.completionCount() > 0): event.accept() self.do_completion() return QtGui.QLineEdit.keyPressEvent(self, event) prefix = self._last_word() if prefix != unicode(self._completer.completionPrefix()): self._update_popup_items(prefix) if len(event.text()) > 0 and len(prefix) > 0: self._completer.complete() #: _drag: 0 - unclicked, 1 - clicked, 2 - dragged def mousePressEvent(self, event): self._drag = 1 return QtGui.QLineEdit.mousePressEvent(self, event) def mouseMoveEvent(self, event): if self._drag == 1: self._drag = 2 return QtGui.QLineEdit.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): if self._drag != 2 and event.button() != Qt.RightButton: self.do_completion() self._drag = 0 return QtGui.QLineEdit.mouseReleaseEvent(self, event) def close_popup(self): if self.popup().isVisible(): self.popup().close() def _update_popup_items(self, prefix): """ Filters the completer's popup items to only show items with the given prefix. """ self._completer.setCompletionPrefix(prefix) self._completer.popup().setCurrentIndex( self._completer.model().index(0,0)) def __del__(self): self.dispose() def dispose(self): self._completer.dispose() class GatherCompletionsThread(QtCore.QThread): def __init__(self, model): QtCore.QThread.__init__(self) self.model = model self.case_sensitive = False def run(self): text = None # Loop when the matched text changes between the start and end time. # This happens when gather_matches() takes too long and the # model's matched_text changes in-between. while text != self.model.matched_text: text = self.model.matched_text items = self.model.gather_matches(self.case_sensitive) if text is not None: self.emit(SIGNAL('items_gathered'), items) class HighlightDelegate(QtGui.QStyledItemDelegate): """A delegate used for auto-completion to give formatted completion""" def __init__(self, parent=None): # model, parent=None): QtGui.QStyledItemDelegate.__init__(self, parent) self.highlight_text = '' self.case_sensitive = False self.doc = QtGui.QTextDocument() try: self.doc.setDocumentMargin(0) except: # older PyQt4 pass def set_highlight_text(self, text, case_sensitive): """Sets the text that will be made bold in the term name when displayed""" self.highlight_text = text self.case_sensitive = case_sensitive def paint(self, painter, option, index): """Overloaded Qt method for custom painting of a model index""" if not self.highlight_text: return QtGui.QStyledItemDelegate.paint(self, painter, option, index) text = unicode(index.data().toPyObject()) if self.case_sensitive: html = text.replace(self.highlight_text, '%s' % self.highlight_text) else: match = re.match(r'(.*)(%s)(.*)' % re.escape(self.highlight_text), text, re.IGNORECASE) if match: start = match.group(1) or '' middle = match.group(2) or '' end = match.group(3) or '' html = (start + ('%s' % middle) + end) else: html = text self.doc.setHtml(html) # Painting item without text, Text Document will paint the text optionV4 = QtGui.QStyleOptionViewItemV4(option) self.initStyleOption(optionV4, index) optionV4.text = QtCore.QString() style = QtGui.QApplication.style() style.drawControl(QtGui.QStyle.CE_ItemViewItem, optionV4, painter) ctx = QtGui.QAbstractTextDocumentLayout.PaintContext() # Highlighting text if item is selected if (optionV4.state & QtGui.QStyle.State_Selected): color = optionV4.palette.color(QtGui.QPalette.Active, QtGui.QPalette.HighlightedText) ctx.palette.setColor(QtGui.QPalette.Text, color) # translate the painter to where the text is drawn rect = style.subElementRect(QtGui.QStyle.SE_ItemViewItemText, optionV4) painter.save() start = rect.topLeft() + QtCore.QPoint(3, 0) painter.translate(start) # tell the text document to draw the html for us self.doc.documentLayout().draw(painter, ctx) painter.restore() class CompletionModel(QtGui.QStandardItemModel): def __init__(self, parent): QtGui.QStandardItemModel.__init__(self, parent) self.matched_text = '' self.case_sensitive = False self.update_thread = GatherCompletionsThread(self) self.connect(self.update_thread, SIGNAL('items_gathered'), self.apply_matches) def lower_completion_cmp(self, a, b): return cmp(a.replace('.','').lower(), a.replace('.','').lower()) def completion_cmp(self, a, b): return cmp(a.replace('.',''), a.replace('.','')) def update(self): case_sensitive = self.update_thread.case_sensitive self.update_matches(case_sensitive) def set_match_text(self, matched_text, case_sensitive): self.matched_text = matched_text self.update_matches(case_sensitive) def update_matches(self, case_sensitive): self.case_sensitive = case_sensitive self.update_thread.case_sensitive = case_sensitive if not self.update_thread.isRunning(): self.update_thread.start() def gather_matches(self, case_sensitive): return ((), (), set()) def apply_matches(self, match_tuple): self.match_tuple = match_tuple matched_refs, matched_paths, dirs = match_tuple QStandardItem = QtGui.QStandardItem file_icon = qtutils.file_icon() dir_icon = qtutils.dir_icon() git_icon = qtutils.git_icon() matched_text = self.matched_text items = [] for ref in matched_refs: item = QStandardItem() item.setText(ref) item.setIcon(git_icon) items.append(item) if matched_paths and (not matched_text or matched_text in '--'): item = QStandardItem() item.setText('--') item.setIcon(file_icon) items.append(item) for match in matched_paths: item = QStandardItem() item.setText(match) if match in dirs: item.setIcon(dir_icon) else: item.setIcon(file_icon) items.append(item) self.clear() self.invisibleRootItem().appendRows(items) class Completer(QtGui.QCompleter): def __init__(self, model, parent): QtGui.QCompleter.__init__(self, parent) self._model = model self.setCompletionMode(QtGui.QCompleter.UnfilteredPopupCompletion) self.setCaseSensitivity(Qt.CaseInsensitive) self.connect(model, SIGNAL('update()'), self.update) self.setModel(model) def update(self): self._model.update() def dispose(self): self._model.dispose() def set_match_text(self, matched_text, case_sensitive): self._model.set_match_text(matched_text, case_sensitive) class GitCompletionModel(CompletionModel): def __init__(self, parent): CompletionModel.__init__(self, parent) self.main_model = model = main.model() msg = model.message_updated model.add_observer(msg, self.emit_update) def gather_matches(self, case_sensitive): if case_sensitive: transform = lambda x: x compare = self.completion_cmp else: transform = lambda x: x.lower() compare = self.lower_completion_cmp matched_text = self.matched_text if matched_text: matched_refs = [r for r in self.matches() if transform(matched_text) in transform(r)] # if we match nothing, still offer to complete something if not matched_refs: matched_refs = self.matches() else: matched_refs = self.matches() matched_refs.sort(cmp=compare) return (matched_refs, (), set()) def emit_update(self): self.emit(SIGNAL('update()')) def matches(self): return [] def dispose(self): self.main_model.remove_observer(self.emit_update) class GitRefCompletionModel(GitCompletionModel): """Completer for branches and tags""" def __init__(self, parent): GitCompletionModel.__init__(self, parent) def matches(self): model = self.main_model return model.local_branches + model.remote_branches + model.tags class GitBranchCompletionModel(GitCompletionModel): """Completer for remote branches""" def __init__(self, parent): GitCompletionModel.__init__(self, parent) def matches(self): model = self.main_model return model.local_branches class GitRemoteBranchCompletionModel(GitCompletionModel): """Completer for remote branches""" def __init__(self, parent): GitCompletionModel.__init__(self, parent) def matches(self): model = self.main_model return model.remote_branches class GitLogCompletionModel(GitRefCompletionModel): """Completer for arguments suitable for git-log like commands""" def __init__(self, parent): GitRefCompletionModel.__init__(self, parent) def gather_matches(self, case_sensitive): (matched_refs, dummy_paths, dummy_dirs) =\ GitRefCompletionModel.gather_matches(self, case_sensitive) file_list = self.main_model.everything() files = set(file_list) files_and_dirs = utils.add_parents(set(files)) if case_sensitive: transform = lambda x: x compare = self.completion_cmp else: transform = lambda x: x.lower() compare = self.lower_completion_cmp dirs = files_and_dirs.difference(files) matched_text = self.matched_text if matched_text: matched_paths = [f for f in files_and_dirs if transform(matched_text) in transform(f)] else: matched_paths = list(files_and_dirs) matched_paths.sort(cmp=compare) return (matched_refs, matched_paths, dirs) def bind_lineedit(model): """Create a line edit bound against a specific model""" class BoundLineEdit(CompletionLineEdit): def __init__(self, parent=None): CompletionLineEdit.__init__(self, model, parent) return BoundLineEdit # Concrete classes GitLogLineEdit = bind_lineedit(GitLogCompletionModel) GitRefLineEdit = bind_lineedit(GitRefCompletionModel) GitBranchLineEdit = bind_lineedit(GitBranchCompletionModel) GitRemoteBranchLineEdit = bind_lineedit(GitRemoteBranchCompletionModel) class GitDialog(QtGui.QDialog): def __init__(self, lineedit, title, button_text, parent): QtGui.QDialog.__init__(self, parent) self.setWindowTitle(title) self.setMinimumWidth(333) self.label = QtGui.QLabel() self.label.setText(title) self.lineedit = lineedit(self) self.setFocusProxy(self.lineedit) self.ok_button = QtGui.QPushButton() self.ok_button.setText(button_text) self.ok_button.setIcon(qtutils.apply_icon()) self.close_button = QtGui.QPushButton() self.close_button.setText(N_('Close')) self.button_layout = QtGui.QHBoxLayout() self.button_layout.setMargin(defs.no_margin) self.button_layout.setSpacing(defs.button_spacing) self.button_layout.addStretch() self.button_layout.addWidget(self.ok_button) self.button_layout.addWidget(self.close_button) self.main_layout = QtGui.QVBoxLayout() self.main_layout.setMargin(defs.margin) self.main_layout.setSpacing(defs.spacing) self.main_layout.addWidget(self.label) self.main_layout.addWidget(self.lineedit) self.main_layout.addLayout(self.button_layout) self.setLayout(self.main_layout) qtutils.connect_button(self.ok_button, self.accept) qtutils.connect_button(self.close_button, self.reject) self.connect(self.lineedit, SIGNAL('textChanged(const QString&)'), self.text_changed) self.setWindowModality(Qt.WindowModal) self.ok_button.setEnabled(False) def text(self): return unicode(self.lineedit.text()) def text_changed(self, txt): self.ok_button.setEnabled(bool(self.text())) def set_text(self, ref): self.lineedit.setText(ref) @classmethod def get(cls, title, button_text, parent, default=None): dlg = cls(title, button_text, parent) if default: dlg.set_text(default) dlg.show() dlg.raise_() def show_popup(): x = dlg.lineedit.x() y = dlg.lineedit.y() + dlg.lineedit.height() point = QtCore.QPoint(x, y) mapped = dlg.mapToGlobal(point) dlg.lineedit.popup().move(mapped.x(), mapped.y()) dlg.lineedit.popup().show() dlg.lineedit.refresh() QtCore.QTimer().singleShot(0, show_popup) if dlg.exec_() == cls.Accepted: return dlg.text() else: return None class GitRefDialog(GitDialog): def __init__(self, title, button_text, parent): GitDialog.__init__(self, GitRefLineEdit, title, button_text, parent) class GitBranchDialog(GitDialog): def __init__(self, title, button_text, parent): GitDialog.__init__(self, GitBranchLineEdit, title, button_text, parent) class GitRemoteBranchDialog(GitDialog): def __init__(self, title, button_text, parent): GitDialog.__init__(self, GitRemoteBranchLineEdit, title, button_text, parent) git-cola-1.9.3/cola/widgets/createbranch.py000066400000000000000000000340421225156173500206140ustar00rootroot00000000000000from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import gitcmds from cola import qtutils from cola import utils from cola.i18n import N_ from cola.interaction import Interaction from cola.models import main from cola.widgets import defs from cola.widgets import completion from cola.widgets.standard import Dialog def create_new_branch(revision=''): """Launches a dialog for creating a new branch""" model = main.MainModel() model.update_status() view = CreateBranchDialog(model, qtutils.active_window()) if revision: view.set_revision(revision) view.show() return view class CreateOpts(object): def __init__(self, model): self.model = model self.reset = False self.track = False self.fetch = True self.checkout = True self.revision = 'HEAD' self.branch = '' class CreateThread(QtCore.QThread): def __init__(self, opts, parent): QtCore.QThread.__init__(self, parent) self.opts = opts def run(self): branch = self.opts.branch revision = self.opts.revision reset = self.opts.reset checkout = self.opts.checkout track = self.opts.track model = self.opts.model results = [] status = 0 if track and '/' in revision: remote = revision.split('/', 1)[0] status, out, err = model.git.fetch(remote) self.emit(SIGNAL('command'), status, out, err) results.append(('fetch', status, out, err)) if status == 0: status, out, err = model.create_branch(branch, revision, force=reset, track=track) self.emit(SIGNAL('command'), status, out, err) results.append(('branch', status, out, err)) if status == 0 and checkout: status, out, err = model.git.checkout(branch) self.emit(SIGNAL('command'), status, out, err) results.append(('checkout', status, out, err)) main.model().update_status() self.emit(SIGNAL('done'), results) class CreateBranchDialog(Dialog): """A dialog for creating branches.""" def __init__(self, model, parent=None): Dialog.__init__(self, parent=parent) self.setWindowModality(Qt.WindowModal) self.setAttribute(Qt.WA_MacMetalStyle) self.setWindowTitle(N_('Create Branch')) self.model = model self.opts = CreateOpts(model) self.thread = CreateThread(self.opts, self) self.progress = QtGui.QProgressDialog(self) self.progress.setRange(0, 0) self.progress.setCancelButton(None) self.progress.setWindowTitle(N_('Create Branch')) self.progress.setWindowModality(Qt.WindowModal) self.branch_name_label = QtGui.QLabel() self.branch_name_label.setText(N_('Branch Name')) self.branch_name = QtGui.QLineEdit() self.rev_label = QtGui.QLabel() self.rev_label.setText(N_('Starting Revision')) self.revision = completion.GitRefLineEdit() current = gitcmds.current_branch() if current: self.revision.setText(current) self.local_radio = QtGui.QRadioButton() self.local_radio.setText(N_('Local branch')) self.local_radio.setChecked(True) self.remote_radio = QtGui.QRadioButton() self.remote_radio.setText(N_('Tracking branch')) self.tag_radio = QtGui.QRadioButton() self.tag_radio.setText(N_('Tag')) self.branch_list = QtGui.QListWidget() self.update_existing_label = QtGui.QLabel() self.update_existing_label.setText(N_('Update Existing Branch:')) self.no_update_radio = QtGui.QRadioButton() self.no_update_radio.setText(N_('No')) self.ffwd_only_radio = QtGui.QRadioButton() self.ffwd_only_radio.setText(N_('Fast Forward Only')) self.ffwd_only_radio.setChecked(True) self.reset_radio = QtGui.QRadioButton() self.reset_radio.setText(N_('Reset')) self.options_bottom_layout = QtGui.QHBoxLayout() self.options_checkbox_layout = QtGui.QVBoxLayout() self.fetch_checkbox = QtGui.QCheckBox() self.fetch_checkbox.setText(N_('Fetch Tracking Branch')) self.fetch_checkbox.setChecked(True) self.options_checkbox_layout.addWidget(self.fetch_checkbox) self.checkout_checkbox = QtGui.QCheckBox() self.checkout_checkbox.setText(N_('Checkout After Creation')) self.checkout_checkbox.setChecked(True) self.options_checkbox_layout.addWidget(self.checkout_checkbox) self.options_bottom_layout.addLayout(self.options_checkbox_layout) self.options_bottom_layout.addStretch() self.create_button = qtutils.create_button(text=N_('Create Branch'), icon=qtutils.git_icon()) self.create_button.setDefault(True) self.close_button = qtutils.create_button(text=N_('Close')) self.branch_name_layout = QtGui.QHBoxLayout() self.branch_name_layout.addWidget(self.branch_name_label) self.branch_name_layout.addWidget(self.branch_name) self.rev_start_radiobtn_layout = QtGui.QHBoxLayout() self.rev_start_radiobtn_layout.addWidget(self.local_radio) self.rev_start_radiobtn_layout.addWidget(self.remote_radio) self.rev_start_radiobtn_layout.addWidget(self.tag_radio) self.rev_start_radiobtn_layout.addStretch() self.rev_start_textinput_layout = QtGui.QHBoxLayout() self.rev_start_textinput_layout.setMargin(0) self.rev_start_textinput_layout.setSpacing(defs.spacing) self.rev_start_textinput_layout.addWidget(self.rev_label) self.rev_start_textinput_layout.addWidget(self.revision) self.rev_start_group = QtGui.QGroupBox() self.rev_start_group.setTitle(N_('Starting Revision')) self.rev_start_layout = QtGui.QVBoxLayout(self.rev_start_group) self.rev_start_layout.setMargin(defs.margin) self.rev_start_layout.setSpacing(defs.spacing) self.rev_start_layout.addLayout(self.rev_start_radiobtn_layout) self.rev_start_layout.addWidget(self.branch_list) self.rev_start_layout.addLayout(self.rev_start_textinput_layout) self.options_radio_layout = QtGui.QHBoxLayout() self.options_radio_layout.addWidget(self.update_existing_label) self.options_radio_layout.addWidget(self.no_update_radio) self.options_radio_layout.addWidget(self.ffwd_only_radio) self.options_radio_layout.addWidget(self.reset_radio) self.option_group = QtGui.QGroupBox() self.option_group.setTitle(N_('Options')) self.options_grp_layout = QtGui.QVBoxLayout(self.option_group) self.options_grp_layout.setMargin(defs.margin) self.options_grp_layout.setSpacing(defs.spacing) self.options_grp_layout.addLayout(self.options_radio_layout) self.options_grp_layout.addLayout(self.options_bottom_layout) self.buttons_layout = QtGui.QHBoxLayout() self.buttons_layout.setMargin(defs.margin) self.buttons_layout.setSpacing(defs.spacing) self.buttons_layout.addWidget(self.create_button) self.buttons_layout.addWidget(self.close_button) self.options_section_layout = QtGui.QHBoxLayout() self.options_section_layout.setMargin(defs.margin) self.options_section_layout.setSpacing(defs.spacing) self.options_section_layout.addWidget(self.option_group) self.options_section_layout.addLayout(self.buttons_layout) self.main_layout = QtGui.QVBoxLayout() self.main_layout.setMargin(defs.margin) self.main_layout.setSpacing(defs.spacing) self.main_layout.addLayout(self.branch_name_layout) self.main_layout.addWidget(self.rev_start_group) self.main_layout.addLayout(self.options_section_layout) self.setLayout(self.main_layout) qtutils.connect_button(self.close_button, self.reject) qtutils.connect_button(self.create_button, self.create_branch) qtutils.connect_button(self.local_radio, self.display_model) qtutils.connect_button(self.remote_radio, self.display_model) qtutils.connect_button(self.tag_radio, self.display_model) self.connect(self.branch_list, SIGNAL('itemSelectionChanged()'), self.branch_item_changed) self.connect(self.thread, SIGNAL('command'), self.thread_command) self.connect(self.thread, SIGNAL('done'), self.thread_done) self.resize(555, 333) self.display_model() def set_revision(self, revision): self.revision.setText(revision) def getopts(self): self.opts.revision = self.revision.value() self.opts.branch = unicode(self.branch_name.text()) self.opts.checkout = self.checkout_checkbox.isChecked() self.opts.reset = self.reset_radio.isChecked() self.opts.fetch = self.fetch_checkbox.isChecked() self.opts.track = self.remote_radio.isChecked() def create_branch(self): """Creates a branch; called by the "Create Branch" button""" self.getopts() revision = self.opts.revision branch = self.opts.branch no_update = self.no_update_radio.isChecked() ffwd_only = self.ffwd_only_radio.isChecked() existing_branches = gitcmds.branch_list() check_branch = False if not branch or not revision: qtutils.critical(N_('Missing Data'), N_('Please provide both a branch ' 'name and revision expression.')) return if branch in existing_branches: if no_update: msg = N_('Branch "%s" already exists.') % branch qtutils.critical(N_('Branch Exists'), msg) return # Whether we should prompt the user for lost commits commits = gitcmds.rev_list_range(revision, branch) check_branch = bool(commits) if check_branch: msg = (N_('Resetting "%(branch)s" to "%(revision)s" ' 'will lose commits.') % dict(branch=branch, revision=revision)) if ffwd_only: qtutils.critical(N_('Branch Exists'), msg) return lines = [msg] for idx, commit in enumerate(commits): subject = commit[1][0:min(len(commit[1]),16)] if len(subject) < len(commit[1]): subject += '...' lines.append('\t' + commit[0][:8] +'\t' + subject) if idx >= 5: skip = len(commits) - 5 lines.append('\t(%s)' % (N_('%d skipped') % skip)) break line = N_('Recovering lost commits may not be easy.') lines.append(line) if not qtutils.confirm(N_('Reset Branch?'), '\n'.join(lines), (N_('Reset "%(branch)s" to "%(revision)s"?') % dict(branch=branch, revision=revision)), N_('Reset Branch'), default=False, icon=qtutils.icon('undo.svg')): return self.setEnabled(False) self.progress.setEnabled(True) QtGui.QApplication.setOverrideCursor(Qt.WaitCursor) # Show a nice progress bar self.progress.setLabelText(N_('Updating...')) self.progress.show() self.thread.start() def thread_command(self, status, out, err): Interaction.log_status(status, out, err) def thread_done(self, results): self.setEnabled(True) self.progress.close() QtGui.QApplication.restoreOverrideCursor() detail_lines = [] for (cmd, status, out, err) in results: if status != 0: Interaction.critical( N_('Error Creating Branch'), (N_('"%(command)s" returned exit status "%(status)d"') % dict(command='git '+cmd, status=status))) return line = '"git %s" returned exit status %d' % (cmd, status) detail_lines.append(line) if out: detail_lines.append(out) if err: detail_lines.append(err) detail_lines.append('') details = '\n'.join(detail_lines) qtutils.information(N_('Create Branch'), N_('Branch created'), details=details) self.accept() def branch_item_changed(self, *rest): """This callback is called when the branch selection changes""" # When the branch selection changes then we should update # the "Revision Expression" accordingly. qlist = self.branch_list (row, selected) = qtutils.selected_row(qlist) if not selected: return # Update the model with the selection sources = self.branch_sources() rev = sources[row] self.revision.setText(rev) # Set the branch field if we're branching from a remote branch. if not self.remote_radio.isChecked(): return branch = utils.basename(rev) if branch == 'HEAD': return # Signal that we've clicked on a remote branch self.branch_name.setText(branch) def display_model(self): """Sets the branch list to the available branches """ branches = self.branch_sources() qtutils.set_items(self.branch_list, branches) def branch_sources(self): """Get the list of items for populating the branch root list. """ if self.local_radio.isChecked(): return self.model.local_branches elif self.remote_radio.isChecked(): return self.model.remote_branches elif self.tag_radio.isChecked(): return self.model.tags git-cola-1.9.3/cola/widgets/createtag.py000066400000000000000000000131321225156173500201270ustar00rootroot00000000000000from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import Qt from cola import cmds from cola import qtutils from cola.i18n import N_ from cola.qtutils import connect_button from cola.qtutils import critical from cola.qtutils import information from cola.widgets import completion from cola.widgets import standard from cola.widgets import text def create_tag(name='', ref='', sign=False): """Entry point for external callers.""" opts = TagOptions(name, ref, sign) view = CreateTag(opts, qtutils.active_window()) view.show() return view class TagOptions(object): """Simple data container for the CreateTag dialog.""" def __init__(self, name, ref, sign): self.name = name or '' self.ref = ref or 'HEAD' self.sign = sign class CreateTag(standard.Dialog): def __init__(self, opts, parent): standard.Dialog.__init__(self, parent=parent) self.setWindowModality(QtCore.Qt.WindowModal) self.setAttribute(Qt.WA_MacMetalStyle) self.setWindowTitle(N_('Create Tag')) self.opts = opts self.main_layt = QtGui.QVBoxLayout(self) self.main_layt.setContentsMargins(6, 12, 6, 6) # Form layout for inputs self.input_form_layt = QtGui.QFormLayout() self.input_form_layt.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow) # Tag label self.tag_name_label = QtGui.QLabel(self) self.tag_name_label.setText(N_('Name')) self.input_form_layt.setWidget(0, QtGui.QFormLayout.LabelRole, self.tag_name_label) self.tag_name = text.HintedLineEdit(N_('vX.Y.Z'), self) self.tag_name.set_value(opts.name) self.tag_name.setToolTip(N_('Specifies the tag name')) self.input_form_layt.setWidget(0, QtGui.QFormLayout.FieldRole, self.tag_name) # Sign Tag self.sign_label = QtGui.QLabel(self) self.sign_label.setText(N_('Sign Tag')) self.input_form_layt.setWidget(1, QtGui.QFormLayout.LabelRole, self.sign_label) self.sign_tag = QtGui.QCheckBox(self) self.sign_tag.setChecked(opts.sign) self.sign_tag.setToolTip(N_('Whether to sign the tag (git tag -s)')) self.input_form_layt.setWidget(1, QtGui.QFormLayout.FieldRole, self.sign_tag) self.main_layt.addLayout(self.input_form_layt) # Tag message self.tag_msg_label = QtGui.QLabel(self) self.tag_msg_label.setText(N_('Message')) self.input_form_layt.setWidget(2, QtGui.QFormLayout.LabelRole, self.tag_msg_label) self.tag_msg = text.HintedTextEdit(N_('Tag message...'), self) self.tag_msg.setToolTip(N_('Specifies the tag message')) self.tag_msg.enable_hint(True) self.input_form_layt.setWidget(2, QtGui.QFormLayout.FieldRole, self.tag_msg) # Revision self.rev_label = QtGui.QLabel(self) self.rev_label.setText(N_('Revision')) self.input_form_layt.setWidget(3, QtGui.QFormLayout.LabelRole, self.rev_label) self.revision = completion.GitRefLineEdit() self.revision.setText(self.opts.ref) self.revision.setToolTip(N_('Specifies the SHA-1 to tag')) self.input_form_layt.setWidget(3, QtGui.QFormLayout.FieldRole, self.revision) # Buttons self.button_hbox_layt = QtGui.QHBoxLayout() self.button_hbox_layt.addStretch() self.create_button = qtutils.create_button(text=N_('Create Tag'), icon=qtutils.git_icon()) self.button_hbox_layt.addWidget(self.create_button) self.main_layt.addLayout(self.button_hbox_layt) self.close_button = qtutils.create_button(text=N_('Close')) self.button_hbox_layt.addWidget(self.close_button) connect_button(self.close_button, self.accept) connect_button(self.create_button, self.create_tag) self.resize(506, 295) def create_tag(self): """Verifies inputs and emits a notifier tag message.""" revision = self.revision.value() tag_name = self.tag_name.value() tag_msg = self.tag_msg.value() sign_tag = self.sign_tag.isChecked() if not revision: critical(N_('Missing Revision'), N_('Please specify a revision to tag.')) return elif not tag_name: critical(N_('Missing Name'), N_('Please specify a name for the new tag.')) return elif (sign_tag and not tag_msg and not qtutils.confirm(N_('Missing Tag Message'), N_('Tag-signing was requested but the tag ' 'message is empty.'), N_('An unsigned, lightweight tag will be ' 'created instead.\n' 'Create an unsigned tag?'), N_('Create Unsigned Tag'), default=False, icon=qtutils.save_icon())): return cmds.do(cmds.Tag, tag_name, revision, sign=sign_tag, message=tag_msg) information(N_('Tag Created'), N_('Created a new tag named "%s"') % tag_name, details=tag_msg or None) self.accept() git-cola-1.9.3/cola/widgets/dag.py000066400000000000000000001357511225156173500167370ustar00rootroot00000000000000import collections import math import sys from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from PyQt4.QtCore import QPointF from PyQt4.QtCore import QRectF from cola import cmds from cola import difftool from cola import observable from cola import qtutils from cola.i18n import N_ from cola.models.dag import DAG from cola.models.dag import RepoReader from cola.widgets import completion from cola.widgets import defs from cola.widgets.createbranch import create_new_branch from cola.widgets.createtag import create_tag from cola.widgets.archive import GitArchiveDialog from cola.widgets.browse import BrowseDialog from cola.widgets.standard import MainWindow from cola.widgets.standard import TreeWidget from cola.widgets.diff import COMMITS_SELECTED from cola.widgets.diff import DiffWidget def git_dag(model, args=None): """Return a pre-populated git DAG widget.""" branch = model.currentbranch # disambiguate between branch names and filenames by using '--' branch_doubledash = branch and (branch + ' --') or '' dag = DAG(branch_doubledash, 1000) dag.set_arguments(args) view = DAGView(model, dag, None) if dag.ref: view.display() return view class ViewerMixin(object): """Implementations must provide selected_items()""" def __init__(self): self.selected = None self.clicked = None self.menu_actions = self.context_menu_actions() def selected_item(self): """Return the currently selected item""" selected_items = self.selected_items() if not selected_items: return None return selected_items[0] def selected_sha1(self): item = self.selected_item() if item is None: return None return item.commit.sha1 def diff_selected_this(self): clicked_sha1 = self.clicked.sha1 selected_sha1 = self.selected.sha1 self.emit(SIGNAL('diff_commits'), selected_sha1, clicked_sha1) def diff_this_selected(self): clicked_sha1 = self.clicked.sha1 selected_sha1 = self.selected.sha1 self.emit(SIGNAL('diff_commits'), clicked_sha1, selected_sha1) def cherry_pick(self): sha1 = self.selected_sha1() if sha1 is None: return cmds.do(cmds.CherryPick, [sha1]) def copy_to_clipboard(self): sha1 = self.selected_sha1() if sha1 is None: return qtutils.set_clipboard(sha1) def create_branch(self): sha1 = self.selected_sha1() if sha1 is None: return create_new_branch(revision=sha1) def create_tag(self): sha1 = self.selected_sha1() if sha1 is None: return create_tag(ref=sha1) def create_tarball(self): sha1 = self.selected_sha1() if sha1 is None: return short_sha1 = sha1[:7] GitArchiveDialog.save(sha1, short_sha1, self) def save_blob_dialog(self): sha1 = self.selected_sha1() if sha1 is None: return return BrowseDialog.browse(sha1) def context_menu_actions(self): return { 'diff_this_selected': qtutils.add_action(self, N_('Diff this -> selected'), self.diff_this_selected), 'diff_selected_this': qtutils.add_action(self, N_('Diff selected -> this'), self.diff_selected_this), 'create_branch': qtutils.add_action(self, N_('Create Branch'), self.create_branch), 'create_patch': qtutils.add_action(self, N_('Create Patch'), self.create_patch), 'create_tag': qtutils.add_action(self, N_('Create Tag'), self.create_tag), 'create_tarball': qtutils.add_action(self, N_('Save As Tarball/Zip...'), self.create_tarball), 'cherry_pick': qtutils.add_action(self, N_('Cherry Pick'), self.cherry_pick), 'save_blob': qtutils.add_action(self, N_('Grab File...'), self.save_blob_dialog), 'copy': qtutils.add_action(self, N_('Copy SHA-1'), self.copy_to_clipboard, QtGui.QKeySequence.Copy), } def update_menu_actions(self, event): selected_items = self.selected_items() item = self.itemAt(event.pos()) if item is None: self.clicked = commit = None else: self.clicked = commit = item.commit has_single_selection = len(selected_items) == 1 has_selection = bool(selected_items) can_diff = bool(commit and has_single_selection and commit is not selected_items[0].commit) if can_diff: self.selected = selected_items[0].commit else: self.selected = None self.menu_actions['diff_this_selected'].setEnabled(can_diff) self.menu_actions['diff_selected_this'].setEnabled(can_diff) self.menu_actions['create_branch'].setEnabled(has_single_selection) self.menu_actions['create_tag'].setEnabled(has_single_selection) self.menu_actions['cherry_pick'].setEnabled(has_single_selection) self.menu_actions['create_patch'].setEnabled(has_selection) self.menu_actions['create_tarball'].setEnabled(has_single_selection) self.menu_actions['save_blob'].setEnabled(has_single_selection) self.menu_actions['copy'].setEnabled(has_single_selection) def context_menu_event(self, event): self.update_menu_actions(event) menu = QtGui.QMenu(self) menu.addAction(self.menu_actions['diff_this_selected']) menu.addAction(self.menu_actions['diff_selected_this']) menu.addSeparator() menu.addAction(self.menu_actions['create_branch']) menu.addAction(self.menu_actions['create_tag']) menu.addSeparator() menu.addAction(self.menu_actions['cherry_pick']) menu.addAction(self.menu_actions['create_patch']) menu.addAction(self.menu_actions['create_tarball']) menu.addSeparator() menu.addAction(self.menu_actions['save_blob']) menu.addAction(self.menu_actions['copy']) menu.exec_(self.mapToGlobal(event.pos())) class CommitTreeWidgetItem(QtGui.QTreeWidgetItem): def __init__(self, commit, parent=None): QtGui.QTreeWidgetItem.__init__(self, parent) self.commit = commit self.setText(0, commit.summary) self.setText(1, commit.author) self.setText(2, commit.authdate) class CommitTreeWidget(ViewerMixin, TreeWidget): def __init__(self, notifier, parent): TreeWidget.__init__(self, parent) ViewerMixin.__init__(self) self.setSelectionMode(self.ContiguousSelection) self.setHeaderLabels([N_('Summary'), N_('Author'), N_('Date, Time')]) self.sha1map = {} self.notifier = notifier self.selecting = False self.commits = [] self.action_up = qtutils.add_action(self, N_('Go Up'), self.go_up, Qt.Key_K) self.action_down = qtutils.add_action(self, N_('Go Down'), self.go_down, Qt.Key_J) notifier.add_observer(COMMITS_SELECTED, self.commits_selected) self.connect(self, SIGNAL('itemSelectionChanged()'), self.selection_changed) # ViewerMixin def go_up(self): self.goto(self.itemAbove) def go_down(self): self.goto(self.itemBelow) def goto(self, finder): items = self.selected_items() item = items and items[0] or None if item is None: return found = finder(item) if found: self.select([found.commit.sha1], block_signals=False) def set_selecting(self, selecting): self.selecting = selecting def selection_changed(self): items = self.selected_items() if not items: return self.set_selecting(True) self.notifier.notify_observers(COMMITS_SELECTED, [i.commit for i in items]) self.set_selecting(False) def commits_selected(self, commits): if self.selecting: return self.select([commit.sha1 for commit in commits]) def select(self, sha1s, block_signals=True): self.clearSelection() for sha1 in sha1s: try: item = self.sha1map[sha1] except KeyError: continue block = self.blockSignals(block_signals) self.scrollToItem(item) item.setSelected(True) self.blockSignals(block) def adjust_columns(self): width = self.width()-20 zero = width*2/3 onetwo = width/6 self.setColumnWidth(0, zero) self.setColumnWidth(1, onetwo) self.setColumnWidth(2, onetwo) def clear(self): QtGui.QTreeWidget.clear(self) self.sha1map.clear() self.commits = [] def add_commits(self, commits): self.commits.extend(commits) items = [] for c in reversed(commits): item = CommitTreeWidgetItem(c) items.append(item) self.sha1map[c.sha1] = item for tag in c.tags: self.sha1map[tag] = item self.insertTopLevelItems(0, items) def create_patch(self): items = self.selectedItems() if not items: return items.reverse() sha1s = [item.commit.sha1 for item in items] all_sha1s = [c.sha1 for c in self.commits] cmds.do(cmds.FormatPatch, sha1s, all_sha1s) # Qt overrides def contextMenuEvent(self, event): self.context_menu_event(event) def mousePressEvent(self, event): if event.button() == Qt.RightButton: event.accept() return QtGui.QTreeWidget.mousePressEvent(self, event) class DAGView(MainWindow): """The git-dag widget.""" def __init__(self, model, dag, parent=None, args=None): MainWindow.__init__(self, parent) self.setAttribute(Qt.WA_MacMetalStyle) self.setMinimumSize(420, 420) # change when widgets are added/removed self.widget_version = 1 self.model = model self.dag = dag self.commits = {} self.commit_list = [] self.old_count = None self.old_ref = None self.thread = ReaderThread(dag, self) self.revtext = completion.GitLogLineEdit() self.maxresults = QtGui.QSpinBox() self.maxresults.setMinimum(1) self.maxresults.setMaximum(99999) self.maxresults.setPrefix('') self.maxresults.setSuffix('') self.zoom_out = qtutils.create_action_button( N_('Zoom Out'), qtutils.theme_icon('zoom-out.png')) self.zoom_in = qtutils.create_action_button( N_('Zoom In'), qtutils.theme_icon('zoom-in.png')) self.zoom_to_fit = qtutils.create_action_button( N_('Zoom to Fit'), qtutils.theme_icon('zoom-fit-best.png')) self.notifier = notifier = observable.Observable() self.notifier.refs_updated = refs_updated = 'refs_updated' self.notifier.add_observer(refs_updated, self.display) self.treewidget = CommitTreeWidget(notifier, self) self.diffwidget = DiffWidget(notifier, self) self.graphview = GraphView(notifier, self) self.controls_layout = QtGui.QHBoxLayout() self.controls_layout.setMargin(defs.no_margin) self.controls_layout.setSpacing(defs.spacing) self.controls_layout.addWidget(self.revtext) self.controls_layout.addWidget(self.maxresults) self.controls_widget = QtGui.QWidget() self.controls_widget.setLayout(self.controls_layout) self.log_dock = qtutils.create_dock(N_('Log'), self, stretch=False) self.log_dock.setWidget(self.treewidget) log_dock_titlebar = self.log_dock.titleBarWidget() log_dock_titlebar.add_corner_widget(self.controls_widget) self.diff_dock = qtutils.create_dock(N_('Diff'), self) self.diff_dock.setWidget(self.diffwidget) self.graph_controls_layout = QtGui.QHBoxLayout() self.graph_controls_layout.setMargin(defs.no_margin) self.graph_controls_layout.setSpacing(defs.button_spacing) self.graph_controls_layout.addWidget(self.zoom_out) self.graph_controls_layout.addWidget(self.zoom_in) self.graph_controls_layout.addWidget(self.zoom_to_fit) self.graph_controls_widget = QtGui.QWidget() self.graph_controls_widget.setLayout(self.graph_controls_layout) self.graphview_dock = qtutils.create_dock(N_('Graph'), self) self.graphview_dock.setWidget(self.graphview) graph_titlebar = self.graphview_dock.titleBarWidget() graph_titlebar.add_corner_widget(self.graph_controls_widget) self.lock_layout_action = qtutils.add_action_bool(self, N_('Lock Layout'), self.set_lock_layout, False) # Create the application menu self.menubar = QtGui.QMenuBar(self) # View Menu self.view_menu = qtutils.create_menu(N_('View'), self.menubar) self.view_menu.addAction(self.log_dock.toggleViewAction()) self.view_menu.addAction(self.graphview_dock.toggleViewAction()) self.view_menu.addAction(self.diff_dock.toggleViewAction()) self.view_menu.addSeparator() self.view_menu.addAction(self.lock_layout_action) self.menubar.addAction(self.view_menu.menuAction()) self.setMenuBar(self.menubar) left = Qt.LeftDockWidgetArea right = Qt.RightDockWidgetArea bottom = Qt.BottomDockWidgetArea self.addDockWidget(left, self.log_dock) self.addDockWidget(right, self.graphview_dock) self.addDockWidget(bottom, self.diff_dock) # Update fields affected by model self.revtext.setText(dag.ref) self.maxresults.setValue(dag.count) self.update_window_title() # Also re-loads dag.* from the saved state if not qtutils.apply_state(self): self.resize_to_desktop() qtutils.connect_button(self.zoom_out, self.graphview.zoom_out) qtutils.connect_button(self.zoom_in, self.graphview.zoom_in) qtutils.connect_button(self.zoom_to_fit, self.graphview.zoom_to_fit) self.thread.connect(self.thread, self.thread.commits_ready, self.add_commits) self.thread.connect(self.thread, self.thread.done, self.thread_done) self.connect(self.treewidget, SIGNAL('diff_commits'), self.diff_commits) self.connect(self.graphview, SIGNAL('diff_commits'), self.diff_commits) self.connect(self.maxresults, SIGNAL('editingFinished()'), self.display) self.connect(self.revtext, SIGNAL('changed()'), self.display) self.connect(self.revtext, SIGNAL('textChanged(QString)'), self.text_changed) self.connect(self.revtext, SIGNAL('returnPressed()'), self.display) # The model is updated in another thread so use # signals/slots to bring control back to the main GUI thread self.model.add_observer(self.model.message_updated, self.emit_model_updated) self.connect(self, SIGNAL('model_updated'), self.model_updated) qtutils.add_action(self, 'Focus search field', lambda: self.revtext.setFocus(), 'Ctrl+l') qtutils.add_close_action(self) def text_changed(self, txt): self.dag.ref = unicode(txt) self.update_window_title() def update_window_title(self): project = self.model.project if self.dag.ref: self.setWindowTitle(N_('%s: %s - DAG') % (project, self.dag.ref)) else: self.setWindowTitle(project + N_(' - DAG')) def export_state(self): state = self.Mixin.export_state(self) state['count'] = self.dag.count return state def apply_state(self, state): result = self.Mixin.apply_state(self, state) try: count = state['count'] if self.dag.overridden('count'): count = self.dag.count except: count = self.dag.count result = False self.dag.set_count(count) self.lock_layout_action.setChecked(state.get('lock_layout', False)) return result def emit_model_updated(self): self.emit(SIGNAL('model_updated')) def model_updated(self): if self.dag.ref: self.revtext.update_matches() return if not self.model.currentbranch: return self.revtext.setText(self.model.currentbranch + ' --') self.display() def display(self): new_ref = unicode(self.revtext.text()) if not new_ref: return new_count = self.maxresults.value() old_ref = self.old_ref old_count = self.old_count if old_ref == new_ref and old_count == new_count: return self.old_ref = new_ref self.old_count = new_count self.thread.stop() self.clear() self.dag.set_ref(new_ref) self.dag.set_count(self.maxresults.value()) self.thread.start() def show(self): self.Mixin.show(self) self.treewidget.adjust_columns() def clear(self): self.graphview.clear() self.treewidget.clear() self.commits.clear() self.commit_list = [] def add_commits(self, commits): self.commit_list.extend(commits) # Keep track of commits for commit_obj in commits: self.commits[commit_obj.sha1] = commit_obj for tag in commit_obj.tags: self.commits[tag] = commit_obj self.graphview.add_commits(commits) self.treewidget.add_commits(commits) def thread_done(self): self.graphview.setFocus() try: commit_obj = self.commit_list[-1] except IndexError: return self.notifier.notify_observers(COMMITS_SELECTED, [commit_obj]) self.graphview.update_scene_rect() self.graphview.set_initial_view() def resize_to_desktop(self): desktop = QtGui.QApplication.instance().desktop() width = desktop.width() height = desktop.height() self.resize(width, height) def diff_commits(self, a, b): paths = self.dag.paths() if paths: difftool.launch([a, b, '--'] + paths) else: difftool.diff_commits(self, a, b) # Qt overrides def closeEvent(self, event): self.revtext.close_popup() self.thread.stop() self.Mixin.closeEvent(self, event) def resizeEvent(self, e): self.Mixin.resizeEvent(self, e) self.treewidget.adjust_columns() class ReaderThread(QtCore.QThread): commits_ready = SIGNAL('commits_ready') done = SIGNAL('done') def __init__(self, dag, parent): QtCore.QThread.__init__(self, parent) self.dag = dag self._abort = False self._stop = False self._mutex = QtCore.QMutex() self._condition = QtCore.QWaitCondition() def run(self): repo = RepoReader(self.dag) repo.reset() commits = [] for c in repo: self._mutex.lock() if self._stop: self._condition.wait(self._mutex) self._mutex.unlock() if self._abort: repo.reset() return commits.append(c) if len(commits) >= 512: self.emit(self.commits_ready, commits) commits = [] if commits: self.emit(self.commits_ready, commits) self.emit(self.done) def start(self): self._abort = False self._stop = False QtCore.QThread.start(self) def pause(self): self._mutex.lock() self._stop = True self._mutex.unlock() def resume(self): self._mutex.lock() self._stop = False self._mutex.unlock() self._condition.wakeOne() def stop(self): self._abort = True self.wait() class Cache(object): pass class Edge(QtGui.QGraphicsItem): item_type = QtGui.QGraphicsItem.UserType + 1 def __init__(self, source, dest): QtGui.QGraphicsItem.__init__(self) self.setAcceptedMouseButtons(Qt.NoButton) self.source = source self.dest = dest self.commit = source.commit self.setZValue(-2) dest_pt = Commit.item_bbox.center() self.source_pt = self.mapFromItem(self.source, dest_pt) self.dest_pt = self.mapFromItem(self.dest, dest_pt) self.line = QtCore.QLineF(self.source_pt, self.dest_pt) width = self.dest_pt.x() - self.source_pt.x() height = self.dest_pt.y() - self.source_pt.y() rect = QtCore.QRectF(self.source_pt, QtCore.QSizeF(width, height)) self.bound = rect.normalized() # Choose a new color for new branch edges if self.source.x() < self.dest.x(): color = EdgeColor.next() line = Qt.SolidLine elif self.source.x() != self.dest.x(): color = EdgeColor.current() line = Qt.SolidLine else: color = EdgeColor.current() line = Qt.SolidLine self.pen = QtGui.QPen(color, 4.0, line, Qt.SquareCap, Qt.RoundJoin) # Qt overrides def type(self): return self.item_type def boundingRect(self): return self.bound def paint(self, painter, option, widget): arc_rect = 10 connector_length = 5 painter.setPen(self.pen) path = QtGui.QPainterPath() if self.source.x() == self.dest.x(): path.moveTo(self.source.x(), self.source.y()) path.lineTo(self.dest.x(), self.dest.y()) painter.drawPath(path) else: #Define points starting from source point1 = QPointF(self.source.x(), self.source.y()) point2 = QPointF(point1.x(), point1.y() - connector_length) point3 = QPointF(point2.x() + arc_rect, point2.y() - arc_rect) #Define points starting from dest point4 = QPointF(self.dest.x(), self.dest.y()) point5 = QPointF(point4.x(),point3.y() - arc_rect) point6 = QPointF(point5.x() - arc_rect, point5.y() + arc_rect) start_angle_arc1 = 180 span_angle_arc1 = 90 start_angle_arc2 = 90 span_angle_arc2 = -90 # If the dest is at the left of the source, then we # need to reverse some values if self.source.x() > self.dest.x(): point5 = QPointF(point4.x(), point4.y() + connector_length) point6 = QPointF(point5.x() + arc_rect, point5.y() + arc_rect) point3 = QPointF(self.source.x() - arc_rect, point6.y()) point2 = QPointF(self.source.x(), point3.y() + arc_rect) span_angle_arc1 = 90 path.moveTo(point1) path.lineTo(point2) path.arcTo(QRectF(point2, point3), start_angle_arc1, span_angle_arc1) path.lineTo(point6) path.arcTo(QRectF(point6, point5), start_angle_arc2, span_angle_arc2) path.lineTo(point4) painter.drawPath(path) class EdgeColor(object): """An edge color factory""" current_color_index = 0 colors = [ QtGui.QColor(Qt.red), QtGui.QColor(Qt.green), QtGui.QColor(Qt.blue), QtGui.QColor(Qt.black), QtGui.QColor(Qt.darkRed), QtGui.QColor(Qt.darkGreen), QtGui.QColor(Qt.darkBlue), QtGui.QColor(Qt.cyan), QtGui.QColor(Qt.magenta), # Orange; Qt.yellow is too low-contrast qtutils.rgba(0xff, 0x66, 0x00), QtGui.QColor(Qt.gray), QtGui.QColor(Qt.darkCyan), QtGui.QColor(Qt.darkMagenta), QtGui.QColor(Qt.darkYellow), QtGui.QColor(Qt.darkGray), ] @classmethod def next(cls): cls.current_color_index += 1 cls.current_color_index %= len(cls.colors) color = cls.colors[cls.current_color_index] color.setAlpha(128) return color @classmethod def current(cls): return cls.colors[cls.current_color_index] class Commit(QtGui.QGraphicsItem): item_type = QtGui.QGraphicsItem.UserType + 2 commit_radius = 12.0 merge_radius = 18.0 item_shape = QtGui.QPainterPath() item_shape.addRect(commit_radius/-2.0, commit_radius/-2.0, commit_radius, commit_radius) item_bbox = item_shape.boundingRect() inner_rect = QtGui.QPainterPath() inner_rect.addRect(commit_radius/-2.0 + 2.0, commit_radius/-2.0 + 2.0, commit_radius - 4.0, commit_radius - 4.0) inner_rect = inner_rect.boundingRect() commit_color = QtGui.QColor(Qt.white) outline_color = commit_color.darker() merge_color = QtGui.QColor(Qt.lightGray) commit_selected_color = QtGui.QColor(Qt.green) selected_outline_color = commit_selected_color.darker() commit_pen = QtGui.QPen() commit_pen.setWidth(1.0) commit_pen.setColor(outline_color) def __init__(self, commit, notifier, selectable=QtGui.QGraphicsItem.ItemIsSelectable, cursor=Qt.PointingHandCursor, xpos=commit_radius/2.0 + 1.0, cached_commit_color=commit_color, cached_merge_color=merge_color): QtGui.QGraphicsItem.__init__(self) self.commit = commit self.notifier = notifier self.setZValue(0) self.setFlag(selectable) self.setCursor(cursor) self.setToolTip(commit.sha1[:7] + ': ' + commit.summary) if commit.tags: self.label = label = Label(commit) label.setParentItem(self) label.setPos(xpos, -self.commit_radius/2.0) else: self.label = None if len(commit.parents) > 1: self.brush = cached_merge_color else: self.brush = cached_commit_color self.pressed = False self.dragged = False def blockSignals(self, blocked): self.notifier.notification_enabled = not blocked def itemChange(self, change, value): if change == QtGui.QGraphicsItem.ItemSelectedHasChanged: # Broadcast selection to other widgets selected_items = self.scene().selectedItems() commits = [item.commit for item in selected_items] self.scene().parent().set_selecting(True) self.notifier.notify_observers(COMMITS_SELECTED, commits) self.scene().parent().set_selecting(False) # Cache the pen for use in paint() if value.toPyObject(): self.brush = self.commit_selected_color color = self.selected_outline_color else: if len(self.commit.parents) > 1: self.brush = self.merge_color else: self.brush = self.commit_color color = self.outline_color commit_pen = QtGui.QPen() commit_pen.setWidth(1.0) commit_pen.setColor(color) self.commit_pen = commit_pen return QtGui.QGraphicsItem.itemChange(self, change, value) def type(self): return self.item_type def boundingRect(self, rect=item_bbox): return rect def shape(self): return self.item_shape def paint(self, painter, option, widget, inner=inner_rect, cache=Cache): # Do not draw outside the exposed rect painter.setClipRect(option.exposedRect) # Draw ellipse painter.setPen(self.commit_pen) painter.setBrush(self.brush) painter.drawEllipse(inner) def mousePressEvent(self, event): QtGui.QGraphicsItem.mousePressEvent(self, event) self.pressed = True self.selected = self.isSelected() def mouseMoveEvent(self, event): if self.pressed: self.dragged = True QtGui.QGraphicsItem.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): QtGui.QGraphicsItem.mouseReleaseEvent(self, event) if (not self.dragged and self.selected and event.button() == Qt.LeftButton): return self.pressed = False self.dragged = False class Label(QtGui.QGraphicsItem): item_type = QtGui.QGraphicsItem.UserType + 3 width = 72 height = 18 item_shape = QtGui.QPainterPath() item_shape.addRect(0, 0, width, height) item_bbox = item_shape.boundingRect() text_options = QtGui.QTextOption() text_options.setAlignment(Qt.AlignCenter) text_options.setAlignment(Qt.AlignVCenter) def __init__(self, commit, other_color=QtGui.QColor(Qt.white), head_color=QtGui.QColor(Qt.green)): QtGui.QGraphicsItem.__init__(self) self.setZValue(-1) # Starts with enough space for two tags. Any more and the commit # needs to be taller to accomodate. self.commit = commit if 'HEAD' in commit.tags: self.color = head_color else: self.color = other_color self.color.setAlpha(180) self.pen = QtGui.QPen() self.pen.setColor(self.color.darker()) self.pen.setWidth(1.0) def type(self): return self.item_type def boundingRect(self, rect=item_bbox): return rect def shape(self): return self.item_shape def paint(self, painter, option, widget, text_opts=text_options, black=Qt.black, cache=Cache): try: font = cache.label_font except AttributeError: font = cache.label_font = QtGui.QApplication.font() font.setPointSize(6) # Draw tags painter.setBrush(self.color) painter.setPen(self.pen) painter.setFont(font) current_width = 0 for tag in self.commit.tags: text_rect = painter.boundingRect( QRectF(current_width, 0, 0, 0), Qt.TextSingleLine, tag) box_rect = text_rect.adjusted(-1, -1, 1, 1) painter.drawRoundedRect(box_rect, 2, 2) painter.drawText(text_rect, Qt.TextSingleLine, tag) current_width += text_rect.width() + 5 class GraphView(ViewerMixin, QtGui.QGraphicsView): x_max = 0 y_min = 0 x_adjust = Commit.commit_radius*4/3 y_adjust = Commit.commit_radius*4/3 x_off = 18 y_off = 24 def __init__(self, notifier, parent): QtGui.QGraphicsView.__init__(self, parent) ViewerMixin.__init__(self) highlight = self.palette().color(QtGui.QPalette.Highlight) Commit.commit_selected_color = highlight Commit.selected_outline_color = highlight.darker() self.selection_list = [] self.notifier = notifier self.commits = [] self.items = {} self.saved_matrix = QtGui.QMatrix(self.matrix()) self.x_offsets = collections.defaultdict(int) self.is_panning = False self.pressed = False self.selecting = False self.last_mouse = [0, 0] self.zoom = 2 self.setDragMode(self.RubberBandDrag) scene = QtGui.QGraphicsScene(self) scene.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex) self.setScene(scene) self.setRenderHint(QtGui.QPainter.Antialiasing) self.setViewportUpdateMode(self.BoundingRectViewportUpdate) self.setCacheMode(QtGui.QGraphicsView.CacheBackground) self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QtGui.QGraphicsView.NoAnchor) self.setBackgroundBrush(QtGui.QColor(Qt.white)) qtutils.add_action(self, N_('Zoom In'), self.zoom_in, Qt.Key_Plus, Qt.Key_Equal) qtutils.add_action(self, N_('Zoom Out'), self.zoom_out, Qt.Key_Minus) qtutils.add_action(self, N_('Zoom to Fit'), self.zoom_to_fit, Qt.Key_F) qtutils.add_action(self, N_('Select Parent'), self.select_parent, 'Shift+J') qtutils.add_action(self, N_('Select Oldest Parent'), self.select_oldest_parent, Qt.Key_J) qtutils.add_action(self, N_('Select Child'), self.select_child, 'Shift+K') qtutils.add_action(self, N_('Select Newest Child'), self.select_newest_child, Qt.Key_K) notifier.add_observer(COMMITS_SELECTED, self.commits_selected) def clear(self): self.scene().clear() self.selection_list = [] self.items.clear() self.x_offsets.clear() self.x_max = 0 self.y_min = 0 self.commits = [] # ViewerMixin interface def selected_items(self): """Return the currently selected items""" return self.scene().selectedItems() def zoom_in(self): self.scale_view(1.5) def zoom_out(self): self.scale_view(1.0/1.5) def commits_selected(self, commits): if self.selecting: return self.select([commit.sha1 for commit in commits]) def select(self, sha1s): """Select the item for the SHA-1""" self.scene().clearSelection() for sha1 in sha1s: try: item = self.items[sha1] except KeyError: continue item.blockSignals(True) item.setSelected(True) item.blockSignals(False) item_rect = item.sceneTransform().mapRect(item.boundingRect()) self.ensureVisible(item_rect) def get_item_by_generation(self, commits, criteria_fn): """Return the item for the commit matching criteria""" if not commits: return None generation = None for commit in commits: if (generation is None or criteria_fn(generation, commit.generation)): sha1 = commit.sha1 generation = commit.generation try: return self.items[sha1] except KeyError: return None def oldest_item(self, commits): """Return the item for the commit with the oldest generation number""" return self.get_item_by_generation(commits, lambda a, b: a > b) def newest_item(self, commits): """Return the item for the commit with the newest generation number""" return self.get_item_by_generation(commits, lambda a, b: a < b) def create_patch(self): items = self.selected_items() if not items: return selected_commits = self.sort_by_generation([n.commit for n in items]) sha1s = [c.sha1 for c in selected_commits] all_sha1s = [c.sha1 for c in self.commits] cmds.do(cmds.FormatPatch, sha1s, all_sha1s) def select_parent(self): """Select the parent with the newest generation number""" selected_item = self.selected_item() if selected_item is None: return parent_item = self.newest_item(selected_item.commit.parents) if parent_item is None: return selected_item.setSelected(False) parent_item.setSelected(True) self.ensureVisible( parent_item.mapRectToScene(parent_item.boundingRect())) def select_oldest_parent(self): """Select the parent with the oldest generation number""" selected_item = self.selected_item() if selected_item is None: return parent_item = self.oldest_item(selected_item.commit.parents) if parent_item is None: return selected_item.setSelected(False) parent_item.setSelected(True) scene_rect = parent_item.mapRectToScene(parent_item.boundingRect()) self.ensureVisible(scene_rect) def select_child(self): """Select the child with the oldest generation number""" selected_item = self.selected_item() if selected_item is None: return child_item = self.oldest_item(selected_item.commit.children) if child_item is None: return selected_item.setSelected(False) child_item.setSelected(True) scene_rect = child_item.mapRectToScene(child_item.boundingRect()) self.ensureVisible(scene_rect) def select_newest_child(self): """Select the Nth child with the newest generation number (N > 1)""" selected_item = self.selected_item() if selected_item is None: return if len(selected_item.commit.children) > 1: children = selected_item.commit.children[1:] else: children = selected_item.commit.children child_item = self.newest_item(children) if child_item is None: return selected_item.setSelected(False) child_item.setSelected(True) scene_rect = child_item.mapRectToScene(child_item.boundingRect()) self.ensureVisible(scene_rect) def set_initial_view(self): self_commits = self.commits self_items = self.items commits = self_commits[-2:] items = [self_items[c.sha1] for c in commits] self.fit_view_to_items(items) def zoom_to_fit(self): """Fit selected items into the viewport""" items = self.selected_items() self.fit_view_to_items(items) def fit_view_to_items(self, items): if not items: rect = self.scene().itemsBoundingRect() else: x_min = sys.maxint y_min = sys.maxint x_max = -sys.maxint ymax = -sys.maxint for item in items: pos = item.pos() item_rect = item.boundingRect() x_off = item_rect.width() y_off = item_rect.height() x_min = min(x_min, pos.x()) y_min = min(y_min, pos.y()-y_off) x_max = max(x_max, pos.x()+x_off) ymax = max(ymax, pos.y()) rect = QtCore.QRectF(x_min, y_min, x_max-x_min, ymax-y_min) x_adjust = GraphView.x_adjust y_adjust = GraphView.y_adjust rect.setX(rect.x() - x_adjust) rect.setY(rect.y() - y_adjust) rect.setHeight(rect.height() + y_adjust*2) rect.setWidth(rect.width() + x_adjust*2) self.fitInView(rect, Qt.KeepAspectRatio) self.scene().invalidate() def save_selection(self, event): if event.button() != Qt.LeftButton: return elif Qt.ShiftModifier != event.modifiers(): return self.selection_list = self.selected_items() def restore_selection(self, event): if Qt.ShiftModifier != event.modifiers(): return for item in self.selection_list: item.setSelected(True) def handle_event(self, event_handler, event): self.update() self.save_selection(event) event_handler(self, event) self.restore_selection(event) def set_selecting(self, selecting): self.selecting = selecting def pan(self, event): pos = event.pos() dx = pos.x() - self.mouse_start[0] dy = pos.y() - self.mouse_start[1] if dx == 0 and dy == 0: return rect = QtCore.QRect(0, 0, abs(dx), abs(dy)) delta = self.mapToScene(rect).boundingRect() tx = delta.width() if dx < 0.0: tx = -tx ty = delta.height() if dy < 0.0: ty = -ty matrix = QtGui.QMatrix(self.saved_matrix).translate(tx, ty) self.setTransformationAnchor(QtGui.QGraphicsView.NoAnchor) self.setMatrix(matrix) def wheel_zoom(self, event): """Handle mouse wheel zooming.""" zoom = math.pow(2.0, event.delta()/512.0) factor = (self.matrix() .scale(zoom, zoom) .mapRect(QtCore.QRectF(0.0, 0.0, 1.0, 1.0)) .width()) if factor < 0.014 or factor > 42.0: return self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse) self.zoom = zoom self.scale(zoom, zoom) def wheel_pan(self, event): """Handle mouse wheel panning.""" if event.delta() < 0: s = -133.0 else: s = 133.0 pan_rect = QtCore.QRectF(0.0, 0.0, 1.0, 1.0) factor = 1.0/self.matrix().mapRect(pan_rect).width() if event.orientation() == Qt.Vertical: matrix = self.matrix().translate(0, s*factor) else: matrix = self.matrix().translate(s*factor, 0) self.setTransformationAnchor(QtGui.QGraphicsView.NoAnchor) self.setMatrix(matrix) def scale_view(self, scale): factor = (self.matrix().scale(scale, scale) .mapRect(QtCore.QRectF(0, 0, 1, 1)) .width()) if factor < 0.07 or factor > 100.0: return self.zoom = scale adjust_scrollbars = True scrollbar = self.verticalScrollBar() if scrollbar: value = scrollbar.value() min_ = scrollbar.minimum() max_ = scrollbar.maximum() range_ = max_ - min_ distance = value - min_ nonzero_range = float(range_) > 0.1 if nonzero_range: scrolloffset = distance/float(range_) else: adjust_scrollbars = False self.setTransformationAnchor(QtGui.QGraphicsView.NoAnchor) self.scale(scale, scale) scrollbar = self.verticalScrollBar() if scrollbar and adjust_scrollbars: min_ = scrollbar.minimum() max_ = scrollbar.maximum() range_ = max_ - min_ value = min_ + int(float(range_) * scrolloffset) scrollbar.setValue(value) def add_commits(self, commits): """Traverse commits and add them to the view.""" self.commits.extend(commits) scene = self.scene() for commit in commits: item = Commit(commit, self.notifier) self.items[commit.sha1] = item for ref in commit.tags: self.items[ref] = item scene.addItem(item) self.layout_commits(commits) self.link(commits) def link(self, commits): """Create edges linking commits with their parents""" scene = self.scene() for commit in commits: try: commit_item = self.items[commit.sha1] except KeyError: # TODO - Handle truncated history viewing continue for parent in reversed(commit.parents): try: parent_item = self.items[parent.sha1] except KeyError: # TODO - Handle truncated history viewing continue edge = Edge(parent_item, commit_item) scene.addItem(edge) def layout_commits(self, nodes): positions = self.position_nodes(nodes) for sha1, (x, y) in positions.items(): item = self.items[sha1] item.setPos(x, y) def position_nodes(self, nodes): positions = {} x_max = self.x_max y_min = self.y_min x_off = self.x_off y_off = self.y_off x_offsets = self.x_offsets for node in nodes: generation = node.generation sha1 = node.sha1 if node.is_fork(): # This is a fan-out so sweep over child generations and # shift them to the right to avoid overlapping edges child_gens = [c.generation for c in node.children] maxgen = max(child_gens) for g in xrange(generation + 1, maxgen): x_offsets[g] += x_off if len(node.parents) == 1: # Align nodes relative to their parents parent_gen = node.parents[0].generation parent_off = x_offsets[parent_gen] x_offsets[generation] = max(parent_off-x_off, x_offsets[generation]) cur_xoff = x_offsets[generation] next_xoff = cur_xoff next_xoff += x_off x_offsets[generation] = next_xoff x_pos = cur_xoff y_pos = -generation * y_off y_pos = min(y_pos, y_min - y_off) #y_pos = y_off positions[sha1] = (x_pos, y_pos) x_max = max(x_max, x_pos) y_min = y_pos self.x_max = x_max self.y_min = y_min return positions def update_scene_rect(self): y_min = self.y_min x_max = self.x_max self.scene().setSceneRect(-GraphView.x_adjust, y_min-GraphView.y_adjust, x_max + GraphView.x_adjust, abs(y_min) + GraphView.y_adjust) def sort_by_generation(self, commits): if len(commits) < 2: return commits commits.sort(cmp=lambda a, b: cmp(a.generation, b.generation)) return commits # Qt overrides def contextMenuEvent(self, event): self.context_menu_event(event) def mousePressEvent(self, event): if event.button() == Qt.MidButton: pos = event.pos() self.mouse_start = [pos.x(), pos.y()] self.saved_matrix = QtGui.QMatrix(self.matrix()) self.is_panning = True return if event.button() == Qt.RightButton: event.ignore() return if event.button() == Qt.LeftButton: self.pressed = True self.handle_event(QtGui.QGraphicsView.mousePressEvent, event) def mouseMoveEvent(self, event): pos = self.mapToScene(event.pos()) if self.is_panning: self.pan(event) return self.last_mouse[0] = pos.x() self.last_mouse[1] = pos.y() self.handle_event(QtGui.QGraphicsView.mouseMoveEvent, event) def mouseReleaseEvent(self, event): self.pressed = False if event.button() == Qt.MidButton: self.is_panning = False return self.handle_event(QtGui.QGraphicsView.mouseReleaseEvent, event) self.selection_list = [] def wheelEvent(self, event): """Handle Qt mouse wheel events.""" if event.modifiers() == Qt.ControlModifier: self.wheel_zoom(event) else: self.wheel_pan(event) git-cola-1.9.3/cola/widgets/defs.py000066400000000000000000000001521225156173500171070ustar00rootroot00000000000000no_margin = 0 small_margin = 2 margin = 4 no_spacing = 0 spacing = 4 handle_width = 4 button_spacing = 12 git-cola-1.9.3/cola/widgets/diff.py000066400000000000000000000420131225156173500171000ustar00rootroot00000000000000from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import Qt, SIGNAL from cola import cmds from cola import core from cola import gitcmds from cola import gravatar from cola import qtutils from cola.cmds import run from cola.compat import set from cola.i18n import N_ from cola.models import main from cola.models import selection from cola.qtutils import DiffSyntaxHighlighter from cola.widgets import defs from cola.widgets.text import MonoTextView COMMITS_SELECTED = 'COMMITS_SELECTED' class DiffTextEdit(MonoTextView): def __init__(self, parent, whitespace=True): MonoTextView.__init__(self, parent) # Diff/patch syntax highlighter self.highlighter = DiffSyntaxHighlighter(self.document(), whitespace=whitespace) class DiffEditor(DiffTextEdit): def __init__(self, parent): DiffTextEdit.__init__(self, parent) self.model = model = main.model() self.action_process_section = qtutils.add_action(self, N_('Process Section'), self.apply_section, Qt.Key_H) self.action_process_selection = qtutils.add_action(self, N_('Process Selection'), self.apply_selection, Qt.Key_S) self.launch_editor = qtutils.add_action(self, cmds.LaunchEditor.name(), run(cmds.LaunchEditor), cmds.LaunchEditor.SHORTCUT, 'Return', 'Enter') self.launch_editor.setIcon(qtutils.options_icon()) self.launch_difftool = qtutils.add_action(self, cmds.LaunchDifftool.name(), run(cmds.LaunchDifftool), cmds.LaunchDifftool.SHORTCUT) self.launch_difftool.setIcon(qtutils.icon('git.svg')) self.action_stage_selection = qtutils.add_action(self, N_('Stage &Selected Lines'), self.stage_selection) self.action_stage_selection.setIcon(qtutils.icon('add.svg')) self.action_stage_selection.setShortcut(Qt.Key_S) self.action_revert_selection = qtutils.add_action(self, N_('Revert Selected Lines...'), self.revert_selection) self.action_revert_selection.setIcon(qtutils.icon('undo.svg')) self.action_unstage_selection = qtutils.add_action(self, N_('Unstage &Selected Lines'), self.unstage_selection) self.action_unstage_selection.setIcon(qtutils.icon('remove.svg')) self.action_unstage_selection.setShortcut(Qt.Key_S) self.action_apply_selection = qtutils.add_action(self, N_('Apply Diff Selection to Work Tree'), self.stage_selection) self.action_apply_selection.setIcon(qtutils.apply_icon()) model.add_observer(model.message_diff_text_changed, self._emit_text) self.connect(self, SIGNAL('copyAvailable(bool)'), self.enable_selection_actions) self.connect(self, SIGNAL('set_text'), self.setPlainText) def _emit_text(self, text): self.emit(SIGNAL('set_text'), text) # Qt overrides def contextMenuEvent(self, event): """Create the context menu for the diff display.""" menu = QtGui.QMenu(self) s = selection.selection() if self.model.stageable(): if s.modified and s.modified[0] in main.model().submodules: action = menu.addAction(qtutils.icon('add.svg'), cmds.Stage.name(), cmds.run(cmds.Stage, s.modified)) action.setShortcut(cmds.Stage.SHORTCUT) menu.addAction(qtutils.git_icon(), N_('Launch git-cola'), cmds.run(cmds.OpenRepo, core.abspath(s.modified[0]))) elif s.modified: action = menu.addAction(qtutils.icon('add.svg'), N_('Stage Section'), self.stage_section) action.setShortcut(Qt.Key_H) menu.addAction(self.action_stage_selection) menu.addSeparator() menu.addAction(qtutils.icon('undo.svg'), N_('Revert Section...'), self.revert_section) menu.addAction(self.action_revert_selection) if self.model.unstageable(): if s.staged and s.staged[0] in main.model().submodules: action = menu.addAction(qtutils.icon('remove.svg'), cmds.Unstage.name(), cmds.do(cmds.Unstage, s.staged)) action.setShortcut(cmds.Unstage.SHORTCUT) menu.addAction(qtutils.git_icon(), N_('Launch git-cola'), cmds.do(cmds.OpenRepo, core.abspath(s.staged[0]))) elif s.staged: action = menu.addAction(qtutils.icon('remove.svg'), N_('Unstage Section'), self.unstage_section) action.setShortcut(Qt.Key_H) menu.addAction(self.action_unstage_selection) if self.model.stageable() or self.model.unstageable(): menu.addSeparator() menu.addAction(self.launch_editor) menu.addAction(self.launch_difftool) menu.addSeparator() action = menu.addAction(qtutils.icon('edit-copy.svg'), N_('Copy'), self.copy) action.setShortcut(QtGui.QKeySequence.Copy) action = menu.addAction(qtutils.icon('edit-select-all.svg'), N_('Select All'), self.selectAll) action.setShortcut(QtGui.QKeySequence.SelectAll) menu.exec_(self.mapToGlobal(event.pos())) def wheelEvent(self, event): if event.modifiers() & Qt.ControlModifier: # Intercept the Control modifier to not resize the text # when doing control+mousewheel event.accept() event = QtGui.QWheelEvent(event.pos(), event.delta(), Qt.NoButton, Qt.NoModifier, event.orientation()) return DiffTextEdit.wheelEvent(self, event) def mousePressEvent(self, event): if event.button() == Qt.RightButton: # Intercept right-click to move the cursor to the current position. # setTextCursor() clears the selection so this is only done when # nothing is selected. _, selection_text = self.offset_and_selection() if not selection_text: cursor = self.cursorForPosition(event.pos()) self.setTextCursor(cursor) return DiffTextEdit.mousePressEvent(self, event) def setPlainText(self, text): """setPlainText(str) while retaining scrollbar positions""" mode = self.model.mode highlight = (mode != self.model.mode_none and mode != self.model.mode_untracked) self.highlighter.set_enabled(highlight) scrollbar = self.verticalScrollBar() if scrollbar: scrollvalue = scrollbar.value() else: scrollvalue = None if text is None: return offset, selection_text = self.offset_and_selection() old_text = unicode(self.toPlainText()) DiffTextEdit.setPlainText(self, text) # If the old selection exists in the new text then # re-select it. if selection_text and selection_text in text: idx = text.index(selection_text) cursor = self.textCursor() cursor.setPosition(idx) cursor.setPosition(idx + len(selection_text), QtGui.QTextCursor.KeepAnchor) self.setTextCursor(cursor) # Otherwise, if the text is identical and there # is no selection then restore the cursor position. elif text == old_text: cursor = self.textCursor() cursor.setPosition(offset) self.setTextCursor(cursor) if scrollbar and scrollvalue is not None: scrollbar.setValue(scrollvalue) def offset_and_selection(self): cursor = self.textCursor() offset = cursor.position() selection_text = unicode(cursor.selection().toPlainText()) return offset, selection_text # Mutators def enable_selection_actions(self, enabled): self.action_apply_selection.setEnabled(enabled) self.action_revert_selection.setEnabled(enabled) self.action_unstage_selection.setEnabled(enabled) self.action_stage_selection.setEnabled(enabled) def apply_section(self): s = selection.single_selection() if self.model.stageable() and s.modified: self.stage_section() elif self.model.unstageable(): self.unstage_section() def apply_selection(self): s = selection.single_selection() if self.model.stageable() and s.modified: self.stage_selection() elif self.model.unstageable(): self.unstage_selection() def stage_section(self): """Stage a specific section.""" self.process_diff_selection(staged=False) def stage_selection(self): """Stage selected lines.""" self.process_diff_selection(staged=False, selected=True) def unstage_section(self, cached=True): """Unstage a section.""" self.process_diff_selection(staged=True) def unstage_selection(self): """Unstage selected lines.""" self.process_diff_selection(staged=True, selected=True) def revert_section(self): """Destructively remove a section from a worktree file.""" if not qtutils.confirm(N_('Revert Section?'), N_('This operation drops uncommitted changes.\n' 'These changes cannot be recovered.'), N_('Revert the uncommitted changes?'), N_('Revert Section'), default=True, icon=qtutils.icon('undo.svg')): return self.process_diff_selection(staged=False, apply_to_worktree=True, reverse=True) def revert_selection(self): """Destructively check out content for the selected file from $head.""" if not qtutils.confirm(N_('Revert Selected Lines?'), N_('This operation drops uncommitted changes.\n' 'These changes cannot be recovered.'), N_('Revert the uncommitted changes?'), N_('Revert Selected Lines'), default=True, icon=qtutils.icon('undo.svg')): return self.process_diff_selection(staged=False, apply_to_worktree=True, reverse=True, selected=True) def process_diff_selection(self, selected=False, staged=True, apply_to_worktree=False, reverse=False): """Implement un/staging of selected lines or sections.""" if selection.selection_model().is_empty(): return offset, selection_text = self.offset_and_selection() cmds.do(cmds.ApplyDiffSelection, staged, selected, offset, selection_text, apply_to_worktree) class DiffWidget(QtGui.QWidget): def __init__(self, notifier, parent): QtGui.QWidget.__init__(self, parent) author_font = QtGui.QFont(self.font()) author_font.setPointSize(int(author_font.pointSize() * 1.1)) summary_font = QtGui.QFont(author_font) summary_font.setWeight(QtGui.QFont.Bold) policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.gravatar_label = gravatar.GravatarLabel() self.author_label = TextLabel() self.author_label.setTextFormat(Qt.RichText) self.author_label.setFont(author_font) self.author_label.setSizePolicy(policy) self.author_label.setAlignment(Qt.AlignBottom) self.author_label.elide() self.summary_label = TextLabel() self.summary_label.setTextFormat(Qt.PlainText) self.summary_label.setFont(summary_font) self.summary_label.setSizePolicy(policy) self.summary_label.setAlignment(Qt.AlignTop) self.summary_label.elide() self.sha1_label = TextLabel() self.sha1_label.setTextFormat(Qt.PlainText) self.sha1_label.setSizePolicy(policy) self.sha1_label.setAlignment(Qt.AlignTop) self.sha1_label.elide() self.diff = DiffTextEdit(self, whitespace=False) self.tasks = set() self.reflector = QtCore.QObject(self) self.info_layout = QtGui.QVBoxLayout() self.info_layout.setMargin(defs.no_margin) self.info_layout.setSpacing(defs.no_spacing) self.info_layout.addWidget(self.author_label) self.info_layout.addWidget(self.summary_label) self.info_layout.addWidget(self.sha1_label) self.logo_layout = QtGui.QHBoxLayout() self.logo_layout.setContentsMargins(defs.margin, 0, defs.margin, 0) self.logo_layout.setSpacing(defs.button_spacing) self.logo_layout.addWidget(self.gravatar_label) self.logo_layout.addLayout(self.info_layout) self.main_layout = QtGui.QVBoxLayout() self.main_layout.setMargin(defs.no_margin) self.main_layout.setSpacing(defs.spacing) self.main_layout.addLayout(self.logo_layout) self.main_layout.addWidget(self.diff) self.setLayout(self.main_layout) notifier.add_observer(COMMITS_SELECTED, self.commits_selected) self.connect(self.reflector, SIGNAL('diff'), self.diff.setText) self.connect(self.reflector, SIGNAL('task_done'), self.task_done) def task_done(self, task): try: self.tasks.remove(task) except: pass def set_diff_sha1(self, sha1): self.diff.setText('+++ ' + N_('Loading...')) task = DiffInfoTask(sha1, self.reflector) self.tasks.add(task) QtCore.QThreadPool.globalInstance().start(task) def commits_selected(self, commits): if len(commits) != 1: return commit = commits[0] sha1 = commit.sha1 email = commit.email or '' summary = commit.summary or '' author = commit.author or '' template_args = { 'author': author, 'email': email, 'summary': summary } author_text = ("""%(author)s <""" """""" """%(email)s>""" % template_args) author_template = '%(author)s <%(email)s>' % template_args self.author_label.set_template(author_text, author_template) self.summary_label.set_text(summary) self.sha1_label.set_text(sha1) self.set_diff_sha1(sha1) self.gravatar_label.set_email(email) class TextLabel(QtGui.QLabel): def __init__(self, parent=None): QtGui.QLabel.__init__(self, parent) self.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.LinksAccessibleByMouse) self._display = '' self._template = '' self._text = '' self._elide = False self._metrics = QtGui.QFontMetrics(self.font()) self.setOpenExternalLinks(True) def elide(self): self._elide = True def set_text(self, text): self.set_template(text, text) def set_template(self, text, template): self._display = text self._text = text self._template = template self.update_text(self.width()) self.setText(self._display) def update_text(self, width): self._display = self._text if not self._elide: return text = self._metrics.elidedText(self._template, Qt.ElideRight, width-2) if unicode(text) != self._template: self._display = text # Qt overrides def setFont(self, font): self._metrics = QtGui.QFontMetrics(font) QtGui.QLabel.setFont(self, font) def resizeEvent(self, event): if self._elide: self.update_text(event.size().width()) block = self.blockSignals(True) self.setText(self._display) self.blockSignals(block) QtGui.QLabel.resizeEvent(self, event) class DiffInfoTask(QtCore.QRunnable): def __init__(self, sha1, reflector): QtCore.QRunnable.__init__(self) self.sha1 = sha1 self.reflector = reflector def run(self): diff = gitcmds.diff_info(self.sha1) self.reflector.emit(SIGNAL('diff'), diff) git-cola-1.9.3/cola/widgets/editremotes.py000066400000000000000000000212661225156173500205230ustar00rootroot00000000000000from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import qtutils from cola.git import git from cola.git import STDOUT from cola.i18n import N_ from cola.models import main from cola.widgets import defs from cola.widgets import text def edit(): window = RemoteEditor(qtutils.active_window()) window.show() window.raise_() return window class RemoteEditor(QtGui.QDialog): def __init__(self, parent): QtGui.QDialog.__init__(self, parent) self.setWindowTitle(N_('Edit Remotes')) self.setWindowModality(Qt.WindowModal) self.default_hint = N_('' 'Add and remove remote repositories using the \n' 'Add(+) and Delete(-) buttons on the left-hand side.\n' '\n' 'Remotes can be renamed by selecting one from the list\n' 'and pressing "enter", or by double-clicking.') self.remote_list = [] self.remotes = QtGui.QListWidget() self.remotes.setToolTip(N_( 'Remote git repositories - double-click to rename')) self.info = text.HintedTextView(self.default_hint, self) font = self.info.font() metrics = QtGui.QFontMetrics(font) width = metrics.width('_' * 72) height = metrics.height() * 13 self.info.setMinimumWidth(width) self.info.setMinimumHeight(height) self.info_thread = RemoteInfoThread(self) self.add_btn = QtGui.QToolButton() self.add_btn.setIcon(qtutils.icon('add.svg')) self.add_btn.setToolTip(N_('Add new remote git repository')) self.refresh_btn = QtGui.QToolButton() self.refresh_btn.setIcon(qtutils.icon('view-refresh.svg')) self.refresh_btn.setToolTip(N_('Refresh')) self.delete_btn = QtGui.QToolButton() self.delete_btn.setIcon(qtutils.icon('remove.svg')) self.delete_btn.setToolTip(N_('Delete remote')) self.close_btn = QtGui.QPushButton(N_('Close')) self._top_layout = QtGui.QSplitter() self._top_layout.setOrientation(Qt.Horizontal) self._top_layout.setHandleWidth(defs.handle_width) self._top_layout.addWidget(self.remotes) self._top_layout.addWidget(self.info) width = self._top_layout.width() self._top_layout.setSizes([width/4, width*3/4]) self._button_layout = QtGui.QHBoxLayout() self._button_layout.addWidget(self.add_btn) self._button_layout.addWidget(self.delete_btn) self._button_layout.addWidget(self.refresh_btn) self._button_layout.addStretch() self._button_layout.addWidget(self.close_btn) self._layout = QtGui.QVBoxLayout() self._layout.setMargin(defs.margin) self._layout.setSpacing(defs.spacing) self._layout.addWidget(self._top_layout) self._layout.addLayout(self._button_layout) self.setLayout(self._layout) self.refresh() qtutils.connect_button(self.add_btn, self.add) qtutils.connect_button(self.delete_btn, self.delete) qtutils.connect_button(self.refresh_btn, self.refresh) qtutils.connect_button(self.close_btn, self.close) self.connect(self.info_thread, SIGNAL('info'), self.info.set_value) self.connect(self.remotes, SIGNAL('itemChanged(QListWidgetItem*)'), self.remote_renamed) self.connect(self.remotes, SIGNAL('itemSelectionChanged()'), self.selection_changed) def refresh(self): remotes = git.remote()[STDOUT].splitlines() self.remotes.clear() self.remotes.addItems(remotes) self.remote_list = remotes self.info.set_hint(self.default_hint) self.info.enable_hint(True) for idx, r in enumerate(remotes): item = self.remotes.item(idx) item.setFlags(item.flags() | Qt.ItemIsEditable) def add(self): widget = AddRemoteWidget(self) if not widget.add_remote(): return name = widget.name.value() url = widget.url.value() status, out, err = git.remote('add', name, url) if status != 0: qtutils.critical(N_('Error creating remote "%s"') % name, out + err) self.refresh() def delete(self): remote = qtutils.selected_item(self.remotes, self.remote_list) if remote is None: return title = N_('Delete Remote') question = N_('Delete remote?') info = N_('Delete remote "%s"') % remote ok_btn = N_('Delete') if not qtutils.confirm(title, question, info, ok_btn): return status, out, err = git.remote('rm', remote) if status != 0: qtutils.critical(N_('Error deleting remote "%s"') % remote, out + err) main.model().update_status() self.refresh() def remote_renamed(self, item): idx = self.remotes.row(item) if idx < 0: return if idx >= len(self.remote_list): return old_name = self.remote_list[idx] new_name = unicode(item.text()) if new_name == old_name: return if not new_name: item.setText(old_name) return title = N_('Rename Remote') question = N_('Rename remote?') info = (N_('Rename remote "%(current)s" to "%(new)s"?') % dict(current=old_name, new=new_name)) ok_btn = N_('Rename') if qtutils.confirm(title, question, info, ok_btn): status, out, err = git.remote('rename', old_name, new_name) if status == 0: self.remote_list[idx] = new_name else: item.setText(old_name) def selection_changed(self): remote = qtutils.selected_item(self.remotes, self.remote_list) if remote is None: return self.info.set_hint(N_('Gathering info for "%s"...') % remote) self.info.enable_hint(True) self.info_thread.remote = remote self.info_thread.start() class RemoteInfoThread(QtCore.QThread): def __init__(self, parent): QtCore.QThread.__init__(self, parent) self.remote = None def run(self): remote = self.remote if remote is None: return status, out, err = git.remote('show', remote) # This call takes a long time and we may have selected a # different remote... if remote == self.remote: self.emit(SIGNAL('info'), out + err) else: self.run() class AddRemoteWidget(QtGui.QDialog): def __init__(self, parent): QtGui.QDialog.__init__(self, parent) self.setWindowModality(Qt.WindowModal) self.add_btn = QtGui.QPushButton(N_('Add Remote')) self.add_btn.setIcon(qtutils.apply_icon()) self.cancel_btn = QtGui.QPushButton(N_('Cancel')) def lineedit(hint): widget = text.HintedLineEdit(hint) widget.enable_hint(True) metrics = QtGui.QFontMetrics(widget.font()) widget.setMinimumWidth(metrics.width('_' * 32)) return widget self.setWindowTitle(N_('Add remote')) self.name = lineedit(N_('Name for the new remote')) self.url = lineedit('git://git.example.com/repo.git') self._form = QtGui.QFormLayout() self._form.setMargin(defs.margin) self._form.setSpacing(defs.spacing) self._form.addRow(N_('Name'), self.name) self._form.addRow(N_('URL'), self.url) self._btn_layout = QtGui.QHBoxLayout() self._btn_layout.setMargin(0) self._btn_layout.setSpacing(defs.button_spacing) self._btn_layout.addStretch() self._btn_layout.addWidget(self.add_btn) self._btn_layout.addWidget(self.cancel_btn) self._layout = QtGui.QVBoxLayout() self._layout.setMargin(defs.margin) self._layout.setSpacing(defs.margin) self._layout.addLayout(self._form) self._layout.addLayout(self._btn_layout) self.setLayout(self._layout) self.connect(self.name, SIGNAL('textChanged(QString)'), self.validate) self.connect(self.url, SIGNAL('textChanged(QString)'), self.validate) self.add_btn.setEnabled(False) qtutils.connect_button(self.add_btn, self.accept) qtutils.connect_button(self.cancel_btn, self.reject) def validate(self, dummy_text): name = self.name.value() url = self.url.value() self.add_btn.setEnabled(bool(name) and bool(url)) def add_remote(self): self.show() self.raise_() return self.exec_() == QtGui.QDialog.Accepted git-cola-1.9.3/cola/widgets/grep.py000066400000000000000000000256761225156173500171450ustar00rootroot00000000000000from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import cmds from cola import utils from cola import qtutils from cola.cmds import do from cola.git import git from cola.i18n import N_ from cola.qtutils import diff_font from cola.widgets import defs from cola.widgets.standard import Dialog from cola.widgets.text import HintedTextView, HintedLineEdit class GrepThread(QtCore.QThread): def __init__(self, parent): QtCore.QThread.__init__(self, parent) self.query = None self.shell = False self.regexp_mode = '--basic-regexp' def run(self): if self.query is None: return query = self.query if self.shell: args = utils.shell_split(query) else: args = [query] status, out, err = git.grep(self.regexp_mode, n=True, *args) if query == self.query: self.emit(SIGNAL('result'), status, out, err) else: self.run() class Grep(Dialog): def __init__(self, parent): Dialog.__init__(self, parent) self.setAttribute(Qt.WA_MacMetalStyle) self.setWindowModality(Qt.WindowModal) self.setWindowTitle(N_('Search')) self.input_label = QtGui.QLabel('git grep') self.input_label.setFont(diff_font()) self.input_txt = HintedLineEdit(N_('command-line arguments'), self) self.input_txt.enable_hint(True) self.regexp_combo = combo = QtGui.QComboBox() combo.setToolTip(N_('Choose the "git grep" regular expression mode')) items = [N_('Basic Regexp'), N_('Extended Regexp'), N_('Fixed String')] combo.addItems(items) combo.setCurrentIndex(0) combo.setEditable(False) combo.setItemData(0, N_('Search using a POSIX basic regular expression'), Qt.ToolTipRole) combo.setItemData(1, N_('Search using a POSIX extended regular expression'), Qt.ToolTipRole) combo.setItemData(2, N_('Search for a fixed string'), Qt.ToolTipRole) combo.setItemData(0, '--basic-regexp', Qt.UserRole) combo.setItemData(1, '--extended-regexp', Qt.UserRole) combo.setItemData(2, '--fixed-strings', Qt.UserRole) self.result_txt = GrepTextView(N_('grep result...'), self) self.result_txt.enable_hint(True) self.edit_button = QtGui.QPushButton(N_('Edit')) self.edit_button.setIcon(qtutils.open_file_icon()) self.edit_button.setEnabled(False) self.edit_button.setShortcut(cmds.Edit.SHORTCUT) self.refresh_button = QtGui.QPushButton(N_('Refresh')) self.refresh_button.setIcon(qtutils.reload_icon()) self.refresh_button.setShortcut(QtGui.QKeySequence.Refresh) self.shell_checkbox = QtGui.QCheckBox(N_('Shell arguments')) self.shell_checkbox.setToolTip( N_('Parse arguments using a shell.\n' 'Queries with spaces will require "double quotes".')) self.shell_checkbox.setChecked(False) self.close_button = QtGui.QPushButton(N_('Close')) self.input_layout = QtGui.QHBoxLayout() self.input_layout.setMargin(0) self.input_layout.setSpacing(defs.button_spacing) self.bottom_layout = QtGui.QHBoxLayout() self.bottom_layout.setMargin(0) self.bottom_layout.setSpacing(defs.button_spacing) self.mainlayout = QtGui.QVBoxLayout() self.mainlayout.setMargin(defs.margin) self.mainlayout.setSpacing(defs.spacing) self.input_layout.addWidget(self.input_label) self.input_layout.addWidget(self.input_txt) self.input_layout.addWidget(self.regexp_combo) self.bottom_layout.addWidget(self.edit_button) self.bottom_layout.addWidget(self.refresh_button) self.bottom_layout.addWidget(self.shell_checkbox) self.bottom_layout.addStretch() self.bottom_layout.addWidget(self.close_button) self.mainlayout.addLayout(self.input_layout) self.mainlayout.addWidget(self.result_txt) self.mainlayout.addLayout(self.bottom_layout) self.setLayout(self.mainlayout) self.grep_thread = GrepThread(self) self.connect(self.grep_thread, SIGNAL('result'), self.process_result) self.connect(self.input_txt, SIGNAL('textChanged(QString)'), lambda s: self.search()) self.connect(self.regexp_combo, SIGNAL('currentIndexChanged(int)'), lambda x: self.search()) self.connect(self.result_txt, SIGNAL('leave()'), lambda: self.input_txt.setFocus()) qtutils.add_action(self.input_txt, 'FocusResults', lambda: self.result_txt.setFocus(), Qt.Key_Down, Qt.Key_Enter, Qt.Key_Return) qtutils.add_action(self, 'FocusSearch', lambda: self.input_txt.setFocus(), 'Ctrl+l') qtutils.connect_button(self.edit_button, self.edit) qtutils.connect_button(self.refresh_button, self.search) qtutils.connect_toggle(self.shell_checkbox, lambda x: self.search()) qtutils.connect_button(self.close_button, self.close) qtutils.add_close_action(self) if not qtutils.apply_state(self): self.resize(666, 420) def done(self, exit_code): qtutils.save_state(self) return Dialog.done(self, exit_code) def regexp_mode(self): idx = self.regexp_combo.currentIndex() data = self.regexp_combo.itemData(idx, Qt.UserRole).toPyObject() return unicode(data) def search(self): self.edit_button.setEnabled(False) self.refresh_button.setEnabled(False) query = self.input_txt.value() if len(query) < 2: self.result_txt.set_value('') return self.grep_thread.query = query self.grep_thread.shell = self.shell_checkbox.isChecked() self.grep_thread.regexp_mode = self.regexp_mode() self.grep_thread.start() def search_for(self, txt): self.input_txt.set_value(txt) self.search() def text_scroll(self): scrollbar = self.result_txt.verticalScrollBar() if scrollbar: return scrollbar.value() return None def set_text_scroll(self, scroll): scrollbar = self.result_txt.verticalScrollBar() if scrollbar and scroll is not None: scrollbar.setValue(scroll) def text_offset(self): return self.result_txt.textCursor().position() def set_text_offset(self, offset): cursor = self.result_txt.textCursor() cursor.setPosition(offset) self.result_txt.setTextCursor(cursor) def process_result(self, status, out, err): if status == 0: value = out + err elif out + err: value = 'git grep: ' + out + err else: value = '' # save scrollbar and text cursor scroll = self.text_scroll() offset = min(len(value), self.text_offset()) self.result_txt.set_value(value) # restore self.set_text_scroll(scroll) self.set_text_offset(offset) self.edit_button.setEnabled(status == 0) self.refresh_button.setEnabled(status == 0) def edit(self): goto_grep(self.result_txt.selected_line()), class GrepTextView(HintedTextView): def __init__(self, hint, parent): HintedTextView.__init__(self, hint, parent) self.goto_action = qtutils.add_action(self, 'Launch Editor', self.edit) self.goto_action.setShortcut(cmds.Edit.SHORTCUT) qtutils.add_action(self, 'Up', lambda: self.move(QtGui.QTextCursor.Up), Qt.Key_K) qtutils.add_action(self, 'Down', lambda: self.move(QtGui.QTextCursor.Down), Qt.Key_J) qtutils.add_action(self, 'Left', lambda: self.move(QtGui.QTextCursor.Left), Qt.Key_H) qtutils.add_action(self, 'Right', lambda: self.move(QtGui.QTextCursor.Right), Qt.Key_L) qtutils.add_action(self, 'StartOfLine', lambda: self.move(QtGui.QTextCursor.StartOfLine), Qt.Key_0) qtutils.add_action(self, 'EndOfLine', lambda: self.move(QtGui.QTextCursor.EndOfLine), Qt.Key_Dollar) qtutils.add_action(self, 'WordLeft', lambda: self.move(QtGui.QTextCursor.WordLeft), Qt.Key_B) qtutils.add_action(self, 'WordRight', lambda: self.move(QtGui.QTextCursor.WordRight), Qt.Key_W) qtutils.add_action(self, 'PageUp', lambda: self.page(-self.height()/2), 'Shift+Space') qtutils.add_action(self, 'PageDown', lambda: self.page(self.height()/2), Qt.Key_Space) def contextMenuEvent(self, event): menu = self.createStandardContextMenu(event.pos()) menu.addSeparator() menu.addAction(self.goto_action) menu.exec_(self.mapToGlobal(event.pos())) def edit(self): goto_grep(self.selected_line()) def page(self, offset): rect = self.cursorRect() x = rect.x() y = rect.y() + offset new_cursor = self.cursorForPosition(QtCore.QPoint(x, y)) if new_cursor is not None: self.set_text_cursor(new_cursor) def set_text_cursor(self, cursor): self.setTextCursor(cursor) self.ensureCursorVisible() self.viewport().update() def move(self, direction): cursor = self.textCursor() if cursor.movePosition(direction): self.set_text_cursor(cursor) def paintEvent(self, event): HintedTextView.paintEvent(self, event) if self.hasFocus(): # Qt doesn't redraw the cursor when using movePosition(). # So.. draw our own cursor. rect = self.cursorRect() painter = QtGui.QPainter(self.viewport()) painter.fillRect(rect, Qt.SolidPattern) def keyPressEvent(self, event): if event.key() == Qt.Key_Up: cursor = self.textCursor() position = cursor.position() if position == 0 and not cursor.hasSelection(): # The cursor is at the beginning of the line. # If we have selection then simply reset the cursor. # Otherwise, emit a signal so that the parent can # change focus. self.emit(SIGNAL('leave()')) return HintedTextView.keyPressEvent(self, event) def goto_grep(line): """Called when Search -> Grep's right-click 'goto' action.""" filename, line_number, contents = line.split(':', 2) do(cmds.Edit, [filename], line_number=line_number) def run_grep(text=None, parent=None): widget = Grep(parent) if text: widget.search_for(text) return widget git-cola-1.9.3/cola/widgets/highlighter.py000066400000000000000000000063551225156173500204770ustar00rootroot00000000000000from PyQt4 import QtCore, QtGui have_pygments = True try: from pygments.styles import get_style_by_name from pygments import lex from pygments.util import ClassNotFound from pygments.lexers import get_lexer_for_filename except ImportError: have_pygments = False def highlight_document(edit, filename): doc = edit.document() if not have_pygments: return try: lexer = get_lexer_for_filename(filename, stripnl=False) except ClassNotFound: return style = get_style_by_name("default") font = doc.defaultFont() base_format = QtGui.QTextCharFormat() base_format.setFont(font) token_formats = {} window = edit.window() if hasattr(window, "processEvents"): processEvents = window.processEvents else: processEvents = QtCore.QCoreApplication.processEvents def get_token_format(token): if token in token_formats: return token_formats[token] if token.parent: parent_format = get_token_format(token.parent) else: parent_format = base_format format = QtGui.QTextCharFormat(parent_format) font = format.font() if style.styles_token(token): tstyle = style.style_for_token(token) if tstyle['color']: format.setForeground (QtGui.QColor("#"+tstyle['color'])) if tstyle['bold']: font.setWeight(QtGui.QFont.Bold) if tstyle['italic']: font.setItalic (True) if tstyle['underline']: format.setFontUnderline(True) if tstyle['bgcolor']: format.setBackground (QtGui.QColor("#"+tstyle['bgcolor'])) # No way to set this for a QTextCharFormat #if tstyle['border']: format. token_formats[token] = format return format text = unicode(doc.toPlainText()) block_count = 0 block = doc.firstBlock() assert(isinstance(block, QtGui.QTextBlock)) block_pos = 0 block_len = block.length() block_formats = [] for token, ttext in lex(text, lexer): format_len = len(ttext) format = get_token_format(token) while format_len > 0: format_range = QtGui.QTextLayout.FormatRange() format_range.start = block_pos format_range.length = min(format_len, block_len) format_range.format = format block_formats.append(format_range) block_len -= format_range.length format_len -= format_range.length block_pos += format_range.length if block_len == 0: block.layout().setAdditionalFormats(block_formats) doc.markContentsDirty(block.position(), block.length()) block = block.next() block_pos = 0 block_len = block.length() block_formats = [] block_count += 1 if block_count % 100 == 0: processEvents() if __name__ == "__main__": import sys app = QtGui.QApplication(sys.argv) python = QtGui.QPlainTextEdit() f = open(__file__, 'r') python.setPlainText(f.read()) f.close() python.setWindowTitle('python') python.show() highlight_document(python, __file__) sys.exit(app.exec_()) git-cola-1.9.3/cola/widgets/log.py000066400000000000000000000024251225156173500167540ustar00rootroot00000000000000import time from PyQt4 import QtGui from cola.i18n import N_ from cola.widgets.text import MonoTextView class LogWidget(QtGui.QWidget): """A simple dialog to display command logs.""" def __init__(self, parent=None, output=None): QtGui.QWidget.__init__(self, parent) self._layout = QtGui.QVBoxLayout(self) self._layout.setMargin(0) self.output_text = MonoTextView(self) self._layout.addWidget(self.output_text) if output: self.set_output(output) def clear(self): self.output_text.clear() def set_output(self, output): self.output_text.setText(output) def log_status(self, status, out, err=None): msg = out if err: msg += '\n' + err if status != 0: msg += '\n' msg += N_('exit code %s') % status self.log(msg) def log(self, msg): if not msg: return cursor = self.output_text.textCursor() cursor.movePosition(cursor.End) text = self.output_text cursor.insertText(time.asctime() + '\n') for line in msg.splitlines(): cursor.insertText(line + '\n') cursor.insertText('\n') cursor.movePosition(cursor.End) text.setTextCursor(cursor) git-cola-1.9.3/cola/widgets/main.py000066400000000000000000000735261225156173500171310ustar00rootroot00000000000000"""This view provides the main git-cola user interface. """ import os from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import cmds from cola import core from cola import gitcmds from cola import guicmds from cola import gitcfg from cola import qtutils from cola import resources from cola import settings from cola import utils from cola import version from cola.bookmarks import manage_bookmarks from cola.git import git from cola.git import STDOUT from cola.i18n import N_ from cola.interaction import Interaction from cola.models import prefs from cola.qtutils import add_action from cola.qtutils import add_action_bool from cola.qtutils import connect_action from cola.qtutils import connect_action_bool from cola.qtutils import create_dock from cola.qtutils import create_menu from cola.qtutils import create_toolbutton from cola.qtutils import options_icon from cola.widgets import action from cola.widgets import cfgactions from cola.widgets import editremotes from cola.widgets import remote from cola.widgets.about import launch_about_dialog from cola.widgets.about import show_shortcuts from cola.widgets.archive import GitArchiveDialog from cola.widgets.browse import worktree_browser from cola.widgets.browse import worktree_browser_widget from cola.widgets.commitmsg import CommitMessageEditor from cola.widgets.compare import compare_branches from cola.widgets.createtag import create_tag from cola.widgets.createbranch import create_new_branch from cola.widgets.dag import git_dag from cola.widgets.diff import DiffEditor from cola.widgets.log import LogWidget from cola.widgets import merge from cola.widgets.prefs import preferences from cola.widgets.recent import browse_recent from cola.widgets.status import StatusWidget from cola.widgets.search import search from cola.widgets.standard import MainWindow from cola.widgets.stash import stash class MainView(MainWindow): def __init__(self, model, parent=None): MainWindow.__init__(self, parent) # Default size; this is thrown out when save/restore is used self.resize(987, 610) self.model = model self.prefs_model = prefs_model = prefs.PreferencesModel() # The widget version is used by import/export_state(). # Change this whenever dockwidgets are removed. self.widget_version = 2 # Keeps track of merge messages we've seen self.merge_message_hash = '' self.setAcceptDrops(True) self.setAttribute(Qt.WA_MacMetalStyle) cfg = gitcfg.instance() self.browser_dockable = (cfg.get('cola.browserdockable') or cfg.get('cola.classicdockable')) if self.browser_dockable: self.browserdockwidget = create_dock(N_('Browser'), self) self.browserwidget = worktree_browser_widget(self) self.browserdockwidget.setWidget(self.browserwidget) # "Actions" widget self.actionsdockwidget = create_dock(N_('Actions'), self) self.actionsdockwidgetcontents = action.ActionButtons(self) self.actionsdockwidget.setWidget(self.actionsdockwidgetcontents) self.actionsdockwidget.toggleViewAction().setChecked(False) self.actionsdockwidget.hide() # "Repository Status" widget self.statuswidget = StatusWidget(self) self.statusdockwidget = create_dock(N_('Status'), self) self.statusdockwidget.setWidget(self.statuswidget) # "Commit Message Editor" widget self.position_label = QtGui.QLabel() font = qtutils.default_monospace_font() font.setPointSize(int(font.pointSize() * 0.8)) self.position_label.setFont(font) self.commitdockwidget = create_dock(N_('Commit'), self) titlebar = self.commitdockwidget.titleBarWidget() titlebar.add_corner_widget(self.position_label) self.commitmsgeditor = CommitMessageEditor(model, self) self.commitdockwidget.setWidget(self.commitmsgeditor) # "Console" widget self.logwidget = LogWidget() self.logdockwidget = create_dock(N_('Console'), self) self.logdockwidget.setWidget(self.logwidget) self.logdockwidget.toggleViewAction().setChecked(False) self.logdockwidget.hide() # "Diff Viewer" widget self.diffdockwidget = create_dock(N_('Diff'), self) self.diffeditor = DiffEditor(self.diffdockwidget) self.diffdockwidget.setWidget(self.diffeditor) # "Diff Options" tool menu self.diff_ignore_space_at_eol_action = add_action(self, N_('Ignore changes in whitespace at EOL'), self._update_diff_opts) self.diff_ignore_space_at_eol_action.setCheckable(True) self.diff_ignore_space_change_action = add_action(self, N_('Ignore changes in amount of whitespace'), self._update_diff_opts) self.diff_ignore_space_change_action.setCheckable(True) self.diff_ignore_all_space_action = add_action(self, N_('Ignore all whitespace'), self._update_diff_opts) self.diff_ignore_all_space_action.setCheckable(True) self.diff_function_context_action = add_action(self, N_('Show whole surrounding functions of changes'), self._update_diff_opts) self.diff_function_context_action.setCheckable(True) self.diffopts_button = create_toolbutton(text=N_('Options'), icon=options_icon(), tooltip=N_('Diff Options')) self.diffopts_menu = create_menu(N_('Diff Options'), self.diffopts_button) self.diffopts_menu.addAction(self.diff_ignore_space_at_eol_action) self.diffopts_menu.addAction(self.diff_ignore_space_change_action) self.diffopts_menu.addAction(self.diff_ignore_all_space_action) self.diffopts_menu.addAction(self.diff_function_context_action) self.diffopts_button.setMenu(self.diffopts_menu) self.diffopts_button.setPopupMode(QtGui.QToolButton.InstantPopup) titlebar = self.diffdockwidget.titleBarWidget() titlebar.add_corner_widget(self.diffopts_button) # All Actions self.menu_unstage_all = add_action(self, N_('Unstage All'), cmds.run(cmds.UnstageAll)) self.menu_unstage_all.setIcon(qtutils.icon('remove.svg')) self.menu_unstage_selected = add_action(self, N_('Unstage From Commit'), cmds.run(cmds.UnstageSelected)) self.menu_unstage_selected.setIcon(qtutils.icon('remove.svg')) self.menu_show_diffstat = add_action(self, N_('Diffstat'), cmds.run(cmds.Diffstat), 'Alt+D') self.menu_stage_modified = add_action(self, N_('Stage Changed Files To Commit'), cmds.run(cmds.StageModified), 'Alt+A') self.menu_stage_modified.setIcon(qtutils.icon('add.svg')) self.menu_stage_untracked = add_action(self, N_('Stage All Untracked'), cmds.run(cmds.StageUntracked), 'Alt+U') self.menu_stage_untracked.setIcon(qtutils.icon('add.svg')) self.menu_export_patches = add_action(self, N_('Export Patches...'), guicmds.export_patches, 'Alt+E') self.new_repository = add_action(self, N_('New Repository...'), guicmds.open_new_repo) self.new_repository.setIcon(qtutils.new_icon()) self.menu_preferences = add_action(self, N_('Preferences'), self.preferences, QtGui.QKeySequence.Preferences, 'Ctrl+O') self.menu_edit_remotes = add_action(self, N_('Edit Remotes...'), lambda: editremotes.edit().exec_()) self.menu_rescan = add_action(self, cmds.Refresh.name(), cmds.run(cmds.Refresh), cmds.Refresh.SHORTCUT) self.menu_rescan.setIcon(qtutils.reload_icon()) self.menu_browse_recent = add_action(self, N_('Recently Modified Files...'), browse_recent, 'Shift+Ctrl+E') self.menu_cherry_pick = add_action(self, N_('Cherry-Pick...'), guicmds.cherry_pick, 'Ctrl+P') self.menu_load_commitmsg = add_action(self, N_('Load Commit Message...'), guicmds.load_commitmsg) self.menu_save_tarball = add_action(self, N_('Save As Tarball/Zip...'), self.save_archive) self.menu_quit = add_action(self, N_('Quit'), self.close, 'Ctrl+Q') self.menu_manage_bookmarks = add_action(self, N_('Bookmarks...'), manage_bookmarks) self.menu_grep = add_action(self, N_('Grep'), guicmds.grep, 'Ctrl+G') self.menu_merge_local = add_action(self, N_('Merge...'), merge.local_merge) self.menu_merge_abort = add_action(self, N_('Abort Merge...'), merge.abort_merge) self.menu_fetch = add_action(self, N_('Fetch...'), remote.fetch) self.menu_push = add_action(self, N_('Push...'), remote.push) self.menu_pull = add_action(self, N_('Pull...'), remote.pull) self.menu_open_repo = add_action(self, N_('Open...'), guicmds.open_repo) self.menu_open_repo.setIcon(qtutils.open_icon()) self.menu_stash = add_action(self, N_('Stash...'), stash, 'Alt+Shift+S') self.menu_clone_repo = add_action(self, N_('Clone...'), guicmds.clone_repo) self.menu_clone_repo.setIcon(qtutils.git_icon()) self.menu_help_docs = add_action(self, N_('Documentation'), resources.show_html_docs, QtGui.QKeySequence.HelpContents) self.menu_help_shortcuts = add_action(self, N_('Keyboard Shortcuts'), show_shortcuts, QtCore.Qt.Key_Question) self.menu_visualize_current = add_action(self, N_('Visualize Current Branch...'), cmds.run(cmds.VisualizeCurrent)) self.menu_visualize_all = add_action(self, N_('Visualize All Branches...'), cmds.run(cmds.VisualizeAll)) self.menu_search_commits = add_action(self, N_('Search...'), search) self.menu_browse_branch = add_action(self, N_('Browse Current Branch...'), guicmds.browse_current) self.menu_browse_other_branch = add_action(self, N_('Browse Other Branch...'), guicmds.browse_other) self.menu_load_commitmsg_template = add_action(self, N_('Get Commit Message Template'), cmds.run(cmds.LoadCommitMessageFromTemplate)) self.menu_help_about = add_action(self, N_('About'), launch_about_dialog) self.menu_diff_expression = add_action(self, N_('Expression...'), guicmds.diff_expression) self.menu_branch_compare = add_action(self, N_('Branches...'), compare_branches) self.menu_create_tag = add_action(self, N_('Create Tag...'), create_tag) self.menu_create_branch = add_action(self, N_('Create...'), create_new_branch, 'Ctrl+B') self.menu_delete_branch = add_action(self, N_('Delete...'), guicmds.delete_branch) self.menu_delete_remote_branch = add_action(self, N_('Delete Remote Branch...'), guicmds.delete_remote_branch) self.menu_checkout_branch = add_action(self, N_('Checkout...'), guicmds.checkout_branch, 'Alt+B') self.menu_branch_review = add_action(self, N_('Review...'), guicmds.review_branch) self.menu_browse = add_action(self, N_('Browser...'), worktree_browser) self.menu_browse.setIcon(qtutils.git_icon()) self.menu_dag = add_action(self, N_('DAG...'), lambda: git_dag(self.model).show()) self.menu_dag.setIcon(qtutils.git_icon()) self.rebase_start_action = add_action(self, N_('Start Interactive Rebase...'), self.rebase_start) self.rebase_edit_todo_action = add_action(self, N_('Edit...'), self.rebase_edit_todo) self.rebase_continue_action = add_action(self, N_('Continue'), self.rebase_continue) self.rebase_skip_action = add_action(self, N_('Skip Current Patch'), self.rebase_skip) self.rebase_abort_action = add_action(self, N_('Abort'), self.rebase_abort) # Relayed actions if not self.browser_dockable: # These shortcuts conflict with those from the # 'Browser' widget so don't register them when # the browser is a dockable tool. status_tree = self.statusdockwidget.widget().tree self.addAction(status_tree.up) self.addAction(status_tree.down) self.addAction(status_tree.process_selection) self.lock_layout_action = add_action_bool(self, N_('Lock Layout'), self.set_lock_layout, False) # Create the application menu self.menubar = QtGui.QMenuBar(self) # File Menu self.file_menu = create_menu(N_('File'), self.menubar) self.file_menu.addAction(self.new_repository) self.file_menu.addAction(self.menu_open_repo) self.menu_open_recent = self.file_menu.addMenu(N_('Open Recent')) self.file_menu.addSeparator() self.file_menu.addAction(self.menu_clone_repo) self.file_menu.addAction(self.menu_manage_bookmarks) self.file_menu.addSeparator() self.file_menu.addAction(self.menu_edit_remotes) self.file_menu.addAction(self.menu_rescan) self.file_menu.addSeparator() self.file_menu.addAction(self.menu_browse_recent) self.file_menu.addSeparator() self.file_menu.addAction(self.menu_load_commitmsg) self.file_menu.addAction(self.menu_load_commitmsg_template) self.file_menu.addSeparator() self.file_menu.addAction(self.menu_save_tarball) self.file_menu.addAction(self.menu_export_patches) self.file_menu.addSeparator() self.file_menu.addAction(self.menu_preferences) self.file_menu.addAction(self.menu_quit) self.menubar.addAction(self.file_menu.menuAction()) # Actions menu self.actions_menu = create_menu(N_('Actions'), self.menubar) self.actions_menu.addAction(self.menu_fetch) self.actions_menu.addAction(self.menu_push) self.actions_menu.addAction(self.menu_pull) self.actions_menu.addAction(self.menu_stash) self.actions_menu.addSeparator() self.actions_menu.addAction(self.menu_create_tag) self.actions_menu.addAction(self.menu_cherry_pick) self.actions_menu.addAction(self.menu_merge_local) self.actions_menu.addAction(self.menu_merge_abort) self.actions_menu.addSeparator() self.actions_menu.addAction(self.menu_grep) self.actions_menu.addAction(self.menu_search_commits) self.menubar.addAction(self.actions_menu.menuAction()) # Index Menu self.commit_menu = create_menu(N_('Index'), self.menubar) self.commit_menu.setTitle(N_('Index')) self.commit_menu.addAction(self.menu_stage_modified) self.commit_menu.addAction(self.menu_stage_untracked) self.commit_menu.addSeparator() self.commit_menu.addAction(self.menu_unstage_all) self.commit_menu.addAction(self.menu_unstage_selected) self.menubar.addAction(self.commit_menu.menuAction()) # Diff Menu self.diff_menu = create_menu(N_('Diff'), self.menubar) self.diff_menu.addAction(self.menu_diff_expression) self.diff_menu.addAction(self.menu_branch_compare) self.diff_menu.addSeparator() self.diff_menu.addAction(self.menu_show_diffstat) self.menubar.addAction(self.diff_menu.menuAction()) # Branch Menu self.branch_menu = create_menu(N_('Branch'), self.menubar) self.branch_menu.addAction(self.menu_branch_review) self.branch_menu.addSeparator() self.branch_menu.addAction(self.menu_create_branch) self.branch_menu.addAction(self.menu_checkout_branch) self.branch_menu.addAction(self.menu_delete_branch) self.branch_menu.addAction(self.menu_delete_remote_branch) self.branch_menu.addSeparator() self.branch_menu.addAction(self.menu_browse_branch) self.branch_menu.addAction(self.menu_browse_other_branch) self.branch_menu.addSeparator() self.branch_menu.addAction(self.menu_visualize_current) self.branch_menu.addAction(self.menu_visualize_all) self.menubar.addAction(self.branch_menu.menuAction()) # Rebase menu self.rebase_menu = create_menu(N_('Rebase'), self.actions_menu) self.rebase_menu.addAction(self.rebase_start_action) self.rebase_menu.addAction(self.rebase_edit_todo_action) self.rebase_menu.addSeparator() self.rebase_menu.addAction(self.rebase_continue_action) self.rebase_menu.addAction(self.rebase_skip_action) self.rebase_menu.addSeparator() self.rebase_menu.addAction(self.rebase_abort_action) self.menubar.addAction(self.rebase_menu.menuAction()) # View Menu self.view_menu = create_menu(N_('View'), self.menubar) self.view_menu.addAction(self.menu_browse) self.view_menu.addAction(self.menu_dag) self.view_menu.addSeparator() if self.browser_dockable: self.view_menu.addAction(self.browserdockwidget.toggleViewAction()) self.setup_dockwidget_view_menu() self.view_menu.addSeparator() self.view_menu.addAction(self.lock_layout_action) self.menubar.addAction(self.view_menu.menuAction()) # Help Menu self.help_menu = create_menu(N_('Help'), self.menubar) self.help_menu.addAction(self.menu_help_docs) self.help_menu.addAction(self.menu_help_shortcuts) self.help_menu.addAction(self.menu_help_about) self.menubar.addAction(self.help_menu.menuAction()) # Set main menu self.setMenuBar(self.menubar) # Arrange dock widgets left = Qt.LeftDockWidgetArea right = Qt.RightDockWidgetArea bottom = Qt.BottomDockWidgetArea self.addDockWidget(left, self.commitdockwidget) if self.browser_dockable: self.addDockWidget(left, self.browserdockwidget) self.tabifyDockWidget(self.browserdockwidget, self.commitdockwidget) self.addDockWidget(left, self.diffdockwidget) self.addDockWidget(bottom, self.actionsdockwidget) self.addDockWidget(bottom, self.logdockwidget) self.tabifyDockWidget(self.actionsdockwidget, self.logdockwidget) self.addDockWidget(right, self.statusdockwidget) # Listen for model notifications model.add_observer(model.message_updated, self._update) model.add_observer(model.message_mode_changed, lambda x: self._update()) prefs_model.add_observer(prefs_model.message_config_updated, self._config_updated) # Set a default value self.show_cursor_position(1, 0) self.connect(self.menu_open_recent, SIGNAL('aboutToShow()'), self.build_recent_menu) self.connect(self.commitmsgeditor, SIGNAL('cursorPosition(int,int)'), self.show_cursor_position) self.connect(self, SIGNAL('update'), self._update_callback) self.connect(self, SIGNAL('install_config_actions'), self._install_config_actions) # Install .git-config-defined actions self._config_task = None self.install_config_actions() # Restore saved settings if not qtutils.apply_state(self): self.set_initial_size() self.statusdockwidget.widget().setFocus() # Route command output here Interaction.log_status = self.logwidget.log_status Interaction.log = self.logwidget.log Interaction.log(version.git_version_str() + '\n' + N_('git cola version %s') % version.version()) def set_initial_size(self): self.statuswidget.set_initial_size() self.commitmsgeditor.set_initial_size() # Qt overrides def closeEvent(self, event): """Save state in the settings manager.""" commit_msg = self.commitmsgeditor.commit_message(raw=True) self.model.save_commitmsg(commit_msg) MainWindow.closeEvent(self, event) def build_recent_menu(self): recent = settings.Settings().recent menu = self.menu_open_recent menu.clear() for r in recent: name = os.path.basename(r) directory = os.path.dirname(r) text = '%s %s %s' % (name, unichr(0x2192), directory) menu.addAction(text, cmds.run(cmds.OpenRepo, r)) # Accessors mode = property(lambda self: self.model.mode) def _config_updated(self, source, config, value): if config == prefs.FONTDIFF: # The diff font font = QtGui.QFont() if not font.fromString(value): return self.logwidget.setFont(font) self.diffeditor.setFont(font) self.commitmsgeditor.setFont(font) elif config == prefs.TABWIDTH: # variable-tab-width setting self.diffeditor.set_tabwidth(value) self.commitmsgeditor.set_tabwidth(value) elif config == prefs.LINEBREAK: # enables automatic line breaks self.commitmsgeditor.set_linebreak(value) elif config == prefs.TEXTWIDTH: # text width used for line wrapping self.commitmsgeditor.set_textwidth(value) def install_config_actions(self): """Install .gitconfig-defined actions""" self._config_task = self._start_config_actions_task() def _start_config_actions_task(self): """Do the expensive "get_config_actions()" call in the background""" class ConfigActionsTask(QtCore.QRunnable): def __init__(self, sender): QtCore.QRunnable.__init__(self) self._sender = sender def run(self): names = cfgactions.get_config_actions() self._sender.emit(SIGNAL('install_config_actions'), names) task = ConfigActionsTask(self) QtCore.QThreadPool.globalInstance().start(task) return task def _install_config_actions(self, names): """Install .gitconfig-defined actions""" if not names: return menu = self.actions_menu menu.addSeparator() for name in names: menu.addAction(name, cmds.run(cmds.RunConfigAction, name)) def _update(self): self.emit(SIGNAL('update')) def _update_callback(self): """Update the title with the current branch and directory name.""" alerts = [] branch = self.model.currentbranch curdir = core.getcwd() is_merging = self.model.is_merging is_rebasing = self.model.is_rebasing msg = N_('Repository: %s') % curdir msg += '\n' msg += N_('Branch: %s') % branch if is_rebasing: msg += '\n\n' msg += N_('This repository is currently being rebased.\n' 'Resolve conflicts, commit changes, and run:\n' ' Rebase > Continue') alerts.append(N_('Rebasing')) elif is_merging: msg += '\n\n' msg += N_('This repository is in the middle of a merge.\n' 'Resolve conflicts and commit changes.') alerts.append(N_('Merging')) if self.mode == self.model.mode_amend: alerts.append(N_('Amending')) l = unichr(0xab) r = unichr(0xbb) title = ('%s: %s %s%s' % ( self.model.project, branch, alerts and ((r+' %s '+l+' ') % ', '.join(alerts)) or '', self.model.git.worktree())) self.setWindowTitle(title) self.commitdockwidget.setToolTip(msg) self.commitmsgeditor.set_mode(self.mode) self.update_actions() if not self.model.amending(): # Check if there's a message file in .git/ merge_msg_path = gitcmds.merge_message_path() if merge_msg_path is None: return merge_msg_hash = utils.checksum(merge_msg_path) if merge_msg_hash == self.merge_message_hash: return self.merge_message_hash = merge_msg_hash cmds.do(cmds.LoadCommitMessageFromFile, merge_msg_path) def update_actions(self): is_rebasing = self.model.is_rebasing can_rebase = not is_rebasing self.rebase_start_action.setEnabled(can_rebase) self.rebase_edit_todo_action.setEnabled(is_rebasing) self.rebase_continue_action.setEnabled(is_rebasing) self.rebase_skip_action.setEnabled(is_rebasing) self.rebase_abort_action.setEnabled(is_rebasing) def apply_state(self, state): """Imports data for save/restore""" result = MainWindow.apply_state(self, state) self.lock_layout_action.setChecked(state.get('lock_layout', False)) return result def setup_dockwidget_view_menu(self): # Hotkeys for toggling the dock widgets if utils.is_darwin(): optkey = 'Meta' else: optkey = 'Ctrl' dockwidgets = ( (optkey + '+0', self.logdockwidget), (optkey + '+1', self.commitdockwidget), (optkey + '+2', self.statusdockwidget), (optkey + '+3', self.diffdockwidget), (optkey + '+4', self.actionsdockwidget), ) for shortcut, dockwidget in dockwidgets: # Associate the action with the shortcut toggleview = dockwidget.toggleViewAction() toggleview.setShortcut('Shift+' + shortcut) self.view_menu.addAction(toggleview) def showdock(show, dockwidget=dockwidget): if show: dockwidget.raise_() dockwidget.widget().setFocus() else: self.setFocus() self.addAction(toggleview) connect_action_bool(toggleview, showdock) # Create a new shortcut Shift+ that gives focus toggleview = QtGui.QAction(self) toggleview.setShortcut(shortcut) def focusdock(dockwidget=dockwidget, showdock=showdock): if dockwidget.toggleViewAction().isChecked(): showdock(True) else: dockwidget.toggleViewAction().trigger() self.addAction(toggleview) connect_action(toggleview, focusdock) def _update_diff_opts(self): space_at_eol = self.diff_ignore_space_at_eol_action.isChecked() space_change = self.diff_ignore_space_change_action.isChecked() all_space = self.diff_ignore_all_space_action.isChecked() function_context = self.diff_function_context_action.isChecked() gitcmds.update_diff_overrides(space_at_eol, space_change, all_space, function_context) self.statuswidget.refresh() def preferences(self): return preferences(model=self.prefs_model, parent=self) def save_archive(self): ref = git.rev_parse('HEAD')[STDOUT] shortref = ref[:7] GitArchiveDialog.save(ref, shortref, self) def dragEnterEvent(self, event): """Accepts drops""" MainWindow.dragEnterEvent(self, event) event.acceptProposedAction() def dropEvent(self, event): """Apply dropped patches with git-am""" event.accept() urls = event.mimeData().urls() if not urls: return paths = map(lambda x: unicode(x.path()), urls) patches = [p for p in paths if p.endswith('.patch')] dirs = [p for p in paths if os.path.isdir(p)] dirs.sort() for d in dirs: patches.extend(self._gather_patches(d)) cmds.do(cmds.ApplyPatches, patches) def _gather_patches(self, path): """Find patches in a subdirectory""" patches = [] for root, subdirs, files in os.walk(path): for name in [f for f in files if f.endswith('.patch')]: patches.append(os.path.join(root, name)) return patches def show_cursor_position(self, rows, cols): display = ' %02d:%02d ' % (rows, cols) if cols > 78: display = ('%s' % display) elif cols > 72: display = ('%s' % display) elif cols > 64: display = ('%s' % display) else: display = ('%s' % display) self.position_label.setText(display) def rebase_start(self): branch = guicmds.choose_ref(N_('Select New Upstream'), N_('Interactive Rebase')) if not branch: return None self.model.is_rebasing = True self._update_callback() cmds.do(cmds.Rebase, branch) def rebase_edit_todo(self): cmds.do(cmds.RebaseEditTodo) def rebase_continue(self): cmds.do(cmds.RebaseContinue) def rebase_skip(self): cmds.do(cmds.RebaseSkip) def rebase_abort(self): cmds.do(cmds.RebaseAbort) git-cola-1.9.3/cola/widgets/merge.py000066400000000000000000000165441225156173500173010ustar00rootroot00000000000000from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import cmds from cola import gitcmds from cola import qtutils from cola.i18n import N_ from cola.models import main from cola.widgets import completion from cola.widgets import defs def local_merge(): """Provides a dialog for merging branches""" model = main.model() view = MergeView(model, qtutils.active_window()) view.show() view.raise_() return view def abort_merge(): """Prompts before aborting a merge in progress """ title = N_('Abort Merge...') txt = N_('Aborting the current merge will cause ' '*ALL* uncommitted changes to be lost.\n' 'Recovering uncommitted changes is not possible.') info_txt = N_('Aborting the current merge?') ok_txt = N_('Abort Merge') if qtutils.confirm(title, txt, info_txt, ok_txt, default=False, icon=qtutils.icon('undo.svg')): gitcmds.abort_merge() class MergeView(QtGui.QDialog): """Provides a dialog for merging branches.""" def __init__(self, model, parent=None): QtGui.QDialog.__init__(self, parent) self.model = model self.setWindowModality(Qt.WindowModal) self.resize(700, 400) # Widgets self.title_label = QtGui.QLabel() self.revision_label = QtGui.QLabel() self.revision_label.setText(N_('Revision To Merge')) self.revision = completion.GitRefLineEdit() self.radio_local = QtGui.QRadioButton() self.radio_local.setText(N_('Local Branch')) self.radio_local.setChecked(True) self.radio_remote = QtGui.QRadioButton() self.radio_remote.setText(N_('Tracking Branch')) self.radio_tag = QtGui.QRadioButton() self.radio_tag.setText(N_('Tag')) self.revisions = QtGui.QListWidget() self.revisions.setAlternatingRowColors(True) self.button_viz = QtGui.QPushButton(self) self.button_viz.setText(N_('Visualize')) self.checkbox_squash = QtGui.QCheckBox(self) self.checkbox_squash.setText(N_('Squash')) self.checkbox_commit = QtGui.QCheckBox(self) self.checkbox_commit.setText(N_('Commit')) self.checkbox_commit.setChecked(True) self.checkbox_commit_state = True self.button_cancel = QtGui.QPushButton(self) self.button_cancel.setText(N_('Cancel')) self.button_merge = QtGui.QPushButton(self) self.button_merge.setText(N_('Merge')) # Layouts self.revlayt = QtGui.QHBoxLayout() self.revlayt.addWidget(self.revision_label) self.revlayt.addWidget(self.revision) self.revlayt.addStretch() self.revlayt.addWidget(self.title_label) self.radiolayt = QtGui.QHBoxLayout() self.radiolayt.addWidget(self.radio_local) self.radiolayt.addWidget(self.radio_remote) self.radiolayt.addWidget(self.radio_tag) self.buttonlayt = QtGui.QHBoxLayout() self.buttonlayt.setSpacing(defs.button_spacing) self.buttonlayt.addWidget(self.button_viz) self.buttonlayt.addStretch() self.buttonlayt.addWidget(self.checkbox_squash) self.buttonlayt.addWidget(self.checkbox_commit) self.buttonlayt.addWidget(self.button_cancel) self.buttonlayt.addWidget(self.button_merge) self.mainlayt = QtGui.QVBoxLayout() self.mainlayt.setMargin(defs.margin) self.mainlayt.setSpacing(defs.spacing) self.mainlayt.addLayout(self.radiolayt) self.mainlayt.addWidget(self.revisions) self.mainlayt.addLayout(self.revlayt) self.mainlayt.addLayout(self.buttonlayt) self.setLayout(self.mainlayt) self.revision.setFocus() # Signal/slot connections self.connect(self.revision, SIGNAL('textChanged(QString)'), self.update_title) self.connect(self.revisions, SIGNAL('itemSelectionChanged()'), self.revision_selected) qtutils.connect_button(self.button_cancel, self.reject) qtutils.connect_button(self.checkbox_squash, self.toggle_squash) qtutils.connect_button(self.radio_local, self.update_revisions) qtutils.connect_button(self.radio_remote, self.update_revisions) qtutils.connect_button(self.radio_tag, self.update_revisions) qtutils.connect_button(self.button_merge, self.merge_revision) qtutils.connect_button(self.button_viz, self.viz_revision) # Observer messages model.add_observer(model.message_updated, self.update_all) self.update_all() def update_all(self): """Set the branch name for the window title and label.""" self.update_title() self.update_revisions() def update_title(self, dummy_txt=None): branch = self.model.currentbranch revision = unicode(self.revision.text()) if revision: txt = (N_('Merge "%(revision)s" into "%(branch)s"') % dict(revision=revision, branch=branch)) else: txt = N_('Merge into "%s"') % branch self.title_label.setText(txt) self.setWindowTitle(txt) def toggle_squash(self): """Toggles the commit checkbox based on the squash checkbox.""" if self.checkbox_squash.isChecked(): self.checkbox_commit_state =\ self.checkbox_commit.checkState() self.checkbox_commit.setCheckState(Qt.Unchecked) self.checkbox_commit.setDisabled(True) else: self.checkbox_commit.setDisabled(False) oldstate = self.checkbox_commit_state self.checkbox_commit.setCheckState(oldstate) def update_revisions(self): """Update the revision list whenever a radio button is clicked""" self.revisions.clear() self.revisions.addItems(self.current_revisions()) def revision_selected(self): """Update the revision field when a list item is selected""" revlist = self.current_revisions() widget = self.revisions row, selected = qtutils.selected_row(widget) if selected and row < len(revlist): revision = revlist[row] self.revision.setText(revision) def current_revisions(self): """Retrieve candidate items to merge""" if self.radio_local.isChecked(): return self.model.local_branches elif self.radio_remote.isChecked(): return self.model.remote_branches elif self.radio_tag.isChecked(): return self.model.tags return [] def viz_revision(self): """Launch a gitk-like viewer on the selection revision""" revision = unicode(self.revision.text()) if not revision: qtutils.information(N_('No Revision Specified'), N_('You must specify a revision to view.')) return cmds.do(cmds.VisualizeRevision, revision) def merge_revision(self): """Merge the selected revision/branch""" revision = unicode(self.revision.text()) if not revision: qtutils.information(N_('No Revision Specified'), N_('You must specify a revision to merge.')) return do_commit = self.checkbox_commit.isChecked() squash = self.checkbox_squash.isChecked() cmds.do(cmds.Merge, revision, not(do_commit), squash) self.accept() git-cola-1.9.3/cola/widgets/prefs.py000066400000000000000000000245171225156173500173200ustar00rootroot00000000000000import os from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import SIGNAL from cola import cmds from cola import qtutils from cola import gitcfg from cola.i18n import N_ from cola.models import prefs from cola.models.prefs import PreferencesModel from cola.models.prefs import SetConfig from cola.models.prefs import FONTDIFF from cola.qtutils import diff_font from cola.widgets import defs from cola.widgets import standard def preferences(model=None, parent=None): if model is None: model = PreferencesModel() view = PreferencesView(model, parent=parent) view.show() view.raise_() return view class FormWidget(QtGui.QWidget): def __init__(self, model, parent, source='user'): QtGui.QWidget.__init__(self, parent) self.model = model self.config_to_widget = {} self.widget_to_config = {} self.source = source self.config = gitcfg.instance() self.defaults = {} self.setLayout(QtGui.QFormLayout()) def add_row(self, label, widget): self.layout().addRow(label, widget) def set_config(self, config_dict): self.config_to_widget.update(config_dict) for config, (widget, default) in config_dict.items(): self.widget_to_config[config] = widget self.defaults[config] = default self.connect_widget_to_config(widget, config) def connect_widget_to_config(self, widget, config): if isinstance(widget, QtGui.QSpinBox): widget.connect(widget, SIGNAL('valueChanged(int)'), self._int_config_changed(config)) elif isinstance(widget, QtGui.QCheckBox): widget.connect(widget, SIGNAL('toggled(bool)'), self._bool_config_changed(config)) elif isinstance(widget, QtGui.QLineEdit): widget.connect(widget, SIGNAL('editingFinished()'), self._text_config_changed(config)) widget.connect(widget, SIGNAL('returnPressed()'), self._text_config_changed(config)) def _int_config_changed(self, config): def runner(value): cmds.do(SetConfig, self.model, self.source, config, value) return runner def _bool_config_changed(self, config): def runner(value): cmds.do(SetConfig, self.model, self.source, config, value) return runner def _text_config_changed(self, config): def runner(): value = unicode(self.sender().text()) cmds.do(SetConfig, self.model, self.source, config, value) return runner def update_from_config(self): if self.source == 'user': getter = self.config.get_user else: getter = self.config.get for config, widget in self.widget_to_config.items(): value = getter(config) if value is None: value = self.defaults[config] self.set_widget_value(widget, value) def set_widget_value(self, widget, value): widget.blockSignals(True) if isinstance(widget, QtGui.QSpinBox): widget.setValue(value) elif isinstance(widget, QtGui.QLineEdit): widget.setText(value) elif isinstance(widget, QtGui.QCheckBox): widget.setChecked(value) widget.blockSignals(False) class RepoFormWidget(FormWidget): def __init__(self, model, parent, source): FormWidget.__init__(self, model, parent, source=source) self.name = QtGui.QLineEdit() self.email = QtGui.QLineEdit() self.merge_verbosity = QtGui.QSpinBox() self.merge_verbosity.setMinimum(0) self.merge_verbosity.setMaximum(5) self.merge_verbosity.setProperty('value', QtCore.QVariant(5)) self.diff_context = QtGui.QSpinBox() self.diff_context.setMinimum(2) self.diff_context.setMaximum(99) self.diff_context.setProperty('value', QtCore.QVariant(5)) self.merge_summary = QtGui.QCheckBox() self.merge_summary.setChecked(True) self.merge_diffstat = QtGui.QCheckBox() self.merge_diffstat.setChecked(True) self.display_untracked = QtGui.QCheckBox() self.display_untracked.setChecked(True) self.add_row(N_('User Name'), self.name) self.add_row(N_('Email Address'), self.email) self.add_row(N_('Merge Verbosity'), self.merge_verbosity) self.add_row(N_('Number of Diff Context Lines'), self.diff_context) self.add_row(N_('Summarize Merge Commits'), self.merge_summary) self.add_row(N_('Show Diffstat After Merge'), self.merge_diffstat) self.add_row(N_('Display Untracked Files'), self.display_untracked) self.set_config({ prefs.DIFFCONTEXT: (self.diff_context, 5), prefs.DISPLAY_UNTRACKED: (self.display_untracked, True), prefs.USER_NAME: (self.name, ''), prefs.USER_EMAIL: (self.email, ''), prefs.MERGE_DIFFSTAT: (self.merge_diffstat, True), prefs.MERGE_SUMMARY: (self.merge_summary, True), prefs.MERGE_VERBOSITY: (self.merge_verbosity, 5), }) class SettingsFormWidget(FormWidget): def __init__(self, model, parent): FormWidget.__init__(self, model, parent) self.fixed_font = QtGui.QFontComboBox() self.fixed_font.setFontFilters(QtGui.QFontComboBox.MonospacedFonts) self.font_size = QtGui.QSpinBox() self.font_size.setMinimum(8) self.font_size.setProperty('value', QtCore.QVariant(12)) self._font_str = None self.tabwidth = QtGui.QSpinBox() self.tabwidth.setWrapping(True) self.tabwidth.setMaximum(42) self.textwidth = QtGui.QSpinBox() self.textwidth.setWrapping(True) self.textwidth.setMaximum(150) self.linebreak = QtGui.QCheckBox() self.editor = QtGui.QLineEdit() self.historybrowser = QtGui.QLineEdit() self.difftool = QtGui.QLineEdit() self.mergetool = QtGui.QLineEdit() self.keep_merge_backups = QtGui.QCheckBox() self.save_gui_settings = QtGui.QCheckBox() self.add_row(N_('Fixed-Width Font'), self.fixed_font) self.add_row(N_('Font Size'), self.font_size) self.add_row(N_('Tab Width'), self.tabwidth) self.add_row(N_('Text Width'), self.textwidth) self.add_row(N_('Auto-Wrap Lines'), self.linebreak) self.add_row(N_('Editor'), self.editor) self.add_row(N_('History Browser'), self.historybrowser) self.add_row(N_('Diff Tool'), self.difftool) self.add_row(N_('Merge Tool'), self.mergetool) self.add_row(N_('Keep *.orig Merge Backups'), self.keep_merge_backups) self.add_row(N_('Save GUI Settings'), self.save_gui_settings) self.set_config({ prefs.SAVEWINDOWSETTINGS: (self.save_gui_settings, True), prefs.TABWIDTH: (self.tabwidth, 8), prefs.TEXTWIDTH: (self.textwidth, 72), prefs.LINEBREAK: (self.linebreak, True), prefs.DIFFTOOL: (self.difftool, 'xxdiff'), prefs.EDITOR: (self.editor, os.getenv('VISUAL', 'gvim')), prefs.HISTORY_BROWSER: (self.historybrowser, 'gitk'), prefs.MERGE_KEEPBACKUP: (self.keep_merge_backups, True), prefs.MERGETOOL: (self.mergetool, 'xxdiff'), }) self.connect(self.fixed_font, SIGNAL('currentFontChanged(const QFont &)'), self.current_font_changed) self.connect(self.font_size, SIGNAL('valueChanged(int)'), self.font_size_changed) def update_from_config(self): FormWidget.update_from_config(self) block = self.fixed_font.blockSignals(True) font = diff_font() self.fixed_font.setCurrentFont(font) self.fixed_font.blockSignals(block) block = self.font_size.blockSignals(True) font_size = font.pointSize() self.font_size.setValue(font_size) self.font_size.blockSignals(block) def font_size_changed(self, size): font = self.fixed_font.currentFont() font.setPointSize(size) cmds.do(SetConfig, self.model, 'user', FONTDIFF, unicode(font.toString())) def current_font_changed(self, font): cmds.do(SetConfig, self.model, 'user', FONTDIFF, unicode(font.toString())) class PreferencesView(standard.Dialog): def __init__(self, model, parent=None): standard.Dialog.__init__(self, parent=parent) self.setWindowTitle(N_('Preferences')) self.setWindowModality(QtCore.Qt.WindowModal) self.resize(600, 360) self._tabbar = QtGui.QTabBar() self._tabbar.setDrawBase(False) self._tabbar.addTab(N_('All Repositories')) self._tabbar.addTab(N_('Current Repository')) self._tabbar.addTab(N_('Settings')) self._user_form = RepoFormWidget(model, self, source='user') self._repo_form = RepoFormWidget(model, self, source='repo') self._options_form = SettingsFormWidget(model, self) self._stackedwidget = QtGui.QStackedWidget() self._stackedwidget.addWidget(self._user_form) self._stackedwidget.addWidget(self._repo_form) self._stackedwidget.addWidget(self._options_form) self.close_button = QtGui.QPushButton(self) self.close_button.setText(N_('Close')) self.close_button.setIcon(qtutils.close_icon()) self._button_layt = QtGui.QHBoxLayout() self._button_layt.setMargin(0) self._button_layt.setSpacing(defs.spacing) self._button_layt.addStretch() self._button_layt.addWidget(self.close_button) self._layt = QtGui.QVBoxLayout() self._layt.setMargin(defs.margin) self._layt.setSpacing(defs.spacing) self._layt.addWidget(self._tabbar) self._layt.addWidget(self._stackedwidget) self._layt.addLayout(self._button_layt) self.setLayout(self._layt) self.connect(self._tabbar, SIGNAL('currentChanged(int)'), self._stackedwidget.setCurrentIndex) self.connect(self._stackedwidget, SIGNAL('currentChanged(int)'), self.update_widget) qtutils.connect_button(self.close_button, self.accept) qtutils.add_close_action(self) self.update_widget(0) def update_widget(self, idx): widget = self._stackedwidget.widget(idx) widget.update_from_config() git-cola-1.9.3/cola/widgets/recent.py000066400000000000000000000123571225156173500174600ustar00rootroot00000000000000from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import SIGNAL from cola import cmds from cola import gitcmds from cola import qtutils from cola.i18n import N_ from cola.widgets import defs from cola.widgets import standard from cola.widgets.browse import GitTreeWidget from cola.widgets.browse import GitFileTreeModel def browse_recent(): parent = qtutils.active_window() dialog = RecentFileDialog(parent) dialog.resize(parent.width(), min(parent.height(), 420)) dialog.show() class UpdateFileListThread(QtCore.QThread): def __init__(self, count): QtCore.QThread.__init__(self) self.count = count def run(self): ref = 'HEAD~%d' % self.count filenames = gitcmds.diff_index_filenames(ref) self.emit(SIGNAL('filenames'), filenames) class RecentFileDialog(standard.Dialog): def __init__(self, parent): standard.Dialog.__init__(self, parent) self.setWindowTitle(N_('Recently Modified Files')) self.setWindowModality(QtCore.Qt.WindowModal) count = 8 self.update_thread = UpdateFileListThread(count) self.count = QtGui.QSpinBox() self.count.setMinimum(0) self.count.setMaximum(10000) self.count.setValue(count) self.count.setSuffix(N_(' commits ago')) self.count_label = QtGui.QLabel() self.count_label.setText(N_('Showing changes since')) self.refresh_button = QtGui.QPushButton() self.refresh_button.setText(N_('Refresh')) self.refresh_button.setIcon(qtutils.reload_icon()) self.refresh_button.setEnabled(False) self.tree = GitTreeWidget(None, parent=self) self.tree_model = GitFileTreeModel(self) self.tree.setModel(self.tree_model) self.expand_button = QtGui.QPushButton() self.expand_button.setText(N_('Expand')) self.expand_button.setIcon(qtutils.open_icon()) self.collapse_button = QtGui.QPushButton() self.collapse_button.setText(N_('Collapse')) self.collapse_button.setIcon(qtutils.dir_close_icon()) self.edit_button = QtGui.QPushButton() self.edit_button.setText(N_('Edit')) self.edit_button.setIcon(qtutils.apply_icon()) self.edit_button.setDefault(True) self.edit_button.setEnabled(False) self.close_button = QtGui.QPushButton() self.close_button.setText(N_('Close')) toplayout = QtGui.QHBoxLayout() toplayout.setMargin(0) toplayout.setSpacing(defs.spacing) toplayout.addWidget(self.count_label) toplayout.addWidget(self.count) toplayout.addStretch() toplayout.addWidget(self.refresh_button) btnlayout = QtGui.QHBoxLayout() btnlayout.setMargin(0) btnlayout.setSpacing(defs.spacing) btnlayout.addWidget(self.expand_button) btnlayout.addWidget(self.collapse_button) btnlayout.addStretch() btnlayout.addWidget(self.edit_button) btnlayout.addWidget(self.close_button) layout = QtGui.QVBoxLayout() layout.setMargin(defs.margin) layout.setSpacing(defs.spacing) layout.addLayout(toplayout) layout.addWidget(self.tree) layout.addLayout(btnlayout) self.setLayout(layout) self.connect(self.tree, SIGNAL('selectionChanged()'), self.selection_changed) self.connect(self.tree, SIGNAL('path_chosen'), self.edit_file) self.connect(self.count, SIGNAL('valueChanged(int)'), self.count_changed) self.connect(self.count, SIGNAL('editingFinished()'), self.refresh) self.connect(self.update_thread, SIGNAL('filenames'), self.set_filenames) qtutils.connect_button(self.refresh_button, self.refresh) qtutils.connect_button(self.expand_button, self.tree.expandAll) qtutils.connect_button(self.collapse_button, self.tree.collapseAll) qtutils.connect_button(self.close_button, self.accept) qtutils.connect_button(self.edit_button, self.edit_selected) qtutils.add_action(self, N_('Refresh'), self.refresh, 'Ctrl+R') self.update_thread.start() def edit_selected(self): filenames = self.tree.selected_files() if not filenames: return self.edit_files(filenames) def edit_files(self, filenames): cmds.do(cmds.Edit, filenames) def edit_file(self, filename): self.edit_files([filename]) def refresh(self): self.refresh_button.setEnabled(False) self.count.setEnabled(False) self.tree_model.clear() self.tree.setEnabled(False) self.update_thread.count = self.count.value() self.update_thread.start() def count_changed(self, value): self.refresh_button.setEnabled(True) def selection_changed(self): """Update actions based on the current selection""" filenames = self.tree.selected_files() self.edit_button.setEnabled(bool(filenames)) def set_filenames(self, filenames): self.count.setEnabled(True) self.tree.setEnabled(True) self.tree_model.clear() self.tree_model.add_files(filenames) self.tree.expandAll() self.tree.select_first_file() self.tree.setFocus() git-cola-1.9.3/cola/widgets/remote.py000066400000000000000000000471211225156173500174700ustar00rootroot00000000000000import fnmatch import time from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import gitcmds from cola import qtutils from cola import utils from cola.i18n import N_ from cola.interaction import Interaction from cola.models import main from cola.qtutils import connect_button from cola.widgets import defs from cola.widgets import standard FETCH = 'Fetch' PUSH = 'Push' PULL = 'Pull' def fetch(): return run(Fetch) def push(): return run(Push) def pull(): return run(Pull) def run(RemoteDialog): """Launches fetch/push/pull dialogs.""" # Copy global stuff over to speedup startup model = main.MainModel() global_model = main.model() model.currentbranch = global_model.currentbranch model.local_branches = global_model.local_branches model.remote_branches = global_model.remote_branches model.tags = global_model.tags model.remotes = global_model.remotes parent = qtutils.active_window() view = RemoteDialog(model, parent) view.show() return view def combine(result, existing): if existing is None: return result if type(existing) is tuple: if len(existing) == 3: return (max(existing[0], result[0]), combine(existing[1], result[1]), combine(existing[2], result[2])) else: raise AssertionError('combine() with length %d' % len(existing)) else: if existing and result: return existing + '\n\n' + result elif existing: return existing else: return result class ActionTask(QtCore.QRunnable): def __init__(self, sender, model_action, remote, kwargs): QtCore.QRunnable.__init__(self) self.sender = sender self.model_action = model_action self.remote = remote self.kwargs = kwargs def run(self): """Runs the model action and captures the result""" status, out, err = self.model_action(self.remote, **self.kwargs) self.sender.emit(SIGNAL('action_completed'), self, status, out, err) class ProgressAnimationThread(QtCore.QThread): def __init__(self, txt, parent, timeout=0.25): QtCore.QThread.__init__(self, parent) self.running = False self.txt = txt self.timeout = timeout self.symbols = [ '.. ', '... ', '.... ', '.....', '.... ', '... ' ] self.idx = -1 def next(self): self.idx = (self.idx + 1) % len(self.symbols) return self.txt + self.symbols[self.idx] def stop(self): self.running = False def run(self): self.running = True while self.running: self.emit(SIGNAL('str'), self.next()) time.sleep(self.timeout) class RemoteActionDialog(standard.Dialog): def __init__(self, model, action, parent): """Customizes the dialog based on the remote action """ standard.Dialog.__init__(self, parent=parent) self.model = model self.action = action self.tasks = [] self.filtered_remote_branches = [] self.selected_remotes = [] self.setAttribute(Qt.WA_MacMetalStyle) self.setWindowModality(Qt.WindowModal) self.setWindowTitle(N_(action)) self.progress = QtGui.QProgressDialog(self) self.progress.setFont(qtutils.diff_font()) self.progress.setRange(0, 0) self.progress.setCancelButton(None) self.progress.setWindowTitle(action) self.progress.setWindowModality(Qt.WindowModal) self.progress.setLabelText(N_('Updating') + '.. ') self.progress_thread = ProgressAnimationThread(N_('Updating'), self) self.local_label = QtGui.QLabel() self.local_label.setText(N_('Local Branch')) self.local_branch = QtGui.QLineEdit() self.local_branches = QtGui.QListWidget() self.local_branches.addItems(self.model.local_branches) self.remote_label = QtGui.QLabel() self.remote_label.setText(N_('Remote')) self.remote_name = QtGui.QLineEdit() self.remotes = QtGui.QListWidget() if action == PUSH: self.remotes.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.remotes.addItems(self.model.remotes) self.remote_branch_label = QtGui.QLabel() self.remote_branch_label.setText(N_('Remote Branch')) self.remote_branch = QtGui.QLineEdit() self.remote_branches = QtGui.QListWidget() self.remote_branches.addItems(self.model.remote_branches) self.ffwd_only_checkbox = QtGui.QCheckBox() self.ffwd_only_checkbox.setText(N_('Fast Forward Only ')) self.ffwd_only_checkbox.setChecked(True) self.tags_checkbox = QtGui.QCheckBox() self.tags_checkbox.setText(N_('Include tags ')) self.rebase_checkbox = QtGui.QCheckBox() self.rebase_checkbox.setText(N_('Rebase ')) self.action_button = QtGui.QPushButton() self.action_button.setText(N_(action)) self.action_button.setIcon(qtutils.ok_icon()) self.close_button = QtGui.QPushButton() self.close_button.setText(N_('Close')) self.close_button.setIcon(qtutils.close_icon()) self.local_branch_layout = QtGui.QHBoxLayout() self.local_branch_layout.addWidget(self.local_label) self.local_branch_layout.addWidget(self.local_branch) self.remote_branch_layout = QtGui.QHBoxLayout() self.remote_branch_layout.addWidget(self.remote_label) self.remote_branch_layout.addWidget(self.remote_name) self.remote_branches_layout = QtGui.QHBoxLayout() self.remote_branches_layout.addWidget(self.remote_branch_label) self.remote_branches_layout.addWidget(self.remote_branch) self.options_layout = QtGui.QHBoxLayout() self.options_layout.setSpacing(defs.button_spacing) self.options_layout.addStretch() self.options_layout.addWidget(self.ffwd_only_checkbox) self.options_layout.addWidget(self.tags_checkbox) self.options_layout.addWidget(self.rebase_checkbox) self.options_layout.addWidget(self.action_button) self.options_layout.addWidget(self.close_button) self.main_layout = QtGui.QVBoxLayout() self.main_layout.setMargin(defs.margin) self.main_layout.setSpacing(defs.spacing) self.main_layout.addLayout(self.remote_branch_layout) self.main_layout.addWidget(self.remotes) if action == PUSH: self.main_layout.addLayout(self.local_branch_layout) self.main_layout.addWidget(self.local_branches) self.main_layout.addLayout(self.remote_branches_layout) self.main_layout.addWidget(self.remote_branches) else: # fetch and pull self.main_layout.addLayout(self.remote_branches_layout) self.main_layout.addWidget(self.remote_branches) self.main_layout.addLayout(self.local_branch_layout) self.main_layout.addWidget(self.local_branches) self.main_layout.addLayout(self.options_layout) self.setLayout(self.main_layout) remotes = self.model.remotes if 'origin' in remotes: idx = remotes.index('origin') if self.select_remote(idx): self.remote_name.setText('origin') else: if self.select_first_remote(): self.remote_name.setText(remotes[0]) # Trim the remote list to just the default remote self.update_remotes() self.set_field_defaults() # Setup signals and slots self.connect(self.remotes, SIGNAL('itemSelectionChanged()'), self.update_remotes) self.connect(self.local_branches, SIGNAL('itemSelectionChanged()'), self.update_local_branches) self.connect(self.remote_branches, SIGNAL('itemSelectionChanged()'), self.update_remote_branches) connect_button(self.action_button, self.action_callback) connect_button(self.close_button, self.close) qtutils.add_action(self, N_('Close'), self.close, QtGui.QKeySequence.Close, 'Esc') self.connect(self, SIGNAL('action_completed'), self.action_completed) self.connect(self.progress_thread, SIGNAL('str'), self.update_progress) if action == PULL: self.tags_checkbox.hide() self.ffwd_only_checkbox.hide() self.local_label.hide() self.local_branch.hide() self.local_branches.hide() self.remote_branch.setFocus() else: self.rebase_checkbox.hide() if not qtutils.apply_state(self): self.resize(666, 420) self.remote_name.setFocus() def set_rebase(self, value): self.rebase_checkbox.setChecked(value) def set_field_defaults(self): # Default to "git fetch origin master" action = self.action if action == FETCH or action == PULL: self.local_branch.setText('') self.remote_branch.setText('') return # Select the current branch by default for push if action == PUSH: branch = self.model.currentbranch try: idx = self.model.local_branches.index(branch) except ValueError: return if self.select_local_branch(idx): self.set_local_branch(branch) self.set_remote_branch('') def set_remote_name(self, remote_name): self.remote_name.setText(remote_name) if remote_name: self.remote_name.selectAll() def set_local_branch(self, branch): self.local_branch.setText(branch) if branch: self.local_branch.selectAll() def set_remote_branch(self, branch): self.remote_branch.setText(branch) if branch: self.remote_branch.selectAll() def set_remote_branches(self, branches): self.remote_branches.clear() self.remote_branches.addItems(branches) self.filtered_remote_branches = branches def select_first_remote(self): """Selects the first remote in the list view""" return self.select_remote(0) def select_remote(self, idx): """Selects a remote by index""" item = self.remotes.item(idx) if item: self.remotes.setItemSelected(item, True) self.remotes.setCurrentItem(item) self.set_remote_name(unicode(item.text())) return True else: return False def select_local_branch(self, idx): """Selects a local branch by index in the list view""" item = self.local_branches.item(idx) if not item: return False self.local_branches.setItemSelected(item, True) self.local_branches.setCurrentItem(item) self.local_branch.setText(item.text()) return True def display_remotes(self, widget): """Display the available remotes in a listwidget""" displayed = [] for remote_name in self.model.remotes: url = self.model.remote_url(remote_name, self.action) display = ('%s\t(%s)' % (remote_name, N_('URL: %s') % url)) displayed.append(display) qtutils.set_items(widget,displayed) def update_remotes(self, *rest): """Update the remote name when a remote from the list is selected""" widget = self.remotes remotes = self.model.remotes selection = qtutils.selected_item(widget, remotes) if not selection: self.selected_remotes = [] return self.set_remote_name(selection) self.selected_remotes = qtutils.selected_items(self.remotes, self.model.remotes) all_branches = gitcmds.branch_list(remote=True) branches = [] patterns = [] for remote in self.selected_remotes: pat = remote + '/*' patterns.append(pat) for branch in all_branches: for pat in patterns: if fnmatch.fnmatch(branch, pat): branches.append(branch) break if branches: self.set_remote_branches(branches) else: self.set_remote_branches(all_branches) self.set_remote_branch('') def update_local_branches(self,*rest): """Update the local/remote branch names when a branch is selected""" branches = self.model.local_branches widget = self.local_branches selection = qtutils.selected_item(widget, branches) if not selection: return self.set_local_branch(selection) self.set_remote_branch(selection) def update_remote_branches(self,*rest): """Update the remote branch name when a branch is selected""" widget = self.remote_branches branches = self.filtered_remote_branches selection = qtutils.selected_item(widget, branches) if not selection: return branch = utils.strip_one(selection) if branch == 'HEAD': return self.set_remote_branch(branch) def common_args(self): """Returns git arguments common to fetch/push/pulll""" remote_name = unicode(self.remote_name.text()) local_branch = unicode(self.local_branch.text()) remote_branch = unicode(self.remote_branch.text()) ffwd_only = self.ffwd_only_checkbox.isChecked() rebase = self.rebase_checkbox.isChecked() tags = self.tags_checkbox.isChecked() return (remote_name, { 'local_branch': local_branch, 'remote_branch': remote_branch, 'ffwd': ffwd_only, 'rebase': rebase, 'tags': tags, }) # Actions def action_callback(self): action = self.action if action == FETCH: model_action = self.model.fetch elif action == PUSH: model_action = self.push_to_all else: # if action == PULL: model_action = self.model.pull remote_name = unicode(self.remote_name.text()) if not remote_name: errmsg = N_('No repository selected.') Interaction.log(errmsg) return remote, kwargs = self.common_args() self.selected_remotes = qtutils.selected_items(self.remotes, self.model.remotes) # Check if we're about to create a new branch and warn. remote_branch = unicode(self.remote_branch.text()) local_branch = unicode(self.local_branch.text()) if action == PUSH and not remote_branch: branch = local_branch candidate = '%s/%s' % (remote, branch) if candidate not in self.model.remote_branches: title = N_('Push') args = dict(branch=branch, remote=remote) msg = N_('Branch "%(branch)s" does not exist in "%(remote)s".\n' 'A new remote branch will be published.') % args info_txt= N_('Create a new remote branch?') ok_text = N_('Create Remote Branch') if not qtutils.confirm(title, msg, info_txt, ok_text, default=False, icon=qtutils.git_icon()): return if not self.ffwd_only_checkbox.isChecked(): if action == FETCH: title = N_('Force Fetch?') msg = N_('Non-fast-forward fetch overwrites local history!') info_txt = N_('Force fetching from %s?') % remote ok_text = N_('Force Fetch') elif action == PUSH: title = N_('Force Push?') msg = N_('Non-fast-forward push overwrites published ' 'history!\n(Did you pull first?)') info_txt = N_('Force push to %s?') % remote ok_text = N_('Force Push') else: # pull: shouldn't happen since the controls are hidden msg = "You probably don't want to do this.\n\tContinue?" return if not qtutils.confirm(title, msg, info_txt, ok_text, default=False, icon=qtutils.discard_icon()): return # Disable the GUI by default self.action_button.setEnabled(False) self.close_button.setEnabled(False) QtGui.QApplication.setOverrideCursor(Qt.WaitCursor) # Show a nice progress bar self.progress.show() self.progress_thread.start() # Use a thread to update in the background task = ActionTask(self, model_action, remote, kwargs) self.tasks.append(task) QtCore.QThreadPool.globalInstance().start(task) def update_progress(self, txt): self.progress.setLabelText(txt) def push_to_all(self, dummy_remote, *args, **kwargs): selected_remotes = self.selected_remotes all_results = None for remote in selected_remotes: result = self.model.push(remote, *args, **kwargs) all_results = combine(result, all_results) return all_results def action_completed(self, task, status, out, err): # Grab the results of the action and finish up self.action_button.setEnabled(True) self.close_button.setEnabled(True) QtGui.QApplication.restoreOverrideCursor() self.progress_thread.stop() self.progress_thread.wait() self.progress.close() if task in self.tasks: self.tasks.remove(task) already_up_to_date = N_('Already up-to-date.') if not out: # git fetch --tags --verbose doesn't print anything... out = already_up_to_date command = 'git %s' % self.action.lower() message = (N_('"%(command)s" returned exit status %(status)d') % dict(command=command, status=status)) details = '' if out: details = out if err: details += '\n\n' + err log_message = message if details: log_message += '\n\n' + details Interaction.log(log_message) if status == 0: self.accept() return if self.action == PUSH: message += '\n\n' message += N_('Have you rebased/pulled lately?') Interaction.critical(self.windowTitle(), message=message, details=details) # Use distinct classes so that each saves its own set of preferences class Fetch(RemoteActionDialog): def __init__(self, model, parent): RemoteActionDialog.__init__(self, model, FETCH, parent) class Push(RemoteActionDialog): def __init__(self, model, parent): RemoteActionDialog.__init__(self, model, PUSH, parent) class Pull(RemoteActionDialog): def __init__(self, model, parent): RemoteActionDialog.__init__(self, model, PULL, parent) def apply_state(self, state): RemoteActionDialog.apply_state(self, state) try: rebase = state['rebase'] except KeyError: pass else: self.rebase_checkbox.setChecked(rebase) def export_state(self): state = RemoteActionDialog.export_state(self) state['rebase'] = self.rebase_checkbox.isChecked() return state def done(self, exit_code): qtutils.save_state(self) return RemoteActionDialog.done(self, exit_code) git-cola-1.9.3/cola/widgets/search.py000066400000000000000000000300321225156173500174330ustar00rootroot00000000000000"""A widget for searching git commits""" import os import time import subprocess from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import SIGNAL from cola import gitcmds from cola import utils from cola import qtutils from cola.i18n import N_ from cola.interaction import Interaction from cola.git import git from cola.git import STDOUT from cola.qtutils import connect_button from cola.qtutils import create_toolbutton from cola.qtutils import dir_icon from cola.widgets import defs from cola.widgets import standard from cola.widgets.diff import DiffTextEdit def mkdate(timespec): return '%04d-%02d-%02d' % time.localtime(timespec)[:3] class SearchOptions(object): def __init__(self): self.query = '' self.max_count = 500 self.start_date = '' self.end_date = '' class SearchWidget(standard.Dialog): def __init__(self, parent): standard.Dialog.__init__(self, parent) self.setAttribute(QtCore.Qt.WA_MacMetalStyle) self.setWindowTitle(N_('Search')) self.mode_combo = QtGui.QComboBox() self.browse_button = create_toolbutton(icon=dir_icon(), tooltip=N_('Browse...')) self.query = QtGui.QLineEdit() self.start_date = QtGui.QDateEdit() self.start_date.setCurrentSection(QtGui.QDateTimeEdit.YearSection) self.start_date.setCalendarPopup(True) self.start_date.setDisplayFormat(N_('yyyy-MM-dd')) self.end_date = QtGui.QDateEdit() self.end_date.setCurrentSection(QtGui.QDateTimeEdit.YearSection) self.end_date.setCalendarPopup(True) self.end_date.setDisplayFormat(N_('yyyy-MM-dd')) self.search_button = QtGui.QPushButton() self.search_button.setText(N_('Search')) self.search_button.setDefault(True) self.max_count = QtGui.QSpinBox() self.max_count.setMinimum(5) self.max_count.setMaximum(9995) self.max_count.setSingleStep(5) self.max_count.setValue(500) self.commit_list = QtGui.QListWidget() self.commit_list.setMinimumSize(QtCore.QSize(1, 1)) self.commit_list.setAlternatingRowColors(True) self.commit_list.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) self.commit_text = DiffTextEdit(self, whitespace=False) self.button_export = QtGui.QPushButton() self.button_export.setText(N_('Export Patches')) self.button_cherrypick = QtGui.QPushButton() self.button_cherrypick.setText(N_('Cherry Pick')) self.button_close = QtGui.QPushButton() self.button_close.setText(N_('Close')) self.top_layout = QtGui.QHBoxLayout() self.top_layout.setMargin(0) self.top_layout.setSpacing(defs.button_spacing) self.top_layout.addWidget(self.query) self.top_layout.addWidget(self.start_date) self.top_layout.addWidget(self.end_date) self.top_layout.addWidget(self.browse_button) self.top_layout.addWidget(self.search_button) self.top_layout.addStretch() self.top_layout.addWidget(self.mode_combo) self.top_layout.addWidget(self.max_count) self.splitter = QtGui.QSplitter() self.splitter.setHandleWidth(defs.handle_width) self.splitter.setOrientation(QtCore.Qt.Vertical) self.splitter.setChildrenCollapsible(True) self.splitter.addWidget(self.commit_list) self.splitter.addWidget(self.commit_text) self.bottom_layout = QtGui.QHBoxLayout() self.bottom_layout.setMargin(0) self.bottom_layout.setSpacing(defs.spacing) self.bottom_layout.addWidget(self.button_export) self.bottom_layout.addWidget(self.button_cherrypick) self.bottom_layout.addStretch() self.bottom_layout.addWidget(self.button_close) self.main_layout = QtGui.QVBoxLayout() self.main_layout.setMargin(defs.margin) self.main_layout.setSpacing(defs.spacing) self.main_layout.addLayout(self.top_layout) self.main_layout.addWidget(self.splitter) self.main_layout.addLayout(self.bottom_layout) self.setLayout(self.main_layout) if self.parent(): self.resize(self.parent().width(), self.parent().height()) else: self.resize(720, 500) def search(): """Return a callback to handle various search actions.""" return search_commits(qtutils.active_window()) class SearchEngine(object): def __init__(self, model): self.model = model def rev_args(self): max_count = self.model.max_count return { 'no_color': True, 'max-count': max_count, 'pretty': 'format:%H %aN - %s - %ar', } def common_args(self): return (self.model.query, self.rev_args()) def search(self): if not self.validate(): return return self.results() def validate(self): return len(self.model.query) > 1 def revisions(self, *args, **kwargs): revlist = git.log(*args, **kwargs)[STDOUT] return gitcmds.parse_rev_list(revlist) def results(self): pass class RevisionSearch(SearchEngine): def results(self): query, opts = self.common_args() args = utils.shell_split(query) return self.revisions(all=True, *args, **opts) class PathSearch(SearchEngine): def results(self): query, args = self.common_args() paths = ['--'] + utils.shell_split(query) return self.revisions(all=True, *paths, **args) class MessageSearch(SearchEngine): def results(self): query, kwargs = self.common_args() return self.revisions(all=True, grep=query, **kwargs) class AuthorSearch(SearchEngine): def results(self): query, kwargs = self.common_args() return self.revisions(all=True, author=query, **kwargs) class CommitterSearch(SearchEngine): def results(self): query, kwargs = self.common_args() return self.revisions(all=True, committer=query, **kwargs) class DiffSearch(SearchEngine): def results(self): query, kwargs = self.common_args() return gitcmds.parse_rev_list( git.log('-S'+query, all=True, **kwargs)[STDOUT]) class DateRangeSearch(SearchEngine): def validate(self): return self.model.start_date < self.model.end_date def results(self): kwargs = self.rev_args() start_date = self.model.start_date end_date = self.model.end_date return self.revisions(date='iso', all=True, after=start_date, before=end_date, **kwargs) class Search(SearchWidget): def __init__(self, model, parent): SearchWidget.__init__(self, parent) self.model = model self.EXPR = N_('Search by Expression') self.PATH = N_('Search by Path') self.MESSAGE = N_('Search Commit Messages') self.DIFF = N_('Search Diffs') self.AUTHOR = N_('Search Authors') self.COMMITTER = N_('Search Committers') self.DATE_RANGE = N_('Search Date Range') # Each search type is handled by a distinct SearchEngine subclass self.engines = { self.EXPR: RevisionSearch, self.PATH: PathSearch, self.MESSAGE: MessageSearch, self.DIFF: DiffSearch, self.AUTHOR: AuthorSearch, self.COMMITTER: CommitterSearch, self.DATE_RANGE: DateRangeSearch, } self.modes = (self.EXPR, self.PATH, self.DATE_RANGE, self.DIFF, self.MESSAGE, self.AUTHOR, self.COMMITTER) self.mode_combo.addItems(self.modes) connect_button(self.search_button, self.search_callback) connect_button(self.browse_button, self.browse_callback) connect_button(self.button_export, self.export_patch) connect_button(self.button_cherrypick, self.cherry_pick) connect_button(self.button_close, self.accept) self.connect(self.mode_combo, SIGNAL('currentIndexChanged(int)'), self.mode_index_changed) self.connect(self.commit_list, SIGNAL('itemSelectionChanged()'), self.display) self.set_start_date(mkdate(time.time()-(87640*31))) self.set_end_date(mkdate(time.time()+87640)) self.set_mode(self.EXPR) self.query.setFocus() def mode_index_changed(self, idx): mode = self.mode() self.update_shown_widgets(mode) if mode == self.PATH: self.browse_callback() def set_commit_list(self, commits): widget = self.commit_list widget.clear() widget.addItems(commits) def set_start_date(self, datestr): self.set_date(self.start_date, datestr) def set_end_date(self, datestr): self.set_date(self.end_date, datestr) def set_date(self, widget, datestr): fmt = QtCore.Qt.ISODate date = QtCore.QDate.fromString(datestr, fmt) if date: widget.setDate(date) def set_mode(self, mode): idx = self.modes.index(mode) self.mode_combo.setCurrentIndex(idx) self.update_shown_widgets(mode) def update_shown_widgets(self, mode): date_shown = mode == self.DATE_RANGE browse_shown = mode == self.PATH self.query.setVisible(not date_shown) self.browse_button.setVisible(browse_shown) self.start_date.setVisible(date_shown) self.end_date.setVisible(date_shown) def mode(self): return str(self.mode_combo.currentText()) def search_callback(self, *args): engineclass = self.engines[self.mode()] self.model.query = unicode(self.query.text()) self.model.max_count = self.max_count.value() fmt = QtCore.Qt.ISODate self.model.start_date = str(self.start_date.date().toString(fmt)) self.model.end_date = str(self.end_date.date().toString(fmt)) self.results = engineclass(self.model).search() if self.results: self.display_results() else: self.commit_list.clear() self.commit_text.setText('') def browse_callback(self): paths = QtGui.QFileDialog.getOpenFileNames(self, N_('Choose Path(s)')) if not paths: return filepaths = [] lenprefix = len(os.getcwd()) + 1 for path in map(lambda x: unicode(x), paths): if not path.startswith(os.getcwd()): continue filepaths.append(path[lenprefix:]) query = subprocess.list2cmdline(filepaths) self.query.setText(query) if query: self.search_callback() def display_results(self): commit_list = map(lambda x: x[1], self.results) self.set_commit_list(commit_list) def display(self, *args): widget = self.commit_list row, selected = qtutils.selected_row(widget) if not selected or len(self.results) < row: self.commit_text.setText('') return revision = self.results[row][0] qtutils.set_clipboard(revision) diff = gitcmds.commit_diff(revision) self.commit_text.setText(diff) def export_patch(self): widget = self.commit_list row, selected = qtutils.selected_row(widget) if not selected or len(self.results) < row: return revision = self.results[row][0] Interaction.log_status(*gitcmds.export_patchset(revision, revision)) def cherry_pick(self): widget = self.commit_list row, selected = qtutils.selected_row(widget) if not selected or len(self.results) < row: return revision = self.results[row][0] Interaction.log_status(*git.cherry_pick(revision)) def search_commits(parent): opts = SearchOptions() widget = Search(opts, parent) widget.show() return widget if __name__ == '__main__': import sys app = QtGui.QApplication(sys.argv) search = Search() search.show() sys.exit(app.exec_()) git-cola-1.9.3/cola/widgets/selectcommits.py000066400000000000000000000106511225156173500210460ustar00rootroot00000000000000"""A GUI for selecting commits""" from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import SIGNAL from cola import gitcmds from cola import qtutils from cola.i18n import N_ from cola.interaction import Interaction from cola.widgets import defs from cola.widgets.diff import DiffTextEdit def select_commits(title, revs, summaries, multiselect=True): """Use the SelectCommitsDialog to select commits from a list.""" model = Model(revs, summaries) parent = qtutils.active_window() dialog = SelectCommitsDialog(model, parent, title, multiselect=multiselect) return dialog.select_commits() class Model(object): def __init__(self, revs, summaries): self.revisions = revs self.summaries = summaries def revision_sha1(self, idx): return self.revisions[idx] class SelectCommitsDialog(QtGui.QDialog): def __init__(self, model, parent=None, title=None, multiselect=True, syntax=True): QtGui.QDialog.__init__(self, parent) self.model = model if title: self.setWindowTitle(title) self.commit_list = QtGui.QListWidget() if multiselect: mode = QtGui.QAbstractItemView.ExtendedSelection else: mode = QtGui.QAbstractItemView.SingleSelection self.commit_list.setSelectionMode(mode) self.commit_list.setAlternatingRowColors(True) self.commit_text = DiffTextEdit(self, whitespace=False) self.label = QtGui.QLabel() self.label.setText(N_('Revision Expression:')) self.revision = QtGui.QLineEdit() self.revision.setReadOnly(True) self.select_button = QtGui.QPushButton(N_('Select')) self.select_button.setIcon(qtutils.apply_icon()) self.select_button.setEnabled(False) self.select_button.setDefault(True) self.close_button = QtGui.QPushButton(N_('Close')) # Make the list widget slighty larger self.splitter = QtGui.QSplitter() self.splitter.setOrientation(QtCore.Qt.Vertical) self.splitter.setHandleWidth(defs.handle_width) self.splitter.setSizes([100, 150]) self.splitter.addWidget(self.commit_list) self.splitter.addWidget(self.commit_text) self.input_layout = QtGui.QHBoxLayout() self.input_layout.setMargin(0) self.input_layout.setSpacing(defs.spacing) self.input_layout.addWidget(self.label) self.input_layout.addWidget(self.revision) self.input_layout.addWidget(self.select_button) self.input_layout.addWidget(self.close_button) self.main_layout = QtGui.QVBoxLayout() self.main_layout.setMargin(defs.margin) self.main_layout.setSpacing(defs.margin) self.main_layout.addWidget(self.splitter) self.main_layout.addLayout(self.input_layout) self.setLayout(self.main_layout) self.connect(self.commit_list, SIGNAL('itemSelectionChanged()'), self.commit_sha1_selected) qtutils.connect_button(self.select_button, self.accept) qtutils.connect_button(self.close_button, self.reject) #self.setTabOrder(self.commit_list, self.commit_text) #self.setTabOrder(self.commit_text, self.revision) #self.setTabOrder(self.revision, self.select_button) #self.setTabOrder(self.select_button, self.close_button) #self.setTabOrder(self.close_button, self.commit_list) self.resize(700, 420) def select_commits(self): summaries = self.model.summaries if not summaries: msg = N_('No commits exist in this branch.') Interaction.log(msg) return [] qtutils.set_items(self.commit_list, summaries) self.show() if self.exec_() != QtGui.QDialog.Accepted: return [] revs = self.model.revisions return qtutils.selection_list(self.commit_list, revs) def commit_sha1_selected(self): row, selected = qtutils.selected_row(self.commit_list) self.select_button.setEnabled(selected) if not selected: self.commit_text.setText('') self.revision.setText('') return # Get the sha1 and put it in the revision line sha1 = self.model.revision_sha1(row) self.revision.setText(sha1) self.revision.selectAll() # Display the sha1's commit commit_diff = gitcmds.commit_diff(sha1) self.commit_text.setText(commit_diff) git-cola-1.9.3/cola/widgets/spellcheck.py000066400000000000000000000144421225156173500203120ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- __copyright__ = """ 2012, Peter Norvig (http://norvig.com/spell-correct.html) 2013, David Aguilar """ import collections import re import sys from PyQt4.Qt import QAction from PyQt4.Qt import QApplication from PyQt4.Qt import QEvent from PyQt4.Qt import QMenu from PyQt4.Qt import QMouseEvent from PyQt4.Qt import QSyntaxHighlighter from PyQt4.Qt import QTextCharFormat from PyQt4.Qt import QTextCursor from PyQt4.Qt import Qt from PyQt4.QtCore import SIGNAL from cola.compat import set from cola.i18n import N_ from cola.widgets.text import HintedTextEdit alphabet = 'abcdefghijklmnopqrstuvwxyz' def train(features, model): for f in features: model[f] += 1 return model def edits1(word): splits = [(word[:i], word[i:]) for i in range(len(word) + 1)] deletes = [a + b[1:] for a, b in splits if b] transposes = [a + b[1] + b[0] + b[2:] for a, b in splits if len(b)>1] replaces = [a + c + b[1:] for a, b in splits for c in alphabet if b] inserts = [a + c + b for a, b in splits for c in alphabet] return set(deletes + transposes + replaces + inserts) def known_edits2(word, words): return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in words) def known(word, words): return set(w for w in word if w in words) def suggest(word, words): candidates = (known([word], words) or known(edits1(word), words) or known_edits2(word, words) or [word]) return candidates def correct(word, words): candidates = suggest(word, words) return max(candidates, key=words.get) class NorvigSpellCheck(object): def __init__(self): self.words = collections.defaultdict(lambda: 1) self.extra_words = set() self.initialized = False def init(self): if self.initialized: return self.initialized = True train(self.read(), self.words) train(self.extra_words, self.words) def add_word(self, word): self.extra_words.add(word) def suggest(self, word): self.init() return suggest(word, self.words) def check(self, word): self.init() return word.replace('.', '') in self.words def read(self): for (path, title) in (('/usr/share/dict/words', True), ('/usr/share/dict/propernames', False)): try: with open(path, 'r') as f: for word in f: yield word.rstrip() if title: yield word.rstrip().title() except IOError: pass raise StopIteration class SpellCheckTextEdit(HintedTextEdit): def __init__(self, hint, parent=None): HintedTextEdit.__init__(self, hint, parent) # Default dictionary based on the current locale. self.spellcheck = NorvigSpellCheck() self.highlighter = Highlighter(self.document(), self.spellcheck) def mousePressEvent(self, event): if event.button() == Qt.RightButton: # Rewrite the mouse event to a left button event so the cursor is # moved to the location of the pointer. event = QMouseEvent(QEvent.MouseButtonPress, event.pos(), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier) HintedTextEdit.mousePressEvent(self, event) def context_menu(self): popup_menu = HintedTextEdit.createStandardContextMenu(self) # Select the word under the cursor. cursor = self.textCursor() cursor.select(QTextCursor.WordUnderCursor) self.setTextCursor(cursor) # Check if the selected word is misspelled and offer spelling # suggestions if it is. spell_menu = None if self.textCursor().hasSelection(): text = unicode(self.textCursor().selectedText()) if not self.spellcheck.check(text): spell_menu = QMenu(N_('Spelling Suggestions')) for word in self.spellcheck.suggest(text): action = SpellAction(word, spell_menu) self.connect(action, SIGNAL('correct'), self.correct) spell_menu.addAction(action) # Only add the spelling suggests to the menu if there are # suggestions. if len(spell_menu.actions()) > 0: popup_menu.addSeparator() popup_menu.addMenu(spell_menu) return popup_menu, spell_menu def contextMenuEvent(self, event): popup_menu = self.context_menu() popup_menu.exec_(self.mapToGlobal(event.pos())) def correct(self, word): """Replaces the selected text with word.""" cursor = self.textCursor() cursor.beginEditBlock() cursor.removeSelectedText() cursor.insertText(word) cursor.endEditBlock() class Highlighter(QSyntaxHighlighter): WORDS = "(?iu)[\w']+" def __init__(self, doc, spellcheck): QSyntaxHighlighter.__init__(self, doc) self.spellcheck = spellcheck self.enabled = False def enable(self, enabled): self.enabled = enabled self.rehighlight() def highlightBlock(self, text): if not self.enabled: return text = unicode(text) fmt = QTextCharFormat() fmt.setUnderlineColor(Qt.red) fmt.setUnderlineStyle(QTextCharFormat.SpellCheckUnderline) for word_object in re.finditer(self.WORDS, text): if not self.spellcheck.check(word_object.group()): self.setFormat(word_object.start(), word_object.end() - word_object.start(), fmt) class SpellAction(QAction): """QAction that returns the text in a signal. """ def __init__(self, *args): QAction.__init__(self, *args) self.connect(self, SIGNAL('triggered()'), self.correct) def correct(self): self.emit(SIGNAL('correct'), unicode(self.text())) def main(args=sys.argv): app = QApplication(args) widget = SpellCheckTextEdit('Type here') widget.show() widget.raise_() return app.exec_() if __name__ == '__main__': sys.exit(main()) git-cola-1.9.3/cola/widgets/standard.py000066400000000000000000000201761225156173500177760ustar00rootroot00000000000000from PyQt4 import QtGui from PyQt4 import QtCore from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from PyQt4.QtGui import QDockWidget from cola import core from cola import qtcompat from cola import qtutils from cola import settings class WidgetMixin(object): # not exported def __init__(self, QtClass): self.QtClass = QtClass # Mix-in for standard view operations def show(self): """Automatically centers dialogs""" if self.parent(): left = self.parent().x() width = self.parent().width() center_x = left + width/2 x = center_x - self.width()/2 y = self.parent().y() self.move(x, y) # Call the base Qt show() return self.QtClass.show(self) def name(self): """Returns the name of the view class""" return self.__class__.__name__.lower() def apply_state(self, state): """Imports data for view save/restore""" result = True try: self.resize(state['width'], state['height']) except: result = False try: self.move(state['x'], state['y']) except: result = False try: if state['maximized']: self.showMaximized() except: result = False return result def export_state(self): """Exports data for view save/restore""" state = self.windowState() maximized = bool(state & Qt.WindowMaximized) return { 'x': self.x(), 'y': self.y(), 'width': self.width(), 'height': self.height(), 'maximized': maximized, } def closeEvent(self, event): s = settings.Settings() s.add_recent(core.getcwd()) qtutils.save_state(self, handler=s) self.QtClass.closeEvent(self, event) class MainWindowMixin(WidgetMixin): def __init__(self, QtClass): WidgetMixin.__init__(self, QtClass) # Dockwidget options self.dockwidgets = [] self.lock_layout = False qtcompat.set_common_dock_options(self) self.widget_version = 0 def export_state(self): """Exports data for save/restore""" state = WidgetMixin.export_state(self) state['lock_layout'] = self.lock_layout return qtutils.export_window_state(self, state, self.widget_version) def apply_state(self, state): WidgetMixin.apply_state(self, state) result = qtutils.apply_window_state(self, state, self.widget_version) self.lock_layout = state.get('lock_layout', self.lock_layout) self.update_dockwidget_lock_state() self.update_dockwidget_tooltips() return result def set_lock_layout(self, lock_layout): self.lock_layout = lock_layout self.update_dockwidget_lock_state() def update_dockwidget_lock_state(self): if self.lock_layout: features = (QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable) else: features = (QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) for widget in self.dockwidgets: widget.titleBarWidget().update_tooltips() widget.setFeatures(features) def update_dockwidget_tooltips(self): for widget in self.dockwidgets: widget.titleBarWidget().update_tooltips() class TreeMixin(object): def __init__(self, QtClass): self.QtClass = QtClass self.setAlternatingRowColors(True) self.setUniformRowHeights(True) self.setAllColumnsShowFocus(True) self.setAnimated(True) self.setRootIsDecorated(False) def keyPressEvent(self, event): """ Make LeftArrow to work on non-directories. When LeftArrow is pressed on a file entry or an unexpanded directory, then move the current index to the parent directory. This simplifies navigation using the keyboard. For power-users, we support Vim keybindings ;-P """ # Check whether the item is expanded before calling the base class # keyPressEvent otherwise we end up collapsing and changing the # current index in one shot, which we don't want to do. index = self.currentIndex() was_expanded = self.isExpanded(index) was_collapsed = not was_expanded # Vim keybindings... # Rewrite the event before marshalling to QTreeView.event() key = event.key() # Remap 'H' to 'Left' if key == Qt.Key_H: event = QtGui.QKeyEvent(event.type(), Qt.Key_Left, event.modifiers()) # Remap 'J' to 'Down' elif key == Qt.Key_J: event = QtGui.QKeyEvent(event.type(), Qt.Key_Down, event.modifiers()) # Remap 'K' to 'Up' elif key == Qt.Key_K: event = QtGui.QKeyEvent(event.type(), Qt.Key_Up, event.modifiers()) # Remap 'L' to 'Right' elif key == Qt.Key_L: event = QtGui.QKeyEvent(event.type(), Qt.Key_Right, event.modifiers()) # Re-read the event key to take the remappings into account key = event.key() result = self.QtClass.keyPressEvent(self, event) # Let others hook in here before we change the indexes self.emit(SIGNAL('indexAboutToChange()')) # Automatically select the first entry when expanding a directory if (key == Qt.Key_Right and was_collapsed and self.isExpanded(index)): index = self.moveCursor(self.MoveDown, event.modifiers()) self.setCurrentIndex(index) # Process non-root entries with valid parents only. elif key == Qt.Key_Left and index.parent().isValid(): # File entries have rowCount() == 0 if self.model().itemFromIndex(index).rowCount() == 0: self.setCurrentIndex(index.parent()) # Otherwise, do this for collapsed directories only elif was_collapsed: self.setCurrentIndex(index.parent()) # If it's a movement key ensure we have a selection elif key in (Qt.Key_Left, Qt.Key_Up, Qt.Key_Right, Qt.Key_Down): # Try to select the first item if the model index is invalid item = self.selected_item() if item is None or not index.isValid(): index = self.model().index(0, 0, QtCore.QModelIndex()) if index.isValid(): self.setCurrentIndex(index) return result def items(self): root = self.invisibleRootItem() child = root.child count = root.childCount() return [child(i) for i in range(count)] def selected_items(self): """Return all selected items""" if hasattr(self, 'selectedItems'): return self.selectedItems() else: item_from_index = self.model().itemFromIndex return [item_from_index(i) for i in self.selectedIndexes()] def selected_item(self): """Return the first selected item""" selected_items = self.selected_items() if not selected_items: return None return selected_items[0] def bind_mixin(Mixin, QtClass): """Construct a class which composes the Mixin over the Qt class""" class BoundMixin(Mixin, QtClass): """A concrete class tied to a specific Qt class""" def __init__(self, parent=None): QtClass.__init__(self, parent) Mixin.__init__(self, QtClass) self.Mixin = BoundMixin return BoundMixin Widget = bind_mixin(WidgetMixin, QtGui.QWidget) Dialog = bind_mixin(WidgetMixin, QtGui.QDialog) MainWindow = bind_mixin(MainWindowMixin, QtGui.QMainWindow) TreeView = bind_mixin(TreeMixin, QtGui.QTreeView) TreeWidget = bind_mixin(TreeMixin, QtGui.QTreeWidget) git-cola-1.9.3/cola/widgets/startup.py000066400000000000000000000112511225156173500176720ustar00rootroot00000000000000""" Provides the git-cola startup dialog The startup dialog is presented when no repositories can be found at startup. """ import os from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import guicmds from cola import settings from cola import qtutils from cola.i18n import N_ from cola.widgets import defs class StartupDialog(QtGui.QDialog): """Provides a GUI to Open or Clone a git repository.""" def __init__(self, parent=None): QtGui.QDialog.__init__(self, parent) self.setWindowTitle(N_('git-cola')) self._gitdir = None self._layt = QtGui.QHBoxLayout() self._layt.setMargin(defs.margin) self._layt.setSpacing(defs.spacing) self._new_btn = QtGui.QPushButton(N_('New...')) self._new_btn.setIcon(qtutils.new_icon()) self._open_btn = QtGui.QPushButton(N_('Open...')) self._open_btn.setIcon(qtutils.open_icon()) self._clone_btn = QtGui.QPushButton(N_('Clone...')) self._clone_btn.setIcon(qtutils.git_icon()) self._close_btn = QtGui.QPushButton(N_('Close')) self._layt.addWidget(self._open_btn) self._layt.addWidget(self._clone_btn) self._layt.addWidget(self._new_btn) self._layt.addStretch() self._layt.addWidget(self._close_btn) self.model = settings.Settings() self._vlayt = QtGui.QVBoxLayout() self._vlayt.setMargin(defs.margin) self._vlayt.setSpacing(defs.margin) self._bookmark_label = QtGui.QLabel(N_('Select Repository...')) self._bookmark_label.setAlignment(Qt.AlignCenter) self._bookmark_model = QtGui.QStandardItemModel() item = QtGui.QStandardItem(N_('Select manually...')) item.setEditable(False) self._bookmark_model.appendRow(item) added = set() all_repos = self.model.bookmarks + self.model.recent for repo in all_repos: if repo in added: continue added.add(repo) item = QtGui.QStandardItem(repo) item.setEditable(False) self._bookmark_model.appendRow(item) selection_mode = QtGui.QAbstractItemView.SingleSelection self._bookmark_list = QtGui.QListView() self._bookmark_list.setSelectionMode(selection_mode) self._bookmark_list.setAlternatingRowColors(True) self._bookmark_list.setModel(self._bookmark_model) if not all_repos: self._bookmark_label.setMinimumHeight(1) self._bookmark_list.setMinimumHeight(1) self._bookmark_label.hide() self._bookmark_list.hide() self._vlayt.addWidget(self._bookmark_label) self._vlayt.addWidget(self._bookmark_list) self._vlayt.addLayout(self._layt) self.setLayout(self._vlayt) qtutils.connect_button(self._open_btn, self._open) qtutils.connect_button(self._clone_btn, self._clone) qtutils.connect_button(self._new_btn, self._new) qtutils.connect_button(self._close_btn, self.reject) self.connect(self._bookmark_list, SIGNAL('activated(const QModelIndex &)'), self._open_bookmark) def find_git_repo(self): """ Return a path to a git repository This is the entry point for external callers. This method finds a git repository by allowing the user to browse to one on the filesystem or by creating a new one with git-clone. """ self.show() self.raise_() if self.exec_() == QtGui.QDialog.Accepted: return self._gitdir return None def _open(self): self._gitdir = self._get_selected_bookmark() if not self._gitdir: self._gitdir = qtutils.opendir_dialog(N_('Open Git Repository...'), os.getcwd()) if self._gitdir: self.accept() def _clone(self): gitdir = guicmds.clone_repo(spawn=False) if gitdir: self._gitdir = gitdir self.accept() def _new(self): gitdir = guicmds.new_repo() if gitdir: self._gitdir = gitdir self.accept() def _open_bookmark(self, index): if(index.row() == 0): self._open() else: self._gitdir = unicode(self._bookmark_model.data(index).toString()) if self._gitdir: self.accept() def _get_selected_bookmark(self): selected = self._bookmark_list.selectedIndexes() if(len(selected) > 0 and selected[0].row() != 0): return unicode(self._bookmark_model.data(selected[0]).toString()) return None git-cola-1.9.3/cola/widgets/stash.py000066400000000000000000000165151225156173500173220ustar00rootroot00000000000000"""Provides the StashView dialog.""" from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import SIGNAL from cola import cmds from cola import qtutils from cola import utils from cola.i18n import N_ from cola.models.stash import StashModel from cola.models.stash import ApplyStash from cola.models.stash import SaveStash from cola.models.stash import DropStash from cola.widgets import defs from cola.widgets.diff import DiffTextEdit from cola.widgets.standard import Dialog def stash(): """Launches a stash dialog using the provided model + view """ model = StashModel() view = StashView(model, qtutils.active_window()) view.show() view.raise_() return view class StashView(Dialog): def __init__(self, model, parent=None): Dialog.__init__(self, parent=parent) self.setAttribute(QtCore.Qt.WA_MacMetalStyle) self.model = model self.stashes = [] self.revids = [] self.names = [] self.setWindowModality(QtCore.Qt.WindowModal) self.setWindowTitle(N_('Stash')) if parent: self.resize(parent.width(), 420) else: self.resize(700, 420) self.stash_list = QtGui.QListWidget(self) self.stash_text = DiffTextEdit(self) self.button_apply =\ self.toolbutton(N_('Apply'), N_('Apply the selected stash'), qtutils.apply_icon()) self.button_save =\ self.toolbutton(N_('Save'), N_('Save modified state to new stash'), qtutils.save_icon()) self.button_drop = \ self.toolbutton(N_('Drop'), N_('Drop the selected stash'), qtutils.discard_icon()) self.button_close = \ self.pushbutton(N_('Close'), N_('Close'), qtutils.close_icon()) self.keep_index = QtGui.QCheckBox(self) self.keep_index.setText(N_('Keep Index')) self.keep_index.setChecked(True) # Arrange layouts self.main_layt = QtGui.QVBoxLayout() self.main_layt.setMargin(defs.margin) self.main_layt.setSpacing(defs.spacing) self.btn_layt = QtGui.QHBoxLayout() self.btn_layt.setMargin(0) self.btn_layt.setSpacing(defs.spacing) self.splitter = QtGui.QSplitter() self.splitter.setHandleWidth(defs.handle_width) self.splitter.setOrientation(QtCore.Qt.Horizontal) self.splitter.setChildrenCollapsible(True) self.splitter.setStretchFactor(0, 1) self.splitter.setStretchFactor(1, 1) self.splitter.insertWidget(0, self.stash_list) self.splitter.insertWidget(1, self.stash_text) self.btn_layt.addWidget(self.button_save) self.btn_layt.addWidget(self.button_apply) self.btn_layt.addWidget(self.button_drop) self.btn_layt.addWidget(self.keep_index) self.btn_layt.addStretch() self.btn_layt.addWidget(self.button_close) self.main_layt.addWidget(self.splitter) self.main_layt.addLayout(self.btn_layt) self.setLayout(self.main_layt) self.splitter.setSizes([self.width()/3, self.width()*2/3]) self.update_from_model() self.update_actions() self.setTabOrder(self.button_save, self.button_apply) self.setTabOrder(self.button_apply, self.button_drop) self.setTabOrder(self.button_drop, self.keep_index) self.setTabOrder(self.keep_index, self.button_close) self.connect(self.stash_list, SIGNAL('itemSelectionChanged()'), self.item_selected) qtutils.connect_button(self.button_apply, self.stash_apply) qtutils.connect_button(self.button_save, self.stash_save) qtutils.connect_button(self.button_drop, self.stash_drop) qtutils.connect_button(self.button_close, self.close) def close(self): self.accept() cmds.do(cmds.Rescan) def toolbutton(self, text, tooltip, icon): return qtutils.create_toolbutton(text=text, tooltip=tooltip, icon=icon) def pushbutton(self, text, tooltip, icon): btn = QtGui.QPushButton(self) btn.setText(text) btn.setToolTip(tooltip) btn.setIcon(icon) return btn def selected_stash(self): """Returns the stash name of the currently selected stash """ list_widget = self.stash_list stash_list = self.revids return qtutils.selected_item(list_widget, stash_list) def selected_name(self): list_widget = self.stash_list stash_list = self.names return qtutils.selected_item(list_widget, stash_list) def item_selected(self): """Shows the current stash in the main view.""" self.update_actions() selection = self.selected_stash() if not selection: return diff_text = self.model.stash_diff(selection) self.stash_text.setPlainText(diff_text) def update_actions(self): has_changes = self.model.has_stashable_changes() has_stash = bool(self.selected_stash()) self.button_save.setEnabled(has_changes) self.button_apply.setEnabled(has_stash) self.button_drop.setEnabled(has_stash) def update_from_model(self): """Initiates git queries on the model and updates the view """ stashes, revids, names = self.model.stash_info() self.stashes = stashes self.revids = revids self.names = names self.stash_list.clear() self.stash_list.addItems(self.stashes) def stash_apply(self): """Applies the currently selected stash """ selection = self.selected_stash() if not selection: return index = self.keep_index.isChecked() cmds.do(ApplyStash, selection, index) self.accept() cmds.do(cmds.Rescan) def stash_save(self): """Saves the worktree in a stash This prompts the user for a stash name and creates a git stash named accordingly. """ stash_name, ok = qtutils.prompt(N_('Save Stash'), N_('Enter a name for the stash')) if not ok or not stash_name: return # Sanitize the stash name stash_name = utils.sanitize(stash_name) if stash_name in self.names: qtutils.critical(N_('Error: Stash exists'), N_('A stash named "%s" already exists') % stash_name) return keep_index = self.keep_index.isChecked() cmds.do(SaveStash, stash_name, keep_index) self.accept() cmds.do(cmds.Rescan) def stash_drop(self): """Drops the currently selected stash """ selection = self.selected_stash() name = self.selected_name() if not selection: return if not qtutils.confirm(N_('Drop Stash?'), N_('Recovering a dropped stash is not possible.'), N_('Drop the "%s" stash?') % name, N_('Drop Stash'), default=True, icon=qtutils.discard_icon()): return cmds.do(DropStash, selection) self.update_from_model() self.stash_text.setPlainText('') git-cola-1.9.3/cola/widgets/status.py000066400000000000000000000761011225156173500175200ustar00rootroot00000000000000import os import subprocess import itertools from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL from cola import cmds from cola import core from cola import qtutils from cola import utils from cola.compat import set from cola.i18n import N_ from cola.interaction import Interaction from cola.models import main from cola.models import selection class StatusWidget(QtGui.QWidget): """ Provides a git-status-like repository widget. This widget observes the main model and broadcasts Qt signals. """ def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.layout = QtGui.QVBoxLayout(self) self.setLayout(self.layout) self.tree = StatusTreeWidget(self) self.layout.addWidget(self.tree) self.layout.setContentsMargins(0, 0, 0, 0) def set_initial_size(self): self.setMaximumWidth(222) QtCore.QTimer.singleShot(1, self.restore_size) def restore_size(self): self.setMaximumWidth(2 ** 13) def refresh(self): self.tree.show_selection() class StatusTreeWidget(QtGui.QTreeWidget): # Item categories idx_header = -1 idx_staged = 0 idx_unmerged = 1 idx_modified = 2 idx_untracked = 3 idx_end = 4 # Read-only access to the mode state mode = property(lambda self: self.m.mode) def __init__(self, parent): QtGui.QTreeWidget.__init__(self, parent) self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.headerItem().setHidden(True) self.setAllColumnsShowFocus(True) self.setSortingEnabled(False) self.setUniformRowHeights(True) self.setAnimated(True) self.setRootIsDecorated(False) self.setIndentation(0) self.add_item(N_('Staged'), hide=True) self.add_item(N_('Unmerged'), hide=True) self.add_item(N_('Modified'), hide=True) self.add_item(N_('Untracked'), hide=True) # Used to restore the selection self.old_scroll = None self.old_selection = None self.old_contents = None self.old_current_item = None self.expanded_items = set() self.process_selection = qtutils.add_action(self, N_('Stage / Unstage'), self._process_selection, cmds.Stage.SHORTCUT) self.launch_difftool = qtutils.add_action(self, cmds.LaunchDifftool.name(), cmds.run(cmds.LaunchDifftool), cmds.LaunchDifftool.SHORTCUT) self.launch_difftool.setIcon(qtutils.icon('git.svg')) self.launch_editor = qtutils.add_action(self, cmds.LaunchEditor.name(), cmds.run(cmds.LaunchEditor), cmds.LaunchEditor.SHORTCUT, 'Return', 'Enter') self.launch_editor.setIcon(qtutils.options_icon()) if not utils.is_win32(): self.open_using_default_app = qtutils.add_action(self, cmds.OpenDefaultApp.name(), self._open_using_default_app, cmds.OpenDefaultApp.SHORTCUT) self.open_using_default_app.setIcon(qtutils.file_icon()) self.open_parent_dir = qtutils.add_action(self, cmds.OpenParentDir.name(), self._open_parent_dir, cmds.OpenParentDir.SHORTCUT) self.open_parent_dir.setIcon(qtutils.open_file_icon()) self.up = qtutils.add_action(self, N_('Move Up'), self.move_up, Qt.Key_K) self.down = qtutils.add_action(self, N_('Move Down'), self.move_down, Qt.Key_J) self.copy_path_action = qtutils.add_action(self, N_('Copy Path to Clipboard'), self.copy_path, QtGui.QKeySequence.Copy) self.copy_path_action.setIcon(qtutils.theme_icon('edit-copy.svg')) self.connect(self, SIGNAL('about_to_update'), self._about_to_update) self.connect(self, SIGNAL('updated'), self._updated) self.m = main.model() self.m.add_observer(self.m.message_about_to_update, self.about_to_update) self.m.add_observer(self.m.message_updated, self.updated) self.connect(self, SIGNAL('itemSelectionChanged()'), self.show_selection) self.connect(self, SIGNAL('itemDoubleClicked(QTreeWidgetItem*,int)'), self.double_clicked) self.connect(self, SIGNAL('itemCollapsed(QTreeWidgetItem*)'), lambda x: self.update_column_widths()) self.connect(self, SIGNAL('itemExpanded(QTreeWidgetItem*)'), lambda x: self.update_column_widths()) def add_item(self, txt, hide=False): """Create a new top-level item in the status tree.""" # TODO no icon font = self.font() font.setBold(True) font.setCapitalization(QtGui.QFont.SmallCaps) item = QtGui.QTreeWidgetItem(self) item.setFont(0, font) item.setText(0, txt) if hide: self.setItemHidden(item, True) def restore_selection(self): if not self.old_selection or not self.old_contents: return old_c = self.old_contents old_s = self.old_selection new_c = self.contents() def mkselect(lst, widget_getter): def select(item, current=False): idx = lst.index(item) widget = widget_getter(idx) if current: self.setCurrentItem(widget) self.setItemSelected(widget, True) return select select_staged = mkselect(new_c.staged, self.staged_item) select_unmerged = mkselect(new_c.unmerged, self.unmerged_item) select_modified = mkselect(new_c.modified, self.modified_item) select_untracked = mkselect(new_c.untracked, self.untracked_item) saved_selection = [ (set(new_c.staged), old_c.staged, set(old_s.staged), select_staged), (set(new_c.unmerged), old_c.unmerged, set(old_s.unmerged), select_unmerged), (set(new_c.modified), old_c.modified, set(old_s.modified), select_modified), (set(new_c.untracked), old_c.untracked, set(old_s.untracked), select_untracked), ] # Restore the current item if self.old_current_item: category, idx = self.old_current_item if category == self.idx_header: item = self.invisibleRootItem().child(idx) if item is not None: self.setCurrentItem(item) self.setItemSelected(item, True) return # Reselect the current item selection_info = saved_selection[category] new = selection_info[0] old = selection_info[1] reselect = selection_info[3] try: item = old[idx] except: return if item in new: reselect(item, current=True) # Restore selection # When reselecting we only care that the items are selected; # we do not need to rerun the callbacks which were triggered # above. Block signals to skip the callbacks. self.blockSignals(True) for (new, old, selection, reselect) in saved_selection: for item in selection: if item in new: reselect(item, current=False) self.blockSignals(False) for (new, old, selection, reselect) in saved_selection: # When modified is staged, select the next modified item # When unmerged is staged, select the next unmerged item # When unstaging, select the next staged item # When staging untracked files, select the next untracked item if len(new) >= len(old): # The list did not shrink so it is not one of these cases. continue for item in selection: # The item still exists so ignore it if item in new or item not in old: continue # The item no longer exists in this list so search for # its nearest neighbors and select them instead. idx = old.index(item) for j in itertools.chain(old[idx+1:], reversed(old[:idx])): if j in new: reselect(j, current=True) return def restore_scrollbar(self): vscroll = self.verticalScrollBar() if vscroll and self.old_scroll is not None: vscroll.setValue(self.old_scroll) self.old_scroll = None def staged_item(self, itemidx): return self._subtree_item(self.idx_staged, itemidx) def modified_item(self, itemidx): return self._subtree_item(self.idx_modified, itemidx) def unmerged_item(self, itemidx): return self._subtree_item(self.idx_unmerged, itemidx) def untracked_item(self, itemidx): return self._subtree_item(self.idx_untracked, itemidx) def unstaged_item(self, itemidx): # is it modified? item = self.topLevelItem(self.idx_modified) count = item.childCount() if itemidx < count: return item.child(itemidx) # is it unmerged? item = self.topLevelItem(self.idx_unmerged) count += item.childCount() if itemidx < count: return item.child(itemidx) # is it untracked? item = self.topLevelItem(self.idx_untracked) count += item.childCount() if itemidx < count: return item.child(itemidx) # Nope.. return None def _subtree_item(self, idx, itemidx): parent = self.topLevelItem(idx) return parent.child(itemidx) def about_to_update(self): self.emit(SIGNAL('about_to_update')) def _about_to_update(self): self.save_selection() self.save_scrollbar() def save_scrollbar(self): vscroll = self.verticalScrollBar() if vscroll: self.old_scroll = vscroll.value() else: self.old_scroll = None def current_item(self): s = self.selected_indexes() if not s: return None current = self.currentItem() if not current: return None idx = self.indexFromItem(current, 0) if idx.parent().isValid(): parent_idx = idx.parent() entry = (parent_idx.row(), idx.row()) else: entry = (self.idx_header, idx.row()) return entry def save_selection(self): self.old_contents = self.contents() self.old_selection = self.selection() self.old_current_item = self.current_item() def updated(self): """Update display from model data.""" self.emit(SIGNAL('updated')) def _updated(self): self.set_staged(self.m.staged) self.set_modified(self.m.modified) self.set_unmerged(self.m.unmerged) self.set_untracked(self.m.untracked) self.restore_selection() self.restore_scrollbar() self.update_column_widths() def set_staged(self, items): """Adds items to the 'Staged' subtree.""" self._set_subtree(items, self.idx_staged, staged=True, check=not self.m.amending()) def set_modified(self, items): """Adds items to the 'Modified' subtree.""" self._set_subtree(items, self.idx_modified) def set_unmerged(self, items): """Adds items to the 'Unmerged' subtree.""" self._set_subtree(items, self.idx_unmerged) def set_untracked(self, items): """Adds items to the 'Untracked' subtree.""" self._set_subtree(items, self.idx_untracked) def _set_subtree(self, items, idx, staged=False, untracked=False, check=True): """Add a list of items to a treewidget item.""" self.blockSignals(True) parent = self.topLevelItem(idx) if items: self.setItemHidden(parent, False) else: self.setItemHidden(parent, True) # sip v4.14.7 and below leak memory in parent.takeChildren() # so we use this backwards-compatible construct instead while parent.takeChild(0) is not None: pass for item in items: treeitem = qtutils.create_treeitem(item, staged=staged, check=check, untracked=untracked) parent.addChild(treeitem) self.expand_items(idx, items) self.blockSignals(False) def update_column_widths(self): self.resizeColumnToContents(0) def expand_items(self, idx, items): """Expand the top-level category "folder" once and only once.""" # Don't do this if items is empty; this makes it so that we # don't add the top-level index into the expanded_items set # until an item appears in a particular category. if not items: return # Only run this once; we don't want to re-expand items that # we've clicked on to re-collapse on updated(). if idx in self.expanded_items: return self.expanded_items.add(idx) item = self.topLevelItem(idx) if item: self.expandItem(item) def contextMenuEvent(self, event): """Create context menus for the repo status tree.""" menu = self.create_context_menu() menu.exec_(self.mapToGlobal(event.pos())) def create_context_menu(self): """Set up the status menu for the repo status tree.""" s = self.selection() menu = QtGui.QMenu(self) selected_indexes = self.selected_indexes() if selected_indexes: category, idx = selected_indexes[0] # A header item e.g. 'Staged', 'Modified', etc. if category == self.idx_header: return self._create_header_context_menu(menu, idx) if s.staged: return self._create_staged_context_menu(menu, s) elif s.unmerged: return self._create_unmerged_context_menu(menu, s) else: return self._create_unstaged_context_menu(menu, s) def _create_header_context_menu(self, menu, idx): if idx == self.idx_staged: menu.addAction(qtutils.icon('remove.svg'), N_('Unstage All'), cmds.run(cmds.UnstageAll)) return menu elif idx == self.idx_unmerged: action = menu.addAction(qtutils.icon('add.svg'), cmds.StageUnmerged.name(), cmds.run(cmds.StageUnmerged)) action.setShortcut(cmds.StageUnmerged.SHORTCUT) return menu elif idx == self.idx_modified: action = menu.addAction(qtutils.icon('add.svg'), cmds.StageModified.name(), cmds.run(cmds.StageModified)) action.setShortcut(cmds.StageModified.SHORTCUT) return menu elif idx == self.idx_untracked: action = menu.addAction(qtutils.icon('add.svg'), cmds.StageUntracked.name(), cmds.run(cmds.StageUntracked)) action.setShortcut(cmds.StageUntracked.SHORTCUT) return menu def _create_staged_context_menu(self, menu, s): if s.staged[0] in self.m.submodules: return self._create_staged_submodule_context_menu(menu, s) if self.m.unstageable(): action = menu.addAction(qtutils.icon('remove.svg'), N_('Unstage Selected'), cmds.run(cmds.Unstage, self.staged())) action.setShortcut(cmds.Unstage.SHORTCUT) menu.addAction(self.launch_editor) menu.addAction(self.launch_difftool) if not utils.is_win32(): menu.addSeparator() action = menu.addAction(qtutils.file_icon(), cmds.OpenDefaultApp.name(), cmds.run(cmds.OpenDefaultApp, self.staged())) action.setShortcut(cmds.OpenDefaultApp.SHORTCUT) action = menu.addAction(qtutils.open_file_icon(), cmds.OpenParentDir.name(), self._open_parent_dir) action.setShortcut(cmds.OpenParentDir.SHORTCUT) if self.m.undoable(): menu.addSeparator() menu.addAction(qtutils.icon('undo.svg'), N_('Revert Unstaged Edits...'), lambda: self._revert_unstaged_edits(staged=True)) menu.addAction(qtutils.icon('undo.svg'), N_('Revert Uncommited Edits...'), lambda: self._revert_uncommitted_edits( self.staged())) menu.addSeparator() menu.addAction(self.copy_path_action) return menu def _create_staged_submodule_context_menu(self, menu, s): menu.addAction(qtutils.git_icon(), N_('Launch git-cola'), cmds.run(cmds.OpenRepo, core.abspath(s.staged[0]))) menu.addAction(self.launch_editor) menu.addSeparator() action = menu.addAction(qtutils.icon('remove.svg'), N_('Unstage Selected'), cmds.run(cmds.Unstage, self.staged())) action.setShortcut(cmds.Unstage.SHORTCUT) menu.addSeparator() menu.addAction(self.copy_path_action) return menu def _create_unmerged_context_menu(self, menu, s): menu.addAction(self.launch_difftool) action = menu.addAction(qtutils.icon('add.svg'), N_('Stage Selected'), cmds.run(cmds.Stage, self.unstaged())) action.setShortcut(cmds.Stage.SHORTCUT) menu.addSeparator() menu.addAction(self.launch_editor) if not utils.is_win32(): menu.addSeparator() action = menu.addAction(qtutils.file_icon(), cmds.OpenDefaultApp.name(), cmds.run(cmds.OpenDefaultApp, self.unmerged())) action.setShortcut(cmds.OpenDefaultApp.SHORTCUT) action = menu.addAction(qtutils.open_file_icon(), cmds.OpenParentDir.name(), self._open_parent_dir) action.setShortcut(cmds.OpenParentDir.SHORTCUT) menu.addSeparator() menu.addAction(self.copy_path_action) return menu def _create_unstaged_context_menu(self, menu, s): modified_submodule = (s.modified and s.modified[0] in self.m.submodules) if modified_submodule: return self._create_modified_submodule_context_menu(menu, s) if self.m.stageable(): action = menu.addAction(qtutils.icon('add.svg'), N_('Stage Selected'), cmds.run(cmds.Stage, self.unstaged())) action.setShortcut(cmds.Stage.SHORTCUT) if self.unstaged(): menu.addAction(self.launch_editor) if s.modified and self.m.stageable(): menu.addAction(self.launch_difftool) if s.modified and self.m.stageable(): if self.m.undoable(): menu.addSeparator() menu.addAction(qtutils.icon('undo.svg'), N_('Revert Unstaged Edits...'), self._revert_unstaged_edits) menu.addAction(qtutils.icon('undo.svg'), N_('Revert Uncommited Edits...'), lambda: self._revert_uncommitted_edits( self.modified())) if self.unstaged() and not utils.is_win32(): menu.addSeparator() action = menu.addAction(qtutils.file_icon(), cmds.OpenDefaultApp.name(), cmds.run(cmds.OpenDefaultApp, self.unstaged())) action.setShortcut(cmds.OpenDefaultApp.SHORTCUT) action = menu.addAction(qtutils.open_file_icon(), cmds.OpenParentDir.name(), self._open_parent_dir) action.setShortcut(cmds.OpenParentDir.SHORTCUT) if s.untracked: menu.addSeparator() menu.addAction(qtutils.discard_icon(), N_('Delete File(s)...'), self._delete_files) menu.addSeparator() menu.addAction(qtutils.icon('edit-clear.svg'), N_('Add to .gitignore'), cmds.run(cmds.Ignore, map(lambda x: '/' + x, self.untracked()))) menu.addSeparator() menu.addAction(self.copy_path_action) return menu def _create_modified_submodule_context_menu(self, menu, s): menu.addAction(qtutils.git_icon(), N_('Launch git-cola'), cmds.run(cmds.OpenRepo, core.abspath(s.modified[0]))) menu.addAction(self.launch_editor) if self.m.stageable(): menu.addSeparator() action = menu.addAction(qtutils.icon('add.svg'), N_('Stage Selected'), cmds.run(cmds.Stage, self.unstaged())) action.setShortcut(cmds.Stage.SHORTCUT) menu.addSeparator() menu.addAction(self.copy_path_action) return menu def _delete_files(self): files = self.untracked() count = len(files) if count == 0: return title = N_('Delete Files?') msg = N_('The following files will be deleted:') + '\n\n' fileinfo = subprocess.list2cmdline(files) if len(fileinfo) > 2048: fileinfo = fileinfo[:2048].rstrip() + '...' msg += fileinfo info_txt = N_('Delete %d file(s)?') % count ok_txt = N_('Delete Files') if qtutils.confirm(title, msg, info_txt, ok_txt, default=True, icon=qtutils.discard_icon()): cmds.do(cmds.Delete, files) def _revert_unstaged_edits(self, staged=False): if not self.m.undoable(): return if staged: items_to_undo = self.staged() else: items_to_undo = self.modified() if items_to_undo: if not qtutils.confirm(N_('Revert Unstaged Changes?'), N_('This operation drops unstaged changes.\n' 'These changes cannot be recovered.'), N_('Revert the unstaged changes?'), N_('Revert Unstaged Changes'), default=True, icon=qtutils.icon('undo.svg')): return args = [] if not staged and self.m.amending(): args.append(self.m.head) cmds.do(cmds.Checkout, args + ['--'] + items_to_undo) else: msg = N_('No files selected for checkout from HEAD.') Interaction.log(msg) def _revert_uncommitted_edits(self, items_to_undo): if items_to_undo: if not qtutils.confirm( N_('Revert Uncommitted Changes?'), N_('This operation drops uncommitted changes.\n' 'These changes cannot be recovered.'), N_('Revert the uncommitted changes?'), N_('Revert Uncommitted Changes'), default=True, icon=qtutils.icon('undo.svg')): return cmds.do(cmds.Checkout, [self.m.head, '--'] + items_to_undo) else: msg = N_('No files selected for checkout from HEAD.') Interaction.log(msg) def single_selection(self): """Scan across staged, modified, etc. and return a single item.""" st = None um = None m = None ut = None s = self.selection() if s.staged: st = s.staged[0] elif s.modified: m = s.modified[0] elif s.unmerged: um = s.unmerged[0] elif s.untracked: ut = s.untracked[0] return selection.State(st, um, m, ut) def selected_indexes(self): """Returns a list of (category, row) representing the tree selection.""" selected = self.selectedIndexes() result = [] for idx in selected: if idx.parent().isValid(): parent_idx = idx.parent() entry = (parent_idx.row(), idx.row()) else: entry = (self.idx_header, idx.row()) result.append(entry) return result def selection(self): """Return the current selection in the repo status tree.""" return selection.State(self.staged(), self.unmerged(), self.modified(), self.untracked()) def contents(self): return selection.State(self.m.staged, self.m.unmerged, self.m.modified, self.m.untracked) def all_files(self): c = self.contents() return c.staged + c.unmerged + c.modified + c.untracked def selected_group(self): """A list of selected files in various states of being""" return selection.pick(self.selection()) def selected_idx(self): c = self.contents() s = self.single_selection() offset = 0 for content, selection in zip(c, s): if len(content) == 0: continue if selection is not None: return offset + content.index(selection) offset += len(content) return None def select_by_index(self, idx): c = self.contents() to_try = [ (c.staged, self.idx_staged), (c.unmerged, self.idx_unmerged), (c.modified, self.idx_modified), (c.untracked, self.idx_untracked), ] for content, toplevel_idx in to_try: if len(content) == 0: continue if idx < len(content): parent = self.topLevelItem(toplevel_idx) item = parent.child(idx) self.select_item(item) return idx -= len(content) def select_item(self, item): self.scrollToItem(item) self.setCurrentItem(item) self.setItemSelected(item, True) def staged(self): return self._subtree_selection(self.idx_staged, self.m.staged) def unstaged(self): return self.unmerged() + self.modified() + self.untracked() def modified(self): return self._subtree_selection(self.idx_modified, self.m.modified) def unmerged(self): return self._subtree_selection(self.idx_unmerged, self.m.unmerged) def untracked(self): return self._subtree_selection(self.idx_untracked, self.m.untracked) def _subtree_selection(self, idx, items): item = self.topLevelItem(idx) return qtutils.tree_selection(item, items) def double_clicked(self, item, idx): """Called when an item is double-clicked in the repo status tree.""" self._process_selection() def _process_selection(self): s = self.selection() if s.staged: cmds.do(cmds.Unstage, s.staged) unstaged = [] if s.unmerged: unstaged.extend(s.unmerged) if s.modified: unstaged.extend(s.modified) if s.untracked: unstaged.extend(s.untracked) if unstaged: cmds.do(cmds.Stage, unstaged) def _open_using_default_app(self): cmds.do(cmds.OpenDefaultApp, self.selected_group()) def _open_parent_dir(self): cmds.do(cmds.OpenParentDir, self.selected_group()) def show_selection(self): """Show the selected item.""" # Sync the selection model selection.selection_model().set_selection(self.selection()) selected_indexes = self.selected_indexes() if not selected_indexes: if self.m.amending(): cmds.do(cmds.SetDiffText, '') else: cmds.do(cmds.ResetMode) return category, idx = selected_indexes[0] # A header item e.g. 'Staged', 'Modified', etc. if category == self.idx_header: cls = { self.idx_staged: cmds.DiffStagedSummary, self.idx_modified: cmds.Diffstat, # TODO implement UnmergedSummary #self.idx_unmerged: cmds.UnmergedSummary, self.idx_untracked: cmds.UntrackedSummary, }.get(idx, cmds.Diffstat) cmds.do(cls) # A staged file elif category == self.idx_staged: cmds.do(cmds.DiffStaged, self.staged()) # A modified file elif category == self.idx_modified: cmds.do(cmds.Diff, self.modified()) elif category == self.idx_unmerged: cmds.do(cmds.Diff, self.unmerged()) elif category == self.idx_untracked: cmds.do(cmds.ShowUntracked, self.unstaged()) def move_up(self): idx = self.selected_idx() all_files = self.all_files() if idx is None: selected_indexes = self.selected_indexes() if selected_indexes: category, toplevel_idx = selected_indexes[0] if category == self.idx_header: item = self.itemAbove(self.topLevelItem(toplevel_idx)) if item is not None: self.select_item(item) return if all_files: self.select_by_index(len(all_files) - 1) return if idx - 1 >= 0: self.select_by_index(idx - 1) else: self.select_by_index(len(all_files) - 1) def move_down(self): idx = self.selected_idx() all_files = self.all_files() if idx is None: selected_indexes = self.selected_indexes() if selected_indexes: category, toplevel_idx = selected_indexes[0] if category == self.idx_header: item = self.itemBelow(self.topLevelItem(toplevel_idx)) if item is not None: self.select_item(item) return if all_files: self.select_by_index(0) return if idx + 1 < len(all_files): self.select_by_index(idx + 1) else: self.select_by_index(0) def copy_path(self): """Copy a selected path to the clipboard""" filename = selection.selection_model().filename() if filename is not None: curdir = os.getcwdu() qtutils.set_clipboard(os.path.join(curdir, filename)) git-cola-1.9.3/cola/widgets/text.py000066400000000000000000000150131225156173500171540ustar00rootroot00000000000000from PyQt4 import QtGui, QtCore from PyQt4.QtCore import Qt, SIGNAL from cola.models.prefs import tabwidth from cola.qtutils import diff_font class MonoTextEdit(QtGui.QTextEdit): def __init__(self, parent): QtGui.QTextEdit.__init__(self, parent) self._tabwidth = 8 self.setMinimumSize(QtCore.QSize(1, 1)) self.setLineWrapMode(QtGui.QTextEdit.NoWrap) self.setAcceptRichText(False) self.setFont(diff_font()) self.set_tabwidth(tabwidth()) self.setCursorWidth(2) def tabwidth(self): return self._tabwidth def set_tabwidth(self, width): self._tabwidth = width font = self.font() fm = QtGui.QFontMetrics(font) pixels = fm.width('m' * width) self.setTabStopWidth(pixels) def set_textwidth(self, width): font = self.font() fm = QtGui.QFontMetrics(font) pixels = fm.width('m' * (width + 2)) self.setLineWrapColumnOrWidth(pixels) def set_linebreak(self, brk): if brk: wrapmode = QtGui.QTextEdit.FixedPixelWidth else: wrapmode = QtGui.QTextEdit.NoWrap self.setLineWrapMode(wrapmode) def selected_line(self): cursor = self.textCursor() offset = cursor.position() contents = unicode(self.toPlainText()) while (offset >= 1 and contents[offset-1] and contents[offset-1] != '\n'): offset -= 1 data = contents[offset:] if '\n' in data: line, rest = data.split('\n', 1) else: line = data return line def mousePressEvent(self, event): # Move the text cursor so that the right-click events operate # on the current position, not the last left-clicked position. if event.button() == Qt.RightButton: if not self.textCursor().hasSelection(): self.setTextCursor(self.cursorForPosition(event.pos())) QtGui.QTextEdit.mousePressEvent(self, event) class MonoTextView(MonoTextEdit): def __init__(self, parent): MonoTextEdit.__init__(self, parent) self.setAcceptDrops(False) self.setTabChangesFocus(True) self.setUndoRedoEnabled(False) self.setTextInteractionFlags(Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse) class HintedTextWidgetEventFilter(QtCore.QObject): def __init__(self, parent): QtCore.QObject.__init__(self, parent) self.widget = parent def eventFilter(self, obj, event): if event.type() == QtCore.QEvent.FocusIn: self.widget.emit_position() if self.widget.is_hint(): self.widget.enable_hint(False) elif event.type() == QtCore.QEvent.FocusOut: if not bool(self.widget.value()): self.widget.enable_hint(True) return False class HintedTextWidgetMixin(object): def __init__(self, hint): self._hint = hint self._event_filter = HintedTextWidgetEventFilter(self) self.installEventFilter(self._event_filter) # Palette for normal text self.default_palette = QtGui.QPalette(self.palette()) # Palette used for the placeholder text self.hint_palette = pal = QtGui.QPalette(self.palette()) color = self.hint_palette.text().color() color.setAlpha(128) pal.setColor(QtGui.QPalette.Active, QtGui.QPalette.Text, color) pal.setColor(QtGui.QPalette.Inactive, QtGui.QPalette.Text, color) def emit_position(self): pass def reset_cursor(self): pass def set_hint(self, hint): is_hint = self.is_hint() self._hint = hint if is_hint: self.enable_hint(True) def hint(self): return self._hint def is_hint(self): return self.strip() == self._hint def value(self): text = self.strip() if text == self._hint: return u'' else: return text def strip(self): return self.as_unicode().strip() def enable_hint(self, hint): blocksignals = self.blockSignals(True) if hint: self.set_value(self.hint()) else: self.clear() self.reset_cursor() self.blockSignals(blocksignals) self.enable_hint_palette(hint) def enable_hint_palette(self, hint): if hint: self.setPalette(self.hint_palette) else: self.setPalette(self.default_palette) def refresh_palette(self): self.enable_hint_palette(self.is_hint()) class HintedTextEditMixin(HintedTextWidgetMixin): def __init__(self, hint): HintedTextWidgetMixin.__init__(self, hint) self.connect(self, SIGNAL('cursorPositionChanged()'), self.emit_position) def as_unicode(self): return unicode(self.toPlainText()) def set_value(self, value): self.setPlainText(value) self.refresh_palette() def emit_position(self): cursor = self.textCursor() position = cursor.position() txt = self.as_unicode() before = txt[:position] row = before.count('\n') line = before.split('\n')[row] col = cursor.columnNumber() if hasattr(self, 'tabwidth'): col += line[:col].count('\t') * (self.tabwidth() - 1) self.emit(SIGNAL('cursorPosition(int,int)'), row+1, col) class HintedTextEdit(MonoTextEdit, HintedTextEditMixin): def __init__(self, hint, parent=None): MonoTextEdit.__init__(self, parent) HintedTextEditMixin.__init__(self, hint) # The read-only variant. class HintedTextView(MonoTextView, HintedTextEditMixin): def __init__(self, hint, parent=None): MonoTextView.__init__(self, parent) HintedTextEditMixin.__init__(self, hint) class HintedLineEdit(QtGui.QLineEdit, HintedTextWidgetMixin): def __init__(self, hint, parent=None): QtGui.QLineEdit.__init__(self, parent) HintedTextWidgetMixin.__init__(self, hint) self.setFont(diff_font()) self.connect(self, SIGNAL('cursorPositionChanged(int,int)'), lambda x, y: self.emit_position()) def emit_position(self): cols = self.cursorPosition() self.emit(SIGNAL('cursorPosition(int,int)'), 1, cols) def set_value(self, value): self.setText(value) self.refresh_palette() def as_unicode(self): return unicode(self.text()) def reset_cursor(self): self.setCursorPosition(0) git-cola-1.9.3/contrib/000077500000000000000000000000001225156173500146725ustar00rootroot00000000000000git-cola-1.9.3/contrib/build-git-cola.sh000066400000000000000000000037101225156173500200230ustar00rootroot00000000000000#!/bin/sh # Author: Aaron Cook # This script will build git-cola on an older Linux distribution, # e.g. RHEL 5. # This script assumes you have the appropriate tars already downloaded # (adjust the versions as needed, or set the appropriate COLA_* variables) # Note the "rm -rf" at the beginning. # Replace COLA_PREFIX with your path, or set the COLA_PREFIX environment # variable. # Set COLA_NUM_JOBS to control the number of cores used to build. # This script defaults to 2. # The only real trick was the python compile options for the utf. # You should run "make prefix=$HOME/apps/git-cola install" in the # git-cola repo after running this script. # To run git cola, I just created another script that adds the proper paths: # !/bin/sh # COLA_PREFIX="$HOME/apps/git-cola" # PATH="$COLA_PREFIX/bin:$PATH" # PYTHONPATH="$COLA_PREFIX/Python:$PYTHONPATH" # export PATH PYTHONPATH # $COLA_PREFIX/bin/git-cola # This is the directory where git-cola will be installed COLA_PREFIX=${COLA_PREFIX:-"$HOME/apps/git-cola"} COLA_NUM_JOBS=${COLA_NUM_JOBS:-2} COLA_QT=${COLA_QT:-qt-x11-opensource-src-4.4.3} COLA_PYQT=${COLA_PYQT:-PyQt-x11-gpl-4.10.1} COLA_SIP=${COLA_SIP:-sip-4.14.6} COLA_PYTHON=${COLA_PYTHON:-Python-2.7.5} rm -rf "$COLA_PREFIX" mkdir -p "$COLA_PREFIX" rm -rf "$COLA_QT" "$COLA_PYQT" "$COLA_SIP" "$COLA_PYTHON" tar -zxvf "$COLA_QT".tar.gz tar -zxvf "$COLA_PYQT".tar.gz tar -zxvf "$COLA_SIP".tar.gz tar -zxvf "$COLA_PYTHON".tgz compile_top="$PWD" cd "$compile_top/$COLA_QT" ./configure -prefix $install_dir -confirm-license make -j "$COLA_NUM_JOBS" && make install cd "$compile_top/$COLA_PYTHON" ./configure --prefix=$install_dir --enable-unicode=ucs4 make -j "$COLA_NUM_JOBS" && make install pybin="$COLA_PREFIX/bin/python" cd "$COMPILE_TOP/$COLA_SIP" "$pybin" ./configure.py && make -j "$COLA_NUM_JOBS" && make install cd "$compile_top/$COLA_PYQT" "$pybin" ./configure.py -q "$COLA_PREFIX/bin/qmake" && make -j "$COLA_NUM_JOBS" && make install git-cola-1.9.3/contrib/darwin/000077500000000000000000000000001225156173500161565ustar00rootroot00000000000000git-cola-1.9.3/contrib/darwin/.gitignore000066400000000000000000000000151225156173500201420ustar00rootroot00000000000000/git-cola.py git-cola-1.9.3/contrib/darwin/Info.plist000066400000000000000000000025671225156173500201400ustar00rootroot00000000000000 CFBundleDevelopmentRegion English CFBundleDisplayName git-cola CFBundleDocumentTypes CFBundleTypeOSTypes **** fold disk CFBundleTypeRole Viewer CFBundleExecutable git-cola CFBundleIconFile git-cola.icns CFBundleIdentifier com.justroots.git-cola CFBundleInfoDictionaryVersion 6.0 CFBundleName git-cola CFBundlePackageType APPL CFBundleShortVersionString 0.0.0 CFBundleSignature ???? CFBundleVersion 0.0.0 LSHasLocalizedDisplayName NSAppleScriptEnabled NSHumanReadableCopyright Copyright not specified NSMainNibFile MainMenu NSPrincipalClass NSApplication git-cola-1.9.3/contrib/darwin/PkgInfo000066400000000000000000000000101225156173500174250ustar00rootroot00000000000000APPL????git-cola-1.9.3/contrib/darwin/git-cola000077500000000000000000000005531225156173500176060ustar00rootroot00000000000000#!/bin/sh # Setup PATH for git-osx-installer and other common locations PATH="$PATH":/usr/local/bin:/usr/local/git/bin export PATH # $0 = Contents/MacOS/git-cola macos="$(dirname "$0")" contents="$(dirname "$macos")" python="$contents/Resources/git-cola" if ! test -e "$python" then python=python fi exec "$python" "$contents/Resources/bin/git-cola" --prompt git-cola-1.9.3/contrib/darwin/git-cola.icns000066400000000000000000000656411225156173500205470ustar00rootroot00000000000000icnskis320гٱX^Tvzg^[[`mw6*hn::[y,~?%^/8(m+8,So_F Уᣫ裫~' & %dX^Tuxf]^[dWIbPbgh+oqvdÄnkeEsGf Уᣫ裫~' & %dX^Twzg^[[`mw6*hn::[y,~?%^/8(m+8,So_F s8mk8~s$#~s3{t~G~RPs3IIFaGEd.baD:))8M4 6 Nil32,Ԅꐁ񚁄Gзӷ·Ԥԭv{{ w}yx-581%*xB63\30`|\_jGp=)!acB9aV6r!6r+1RL)s0p%W?$}51r/U+kK:Qa_`__]6'Ya^`_^gU&Ie]``]i19g3D)SC *D4k "A;a"c9 %_# `_i/x*&'*xR6x &،똈񢈋n}}|b`|}}o[|}|d`^Ԃ'W_^]ab^_^^`Xv[`^^aWx-591%*xB73[30`|\_jFo>) bcA>f^9~y5H>CRR&:C2$s8tU79@N߀Y^=H4jו.^E͵,` Q|<_k%D2+xax,/0.'*xZ'?})/،똈񢈋n}}|b`|}}o[|}|d`^Ԃ'W_^]ab^_^^`Xv[`^^aWx-581%*xB63\30`|\_jGp=)!acB9aV6r!6r+1RL)s0p%W?$}51r/U+kK:Qa_`__]6'Ya^`_^gU&Ie]``]i19g3D)SC *D4k "A;a"c9 %_# `_i/x*&'*xR6x &l8mkcaaaacZ Ycaaa`dHe`aa`g2[W#]Y%njkkkle cmjkkjn"Qpjkkjq9..*" I0 4j4퐁9 pUyv>wt<0yx5 iO0 3i{G' &#it32  |ș ֙™ʙ ڙę̙ ܙƙΙ  ޙ  ̙  {   +!&&     +$""$+ +$""$++$""$+ &.:++3.A S^R >++++? S^S @,+64-8.64-8.8/243@!r} D-3@!r} D-0@{r=0+G#"I3@+G#"I3@@&G E(3G$"I.@@3G$"I.@@.F  E13F"!H.@3F"!H.@.E D11A!{C,1A!{C,,A{?# #; u{>)  #; u{>)  !<{u:"  "%9ou9(" "%9ou9(""$7uo5$" &+ "$$#%-i n.%#$$" *&&+ "$$#%-i n.%#$$" *& &+ "$$#%,n i-%#$$" +&'os$$$'os$$$$so&$!"!!"_b+(_b++b]( nv+ ) n v++ vr ,  e}m() e} m(, m}i ) ]rd$& ]r d$(dr` ) Th["$ Th ["&[hX 'N`TN` T"T`Q" 3X5    3X5    5X2  :P; :P;  ;P: +G-    +G-    -G+   %? '    %? '   '? %    !7"    !7"   "7!  /  /  /  &  &  &              ޕߕߝ ]u  ko  oi j|owwsI]TK]QQ]N&1,(1++1) +$""$+ +$""$++$""$+ &.:++3.A S^R >++++? S^S @,+64.8.64.8.8/243@!r} D-3@!r} D-0D{r=0+G$"I3@+G$"I3@@&K  E(3K%#M:@@3K%#M:@@.J!!H13M&$K:@3M&$K:@@.M!"K11L%$J731L%$J733,K!"J. + ,I% $H)' + + ,I% $H)' + + ')F! !D+ + &-0/613G' #F116/0-& &-0/613G' #F116/0-& &-0/611F" #E216/0-& .5>/234?# @44332/<9,.5>/234?# @44332/<9,.:=/234? =432/>5.; #%%# 61$$); #%%# 61$$17 #&%# :)$%&+#6$'9%&+#6$$6#+×&%9' B3@U(DB3@@3CD&U E33@+G E3333IęK+@ G1333I G1331K™M33 I/331L I/33/JL13 H1333J H1331HJ33 B+@@,E B+@@+CE,@y<&(?y<&&=x?(&Ζ".'+1&Ζ".''.#Η&1+6{1 ++!6{1 ++ 2{6!+ +1;779979@"v | A879976:0)+1;779979@"v | A879976:0) )0:679978A| v @979977;1  $$#$)(($)<t z<-#(()$!"$$$#$)(($)<t z<-#(()$!"$ $"!$)((#(:z t;)#(()$#$$$'9rx<$$$'9rx<$$$$:xr8&$$=ou<,$=ou<,!=uo;#&:ms=.&:ms=.#:sm8$(7kp:$(7kp:$$7pk5&6hn7&6hn7&4nh5$-HP. $-HP.  /MG,"#)  $'#)  $'(%  &"* *-#* *-#(*) (-+& (-+&&+-' "$(($"#  "$(($"# #"$(($"  ޕߕߝ ]u  ko  oi j|owwsI]TK]QQ]N&1,(1++1) +$""$+ +$""$++$""$+ &.:++3.A S^R >++++? S^S @,+64-8.64-8.8/243@!r} D-3@!r} D-0@{r=0+G#"I3@+G#"I3@@&G E(3G$"I.@@3G$"I.@@.F  E13F"!H.@3F"!H.@.E D11A!{C,1A!{C,,A{?# #; u{>)  #; u{>)  !<{u:"  "%9ou9(" "%9ou9(""$7uo5$" &+ "$$#%-i n.%#$$" *&&+ "$$#%-i n.%#$$" *& &+ "$$#%,n i-%#$$" +&'os$$$'os$$$$so&$!"!!"_b+(_b++b]( nv+ ) n v++ vr ,  e}m() e} m(, m}i ) ]rd$& ]r d$(dr` ) Th["$ Th ["&[hX 'N`TN` T"T`Q" 3X5    3X5    5X2  :P; :P;  ;P: +G-    +G-    -G+   %? '    %? '   '? %    !7"    !7"   "7!  /  /  /  &  &  &             t8mk@Zh^da^9YAIIAMnU]]U 68888888888888888888888887 78888888888888888888888887 78888888888888888888888887        !,3553-"  !,3553-"  "-3553-"  9gl;  9gl;  ;li9 ;>;>=< &y)  &y)  )|' 484886=B=BA?AFAFECBGBGFDCHCHGE IN  IN  MK "%&&*7^b9*&&%" "%&&*7^b9*&&%"  "%&&*9b`8*&&%"5PyyS6  5PyyS6  5Qy좋yP5 @E@EDA/ -//- B@BA@NKNMKSPSRPTQTSQRORQOMJMLJ@=@?=,  *,  ,* 9=9=<9/E]dffhrshffd^F0  /E]dffhrshffd^F0  0F^dffhsrhffd]E/  #2Z^3$  #2Z^3$  $3][2$  GL  GL  KI CHCHGEBGBGFDAFAFEC=A=A@>373764 $n{'  $n{'  &wr% 7979983RU5 3RU5  5US4&+--+&&+--+&&+--+&   icnV Bgit-cola-1.9.3/contrib/win32/000077500000000000000000000000001225156173500156345ustar00rootroot00000000000000git-cola-1.9.3/contrib/win32/README.md000066400000000000000000000010371225156173500171140ustar00rootroot00000000000000Windows Tips ============ * git-cola is tested on msysgit * Other git environments should work fine as long as `git` can be found in the $PATH. * The provided `cola` shell script can be used to launch *git-cola* if you do not want to keep `python.exe` in your $PATH. * If your python is installed in a location other than `/c/Python*/` then you can tell the `cola` script about it by setting the `cola.pythonlocation` git configuration variable. e.g.: $ git config --global cola.pythonlocation "/c/Program Files/Python27/python.exe" git-cola-1.9.3/contrib/win32/cola000077500000000000000000000021571225156173500165050ustar00rootroot00000000000000#!/bin/sh # Windows doesn't have the 'dirname' command, so fake it dirname() { dir=$(echo "$@" | perl -pe 's,(.*)/[^/]+,\1,') test "$dir" = "$1" && dir=. echo "$dir" } mydir="$(dirname "$0")" parentdir="$(dirname "$mydir")" # Windows uses 'git-cola.pyw' instead of 'git-cola' COLA="$parentdir"/bin/git-cola if test -f "$COLA".pyw; then COLA="$COLA".pyw fi # The path to python can be specified by setting the # PYTHON environment variable. if test -z "$PYTHON" then PYTHON="$(which python.exe 2>/dev/null)" fi # The path to python can be specified in the # `cola.pythonlocation` git configuration variable. if test -z "$PYTHON" then PYTHON="$(git config cola.pythonlocation)" fi if test -n "$PYTHON" then exec "$PYTHON" "$COLA" "$@" fi # Find a suitable Python and use it to run cola. # If your python is installed in another location then # add that path to the top of the list below or # set the `cola.pythonlocation` git configuration variable. for python in \ "/c/Python27" \ "/c/Python26" \ "/c/Python25" do if test -d "$python" then PATH="$python":"$PATH" exec "$python/python.exe" "$COLA" "$@" fi done exit 1 git-cola-1.9.3/contrib/win32/create-installer.sh000077500000000000000000000034641225156173500214400ustar00rootroot00000000000000#!/bin/sh cd "$(git rev-parse --show-toplevel)" WIN32="$PWD/contrib/win32" if ! test -d "$WIN32" then echo "Please run this script from the git-cola source tree" exit 1 fi # Add Python and Gettext to our path for python in "/c/Python27" "/c/Python26" "/c/Python25" do if test -d "$python" then break fi done PATH="$python":/bin:/usr/bin:/mingw/bin:"/c/Program Files/Gnu/bin":"$WIN32":"$PATH" export PATH VERSION=$(bin/git-cola version --brief) while test $# -gt 0; do case "$1" in -v|--version) shift VERSION="$1" shift ;; *) echo "Usage: $0 [--version ]" exit 1 ;; esac done BASENAME=git-cola-$VERSION ETC=$BASENAME/etc ROOT=$BASENAME TARGET="$ROOT".exe echo "Building installer for git-cola $VERSION" python setup.py --quiet install \ --prefix="$ROOT" \ --install-scripts="$ROOT"/bin rm -rf "$ROOT/lib" "$ROOT/Lib" build cp "$BASENAME/bin/git-cola" $BASENAME/bin/git-cola.pyw cp "$BASENAME/bin/git-dag" $BASENAME/bin/git-dag.pyw mkdir -p $ETC 2>/dev/null cp "$WIN32/git.bmp" "$WIN32/gpl-2.0.rtf" "$WIN32/git.ico" "$ETC" NOTES="$ETC/ReleaseNotes.txt" printf "git-cola: v$VERSION\nBottled-on: $(date)\n\n\n" > $NOTES printf "To run cola, just type 'cola' from a Git Bash session.\n\n\n" >> $NOTES tag=$(git tag | tail -2 | head -1) echo "--------------------------------------------------------" >> $NOTES echo " Changes since $tag" >> $NOTES echo "--------------------------------------------------------" >> $NOTES echo >> $NOTES git shortlog $tag.. >> $NOTES # LF -> CRLF vim -c "set ff=dos" -c "wq" $NOTES sed -e "s/%APPVERSION%/$VERSION/" -e "s/%OUTPUTDIR%/../" \ < "$WIN32/install.iss" > "$BASENAME/install.iss" && ( cd "$BASENAME" && echo "Lauching Inno Setup compiler ..." && /share/InnoSetup/ISCC.exe install.iss | grep -Ev "\s*Reading|\s*Compressing" ) && rm -rf "$BASENAME" git-cola-1.9.3/contrib/win32/dag000077500000000000000000000011211225156173500163100ustar00rootroot00000000000000#!/bin/sh # Windows doesn't have the 'dirname' command, so fake it dirname() { dir=$(echo "$@" | perl -pe 's,(.*)/[^/]+,\1,') test "$dir" = "$1" && dir=. echo "$dir" } mydir="$(dirname "$0")" parentdir="$(dirname "$mydir")" # Windows uses 'git-cola.pyw' instead of 'git-cola' COLA="$parentdir"/bin/git-dag if test -f "$COLA".pyw; then COLA="$COLA".pyw fi # Find a suitable Python and use it to run cola for python in "/c/Python27" "/c/Python26" "/c/Python25"; do if test -d "$python"; then PATH="$PATH":"$python" export PATH exec "$python/python.exe" "$COLA" "$@" fi done exit 1 git-cola-1.9.3/contrib/win32/git.bmp000066400000000000000000003171501225156173500171260ustar00rootroot00000000000000BMh6(2%.%.ٲfffffffffffffffooo⼼ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffşoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffϕfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyyyyffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooٲfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffϩyyyfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooo⩩ooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyfffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffٌfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffόffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooyyyffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffyyyffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffoooffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff삂ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff₂fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffooofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffłfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff켼ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffŲfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8ai-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8aiL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@xoߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟL@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@L@ߟgit-cola-1.9.3/contrib/win32/git.ico000066400000000000000000000537261225156173500171300ustar00rootroot0000000000000000f h00 %  B hnS(0` L@J>K?OCI<dYdYK?dZODE?b]K>IEIDKDKDK5K5M4M4M5-8,3).(+'''')))()**.+1,5(3HS-8-9-:-:)4IS)4JS.9.:/:1</:(5#0-))'6C,7*6*5*6*6*6)5(4(4"/+(%$"0=rpXmlVnmXbcf^_kY\pY[phh`ffafffeedffemmmhhhccceeedddxxxjjjgggtttiiinnnlllkkkzzzaaa```HHHzzzmmmfffeeeeeecccfffmmm\\\mmmhhhgggeeeeeedddeeeeeefffdddnnnhhheeefffccchhh^^^mmmyyynnnddddddfffdddccciiigggffffffffffffffffffeeefffffffffeeegggcccfffpppgggqqqzzzqqqhhheeeeeegggeeegggtttiiimmmhhhffffffffffffeeefffgggddddddddddddeeehhheeehhhppp}}}tttX\SZSYSYWbXfeZYSSSSSWSW]WXYe]XXSYSSSYSSSZSSSSYSSYSSSSSSYYSSSYYSSXSSYYZSSSSSSSYSSZXYSSXYSYSSYSdXSXSWYYSYYSYZZc]]SSYS]XSYSS_]WYX__YYYSaWSYSYSSSYbZSSYSYSYSVWSYSSYSSY`WYWa_SSYSSSY]SYSSSWZSY]SYYXSYYZYYWYSXWZZSZX_SSSSSY]XSYY]Y]^_SSSYZZZZYW[SWSWW\SSSSYSSYSSYSSYZZSSSSSSSYYSSYSYYVWXSSSSSSYSSYSSYSSSQRSMTUSSSSSSSSSSSSJKLMNOOOPPPPOOOP:;;<=>?@ABCDEFFFGGGGFFHI./010234566677776689,-&'(())))))('*+ !"#$%    ??~||> ?  ( @L@K?K?SFI=[O\PYKRDPCNALAM@NBPCMA^QK>KCLBJAM5M4M3N51=-8*/%! !))+1*5>I1=+3*/)+(')**+*,*,*-*1+1,5?I.;*6+7+81=0</<.;-:-9*5?H)7&1$1$2*7)6'4&3&3%1$07BvuFtrJsoKsoLspLrnLlkbhh]mmWmlXkjZji[jiZji\ggfccedddddeeeeffggggfffghhccchhhiiijjjlllbbbmmmaaa```_YYX[X[*)-1+2>?7?28.0*&R1O7L9M5M4M3N5N3P1'*#($;2 N3L;JDKCKCLBJAJAM:P)b1,`H\@V7T9Q;N=L@L@L@K>L@L@M<O9R7P2`A"_PYKSFRDPCNAL@L@L@K?LAL@M@NBPCMA^Q6'>/b]b___bba_]]bbbb__ba___b]__b]bbbd_bd_bbekl__bjb__b__bb_bab__b_b_b__a_bh_i__b___fgbfb]ee__bfe_b__]dbbeee_bb__b[\]^_`ab__bb_cSTUVWXXXXXYZXMNOPPPPQRPABCDEFGHIJIIIIKL56789:;<===>>?@'()*+,-./0123%4 !"!"#$%&   801???????( @L@K?L=L?K>K@J=SFN8LBJ@LAI;TAM5W W" !! "+&!," (hg_hhagg_omUomTnmTolUpnTnngggeddcppoggfhhfdddgggeeedeefffiiihhhAJ5M4M3M5N=18-/*% !!))1+5*I>=13+/*+)'(*)+*,*,*-*1*1+5,I?;.6*7+8+=1<0KCLBJAM5M4M3N51=-8*/%! !))+1*5>I1=+3*/)+(')**+*,*,*-*1+1,5?I.;*6+7+81=0</<.;-:-9*5?H)7&1$1$2*7)6'4&3&3%1$07BvuFtrJsoKsoLspLrnLlkbhh]mmWmlXkjZ22422224222546421401232*+,+-./%&%'()"#$ !   O(0` %)DesP.IEEE???^^^fffdddfffeeefffeeeeeeQQQ###U$!+++yXXXHHH```dddeeefffffffffffffffhhhfffhhh^^^///d)<<>>ghhheeefffcccHHHC ```dddfffdddcccNNNOSSS_ffffffeeefffl\^^^eeegggcccfff yzzzaaaFeeeeeegggeeegggggg,,,;PPPcfffffffffeee\\\dddddddddeee@@@MvvvfffhhhfffhhhhhhjjjFOOOgffffffeeeeee^^^fffeeeffffffeeeAAAv8 rrr,,,;fffeeeddddddeeefffGOOOhffffffeeefffeeeeeeffffffeeefff[[[UUUShhhhhhcccfffffffffIMMMhffffffdddddddddddddddeeeeeeeeeffffff444]jjaThh`ffafffbcf7VVUpffefffffffffffffffffffffffffffffffff999ImlTkjTnmX::0K\\TNbcf^_kY\pY\pY\pY[pY[pY[pY[pY\pY\pY\pBDS $001234445F))#UNNNNNNNNN&'$Y8% %m],7*6*6*5*6*6*6)5(4(4"/+(%%%$$$$%%"&1z&-8-8-8-8.9.:/:1IEIDKDKDKD.s)cN=L@L@K?J>K>*k#aL@L@L@J>L@(f!o1PihffffhL@L@L@J>K?%]reffffg_@C87./w'/w(/w(/w(/w(.t'/w(L@L@L@K?K?D;'b!,q%/w(/w(/w(/w(/v',|(,]*n#L@L@L@L@L@L@L@L@L@L@L@L@L@L@K?K?L@L@L@L@L@L@IF;C8C8D9D9D9C8D9L@L@L@K?K?E:0z)>4D9D9D9D9C9B6QHkL@L@L@J>J>$\bL@L@L@J>L@)h"bPCL@L@L@J>L@+l$dRDL@L@L@L@L@,p%_SFL@L@L@L@L@3+@K?J>G!$1%1%1%1%1%1%1%3$/;E 4B)7&1$1$2*7)6'4&3&3%1&3&3&3&3$07B 7D.;*6+7+81=0I[ 8F5B1=/5__YLYJXI[X[*)-1+2>?7?28.0*&R1O7L9M5M4M3N5N3P1'*#($;2 N3L;JDKCKCLBJAJAM:P)b1,`H\@V7T9Q;N=L@L@L@K>L@L@M<O9R7P2`A"_PYKSFRDPCNAL@L@L@K?LAL@M@NBPCMA^Q6'>/[LSFL@L@L@L@L@L@L@L@K?K?L@L@L@I=\P3&7([LSFL@L@L@L@L@L@L@L@K?K?L@L@L@I=[O0#7([LSFL@L@L@L@L@L@L@K?L@L@{K?L@L@I=[Oe2%7(_PYKSFRDPCNAL@L@L@K?L@L@L@PCREQDbU7);,bS_P[LWISFPCL@L@L@L@K?L@PCTFWJYKj[>.@0QDNBL@L@L@L@L@L@NBSFPCL@L@L@L@L@L@PC801???????(  @tttoooggggggfffeeeeeeggg*ffffff```iiipppffffffeeeeeeeeeeeefffffffffwwwyyyoooeeeeeeeeeeeeLhhhKiiifffhhheeeooowwwmmmfffeeecccddcggg___gggfffeeeooozz{oopdddgggdddfffFeeedeeeeeeeeooo||vssmnnggge`_^DddciggeppowggfhhfgdddoopeusZON/omUomTolTFomUnmTolUpnTomTwvbjkzOPVdepfgfgfbhg_dhhaRgg_bii`Ahg^ppn3@&1!," ( !5>.2" !!  "+& "'9T7ZXW YW WnVX<] I)>HN\O-N1M6M5M5M3N1QG718}]DU>N8L=LBJ@LBLAI;TA9L1\JTDL=L?L@K>K@K@J=SF9(K:[LSFL@L@L@K?L@L@L@SG7*J=[LSFL@L@L@L@L@L@J>SG8+J=Ogit-cola-1.9.3/contrib/win32/gpl-2.0.rtf000066400000000000000000000400701225156173500174310ustar00rootroot00000000000000{\rtf1\ansi\ansicpg1250\deff0\deflang1033\deflangfe1060{\fonttbl{\f0\fswiss\fprq2\fcharset238 Verdana;}{\f1\fmodern\fprq1\fcharset238 Lucida Console;}} {\*\generator Msftedit 5.41.15.1507;}\viewkind4\uc1\pard\nowidctlpar\sb100\sa100\qc\lang1060\kerning36\b\f0\fs28 GNU General Public License\par \kerning0\b0\fs16 Version 2, June 1991\par \pard\nowidctlpar\f1\fs14\par Copyright (C) 1989, 1991 Free Software Foundation, Inc.\par 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\par \par Everyone is permitted to copy and distribute verbatim copies\par of this license document, but changing it is not allowed.\par \par \pard\keepn\nowidctlpar\sb100\sa100\qc\b\f0\fs20 Preamble\fs24\par \pard\nowidctlpar\fi142\sb100\sa100\b0\fs16 The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. \par When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. \par To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. \par For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. \par We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. \par Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. \par Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. \par The precise terms and conditions for copying, distribution and modification follow. \par \pard\keepn\nowidctlpar\sb100\sa100\qc\b\fs20 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\par \pard\nowidctlpar\fi142\sb100\sa100\fs16 0.\b0 This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". \par \pard\nowidctlpar\sb100\sa100 Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. \par \pard\nowidctlpar\fi142\sb100\sa100\b 1.\b0 You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. \par \pard\nowidctlpar\sb100\sa100 You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. \par \pard\nowidctlpar\fi142\sb100\sa100\b 2.\b0 You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: \par \pard\nowidctlpar\li284\sb100\sa100\b a)\b0 You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. \par \b b)\b0 You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. \par \b c)\b0 If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) \par \pard\nowidctlpar\sb100\sa100 These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. \par Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. \par In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. \par \pard\nowidctlpar\fi142\sb100\sa100\b 3.\b0 You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: \v \v0\par \pard\nowidctlpar\li284\sb100\sa100\b a)\b0 Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, \par \b b)\b0 Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, \par \b c)\b0 Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) \par \pard\nowidctlpar\sb100\sa100 The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. \par If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. \par \pard\nowidctlpar\fi142\sb100\sa100\b 4.\b0 You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. \par \b 5.\b0 You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. \par \b 6.\b0 Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. \par \b 7.\b0 If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. \par \pard\nowidctlpar\sb100\sa100 If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. \par It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. \par This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. \par \pard\nowidctlpar\fi142\sb100\sa100\b 8.\b0 If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. \par \b 9.\b0 The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. \par \pard\nowidctlpar\sb100\sa100 Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. \par \pard\nowidctlpar\fi142\sb100\sa100\b 10.\b0 If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. \par \pard\nowidctlpar\sb100\sa100\qc\fs20 NO WARRANTY\par \pard\nowidctlpar\fi142\sb100\sa100\b\fs16 11.\b0 BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. \par \b 12.\b0 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. \par \pard\keepn\nowidctlpar\sb100\sa100\qc\b END OF TERMS AND CONDITIONS\fs20\par } git-cola-1.9.3/contrib/win32/install.iss000066400000000000000000000366271225156173500200400ustar00rootroot00000000000000#define APP_NAME 'git-cola' #define APP_LONGNAME 'git-cola - The highly caffeinated Git GUI' #define APP_VERSION '%APPVERSION%' #define APP_URL 'http://git-cola.github.io/' [Setup] ; Compiler-related InternalCompressLevel=max OutputBaseFilename={#emit APP_NAME+'-'+APP_VERSION} OutputDir=%OUTPUTDIR% SolidCompression=yes ; Installer-related AllowNoIcons=yes AppName={#emit APP_LONGNAME} AppPublisherURL={#emit APP_URL} AppVersion={#emit APP_VERSION} AppVerName={#emit APP_LONGNAME+' '+APP_VERSION} ChangesEnvironment=yes DefaultDirName={pf}\{#emit APP_NAME} DefaultGroupName={#emit APP_LONGNAME} DisableReadyPage=yes InfoBeforeFile=etc\gpl-2.0.rtf PrivilegesRequired=none UninstallDisplayIcon=etc\git.ico ; Cosmetic SetupIconFile=etc\git.ico WizardSmallImageFile=etc\git.bmp [Tasks] Name: quicklaunchicon; Description: "Create a &Quick Launch icon"; GroupDescription: "Additional icons:"; Flags: checkedonce Name: desktopicon; Description: "Create a &Desktop icon"; GroupDescription: "Additional icons:"; Flags: checkedonce Name: guiextension; Description: "Add ""Git &Cola Here"""; GroupDescription: "Windows Explorer integration:"; Flags: checkedonce [Files] Source: "*"; DestDir: "{app}"; Excludes: "\*.bmp, \install.*, \tmp.*, \bin\*install*"; Flags: recursesubdirs Source: "etc\ReleaseNotes.txt"; DestDir: "{app}\etc"; Flags: isreadme [Icons] Name: "{group}\git-cola"; Filename: "{code:GetPythonExe}"; Parameters: """{app}\bin\git-cola.pyw"" --prompt --git-path ""{code:GetGitExe}"""; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico" Name: "{group}\git-dag"; Filename: "{code:GetPythonExe}"; Parameters: """{app}\bin\git-dag.pyw"" --prompt --git-path ""{code:GetGitExe}"""; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico" Name: "{group}\git-cola Homepage"; Filename: "{#emit APP_URL}"; WorkingDir: "%USERPROFILE%"; Name: "{group}\Release Notes"; Filename: "{app}\etc\ReleaseNotes.txt"; WorkingDir: "%USERPROFILE%"; Name: "{group}\License"; Filename: "{app}\etc\gpl-2.0.rtf"; WorkingDir: "%USERPROFILE%"; Name: "{group}\Uninstall git-cola"; Filename: "{uninstallexe}" Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\git-cola"; Filename: "{code:GetPythonExe}"; Parameters: """{app}\bin\git-cola.pyw"" --prompt --git-path ""{code:GetGitExe}"""; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"; Tasks: quicklaunchicon Name: "{code:GetShellFolder|desktop}\git-cola"; Filename: "{code:GetPythonExe}"; Parameters: """{app}\bin\git-cola.pyw"" --prompt --git-path ""{code:GetGitExe}"""; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"; Tasks: desktopicon Name: "{code:GetShellFolder|desktop}\git-dag"; Filename: "{code:GetPythonExe}"; Parameters: """{app}\bin\git-dag.pyw"" --prompt --git-path ""{code:GetGitExe}"""; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"; Tasks: desktopicon [Messages] BeveledLabel={#emit APP_URL} SetupAppTitle={#emit APP_NAME} Setup SetupWindowTitle={#emit APP_NAME} Setup [UninstallDelete] Type: files; Name: "{app}\bin\*" Type: files; Name: "{app}\etc\*" Type: files; Name: "{app}\share\git-cola\bin\*" Type: files; Name: "{app}\share\git-cola\icons\*" Type: files; Name: "{app}\share\git-cola\lib\cola\*" Type: files; Name: "{app}\share\git-cola\lib\cola\models\*" Type: files; Name: "{app}\share\git-cola\lib\cola\widgets\*" Type: dirifempty; Name: "{app}\share\git-cola\lib\cola\models" Type: dirifempty; Name: "{app}\share\git-cola\lib\cola\widgets" Type: dirifempty; Name: "{app}\share\git-cola\lib\cola" Type: dirifempty; Name: "{app}\share\git-cola\lib" Type: dirifempty; Name: "{app}\share\git-cola\icons" Type: dirifempty; Name: "{app}\share\git-cola\bin" Type: dirifempty; Name: "{app}\etc" Type: dirifempty; Name: "{app}\bin" [Code] { Helper methods } var PythonPage:TWizardPage; GitPage:TWizardPage; EdtPython:TEdit; EdtGit:TEdit; function GetEnvStrings(VarName:string;AllUsers:Boolean):TArrayOfString; var Path:string; i:Longint; p:Integer; begin Path:=''; // See http://www.jrsoftware.org/isfaq.php#env if AllUsers then begin // We ignore errors here. The resulting array of strings will be empty. RegQueryStringValue(HKEY_LOCAL_MACHINE,'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',VarName,Path); end else begin // We ignore errors here. The resulting array of strings will be empty. RegQueryStringValue(HKEY_CURRENT_USER,'Environment',VarName,Path); end; // Make sure we have at least one semicolon. Path:=Path+';'; // Split the directories in PATH into an array of strings. i:=0; SetArrayLength(Result,0); p:=Pos(';',Path); while p>0 do begin SetArrayLength(Result,i+1); if p>1 then begin Result[i]:=Copy(Path,1,p-1); i:=i+1; end; Path:=Copy(Path,p+1,Length(Path)); p:=Pos(';',Path); end; end; function SetEnvStrings(VarName:string;AllUsers,DeleteIfEmpty:Boolean;DirStrings:TArrayOfString):Boolean; var Path,KeyName:string; i:Longint; begin // Merge all non-empty directory strings into a PATH variable. Path:=''; for i:=0 to GetArrayLength(DirStrings)-1 do begin if Length(DirStrings[i])>0 then begin if Length(Path)>0 then begin Path:=Path+';'+DirStrings[i]; end else begin Path:=DirStrings[i]; end; end; end; // See http://www.jrsoftware.org/isfaq.php#env if AllUsers then begin KeyName:='SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; if DeleteIfEmpty and (Length(Path)=0) then begin Result:=(not RegValueExists(HKEY_LOCAL_MACHINE,KeyName,VarName)) or RegDeleteValue(HKEY_LOCAL_MACHINE,KeyName,VarName); end else begin Result:=RegWriteStringValue(HKEY_LOCAL_MACHINE,KeyName,VarName,Path); end; end else begin KeyName:='Environment'; if DeleteIfEmpty and (Length(Path)=0) then begin Result:=(not RegValueExists(HKEY_CURRENT_USER,KeyName,VarName)) or RegDeleteValue(HKEY_CURRENT_USER,KeyName,VarName); end else begin Result:=RegWriteStringValue(HKEY_CURRENT_USER,KeyName,VarName,Path); end; end; end; procedure BrowseForPythonFolder(Sender:TObject); var Path:string; begin Path:=GetPreviousData('PythonPath', 'C:\Python27'); EdtPython.Text:=Path; Path:=ExtractFilePath(EdtPython.Text); BrowseForFolder('Please select the Python folder:',Path,False); Path:=Path+'\pythonw.exe'; if FileExists(Path) then begin EdtPython.Text:=Path; end else begin MsgBox('Please enter a valid path to pythonw.exe.',mbError,MB_OK); end; end; function GetPythonExe(Param: String): String; begin Result:=EdtPython.Text; end; procedure BrowseForGitFolder(Sender:TObject); var Path:string; OldPath:string; begin Path:=GetPreviousData('GitPath', 'C:\Program Files\Git'); EdtGit.Text:=Path; Path:=ExtractFilePath(EdtGit.Text); BrowseForFolder('Please select the Git folder:',Path,False); OldPath:=Path; { Check for both $DIR\git.exe and $DIR\bin\git.exe } Path:=OldPath+'\bin\git.exe'; if FileExists(Path) then begin EdtGit.Text:=Path; Exit; end; Path:=OldPath+'\git.exe'; if FileExists(Path) then begin EdtGit.Text:=Path; end else begin MsgBox('Please enter a valid path to git.exe.',mbError,MB_OK); end; end; function GetGitExe(Param: String): String; begin Result:=EdtGit.Text; end; procedure RegisterPreviousData(PreviousDataKey:Integer); var Path:string; begin Path:=ExtractFilePath(EdtPython.Text); SetPreviousData(PreviousDataKey, 'PythonPath', Path); Path:=ExtractFilePath(ExtractFilePath(EdtGit.Text)); SetPreviousData(PreviousDataKey, 'GitPath', Path); end; { Installer code } procedure InitializeWizard; var BtnPython:TButton; BtnGit:TButton; LblPython:TLabel; LblGit:TLabel; begin // Create a custom page for finding Python PythonPage:=CreateCustomPage( wpSelectTasks, 'Setup Python', 'Where is your Python folder?' ); LblPython:=TLabel.Create(PythonPage); with LblPython do begin Parent:=PythonPage.Surface; Caption:= 'Please provide the path to pythonw.exe.'; Left:=ScaleX(28); Top:=ScaleY(100); Width:=ScaleX(316); Height:=ScaleY(39); end; EdtPython:=TEdit.Create(PythonPage); with EdtPython do begin Parent:=PythonPage.Surface; Text:=GetPreviousData('PythonPath', 'C:\Python26'); Text:=Text+'pythonw.exe'; if not FileExists(Text) then begin Text:=''; end; Left:=ScaleX(28); Top:=ScaleY(148); Width:=ScaleX(316); Height:=ScaleY(13); end; BtnPython:=TButton.Create(PythonPage); with BtnPython do begin Parent:=PythonPage.Surface; Caption:='...'; OnClick:=@BrowseForPythonFolder; Left:=ScaleX(348); Top:=ScaleY(148); Width:=ScaleX(21); Height:=ScaleY(21); end; // Create a custom page for finding Git GitPage:=CreateCustomPage( wpSelectTasks, 'Setup Git', 'Where is your Git folder?' ); LblGit:=TLabel.Create(GitPage); with LblGit do begin Parent:=GitPage.Surface; Caption:= 'Please provide the path to git.exe.'; Left:=ScaleX(28); Top:=ScaleY(100); Width:=ScaleX(316); Height:=ScaleY(39); end; EdtGit:=TEdit.Create(GitPage); with EdtGit do begin Parent:=GitPage.Surface; Text:=GetPreviousData('GitPath', 'C:\Program Files\Git'); Text:=Text+'git.exe'; if not FileExists(Text) then begin Text:=''; end; Left:=ScaleX(28); Top:=ScaleY(148); Width:=ScaleX(316); Height:=ScaleY(13); end; BtnGit:=TButton.Create(GitPage); with BtnGit do begin Parent:=GitPage.Surface; Caption:='...'; OnClick:=@BrowseForGitFolder; Left:=ScaleX(348); Top:=ScaleY(148); Width:=ScaleX(21); Height:=ScaleY(21); end; end; function NextButtonClick(CurPageID:Integer):Boolean; begin if CurPageID = PythonPage.ID then begin Result:=FileExists(EdtPython.Text); if not Result then begin MsgBox('Please enter a valid path to pythonw.exe.',mbError,MB_OK); end; Exit; end; if CurPageID = GitPage.ID then begin Result:=FileExists(EdtGit.Text); if not Result then begin MsgBox('Please enter a valid path to git.exe.',mbError,MB_OK); end; Exit; end; Result:=True; end; procedure CurStepChanged(CurStep:TSetupStep); var AppDir,BinDir,Msg:string; EnvPath:TArrayOfString; i:Longint; RootKey:Integer; begin if CurStep<>ssPostInstall then begin Exit; end; AppDir:=ExpandConstant('{app}'); BinDir:=ExpandConstant('{app}\bin'); { Modify the environment This must happen no later than ssPostInstall to make "ChangesEnvironment=yes" not happend before the change! } // Get the current user's directories in PATH. EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn); // First, remove the installation directory from PATH in any case. for i:=0 to GetArrayLength(EnvPath)-1 do begin if Pos(AppDir,EnvPath[i])=1 then begin EnvPath[i]:=''; end; end; // Modify the PATH variable as requested by the user. i:=GetArrayLength(EnvPath); SetArrayLength(EnvPath,i+1); // Add \bin to the path EnvPath[i]:=BinDir // Set the current user's PATH directories. if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin Msg:='Line {#emit __LINE__}: Unable to set the PATH environment variable.'; MsgBox(Msg,mbError,MB_OK); Log(Msg); // This is not a critical error, the user can probably fix it manually, // so we continue. end; { Create the Windows Explorer shell extensions } if IsAdminLoggedOn then begin RootKey:=HKEY_LOCAL_MACHINE; end else begin RootKey:=HKEY_CURRENT_USER; end; if IsTaskSelected('guiextension') then begin if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_cola','','Git &Cola Here')) or (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_cola\command','','"'+EdtPython.Text+'" "'+AppDir+'\bin\git-cola.pyw" "--repo" "%1" "--git-path" "'+EdtGit.Text+'"')) then begin Msg:='Line {#emit __LINE__}: Unable to create "Git Cola Here" shell extension.'; MsgBox(Msg,mbError,MB_OK); Log(Msg); // This is not a critical error, the user can probably fix it manually, // so we continue. end; end; end; { Uninstaller code } function InitializeUninstall:Boolean; begin Result:=True; end; procedure CurUninstallStepChanged(CurUninstallStep:TUninstallStep); var AppDir,Command,Msg:string; EnvPath:TArrayOfString; i:Longint; RootKey:Integer; begin if CurUninstallStep<>usUninstall then begin Exit; end; { Modify the environment This must happen no later than usUninstall to make "ChangesEnvironment=yes" not happend before the change! } AppDir:=ExpandConstant('{app}'); Command:=AppDir+'\setup.ini'; // Get the current user's directories in PATH. EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn); // Remove the installation directory from PATH in any case, even if it // was not added by the installer. for i:=0 to GetArrayLength(EnvPath)-1 do begin if Pos(AppDir,EnvPath[i])=1 then begin EnvPath[i]:=''; end; end; // Reset the current user's directories in PATH. if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to PATH.'; MsgBox(Msg,mbError,MB_OK); Log(Msg); // This is not a critical error, the user can probably fix it manually, // so we continue. end; if (FileExists(Command) and (not DeleteFile(Command))) then begin Msg:='Line {#emit __LINE__}: Unable to delete file "'+Command+'".'; MsgBox(Msg,mbError,MB_OK); Log(Msg); // This is not a critical error, the user can probably fix it manually, // so we continue. end; { Delete the Windows Explorer shell extensions } if IsAdminLoggedOn then begin RootKey:=HKEY_LOCAL_MACHINE; end else begin RootKey:=HKEY_CURRENT_USER; end; Command:=''; RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_cola\command','',Command); if Pos(AppDir,Command)>0 then begin if not RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_cola') then begin Msg:='Line {#emit __LINE__}: Unable to remove "Git Cola Here" shell extension.'; MsgBox(Msg,mbError,MB_OK); Log(Msg); // This is not a critical error, the user can probably fix it manually, // so we continue. end; end; end; function GetShellFolder(Param:string):string; begin if IsAdminLoggedOn then begin Param:='{common'+Param+'}'; end else begin Param:='{user'+Param+'}'; end; Result:=ExpandConstant(Param); end; git-cola-1.9.3/contrib/win32/py2exe-setup.cmd000077500000000000000000000000371225156173500206760ustar00rootroot00000000000000@python py2exe-setup.py py2exe git-cola-1.9.3/contrib/win32/py2exe-setup.py000077500000000000000000000003661225156173500205700ustar00rootroot00000000000000from distutils.core import setup import py2exe setup( windows = [ { "script" : "git-cola", }, ], options = { "py2exe" : { "includes" : ["PyQt4._qt", "pprint", "sip"], } } ) git-cola-1.9.3/extras/000077500000000000000000000000001225156173500145405ustar00rootroot00000000000000git-cola-1.9.3/extras/__init__.py000066400000000000000000000002231225156173500166460ustar00rootroot00000000000000from extras.build_mo import build_mo from extras.build_pot import build_pot cmdclass = { 'build_mo': build_mo, 'build_pot': build_pot, } git-cola-1.9.3/extras/build_mo.py000066400000000000000000000073311225156173500167100ustar00rootroot00000000000000"""build_mo command for setup.py""" from distutils import log from distutils.command.build import build from distutils.core import Command from distutils.dep_util import newer from distutils.spawn import find_executable import os import re class build_mo(Command): """Subcommand of build command: build_mo""" description = 'compile po files to mo files' # List of options: # - long name, # - short name (None if no short name), # - help string. user_options = [('build-dir=', 'd', 'Directory to build locale files'), ('output-base=', 'o', 'mo-files base name'), ('source-dir=', None, 'Directory with sources po files'), ('force', 'f', 'Force creation of mo files'), ('lang=', None, 'Comma-separated list of languages ' 'to process')] boolean_options = ['force'] def initialize_options(self): self.build_dir = None self.output_base = None self.source_dir = None self.force = None self.lang = None def finalize_options(self): self.set_undefined_options('build', ('force', 'force')) self.prj_name = self.distribution.get_name() if self.build_dir is None: self.build_dir = os.path.join('share', 'locale') if not self.output_base: self.output_base = self.prj_name or 'messages' if self.source_dir is None: self.source_dir = 'po' if self.lang is None: if self.prj_name: re_po = re.compile(r'^(?:%s-)?([a-zA-Z_]+)\.po$' % self.prj_name) else: re_po = re.compile(r'^([a-zA-Z_]+)\.po$') self.lang = [] for i in os.listdir(self.source_dir): mo = re_po.match(i) if mo: self.lang.append(mo.group(1)) else: self.lang = [i.strip() for i in self.lang.split(',') if i.strip()] def run(self): """Run msgfmt for each language""" if not self.lang: return if find_executable('msgfmt') is None: log.warn("GNU gettext msgfmt utility not found!") log.warn("Skip compiling po files.") return if 'en' in self.lang: if find_executable('msginit') is None: log.warn("GNU gettext msginit utility not found!") log.warn("Skip creating English PO file.") else: log.info('Creating English PO file...') pot = (self.prj_name or 'messages') + '.pot' if self.prj_name: en_po = '%s-en.po' % self.prj_name else: en_po = 'en.po' self.spawn(['msginit', '--no-translator', '-l', 'en', '-i', os.path.join(self.source_dir, pot), '-o', os.path.join(self.source_dir, en_po), ]) basename = self.output_base if not basename.endswith('.mo'): basename += '.mo' po_prefix = '' if self.prj_name: po_prefix = self.prj_name + '-' for lang in self.lang: po = os.path.join(self.source_dir, lang + '.po') if not os.path.isfile(po): po = os.path.join(self.source_dir, po_prefix + lang + '.po') dir_ = os.path.join(self.build_dir, lang, 'LC_MESSAGES') self.mkpath(dir_) mo = os.path.join(dir_, basename) if self.force or newer(po, mo): log.info('Compile: %s -> %s' % (po, mo)) self.spawn(['msgfmt', '-o', mo, po]) build.sub_commands.insert(0, ('build_mo', None)) git-cola-1.9.3/extras/build_pot.py000066400000000000000000000074361225156173500171050ustar00rootroot00000000000000"""build_pot command for setup.py""" import os import glob from distutils import log from distutils.core import Command from distutils.errors import DistutilsOptionError class build_pot(Command): """Distutils command build_pot""" description = 'extract strings from python sources for translation' # List of options: # - long name, # - short name (None if no short name), # - help string. user_options = [('build-dir=', 'd', 'Directory to put POT file'), ('output=', 'o', 'POT filename'), ('lang=', None, 'Comma-separated list of languages ' 'to update po-files'), ('no-lang', 'N', "Don't update po-files"), ('english', 'E', 'Regenerate English PO file'), ] boolean_options = ['no-lang', 'english'] def initialize_options(self): self.build_dir = None self.output = None self.lang = None self.no_lang = False self.english = False def finalize_options(self): if self.build_dir is None: self.build_dir = 'po' if not self.output: self.output = (self.distribution.get_name() or 'messages')+'.pot' if self.lang is not None: self.lang = [i.strip() for i in self.lang.split(',') if i.strip()] if self.lang and self.no_lang: raise DistutilsOptionError("You can't use options " "--lang=XXX and --no-lang in the same time.") def _force_LF(self, src, dst=None): f = open(src, 'rU') try: content = f.read() finally: f.close() if dst is None: dst = src f = open(dst, 'wb') try: f.write(content) finally: f.close() def run(self): """Run xgettext for project sources""" # project name based on `name` argument in setup() call prj_name = self.distribution.get_name() # output file if self.build_dir != '.': fullname = os.path.join(self.build_dir, self.output) else: fullname = self.output log.info('Generate POT file: ' + fullname) if not os.path.isdir(self.build_dir): log.info('Make directory: ' + self.build_dir) os.makedirs(self.build_dir) self.spawn(['xgettext', '--keyword=N_', '-p', self.build_dir, '-o', self.output] + glob.glob('cola/*.py') + glob.glob('cola/*/*.py')) self._force_LF(fullname) # regenerate english PO if self.english: log.info('Regenerating English PO file...') if prj_name: en_po = prj_name + '-' + 'en.po' else: en_po = 'en.po' self.spawn(['msginit', '--no-translator', '-l', 'en', '-i', os.path.join(self.build_dir, self.output), '-o', os.path.join(self.build_dir, en_po), ]) # search and update all po-files if self.no_lang: return for po in glob.glob(os.path.join(self.build_dir,'*.po')): if self.lang is not None: po_lang = os.path.splitext(os.path.basename(po))[0] if prj_name and po_lang.startswith(prj_name+'-'): po_lang = po_lang[5:] if po_lang not in self.lang: continue new_po = po + ".new" cmd = "msgmerge %s %s -o %s" % (po, fullname, new_po) self.spawn(cmd.split()) # force LF line-endings log.info("%s --> %s" % (new_po, po)) self._force_LF(new_po, po) os.unlink(new_po) git-cola-1.9.3/extras/sphinxtogithub/000077500000000000000000000000001225156173500176175ustar00rootroot00000000000000git-cola-1.9.3/extras/sphinxtogithub/__init__.py000066400000000000000000000012351225156173500217310ustar00rootroot00000000000000"""Script for preparing the html output of the Sphinx documentation system for github pages. """ VERSION = (1, 0, 0, 'dev') __version__ = ".".join(map(str, VERSION[:-1])) __release__ = ".".join(map(str, VERSION)) __author__ = "Michael Jones" __contact__ = "http://github.com/michaeljones" __homepage__ = "http://github.com/michaeljones/sphinx-to-github" __docformat__ = "restructuredtext" from sphinxtogithub import ( setup, sphinx_extension, LayoutFactory, Layout, DirectoryHandler, VerboseRename, ForceRename, Remover, FileHandler, Replacer, DirHelper, FileSystemHelper, OperationsFactory, HandlerFactory ) git-cola-1.9.3/extras/sphinxtogithub/sphinxtogithub.py000066400000000000000000000237471225156173500232650ustar00rootroot00000000000000#! /usr/bin/env python from optparse import OptionParser import warnings import os import sys import shutil class DirHelper(object): def __init__(self, is_dir, list_dir, walk, rmtree): self.is_dir = is_dir self.list_dir = list_dir self.walk = walk self.rmtree = rmtree class FileSystemHelper(object): def __init__(self, open_, path_join, move, exists): self.open_ = open_ self.path_join = path_join self.move = move self.exists = exists class Replacer(object): "Encapsulates a simple text replace" def __init__(self, from_, to): self.from_ = from_ self.to = to def process(self, text): return text.replace( self.from_, self.to ) class FileHandler(object): "Applies a series of replacements the contents of a file inplace" def __init__(self, name, replacers, opener): self.name = name self.replacers = replacers self.opener = opener def process(self): text = self.opener(self.name).read() for replacer in self.replacers: text = replacer.process( text ) self.opener(self.name, "w").write(text) class Remover(object): def __init__(self, exists, remove): self.exists = exists self.remove = remove def __call__(self, name): if self.exists(name): self.remove(name) class ForceRename(object): def __init__(self, renamer, remove): self.renamer = renamer self.remove = remove def __call__(self, from_, to): self.remove(to) self.renamer(from_, to) class VerboseRename(object): def __init__(self, renamer, stream): self.renamer = renamer self.stream = stream def __call__(self, from_, to): self.stream.write( "Renaming directory '%s' -> '%s'\n" % (os.path.basename(from_), os.path.basename(to)) ) self.renamer(from_, to) class DirectoryHandler(object): "Encapsulates renaming a directory by removing its first character" def __init__(self, name, root, renamer): self.name = name self.new_name = name[1:] self.root = root + os.sep self.renamer = renamer def path(self): return os.path.join(self.root, self.name) def relative_path(self, directory, filename): path = directory.replace(self.root, "", 1) return os.path.join(path, filename) def new_relative_path(self, directory, filename): path = self.relative_path(directory, filename) return path.replace(self.name, self.new_name, 1) def process(self): from_ = os.path.join(self.root, self.name) to = os.path.join(self.root, self.new_name) self.renamer(from_, to) class HandlerFactory(object): def create_file_handler(self, name, replacers, opener): return FileHandler(name, replacers, opener) def create_dir_handler(self, name, root, renamer): return DirectoryHandler(name, root, renamer) class OperationsFactory(object): def create_force_rename(self, renamer, remover): return ForceRename(renamer, remover) def create_verbose_rename(self, renamer, stream): return VerboseRename(renamer, stream) def create_replacer(self, from_, to): return Replacer(from_, to) def create_remover(self, exists, remove): return Remover(exists, remove) class Layout(object): """ Applies a set of operations which result in the layout of a directory changing """ def __init__(self, directory_handlers, file_handlers): self.directory_handlers = directory_handlers self.file_handlers = file_handlers def process(self): for handler in self.file_handlers: handler.process() for handler in self.directory_handlers: handler.process() class NullLayout(object): """ Layout class that does nothing when asked to process """ def process(self): pass class LayoutFactory(object): "Creates a layout object" def __init__(self, operations_factory, handler_factory, file_helper, dir_helper, verbose, stream, force): self.operations_factory = operations_factory self.handler_factory = handler_factory self.file_helper = file_helper self.dir_helper = dir_helper self.verbose = verbose self.output_stream = stream self.force = force def create_layout(self, path): path = str(path) contents = self.dir_helper.list_dir(path) renamer = self.file_helper.move if self.force: remove = self.operations_factory.create_remover(self.file_helper.exists, self.dir_helper.rmtree) renamer = self.operations_factory.create_force_rename(renamer, remove) if self.verbose: renamer = self.operations_factory.create_verbose_rename(renamer, self.output_stream) # Build list of directories to process directories = [d for d in contents if self.is_underscore_dir(path, d)] underscore_directories = [ self.handler_factory.create_dir_handler(d, path, renamer) for d in directories ] if not underscore_directories: if self.verbose: self.output_stream.write( "No top level directories starting with an underscore " "were found in '%s'\n" % path ) return NullLayout() # Build list of files that are in those directories replacers = [] for handler in underscore_directories: for directory, dirs, files in self.dir_helper.walk(handler.path()): for f in files: replacers.append( self.operations_factory.create_replacer( handler.relative_path(directory, f), handler.new_relative_path(directory, f) ) ) # Build list of handlers to process all files filelist = [] for root, dirs, files in self.dir_helper.walk(path): for f in files: if f.endswith(".html"): filelist.append( self.handler_factory.create_file_handler( self.file_helper.path_join(root, f), replacers, self.file_helper.open_) ) if f.endswith(".js"): filelist.append( self.handler_factory.create_file_handler( self.file_helper.path_join(root, f), [self.operations_factory.create_replacer("'_sources/'", "'sources/'")], self.file_helper.open_ ) ) return Layout(underscore_directories, filelist) def is_underscore_dir(self, path, directory): return (self.dir_helper.is_dir(self.file_helper.path_join(path, directory)) and directory.startswith("_")) def sphinx_extension(app, exception): "Wrapped up as a Sphinx Extension" if not app.builder.name in ("html", "dirhtml"): return if not app.config.sphinx_to_github: if app.config.sphinx_to_github_verbose: print "Sphinx-to-github: Disabled, doing nothing." return if exception: if app.config.sphinx_to_github_verbose: print "Sphinx-to-github: Exception raised in main build, doing nothing." return dir_helper = DirHelper( os.path.isdir, os.listdir, os.walk, shutil.rmtree ) file_helper = FileSystemHelper( open, os.path.join, shutil.move, os.path.exists ) operations_factory = OperationsFactory() handler_factory = HandlerFactory() layout_factory = LayoutFactory( operations_factory, handler_factory, file_helper, dir_helper, app.config.sphinx_to_github_verbose, sys.stdout, force=True ) layout = layout_factory.create_layout(app.outdir) layout.process() def setup(app): "Setup function for Sphinx Extension" if (not hasattr(app, 'add_config_value') or not hasattr(app, 'connect')): warnings.warn('Could not call add_config_value() in sphinxtogithub') return app.add_config_value("sphinx_to_github", True, '') app.add_config_value("sphinx_to_github_verbose", True, '') app.connect("build-finished", sphinx_extension) def main(args): usage = "usage: %prog [options] " parser = OptionParser(usage=usage) parser.add_option("-v","--verbose", action="store_true", dest="verbose", default=False, help="Provides verbose output") opts, args = parser.parse_args(args) try: path = args[0] except IndexError: sys.stderr.write( "Error - Expecting path to html directory:" "sphinx-to-github \n" ) return dir_helper = DirHelper( os.path.isdir, os.listdir, os.walk, shutil.rmtree ) file_helper = FileSystemHelper( open, os.path.join, shutil.move, os.path.exists ) operations_factory = OperationsFactory() handler_factory = HandlerFactory() layout_factory = LayoutFactory( operations_factory, handler_factory, file_helper, dir_helper, opts.verbose, sys.stdout, force=False ) layout = layout_factory.create_layout(path) layout.process() if __name__ == "__main__": main(sys.argv[1:]) git-cola-1.9.3/po/000077500000000000000000000000001225156173500136505ustar00rootroot00000000000000git-cola-1.9.3/po/.gitignore000066400000000000000000000000111225156173500156300ustar00rootroot00000000000000*.msg *~ git-cola-1.9.3/po/README000066400000000000000000000001451225156173500145300ustar00rootroot00000000000000These are from the git-gui sources. Please see git-gui's po/README file for more details. TODO: todo git-cola-1.9.3/po/de.po000066400000000000000000002417071225156173500146130ustar00rootroot00000000000000# Copyright (C) 2007 Shawn Pearce, et al. # This file is distributed under the same license as the git package. # Christian Stimming , 2007 # msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-09-24 21:42-0700\n" "PO-Revision-Date: 2013-05-16 19:54+0100\n" "Last-Translator: Sven Claussner <>\n" "Language-Team: German\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.5.4\n" #: cola/bookmarks.py:32 msgid "Bookmarks" msgstr "Favoriten" #: cola/bookmarks.py:47 msgid "Open" msgstr "Öffnen" #: cola/bookmarks.py:53 msgid "Add" msgstr "Hinzufügen" #: cola/bookmarks.py:58 cola/guicmds.py:25 cola/guicmds.py:33 #: cola/widgets/editremotes.py:127 msgid "Delete" msgstr "Löschen" #: cola/bookmarks.py:65 cola/stash/view.py:42 cola/widgets/archive.py:65 #: cola/widgets/browse.py:117 msgid "Save" msgstr "Speichern" #: cola/bookmarks.py:71 cola/difftool.py:96 cola/qt.py:57 cola/qt.py:243 #: cola/prefs/view.py:241 cola/stash/view.py:50 cola/stash/view.py:51 #: cola/widgets/about.py:66 cola/widgets/about.py:126 #: cola/widgets/browse.py:116 cola/widgets/cfgactions.py:87 #: cola/widgets/cfgactions.py:239 cola/widgets/compare.py:94 #: cola/widgets/createbranch.py:159 cola/widgets/createtag.py:104 #: cola/widgets/editremotes.py:55 cola/widgets/grep.py:75 #: cola/widgets/recent.py:75 cola/widgets/remote.py:157 #: cola/widgets/search.py:81 cola/widgets/selectcommits.py:59 #: cola/widgets/startup.py:42 msgid "Close" msgstr "Schließen" #: cola/bookmarks.py:102 msgid "Bookmarks Saved" msgstr "Favoriten gesichert" #: cola/bookmarks.py:103 msgid "Successfully saved bookmarks" msgstr "Die Favoriten wurden erfolgreich gesichert." #: cola/bookmarks.py:107 msgid "Path to git repository" msgstr "Pfad zum Projektarchiv" #: cola/bookmarks.py:108 msgid "Enter Git Repository" msgstr "Git Projektarchiv:" #: cola/cmds.py:105 msgid "Amend" msgstr "Ergänzen" #: cola/cmds.py:140 msgid "Cannot Amend" msgstr "Fehler beim Ergänzen" #: cola/cmds.py:141 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "Es werden gerade Änderungen eingepflegt.Sie können deshalb im Moment keine " "Ergänzungen vornehmen." #: cola/cmds.py:204 #, python-format msgid "PATCH %(current)d/%(count)d" msgstr "" #: cola/cmds.py:208 msgid "Summary:" msgstr "Zusammenfassung" #: cola/cmds.py:217 msgid "Patch(es) Applied" msgstr "Patch(es) angewendet" #: cola/cmds.py:218 #, python-format msgid "%d patch(es) applied." msgstr "%d Patch(es) angewendet" #: cola/cmds.py:322 #, python-format msgid "Created commit: %s" msgstr "Änderung %s übertragen:" #: cola/cmds.py:324 #, python-format msgid "Commit failed: %s" msgstr "Versionierung fehlgeschlagen: %s" #: cola/cmds.py:369 cola/cmds.py:1186 msgid "Error" msgstr "Fehler" #: cola/cmds.py:370 #, python-format msgid "Deleting \"%s\" failed" msgstr "Fehler beim Löschen von \"%s\"" #: cola/cmds.py:406 msgid "Remote Branch Deleted" msgstr "Externer Zweig gelöscht" #: cola/cmds.py:407 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "\"%(branch)s\" wurde von \"%(remote)s\" gelöscht." #: cola/cmds.py:411 cola/guicmds.py:108 cola/widgets/remote.py:472 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "\"%(command)s\" wurde mit Code %(status)d beendet" #: cola/cmds.py:414 msgid "Error Deleting Remote Branch" msgstr "Fehler beim Löschen des externen Zweigs" #: cola/cmds.py:493 cola/widgets/grep.py:60 cola/widgets/recent.py:69 msgid "Edit" msgstr "Bearbeiten" #: cola/cmds.py:529 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/cmds.py:531 #, fuzzy msgid "Error Editing File" msgstr "Fehler beim Laden des Vergleichs:" #: cola/cmds.py:554 msgid "Launch Diff Tool" msgstr "Mit direktem Vorgänger vergleichen" #: cola/cmds.py:577 msgid "Launch Editor" msgstr "Mit Editor bearbeiten" #: cola/cmds.py:598 msgid "Error: Cannot find commit template" msgstr "" "Fehler: ich kann die Textvorlage zum Versionieren der Änderungen nicht finden" #: cola/cmds.py:599 #, python-format msgid "%s: No such file or directory." msgstr "Fehler: Datei oder Verzeichnis »%s« nicht gefunden" #: cola/cmds.py:616 msgid "Error: Unconfigured commit template" msgstr "Fehler: Keine Textvorlage zum Versionieren von Änderungen festgelegt." #: cola/cmds.py:617 msgid "" "A commit template has not been configured.\n" "Use \"git config\" to define \"commit.template\"\n" "so that it points to a commit template." msgstr "" "Eine Vorlage für die Versionsbeschreibung ist noch nicht festgelegt.\n" "Legen Sie bitte zuerst mit \"git config commit.template\" eine Vorlage fest." #: cola/cmds.py:669 msgid "Open Using Default Application" msgstr "Mit der Standardanwendung öffnen" #: cola/cmds.py:692 msgid "Open Parent Directory" msgstr "Übergeordnetes Verzeichnis öffnen" #: cola/cmds.py:732 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Fehler: Konnte das Projektarchiv \"%s\" nicht klonen" #: cola/cmds.py:733 #, python-format msgid "git clone returned exit code %s" msgstr "git clone wurde mit dem Fehlercode %s beendet" #: cola/cmds.py:756 cola/widgets/action.py:19 cola/widgets/editremotes.py:49 #: cola/widgets/grep.py:65 cola/widgets/recent.py:52 #: cola/widgets/recent.py:121 msgid "Refresh" msgstr "Ansicht aktualisieren" #: cola/cmds.py:784 #, python-format msgid "Run \"%s\"?" msgstr "Möchten Sie \"%s\" ausführen?" #: cola/cmds.py:791 msgid "Please select a file" msgstr "Bitte wählen Sie eine Datei" #: cola/cmds.py:792 #, python-format msgid "\"%s\" requires a selected file." msgstr "\"%s\" erwartet, dass eine Datei ausgewählt wird." #: cola/cmds.py:804 msgid "Invalid Revision" msgstr "Zweig oder Markierung ungültig" #: cola/cmds.py:805 msgid "The revision expression cannot be empty." msgstr "Der Ausdruck darf nicht leer sein." #: cola/cmds.py:820 #, python-format msgid "Running command: %s" msgstr "Führe Befehl \"%s\" aus" #: cola/cmds.py:829 cola/cmds.py:1006 cola/interaction.py:70 #, python-format msgid "Output: %s" msgstr "Ausgabe: \"%s\"" #: cola/cmds.py:830 cola/guicmds.py:113 cola/interaction.py:71 #, python-format msgid "Errors: %s" msgstr "Fehler: \"%s\"" #: cola/cmds.py:876 msgid "Sign Off" msgstr "Unterzeichnen" #: cola/cmds.py:897 msgid "unknown" msgstr "unbekannt" #: cola/cmds.py:910 cola/widgets/action.py:17 msgid "Stage" msgstr "Änderung vormerken" #: cola/cmds.py:917 #, python-format msgid "Staging: %s" msgstr "Vermerke Änderung an »%s«" #: cola/cmds.py:934 msgid "Stage Modified" msgstr "Vermerke Änderung" #: cola/cmds.py:948 msgid "Stage Unmerged" msgstr "Nicht zusammengeführte Dateien vormerken" #: cola/cmds.py:962 msgid "Stage Untracked" msgstr "Neue Dateien vormerken" #: cola/cmds.py:980 #, python-format msgid "Tagging \"%(revision)s\" as \"%(name)s\"" msgstr "Markiere \"%(revision)s\" mit \"%(name)s\"" #: cola/cmds.py:988 msgid "GPG-signed" msgstr "mit GPG signiert" #: cola/cmds.py:1020 cola/widgets/action.py:18 msgid "Unstage" msgstr "Änderung nicht vormerken" #: cola/cmds.py:1027 #, python-format msgid "Unstaging: %s" msgstr "Entferne Datei »%s« aus Vormerkliste" #: cola/cmds.py:1055 #, python-format msgid "Untracking: %s" msgstr "Führe keine Versionskontrolle mehr für \"%s\" aus." #: cola/cmds.py:1137 #, fuzzy msgid "Error Launching History Browser" msgstr "Werkzeug für die Verlaufsansicht" #: cola/cmds.py:1138 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/difftool.py:76 msgid "git-cola diff" msgstr "" #: cola/difftool.py:92 cola/widgets/compare.py:90 msgid "Compare" msgstr "Vergleichen" #: cola/gitcmds.py:402 msgid "Nothing to do" msgstr "Nichts zu tun" #: cola/guicmds.py:25 msgid "Delete Branch" msgstr "Zweig löschen" #: cola/guicmds.py:33 msgid "Delete Remote Branch" msgstr "Externen Zweig löschen" #: cola/guicmds.py:53 msgid "Browse Commits..." msgstr "Zweig zur Ansicht wählen" #: cola/guicmds.py:53 msgid "Browse" msgstr "Ansehen" #: cola/guicmds.py:61 msgid "Checkout Branch" msgstr "Zweig wechseln" #: cola/guicmds.py:61 msgid "Checkout" msgstr "Umstellen" #: cola/guicmds.py:70 msgid "Cherry-Pick Commit" msgstr "Einzelne Version übernehmen" #: cola/guicmds.py:107 msgid "Error Creating Repository" msgstr "Fehler beim Anlegen des Projektarchivs" #: cola/guicmds.py:110 #, python-format msgid "" "Output:\n" "%s" msgstr "" "Ausgabe:\n" "%s" #: cola/guicmds.py:132 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "Quell-Pfad oder -URL" #: cola/guicmds.py:153 msgid "Error Cloning" msgstr "Fehler beim Klonen" #: cola/guicmds.py:154 cola/guicmds.py:155 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "Die Adresse \"%s\" lässt sich nicht auswerten." #: cola/guicmds.py:159 msgid "Select a parent directory for the new clone" msgstr "Wählen Sie das übergeordnete Verzeichnis für den Klon" #: cola/guicmds.py:169 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "\"%s\" existiert bereits, git-cola wird ein neues Verzeichnis anlegen." #: cola/guicmds.py:185 cola/widgets/search.py:75 msgid "Export Patches" msgstr "Patches exportieren" #: cola/guicmds.py:214 cola/widgets/startup.py:124 msgid "Open Git Repository..." msgstr "Projektarchiv öffnen" #: cola/guicmds.py:223 msgid "Load Commit Message" msgstr "Versionsbeschreibung aus Datei einfügen" #: cola/guicmds.py:251 msgid "Select New Base" msgstr "Neuen Anfang auswählen" #: cola/guicmds.py:251 msgid "Rebase" msgstr "Anfang verschieben" #: cola/guicmds.py:261 msgid "Select Branch to Review" msgstr "Zweig zum Vergleichen auswählen" #: cola/guicmds.py:261 msgid "Review" msgstr "Vergleichen" #: cola/inotify.py:47 msgid "inotify is disabled because \"cola.inotify\" is false" msgstr "Inotify ist deaktiviert, da \"cola.inotify\" auf FALSCH gesetzt ist." #: cola/inotify.py:53 msgid "" "file notification: disabled\n" "Note: install pywin32 to enable.\n" msgstr "" "git-cola wird nicht über Änderungen im Dateisystem benachrichtigt.\n" "Installieren Sie pywin32, um diese Funktion zu nutzen.\n" #: cola/inotify.py:56 msgid "" "inotify: disabled\n" "Note: install python-pyinotify to enable inotify.\n" msgstr "" "inotify: deaktiviert\n" "Installieren Sie python-pyinotify, um diese Funktion zu nutzen.\n" #: cola/inotify.py:62 msgid "On Debian systems try: sudo aptitude install python-pyinotify" msgstr "" "Wenn Sie git-cola auf einem Debian-System gestartet haben, versuchen Sie es " "mit \"sudo aptitude install python-pyinotify\" " #: cola/inotify.py:71 msgid "File notification enabled." msgstr "Benachrichtigungen über Änderungen im Dateisystem aktiviert." #: cola/inotify.py:73 msgid "inotify enabled." msgstr "inotify aktiviert" #: cola/interaction.py:53 msgid "Continue" msgstr "Fortsetzen" #: cola/interaction.py:63 #, python-format msgid "Run %s?" msgstr "Möchten Sie \"%s\" ausführen?" #: cola/interaction.py:64 #, python-format msgid "Run the \"%s\" command?" msgstr "Möchten Sie den Befehl \"%s\" ausführen?" #: cola/interaction.py:65 cola/widgets/cfgactions.py:240 msgid "Run" msgstr "Ausführen" #: cola/interaction.py:72 #, python-format msgid "Exit code: %s" msgstr "Ende-Code: %s" #: cola/qt.py:60 cola/qt.py:100 msgid "Detach" msgstr "Loslösen" #: cola/qt.py:98 msgid "Attach" msgstr "Anhängen" #: cola/qtutils.py:396 msgid "Close..." msgstr "Schließen..." #: cola/classic/controller.py:69 msgid "Select Previous Version" msgstr "Vorherige Version auswählen" #: cola/classic/model.py:37 cola/widgets/createtag.py:51 #: cola/widgets/editremotes.py:220 msgid "Name" msgstr "" #: cola/classic/model.py:39 cola/main/view.py:91 msgid "Status" msgstr "Zustand" #: cola/classic/model.py:41 msgid "Age" msgstr "Alter" #: cola/classic/model.py:43 cola/widgets/createtag.py:74 msgid "Message" msgstr "Beschreibung" #: cola/classic/model.py:45 cola/dag/view.py:371 msgid "Author" msgstr "Autor" #: cola/classic/model.py:342 #, python-format msgid "%d minutes ago" msgstr "vor %d Minuten" #: cola/classic/model.py:345 #, python-format msgid "%d hours ago" msgstr "vor %d Stunden" #: cola/classic/model.py:346 #, python-format msgid "%d days ago" msgstr "vor %d Tagen" #: cola/classic/model.py:359 cola/widgets/status.py:73 msgid "Unmerged" msgstr "Nicht zusammengeführt" #: cola/classic/model.py:361 msgid "Partially Staged" msgstr "Teilweise vorgemerkt" #: cola/classic/model.py:363 cola/widgets/status.py:74 msgid "Modified" msgstr "Geändert" #: cola/classic/model.py:365 cola/widgets/status.py:72 msgid "Staged" msgstr "Vorgemerkt" #: cola/classic/model.py:367 msgid "Changed Upstream" msgstr "Im Quell-Projektarchiv geändert" #: cola/classic/view.py:47 cola/main/view.py:545 #, python-format msgid "Repository: %s" msgstr "Projektarchiv: %s" #: cola/classic/view.py:49 cola/main/view.py:547 #, python-format msgid "Branch: %s" msgstr "Zweig: %s" #: cola/classic/view.py:52 #, python-format msgid "%s: %s - Browse" msgstr "%s: %s - Übersicht" #: cola/classic/view.py:54 cola/main/view.py:552 msgid "Amending" msgstr "Am Nachbessern" #: cola/classic/view.py:79 msgid "View History..." msgstr "Verlauf anzeigen" #: cola/classic/view.py:80 msgid "View history for selected path(s)." msgstr "Zeige den Verlauf für den ausgewählten Pfad" #: cola/classic/view.py:84 cola/widgets/status.py:506 #: cola/widgets/status.py:536 cola/widgets/status.py:593 msgid "Stage Selected" msgstr "Auswahl vormerken" #: cola/classic/view.py:85 msgid "Stage selected path(s) for commit." msgstr "Änderungen am ausgewählten Pfad vormerken" #: cola/classic/view.py:90 cola/widgets/status.py:452 #: cola/widgets/status.py:494 msgid "Unstage Selected" msgstr "Vormerkung für Auswahl aufheben" #: cola/classic/view.py:91 msgid "Remove selected path(s) from the staging area." msgstr "Änderungen am ausgewählten Pfad nicht mehr vormerken" #: cola/classic/view.py:96 msgid "Untrack Selected" msgstr "Auswahl von Versionskontrolle ausnehmen" #: cola/classic/view.py:97 msgid "Stop tracking path(s)" msgstr "Führe keine Versionskontrolle für den ausgewählten Pfad durch" #: cola/classic/view.py:102 msgid "Launch git-difftool on the current path." msgstr "Aktuellen Pfad im Vergleichswerkzeug öffnen" #: cola/classic/view.py:106 msgid "Diff Against Predecessor..." msgstr "Mit einem Vorgänger vergleichen..." #: cola/classic/view.py:107 msgid "Launch git-difftool against previous versions." msgstr "Vergleicht mit einer Vorgängerversion." #: cola/classic/view.py:111 msgid "Revert Uncommitted Changes..." msgstr "Nicht versionierte Änderungen verwerfen" #: cola/classic/view.py:112 msgid "Revert changes to selected path(s)." msgstr "Verwirft Änderungen am ausgewählten Pfad" #: cola/classic/view.py:117 msgid "Edit selected path(s)." msgstr "Ausgewählten Pfad bearbeiten" #: cola/classic/view.py:293 cola/widgets/status.py:652 msgid "Revert Uncommitted Changes?" msgstr "Möchten Sie die Änderungen verwerfen?" #: cola/classic/view.py:294 cola/widgets/diff.py:246 cola/widgets/diff.py:259 #: cola/widgets/status.py:653 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "Damit verwerfen Sie unversionierte Änderungen.\n" "Dieser Schritt kann nicht rückgängig gemacht werden." #: cola/classic/view.py:296 cola/widgets/diff.py:248 cola/widgets/diff.py:261 #: cola/widgets/status.py:655 msgid "Revert the uncommitted changes?" msgstr "Möchten Sie die unversionierten Änderungen verwerfen?" #: cola/classic/view.py:297 cola/widgets/status.py:656 msgid "Revert Uncommitted Changes" msgstr "Unversionierte Änderungen zurücknehmen" #: cola/dag/view.py:166 msgid "Loading..." msgstr "Lade..." #: cola/dag/view.py:272 msgid "Diff this -> selected" msgstr "Mit Auswahl vergleichen" #: cola/dag/view.py:275 msgid "Diff selected -> this" msgstr "Auswahl mit diesem vergleichen" #: cola/dag/view.py:278 cola/widgets/createbranch.py:89 #: cola/widgets/createbranch.py:98 cola/widgets/createbranch.py:155 #: cola/widgets/createbranch.py:330 msgid "Create Branch" msgstr "Zweig erstellen" #: cola/dag/view.py:281 msgid "Create Patch" msgstr "Patch erstellen" #: cola/dag/view.py:284 cola/widgets/createtag.py:38 #: cola/widgets/createtag.py:99 msgid "Create Tag" msgstr "Markierung erzeugen" #: cola/dag/view.py:287 cola/main/view.py:208 msgid "Save As Tarball/Zip..." msgstr "Als TAR- oder ZIP-Archiv exportieren..." #: cola/dag/view.py:290 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "Einzelne Version übernehmen" #: cola/dag/view.py:293 msgid "Grab File..." msgstr "Datei extrahieren..." #: cola/dag/view.py:296 msgid "Copy SHA-1" msgstr "Eindeutigen Schlüssel der Version kopieren" #: cola/dag/view.py:371 msgid "Summary" msgstr "Zusammenfassung" #: cola/dag/view.py:371 msgid "Date, Time" msgstr "Datum und Zeit" #: cola/dag/view.py:378 msgid "Go Up" msgstr "Nach oben" #: cola/dag/view.py:381 msgid "Go Down" msgstr "Nach unten" #: cola/dag/view.py:511 cola/dag/view.py:1181 msgid "Zoom Out" msgstr "Verkleinern" #: cola/dag/view.py:514 cola/dag/view.py:1178 msgid "Zoom In" msgstr "Vergrößern" #: cola/dag/view.py:517 cola/dag/view.py:1184 msgid "Zoom to Fit" msgstr "In Ansicht einpassen" #: cola/dag/view.py:536 msgid "Log" msgstr "" #: cola/dag/view.py:541 cola/main/view.py:114 cola/main/view.py:384 msgid "Diff" msgstr "Vergleich" #: cola/dag/view.py:554 #, fuzzy msgid "Graph" msgstr "Suchen..." #: cola/dag/view.py:563 #, fuzzy msgid "View" msgstr "Vergleichen" #: cola/dag/view.py:636 #, python-format msgid "%s: %s - DAG" msgstr "%s: %s - Verlauf" #: cola/dag/view.py:638 msgid " - DAG" msgstr " - Verlauf" #: cola/dag/view.py:1187 msgid "Select Parent" msgstr "Vorgänger Auswählen" #: cola/dag/view.py:1190 msgid "Select Oldest Parent" msgstr "Ältesten Vorgänger auswählen" #: cola/dag/view.py:1193 msgid "Select Child" msgstr "Nachfolger auswählen" #: cola/dag/view.py:1196 msgid "Select Newest Child" msgstr "Jüngsten Nachfolger auswählen" #: cola/main/view.py:78 msgid "Browser" msgstr "Verzeichnisstruktur" #: cola/main/view.py:83 msgid "Action" msgstr "Befehle" #: cola/main/view.py:99 cola/merge/view.py:45 msgid "Commit" msgstr "Version" #: cola/main/view.py:108 msgid "Console" msgstr "Meldungen" #: cola/main/view.py:120 msgid "Ignore changes in whitespace at EOL" msgstr "Leerzeichen am Zeilenende ignorieren" #: cola/main/view.py:125 msgid "Ignore changes in amount of whitespace" msgstr "Anzahl von Leerzeichen ignorieren" #: cola/main/view.py:130 msgid "Ignore all whitespace" msgstr "Alle Leerzeichen ignorieren" #: cola/main/view.py:135 msgid "Show whole surrounding functions of changes" msgstr "Gesamte übergeordnete Funktion anzeigen" #: cola/main/view.py:139 cola/widgets/createbranch.py:194 msgid "Options" msgstr "Optionen" #: cola/main/view.py:141 cola/main/view.py:142 msgid "Diff Options" msgstr "Vergleichsoptionen" #: cola/main/view.py:157 cola/widgets/status.py:423 msgid "Unstage All" msgstr "Alle Vormerkungen aufheben" #: cola/main/view.py:161 msgid "Unstage From Commit" msgstr "Vormerkung dieser Datei aufheben" #: cola/main/view.py:165 msgid "Diffstat" msgstr "Vergleichsstatistik" #: cola/main/view.py:168 msgid "Stage Changed Files To Commit" msgstr "Geänderte Dateien vormerken" #: cola/main/view.py:173 msgid "Stage All Untracked" msgstr "Alle neuen Dateien vormerken" #: cola/main/view.py:178 msgid "Export Patches..." msgstr "Patches exportieren..." #: cola/main/view.py:181 #, fuzzy msgid "New Repository..." msgstr "Wähle Projektarchiv..." #: cola/main/view.py:185 cola/prefs/view.py:220 msgid "Preferences" msgstr "Einstellungen" #: cola/main/view.py:189 msgid "Edit Remotes..." msgstr "Externe Projektarchive verwalten..." #: cola/main/view.py:197 msgid "Recently Modified Files..." msgstr "Kürzlich geänderte Dateien suchen..." #: cola/main/view.py:201 msgid "Cherry-Pick..." msgstr "Version übernehmen..." #: cola/main/view.py:205 msgid "Load Commit Message..." msgstr "Versionsbeschreibung aus Datei einfügen..." #: cola/main/view.py:211 msgid "Quit" msgstr "Beenden" #: cola/main/view.py:213 msgid "Bookmarks..." msgstr "Favoriten..." #: cola/main/view.py:215 msgid "Grep" msgstr "Suchen..." #: cola/main/view.py:217 msgid "Merge..." msgstr "Zusammenführen..." #: cola/main/view.py:220 cola/merge/__init__.py:20 msgid "Abort Merge..." msgstr "Zusammenführung abbrechen..." #: cola/main/view.py:223 cola/widgets/action.py:20 msgid "Fetch..." msgstr "Abrufen..." #: cola/main/view.py:225 cola/widgets/action.py:21 msgid "Push..." msgstr "Veröffentlichen..." #: cola/main/view.py:227 cola/widgets/action.py:22 msgid "Pull..." msgstr "Abrufen und zusammenführen..." #: cola/main/view.py:230 cola/widgets/startup.py:36 msgid "Open..." msgstr "Öffnen..." #: cola/main/view.py:234 cola/widgets/action.py:23 msgid "Stash..." msgstr "Git-Zwischenablage..." #: cola/main/view.py:237 cola/widgets/startup.py:39 msgid "Clone..." msgstr "Klonen..." #: cola/main/view.py:241 msgid "Documentation" msgstr "Online-Hilfe" #: cola/main/view.py:245 msgid "Keyboard Shortcuts" msgstr "Tastenkürzel" #: cola/main/view.py:250 msgid "Visualize Current Branch..." msgstr "Verlauf ansehen (aktueller Zweig)" #: cola/main/view.py:253 msgid "Visualize All Branches..." msgstr "Verlauf ansehen (alle Zweige)" #: cola/main/view.py:256 msgid "Search..." msgstr "Suchen..." #: cola/main/view.py:258 msgid "Browse Current Branch..." msgstr "Verzeichnisstruktur ansehen (aktueller Zweig)" #: cola/main/view.py:260 msgid "Browse Other Branch..." msgstr "Verzeichnisstruktur ansehen (beliebiger Zweig)..." #: cola/main/view.py:262 msgid "Get Commit Message Template" msgstr "Versionsbeschreibung aus Vorlage einfügen" #: cola/main/view.py:265 msgid "About" msgstr "Über git-cola" #: cola/main/view.py:268 msgid "Expression..." msgstr "Mit Suchausdruck..." #: cola/main/view.py:270 msgid "Branches..." msgstr "Zweige..." #: cola/main/view.py:273 msgid "Create Tag..." msgstr "Neue Markierung..." #: cola/main/view.py:276 msgid "Create..." msgstr "Neu..." #: cola/main/view.py:279 msgid "Delete..." msgstr "Löschen..." #: cola/main/view.py:282 msgid "Delete Remote Branch..." msgstr "Externen Zweig löschen..." #: cola/main/view.py:285 msgid "Checkout..." msgstr "Wechseln..." #: cola/main/view.py:287 msgid "Rebase..." msgstr "Anfang verschieben..." #: cola/main/view.py:289 msgid "Review..." msgstr "Mit anderem Zweig vergleichen..." #: cola/main/view.py:292 msgid "Browser..." msgstr "Übersicht" #: cola/main/view.py:296 msgid "DAG..." msgstr "Verlauf" #: cola/main/view.py:313 msgid "File" msgstr "Projektarchiv" #: cola/main/view.py:316 msgid "Open Recent" msgstr "Kürzlich verwendetes Projektarchiv öffnen" #: cola/main/view.py:338 cola/main/view.py:339 msgid "Index" msgstr "Vormerkliste" #: cola/main/view.py:349 msgid "Branch" msgstr "Zweig" #: cola/main/view.py:367 msgid "Actions" msgstr "Befehle" #: cola/main/view.py:393 msgid "Tools" msgstr "Ansicht" #: cola/main/view.py:404 msgid "Help" msgstr "Hilfe" #: cola/main/view.py:462 #, python-format msgid "git cola version %s" msgstr "" #: cola/merge/__init__.py:21 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Achtung:\n" "Wenn Sie die Zusammenführung abbrechen, gehen alle noch nicht versionierten " "Änderungen unwiederbringlich verloren." #: cola/merge/__init__.py:24 msgid "Aborting the current merge?" msgstr "Möchten Sie die Zusammenführung abbrechen?" #: cola/merge/__init__.py:25 msgid "Abort Merge" msgstr "Zusammenführung abbrechen" #: cola/merge/view.py:23 msgid "Revision To Merge" msgstr "Zusammenführen von Zweig oder Markierung" #: cola/merge/view.py:28 cola/widgets/cfgactions.py:220 #: cola/widgets/remote.py:122 msgid "Local Branch" msgstr "Lokaler Zweig" #: cola/merge/view.py:31 cola/widgets/cfgactions.py:221 msgid "Tracking Branch" msgstr "Nachverfolgter Zweig" #: cola/merge/view.py:33 cola/widgets/cfgactions.py:222 #: cola/widgets/createbranch.py:122 msgid "Tag" msgstr "Markierung" #: cola/merge/view.py:39 msgid "Visualize" msgstr "In Verlaufsansicht anzeigen" #: cola/merge/view.py:42 msgid "Squash" msgstr "Versionen vereinigen" #: cola/merge/view.py:50 cola/widgets/archive.py:62 #: cola/widgets/editremotes.py:204 msgid "Cancel" msgstr "Abbrechen" #: cola/merge/view.py:53 msgid "Merge" msgstr "Zusammenführen" #: cola/merge/view.py:115 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "\"%(revision)s\" nach \"%(branch)s\" übernehmen" #: cola/merge/view.py:118 #, python-format msgid "Merge into \"%s\"" msgstr "Zusammenführen in »%s«" #: cola/merge/view.py:162 cola/merge/view.py:171 msgid "No Revision Specified" msgstr "Kein Zweig und keine Markierung ausgewählt" #: cola/merge/view.py:163 msgid "You must specify a revision to view." msgstr "" "Bitte wählen Sie zuerst einen Zweig oder \n" "eine Markierung für die Verlaufsansicht aus." #: cola/merge/view.py:172 msgid "You must specify a revision to merge." msgstr "" "Sie müssen einen Zweig oder eine Markierung für die Zusammenführung " "auswählen." #: cola/prefs/view.py:116 msgid "User Name" msgstr "Benutzername" #: cola/prefs/view.py:117 msgid "Email Address" msgstr "E-Mail-Adresse" #: cola/prefs/view.py:118 msgid "Merge Verbosity" msgstr "Ausführlichkeit der Meldungen beim Zusammenführen" #: cola/prefs/view.py:119 msgid "Number of Diff Context Lines" msgstr "Anzahl der Kontextzeilen beim Vergleich" #: cola/prefs/view.py:120 msgid "Summarize Merge Commits" msgstr "Zusammenfassung beim Zusammenführen anzeigen" #: cola/prefs/view.py:121 msgid "Show Diffstat After Merge" msgstr "Vergleichsstatistik nach Zusammenführen anzeigen" #: cola/prefs/view.py:122 msgid "Display Untracked Files" msgstr "" #: cola/prefs/view.py:163 msgid "Fixed-Width Font" msgstr "Schriftart" #: cola/prefs/view.py:164 msgid "Font Size" msgstr "Schriftgröße" #: cola/prefs/view.py:165 msgid "Tab Width" msgstr "Tabulatorweite" #: cola/prefs/view.py:166 msgid "Text Width" msgstr "Textbreite" #: cola/prefs/view.py:167 cola/widgets/commitmsg.py:99 msgid "Auto-Wrap Lines" msgstr "Zeilen automatisch umbrechen" #: cola/prefs/view.py:168 msgid "Editor" msgstr "Editor" #: cola/prefs/view.py:169 msgid "History Browser" msgstr "Werkzeug für die Verlaufsansicht" #: cola/prefs/view.py:170 msgid "Diff Tool" msgstr "Werkzeug zum Dateivergleich" #: cola/prefs/view.py:171 msgid "Merge Tool" msgstr "Werkzeug zum Zusammenführen" #: cola/prefs/view.py:172 msgid "Keep *.orig Merge Backups" msgstr "Sicherheitskopie beim Zusammenführen anlegen (Datei.orig)" #: cola/prefs/view.py:173 msgid "Save GUI Settings" msgstr "Einstellungen der Programmoberfläche sichern" #: cola/prefs/view.py:227 msgid "All Repositories" msgstr "Alle Projektarchive" #: cola/prefs/view.py:228 msgid "Current Repository" msgstr "Aktuelles Projektarchiv" #: cola/prefs/view.py:229 msgid "Settings" msgstr "Allgemein" #: cola/stash/view.py:28 msgid "Stash" msgstr "Git-Zwischenablage" #: cola/stash/view.py:38 msgid "Apply" msgstr "Anwenden" #: cola/stash/view.py:39 msgid "Apply the selected stash" msgstr "Die ausgewählte Ablage in den Arbeitsbereich zurück übernehmen" #: cola/stash/view.py:43 msgid "Save modified state to new stash" msgstr "Änderungen in einer neuen Ablage speichern" #: cola/stash/view.py:46 msgid "Drop" msgstr "Löschen" #: cola/stash/view.py:47 msgid "Drop the selected stash" msgstr "Die ausgewählte Ablage löschen" #: cola/stash/view.py:54 msgid "Keep Index" msgstr "Vormerkliste unverändert lassen" #: cola/stash/view.py:175 msgid "Save Stash" msgstr "Ablage speichern" #: cola/stash/view.py:176 msgid "Enter a name for the stash" msgstr "Geben Sie einen Namen für die Ablage an" #: cola/stash/view.py:182 msgid "Error: Stash exists" msgstr "Fehler: Diese Ablage existiert bereits" #: cola/stash/view.py:183 #, python-format msgid "A stash named \"%s\" already exists" msgstr "Eine Ablage mit dem Namen »%s« existiert bereits." #: cola/stash/view.py:198 msgid "Drop Stash?" msgstr "Möchten Sie die Ablage löschen?" #: cola/stash/view.py:199 msgid "Recovering a dropped stash is not possible." msgstr "Eine gelöschte Ablage kann nicht wiederhergestellt werden." #: cola/stash/view.py:200 #, python-format msgid "Drop the \"%s\" stash?" msgstr "Möchten Sie die Ablage \"%s\" löschen?" #: cola/stash/view.py:201 msgid "Drop Stash" msgstr "Ablage löschen" #: cola/widgets/about.py:47 msgid "About git-cola" msgstr "Über git-cola" #: cola/widgets/about.py:97 msgid "" "This PyQt4 does not include QtWebKit.\n" "The keyboard shortcuts feature is unavailable." msgstr "" "Das vorhandene PyQt4 enthält nicht die Komponente \"QtWebKit\".\n" "Deshalb ist die Anzeige der Tastenkürzel nicht verfügbar." #: cola/widgets/about.py:104 msgid "hotkeys.html" msgstr "hotkeys_de.html" #: cola/widgets/about.py:122 msgid "Shortcuts" msgstr "Tastenkürzel" #: cola/widgets/archive.py:46 msgid "Save Archive" msgstr "Als TAR- oder ZIP-Archiv exportieren" #: cola/widgets/archive.py:69 msgid "Prefix" msgstr "Verzeichnis" #: cola/widgets/archive.py:74 msgid "Advanced" msgstr "Erweitert" #: cola/widgets/archive.py:141 cola/widgets/browse.py:49 msgid "File Saved" msgstr "Datei gespeichert" #: cola/widgets/archive.py:142 cola/widgets/browse.py:50 #, python-format msgid "File saved to \"%s\"" msgstr "Datei \"%s\" gespeichert" #: cola/widgets/archive.py:149 msgid "Overwrite File?" msgstr "Möchten Sie die Datei überschreiben?" #: cola/widgets/archive.py:150 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "Die Datei \"%s\" existiert bereits und wird überschrieben." #: cola/widgets/archive.py:151 #, python-format msgid "Overwrite \"%s\"?" msgstr "Möchten Sie die Datei\"%s\" überschreiben?" #: cola/widgets/archive.py:152 msgid "Overwrite" msgstr "Überschreiben" #: cola/widgets/browse.py:42 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" "Datei \"%(filename)s\" von \"%(ref)s\" nach \"%(destination)s\" gesichert" #: cola/widgets/browse.py:63 #, python-format msgid "Browsing %s" msgstr "Verzeichnisstruktur von »%s«" #: cola/widgets/browse.py:81 #, python-format msgid "Select file from \"%s\"" msgstr "Wähle Datei von \"%s\" aus" #: cola/widgets/browse.py:90 msgid "Select File" msgstr "Wähle Datei aus" #: cola/widgets/browse.py:117 cola/widgets/selectcommits.py:54 msgid "Select" msgstr "Auswählen" #: cola/widgets/cfgactions.py:85 msgid "Abort" msgstr "Abbrechen" #: cola/widgets/cfgactions.py:147 cola/widgets/cfgactions.py:151 msgid "Abort Action" msgstr "Befehl abbrechen" #: cola/widgets/cfgactions.py:148 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "Zurzeit wird noch ein Befehl ausgeführt.\n" "Wenn Sie ihn abbrechen, könnten Daten verloren gehen." #: cola/widgets/cfgactions.py:150 msgid "Abort the action?" msgstr "Möchten Sie den Befehl abbrechen?" #: cola/widgets/cfgactions.py:201 msgid "Arguments" msgstr "Argumente" #: cola/widgets/cfgactions.py:226 cola/widgets/createtag.py:85 msgid "Revision" msgstr "Version" #: cola/widgets/commitmsg.py:50 msgid "Sign off on this commit" msgstr "Unterzeichne diese Version" #: cola/widgets/commitmsg.py:53 cola/widgets/commitmsg.py:69 msgid "Commit@@verb" msgstr "Version aufnehmen" #: cola/widgets/commitmsg.py:56 msgid "Commit staged changes" msgstr "Vorgemerkte Änderungen versionieren" #: cola/widgets/commitmsg.py:67 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "Vorgemerkte Änderungen versionieren\n" "Tastenkürzel: Strg+Enter" #: cola/widgets/commitmsg.py:75 msgid "Actions..." msgstr "Befehle..." #: cola/widgets/commitmsg.py:85 msgid "Amend Last Commit" msgstr "Letzte Version nachbessern" #: cola/widgets/commitmsg.py:92 msgid "Check Spelling" msgstr "Rechtschreibung prüfen" #: cola/widgets/commitmsg.py:104 msgid "Load Previous Commit Message" msgstr "Lade zuletzt verwendete Versionsbeschreibung" #: cola/widgets/commitmsg.py:135 cola/widgets/status.py:117 msgid "Move Down" msgstr "Nach unten bewegen" #: cola/widgets/commitmsg.py:342 msgid "" "Please supply a commit message.\n" "\n" "A good commit message has the following format:\n" "\n" "- First line: Describe in one sentence what you did.\n" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" "Bitte geben Sie eine Versionsbeschreibung ein.\n" "\n" "Eine gute Versionsbeschreibung enthält folgende Abschnitte:\n" "\n" "- Erste Zeile: Eine Zusammenfassung, was man gemacht hat.\n" "\n" "- Zweite Zeile: Leerzeile\n" "\n" "- Rest: Eine ausführliche Beschreibung, warum diese Änderung hilfreich ist.\n" #: cola/widgets/commitmsg.py:349 msgid "Missing Commit Message" msgstr "Die Versionsbeschreibung fehlt" #: cola/widgets/commitmsg.py:355 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Keine Änderungen vorhanden, die versioniert werden könnten.\n" "\n" "Bitte stellen Sie mindestens eine geänderte Datei bereit." #: cola/widgets/commitmsg.py:359 msgid "Would you like to stage and commit all modified files?" msgstr "Möchten Sie alle veränderten Dateien vormerken und versionieren?" #: cola/widgets/commitmsg.py:361 msgid "Stage and commit?" msgstr "Vormerken und versionieren?" #: cola/widgets/commitmsg.py:364 msgid "Stage and Commit" msgstr "Vormerken und versionieren" #: cola/widgets/commitmsg.py:369 msgid "Nothing to commit" msgstr "Keine Änderungen, die eingetragen werden können." #: cola/widgets/commitmsg.py:376 msgid "Rewrite Published Commit?" msgstr "Möchten Sie die bereits veröffentlichte Version nochmals schreiben?" #: cola/widgets/commitmsg.py:377 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "Diese Version wurde bereits veröffentlicht.\n" "Mit dieser Operation werden Sie den Verlauf im externen Projektarchiv " "verändern.Möchten Sie das wirklich?" #: cola/widgets/commitmsg.py:380 msgid "Amend the published commit?" msgstr "Möchten Sie die veröffentlichte Version nachbessern?" #: cola/widgets/commitmsg.py:381 msgid "Amend Commit" msgstr "Letzte Version nachbessern" #: cola/widgets/commitmsg.py:386 msgid "Commit failed" msgstr "Versionierung fehlgeschlagen." #: cola/widgets/commitmsg.py:387 #, python-format msgid "\"git commit\" returned exit code %s" msgstr "\"git commit\" wurde mit dem Code %s beendet" #: cola/widgets/commitmsg.py:409 msgid "More..." msgstr "Mehr..." #: cola/widgets/commitmsg.py:413 msgid "Select Commit Message" msgstr "Wählen Sie eine Versionsbeschreibung aus" #: cola/widgets/commitmsg.py:450 msgid "Commit summary" msgstr "Kurzbeschreibung der Version" #: cola/widgets/commitmsg.py:465 msgid "Extended description..." msgstr "Ausführliche Versionsbeschreibung" #: cola/widgets/compare.py:37 msgid "*** Branch Point ***" msgstr "*** Abzweigung ***" #: cola/widgets/compare.py:38 msgid "*** Sandbox ***" msgstr "*** Arbeitsbereich ***" #: cola/widgets/compare.py:39 cola/widgets/compare.py:62 #: cola/widgets/compare.py:68 msgid "Local" msgstr "Lokal" #: cola/widgets/compare.py:44 msgid "Branch Diff Viewer" msgstr "Zweige vergleichen" #: cola/widgets/compare.py:63 cola/widgets/compare.py:69 #: cola/widgets/remote.py:129 msgid "Remote" msgstr "Externes Projektarchiv" #: cola/widgets/compare.py:98 msgid "File Differences" msgstr "Dateiunterschiede" #: cola/widgets/createbranch.py:102 msgid "Branch Name" msgstr "Name des Zweigs" #: cola/widgets/createbranch.py:107 cola/widgets/createbranch.py:178 msgid "Starting Revision" msgstr "Abzweigen von" #: cola/widgets/createbranch.py:115 msgid "Local branch" msgstr "Lokalem Zweig" #: cola/widgets/createbranch.py:119 msgid "Tracking branch" msgstr "Nachverfolgtem Zweig" #: cola/widgets/createbranch.py:127 msgid "Update Existing Branch:" msgstr "Existierenden Zweig aktualisieren:" #: cola/widgets/createbranch.py:130 msgid "No" msgstr "Nein" #: cola/widgets/createbranch.py:133 msgid "Fast Forward Only" msgstr "Bei lokalen Änderungen abbrechen" #: cola/widgets/createbranch.py:137 msgid "Reset" msgstr "Zurücksetzen" #: cola/widgets/createbranch.py:143 msgid "Fetch Tracking Branch" msgstr "Nachverfolgten Zweig abrufen" #: cola/widgets/createbranch.py:148 msgid "Checkout After Creation" msgstr "Zweig nach dem Erstellen im Arbeitsbereich bearbeiten" #: cola/widgets/createbranch.py:259 msgid "Missing Data" msgstr "Fehlende Daten" #: cola/widgets/createbranch.py:260 msgid "Please provide both a branch name and revision expression." msgstr "Bitte geben Sie Zweig und Revision an." #: cola/widgets/createbranch.py:265 #, python-format msgid "Branch \"%s\" already exists." msgstr "Der Zweig »%s« existiert bereits." #: cola/widgets/createbranch.py:266 cola/widgets/createbranch.py:277 msgid "Branch Exists" msgstr "Zweig existiert bereits" #: cola/widgets/createbranch.py:273 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "" "Beim Zurücksetzen von »\"%(branch)s\" « nach »\"%(revision)s\"« werden " "Versionen verworfen." #: cola/widgets/createbranch.py:288 #, python-format msgid "%d skipped" msgstr "%d übersprungen" #: cola/widgets/createbranch.py:290 msgid "Recovering lost commits may not be easy." msgstr "" "Verworfene Versionen können nur mit größerem Aufwand wiederhergestellt " "werden." #: cola/widgets/createbranch.py:292 msgid "Reset Branch?" msgstr "Zweig zurücksetzen?" #: cola/widgets/createbranch.py:294 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "Möchten Sie \"%(branch)s\" auf \"%(revision)s\" zurücksetzen?" #: cola/widgets/createbranch.py:296 msgid "Reset Branch" msgstr "Zweig zurücksetzen" #: cola/widgets/createbranch.py:305 msgid "Updating..." msgstr "Aktualisiere..." #: cola/widgets/createbranch.py:321 msgid "Error Creating Branch" msgstr "Fehler beim Erstellen des Zweigs" #: cola/widgets/createbranch.py:322 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" "Das Kommando \"%(command)s\" wurde mit dem Code \"%(status)d\" beendet." #: cola/widgets/createbranch.py:331 msgid "Branch created" msgstr "Zweig erzeugt" #: cola/widgets/createtag.py:55 msgid "vX.Y.Z" msgstr "Eindeutige Kurzbezeichnung, z.B. v.X.Y.Z" #: cola/widgets/createtag.py:56 msgid "Specifies the tag name" msgstr "Legt den Namen der Markierung fest" #: cola/widgets/createtag.py:62 msgid "Sign Tag" msgstr "Markierung unterzeichnen" #: cola/widgets/createtag.py:67 msgid "Whether to sign the tag (git tag -s)" msgstr "" "Legt fest, ob die Markierung unterzeichnet werden soll (siehe Befehl 'git " "tag -s')" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Beschreibung" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "Legt die Beschreibung der Markierung fest." #: cola/widgets/createtag.py:91 msgid "Specifies the SHA-1 to tag" msgstr "Legt den SHA-1-Wert für die Markierung fest" #: cola/widgets/createtag.py:121 msgid "Missing Revision" msgstr "Zweig oder Markierung fehlt" #: cola/widgets/createtag.py:122 msgid "Please specify a revision to tag." msgstr "Bitte wählen Sie einen Zweig zum markieren" #: cola/widgets/createtag.py:125 msgid "Missing Name" msgstr "Fehlender Name" #: cola/widgets/createtag.py:126 msgid "Please specify a name for the new tag." msgstr "Bitte geben Sie einen Namen für die neue Markierung an." #: cola/widgets/createtag.py:129 msgid "Missing Tag Message" msgstr "Die Markierung hat keine Beschreibung" #: cola/widgets/createtag.py:130 msgid "Tag-signing was requested but the tag message is empty." msgstr "" "Die Markierung sollte unterzeichnet werden, aber die dafür notwendige " "Beschreibung des Inhalts fehlt." #: cola/widgets/createtag.py:132 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "Anstelle dessen wird eine einfache, nicht unterzeichnete Markierung " "erstellt.\n" "Möchten Sie fortfahren?" #: cola/widgets/createtag.py:135 msgid "Create Unsigned Tag" msgstr "Erzeuge nicht unterzeichnete Markierung" #: cola/widgets/createtag.py:142 msgid "Tag Created" msgstr "Markierung erzeugt" #: cola/widgets/createtag.py:143 #, python-format msgid "Created a new tag named \"%s\"" msgstr "Erzeuge eine Markierung mit dem Namen \"%s\"" #: cola/widgets/diff.py:22 msgid "Process Section" msgstr "Abschnitt verarbeiten" #: cola/widgets/diff.py:25 msgid "Process Selection" msgstr "Auswahl verarbeiten" #: cola/widgets/diff.py:40 msgid "Stage &Selected Lines" msgstr "Änderungen an den ausgewählte Zeilen vormerken" #: cola/widgets/diff.py:46 msgid "Revert Selected Lines..." msgstr "Änderungen an ausgewählte Zeilen verwerfen" #: cola/widgets/diff.py:51 msgid "Unstage &Selected Lines" msgstr "Änderungen an ausgewählten Zeilen nicht vormerken" #: cola/widgets/diff.py:57 msgid "Apply Diff Selection to Work Tree" msgstr "Auswahl auf den Arbeitsbereich anwenden" #: cola/widgets/diff.py:86 cola/widgets/diff.py:108 cola/widgets/status.py:486 #: cola/widgets/status.py:584 msgid "Launch git-cola" msgstr "Starte git-cola" #: cola/widgets/diff.py:91 msgid "Stage Section" msgstr "Änderungen am Abschnitt vormerken" #: cola/widgets/diff.py:97 msgid "Revert Section..." msgstr "Abschnitt verwerfen..." #: cola/widgets/diff.py:113 msgid "Unstage Section" msgstr "Änderungen am Abschnitt nicht vormerken" #: cola/widgets/diff.py:125 msgid "Copy" msgstr "Kopieren" #: cola/widgets/diff.py:129 msgid "Select All" msgstr "Alle auswählen" #: cola/widgets/diff.py:245 msgid "Revert Section?" msgstr "Möchten Sie den Abschnitt verwerfen?" #: cola/widgets/diff.py:249 msgid "Revert Section" msgstr "Abschnitt verwerfen" #: cola/widgets/diff.py:258 msgid "Revert Selected Lines?" msgstr "Möchten Sie die Änderungen an den ausgewählten Zeilen verwerfen?" #: cola/widgets/diff.py:262 msgid "Revert Selected Lines" msgstr "Änderungen an den ausgewählten Zeilen verwerfen" #: cola/widgets/editremotes.py:19 msgid "Edit Remotes" msgstr "Externe Projektarchive verwalten" #: cola/widgets/editremotes.py:22 msgid "" "Add and remove remote repositories using the \n" "Add(+) and Delete(-) buttons on the left-hand side.\n" "\n" "Remotes can be renamed by selecting one from the list\n" "and pressing \"enter\", or by double-clicking." msgstr "" "Verwenden Sie die Knöpfe unterhalb der Liste auf der linken Seite,\n" "um externe Projektarchive zur Liste hinzuzufügen, zu löschen oder\n" "die Liste zu aktualisieren. Um den Namen eines externen Projekt-\n" "archivs zu ändern, wählen Sie es aus und drücken die \"Enter\"-\n" "Taste oder klicken doppelt mit der Maus darauf." #: cola/widgets/editremotes.py:32 msgid "Remote git repositories - double-click to rename" msgstr "Externe Projektarchive - zum Umbenennen doppelklicken" #: cola/widgets/editremotes.py:45 msgid "Add new remote git repository" msgstr "Externes Projektarchiv hinzufügen" #: cola/widgets/editremotes.py:53 msgid "Delete remote" msgstr "Externes Projektarchiv entfernen" #: cola/widgets/editremotes.py:116 #, python-format msgid "Error creating remote \"%s\"" msgstr "Fehler beim Hinzufügen des externen Projektarchivs \"%s\"" #: cola/widgets/editremotes.py:124 msgid "Delete Remote" msgstr "Externes Projektarchiv entfernen" #: cola/widgets/editremotes.py:125 msgid "Delete remote?" msgstr "Möchten Sie das externe Projektarchiv entfernen?" #: cola/widgets/editremotes.py:126 #, python-format msgid "Delete remote \"%s\"" msgstr "Entferne externes Projektarchiv \"%s\"" #: cola/widgets/editremotes.py:134 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Fehler beim Entfernen des externen Projektarchivs \"%s\"" #: cola/widgets/editremotes.py:153 msgid "Rename Remote" msgstr "Externes Projektarchiv umbenennen" #: cola/widgets/editremotes.py:154 msgid "Rename remote?" msgstr "Möchten Sie das externe Projektarchiv umbenennen?" #: cola/widgets/editremotes.py:155 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "Benenne das externe Projektarchiv \"%(current)s\" um zu \"%(new)s\"." #: cola/widgets/editremotes.py:157 msgid "Rename" msgstr "Umbenennen" #: cola/widgets/editremotes.py:169 #, python-format msgid "Gathering info for \"%s\"..." msgstr "Frage Informationen zu »%s« ab..." #: cola/widgets/editremotes.py:201 msgid "Add Remote" msgstr "Hinzufügen" #: cola/widgets/editremotes.py:213 msgid "Add remote" msgstr "Externes Projektarchiv hinzufügen" #: cola/widgets/editremotes.py:214 msgid "Name for the new remote" msgstr "Name des neuen externen Projektarchivs" #: cola/widgets/editremotes.py:221 msgid "URL" msgstr "URL" #: cola/widgets/grep.py:47 cola/widgets/search.py:40 cola/widgets/search.py:58 msgid "Search" msgstr "Suchen" #: cola/widgets/grep.py:52 msgid "command-line arguments" msgstr "Kommandozeilenargumente" #: cola/widgets/grep.py:56 msgid "grep result..." msgstr "Suchergebnis" #: cola/widgets/grep.py:69 msgid "Shell arguments" msgstr "Als Kommandozeilenargumente" #: cola/widgets/grep.py:71 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "Führt die Suche in einer Kommandozeile aus.\n" "Setzen Sie Texte mit Leerzeichen in \"Gänsefüßchen\"." #: cola/widgets/log.py:34 #, python-format msgid "exit code %s" msgstr "Ende-Code %s" #: cola/widgets/recent.py:36 msgid "Recently Modified Files" msgstr "Kürzlich geänderte Dateien suchen" #: cola/widgets/recent.py:46 msgid " commits ago" msgstr " Versionen davor" #: cola/widgets/recent.py:49 msgid "Showing changes since" msgstr "Änderungen seit" #: cola/widgets/recent.py:61 msgid "Expand" msgstr "Ausklappen" #: cola/widgets/recent.py:65 msgid "Collapse" msgstr "Zuklappen" #: cola/widgets/remote.py:136 msgid "Remote Branch" msgstr "Externer Zweig" #: cola/widgets/remote.py:143 msgid "Fast Forward Only " msgstr "Nur Fast Forward" #: cola/widgets/remote.py:147 msgid "Include tags " msgstr "Markierungen übernehmen" #: cola/widgets/remote.py:150 msgid "Rebase " msgstr "Zweiganfang verschieben" #: cola/widgets/remote.py:314 #, python-format msgid "URL: %s" msgstr "URL: %s" #: cola/widgets/remote.py:393 msgid "No repository selected." msgstr "Kein Projektarchiv ausgewählt." #: cola/widgets/remote.py:406 msgid "Push" msgstr "Veröffentlichen" #: cola/widgets/remote.py:408 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "Der Zweig \"%(branch)s\" existiert nicht im externen Projektarchiv \"%" "(remote)s\".\n" "Dort wird damit ein neuer Zweig angelegt." #: cola/widgets/remote.py:410 msgid "Create a new remote branch?" msgstr "Möchten Sie einen neuen Zweig im externen Projektarchiv erzeugen?" #: cola/widgets/remote.py:411 msgid "Create Remote Branch" msgstr "Neuen Zweig im externen Projektarchiv erzeugen" #: cola/widgets/remote.py:419 msgid "Force Fetch?" msgstr "Möchten Sie den Abruf erzwingen?" #: cola/widgets/remote.py:420 msgid "Non-fast-forward fetch overwrites local history!" msgstr "Achtung: Die lokale Vormerkliste wird dabei überschrieben!" #: cola/widgets/remote.py:421 #, python-format msgid "Force fetching from %s?" msgstr "Möchten Sie den Abruf von \"%s\" erzwingen?" #: cola/widgets/remote.py:422 msgid "Force Fetch" msgstr "Abruf erzwingen" #: cola/widgets/remote.py:424 msgid "Force Push?" msgstr "Möchten Sie die Veröffentlichung erzwingen?" #: cola/widgets/remote.py:425 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "Achtung: Die Vormerkliste beim externen Projektarchiv wird dabei " "überschrieben!\n" "Haben Sie zuerst die externen Versionen bei sich übernommen?" #: cola/widgets/remote.py:427 #, python-format msgid "Force push to %s?" msgstr "Möchten Sie die Veröffentlichung in \"%s\" erzwingen?" #: cola/widgets/remote.py:428 msgid "Force Push" msgstr "Veröffentlichung erzwingen" #: cola/widgets/remote.py:462 msgid "Already up-to-date." msgstr "Ist bereits aktuell" #: cola/widgets/remote.py:485 msgid "Have you rebased/pulled lately?" msgstr "" "Haben Sie neulich Änderungen abgeholt und ggf. den Zweiganfang verschoben?" #: cola/widgets/search.py:44 msgid "Browse..." msgstr "..." #: cola/widgets/search.py:50 cola/widgets/search.py:55 msgid "yyyy-MM-dd" msgstr "" #: cola/widgets/search.py:220 msgid "Search by Expression" msgstr "Regulärer Ausdruck" #: cola/widgets/search.py:221 msgid "Search by Path" msgstr "Datei" #: cola/widgets/search.py:222 msgid "Search Commit Messages" msgstr "In Versionsbeschreibungen" #: cola/widgets/search.py:223 msgid "Search Diffs" msgstr "In Versionsunterschieden" #: cola/widgets/search.py:224 msgid "Search Authors" msgstr "Autor" #: cola/widgets/search.py:225 msgid "Search Committers" msgstr "Eintragender" #: cola/widgets/search.py:226 msgid "Search Date Range" msgstr "Datum von-bis" #: cola/widgets/search.py:319 msgid "Choose Path(s)" msgstr "Pfad wählen" #: cola/widgets/selectcommits.py:50 msgid "Revision Expression:" msgstr "Eindeutiger Schlüssel der Version" #: cola/widgets/selectcommits.py:101 msgid "No commits exist in this branch." msgstr "In diesem Zweig sind keine Versionen gespeichert" #: cola/widgets/spellcheck.py:139 msgid "Spelling Suggestions" msgstr "Rechtschreibvorschläge" #: cola/widgets/startup.py:26 msgid "git-cola" msgstr "" #: cola/widgets/startup.py:33 msgid "New..." msgstr "Neu..." #: cola/widgets/startup.py:56 msgid "Select Repository..." msgstr "Wähle Projektarchiv..." #: cola/widgets/startup.py:61 msgid "Select manually..." msgstr "Selbst auswählen..." #: cola/widgets/status.py:75 msgid "Untracked" msgstr "Nicht unter Versionskontrolle" #: cola/widgets/status.py:85 msgid "Stage / Unstage" msgstr "Vormerken/Nicht vormerken" #: cola/widgets/status.py:114 msgid "Move Up" msgstr "Nach oben bewegen" #: cola/widgets/status.py:121 msgid "Copy Path to Clipboard" msgstr "Kopiere Pfad in Zwischenablage" #: cola/widgets/status.py:474 cola/widgets/status.py:550 msgid "Revert Unstaged Edits..." msgstr "Nicht vorgemerkte Änderungen zurücknehmen..." #: cola/widgets/status.py:477 cola/widgets/status.py:553 msgid "Revert Uncommited Edits..." msgstr "Nicht versionierte Änderungen zurücknehmen..." #: cola/widgets/status.py:572 msgid "Delete File(s)..." msgstr "Lösche Datei(en)..." #: cola/widgets/status.py:575 msgid "Add to .gitignore" msgstr "Von Versionskontrolle ausschließen" #: cola/widgets/status.py:608 msgid "Delete Files?" msgstr "Datei(en) löschen?" #: cola/widgets/status.py:609 msgid "The following files will be deleted:" msgstr "Die folgenden Zeilen werden gleich gelöscht:" #: cola/widgets/status.py:616 #, python-format msgid "Delete %d file(s)?" msgstr "Wollen Sie %d Datei(en) löschen?" #: cola/widgets/status.py:617 msgid "Delete Files" msgstr "Lösche Dateien" #: cola/widgets/status.py:633 msgid "Revert Unstaged Changes?" msgstr "Wollen sie die nicht vorgemerkten Änderungen zurücknehmen?" #: cola/widgets/status.py:634 msgid "" "This operation drops unstaged changes.\n" "These changes cannot be recovered." msgstr "" "Damit verwerfen Sie nicht vorgemerkte Änderungen.\n" "Diese können nicht mehr wiederhergestellt werden." #: cola/widgets/status.py:636 msgid "Revert the unstaged changes?" msgstr "Möchten Sie die nicht vorgemerkten Änderungen zurücknehmen?" #: cola/widgets/status.py:637 msgid "Revert Unstaged Changes" msgstr "Nehme nicht vorgemerkte Änderungen zurück" #: cola/widgets/status.py:646 cola/widgets/status.py:662 msgid "No files selected for checkout from HEAD." msgstr "Es sind keine Dateien zum Auschecken von HEAD ausgewählt." #~ msgid "Display" #~ msgstr "Anzeigen" #~ msgid "Success" #~ msgstr "Erfolgreich" #~ msgid "\"git %s\" succeeded." #~ msgstr "\"git %s\" erfolgreich ausgeführt." #~ msgid "Launch Merge Tool" #~ msgstr "Starte Werkzeug für die Zusammenführung" #~ msgid "Rescan" #~ msgstr "Ansicht aktualisieren" #~ msgid "Browse Revision..." #~ msgstr "Zweig oder Markierung wählen" #~ msgid "Rebase Branch" #~ msgstr "Anfang des Zweigs verschieben" #~ msgid "Fetch" #~ msgstr "Abrufen" #~ msgid "Pull" #~ msgstr "Abrufen und zusammenführen" #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: Programmfehler" #~ msgid "Invalid font specified in %s:" #~ msgstr "Ungültige Zeichensatz-Angabe in %s:" #~ msgid "Main Font" #~ msgstr "Programmschriftart" #~ msgid "Diff/Console Font" #~ msgstr "Vergleich-Schriftart" #~ msgid "Cannot find git in PATH." #~ msgstr "Git kann im PATH nicht gefunden werden." #~ msgid "Cannot parse Git version string:" #~ msgstr "Git Versionsangabe kann nicht erkannt werden:" #~ msgid "" #~ "Git version cannot be determined.\n" #~ "\n" #~ "%s claims it is version '%s'.\n" #~ "\n" #~ "%s requires at least Git 1.5.0 or later.\n" #~ "\n" #~ "Assume '%s' is version 1.5.0?\n" #~ msgstr "" #~ "Die Version von Git kann nicht bestimmt werden.\n" #~ "\n" #~ "»%s« behauptet, es sei Version »%s«.\n" #~ "\n" #~ "%s benötigt mindestens Git 1.5.0 oder höher.\n" #~ "\n" #~ "Soll angenommen werden, »%s« sei Version 1.5.0?\n" #~ msgid "Git directory not found:" #~ msgstr "Git-Verzeichnis nicht gefunden:" #~ msgid "Cannot move to top of working directory:" #~ msgstr "" #~ "Es konnte nicht in das oberste Verzeichnis der Arbeitskopie gewechselt " #~ "werden:" #~ msgid "Cannot use funny .git directory:" #~ msgstr "Unerwartete Struktur des .git Verzeichnis:" #~ msgid "No working directory" #~ msgstr "Kein Arbeitsverzeichnis" #~ msgid "Refreshing file status..." #~ msgstr "Dateistatus aktualisieren..." #~ msgid "Ready." #~ msgstr "Bereit." #~ msgid "Modified, not staged" #~ msgstr "Verändert, nicht bereitgestellt" #~ msgid "Portions staged for commit" #~ msgstr "Teilweise bereitgestellt zum Eintragen" #~ msgid "Staged for commit, missing" #~ msgstr "Bereitgestellt zum Eintragen, fehlend" #~ msgid "Staged for removal" #~ msgstr "Bereitgestellt zum Löschen" #~ msgid "Staged for removal, still present" #~ msgstr "Bereitgestellt zum Löschen, trotzdem vorhanden" #~ msgid "Requires merge resolution" #~ msgstr "Konfliktauflösung nötig" #~ msgid "Starting gitk... please wait..." #~ msgstr "Gitk wird gestartet... bitte warten." #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "Gitk kann nicht gestartet werden:\n" #~ "\n" #~ "%s existiert nicht" #~ msgid "Repository" #~ msgstr "Projektarchiv" #~ msgid "Commit@@noun" #~ msgstr "Version" #~ msgid "Browse %s's Files" #~ msgstr "Zweig »%s« durchblättern" #~ msgid "Visualize %s's History" #~ msgstr "Historie von »%s« darstellen" #~ msgid "Database Statistics" #~ msgstr "Datenbankstatistik" #~ msgid "Compress Database" #~ msgstr "Datenbank komprimieren" #~ msgid "Verify Database" #~ msgstr "Datenbank überprüfen" #~ msgid "Create Desktop Icon" #~ msgstr "Desktop-Icon erstellen" #~ msgid "Undo" #~ msgstr "Rückgängig" #~ msgid "Redo" #~ msgstr "Wiederholen" #~ msgid "Cut" #~ msgstr "Ausschneiden" #~ msgid "Paste" #~ msgstr "Einfügen" #~ msgid "Rename..." #~ msgstr "Umbenennen..." #~ msgid "New Commit" #~ msgstr "Neue Version" #~ msgid "Local Merge..." #~ msgstr "Lokales Zusammenführen..." #~ msgid "Preferences..." #~ msgstr "Einstellungen..." #~ msgid "Current Branch:" #~ msgstr "Aktueller Zweig:" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "Bereitstellung (zum Eintragen)" #~ msgid "Initial Commit Message:" #~ msgstr "Erste Versionsbeschreibung:" #~ msgid "Amended Commit Message:" #~ msgstr "Nachgebesserte Beschreibung:" #~ msgid "Amended Initial Commit Message:" #~ msgstr "Nachgebesserte erste Beschreibung:" #~ msgid "Amended Merge Commit Message:" #~ msgstr "Nachgebesserte Zusammenführungs-Beschreibung:" #~ msgid "Apply/Reverse Hunk" #~ msgstr "Kontext anwenden/umkehren" #~ msgid "Show Less Context" #~ msgstr "Weniger Zeilen anzeigen" #~ msgid "Show More Context" #~ msgstr "Mehr Zeilen anzeigen" #~ msgid "Decrease Font Size" #~ msgstr "Schriftgröße verkleinern" #~ msgid "Increase Font Size" #~ msgstr "Schriftgröße vergrößern" #~ msgid "Unstage Hunk From Commit" #~ msgstr "Kontext aus Bereitstellung herausnehmen" #~ msgid "Stage Hunk For Commit" #~ msgstr "Kontext zur Bereitstellung hinzufügen" #~ msgid "Initializing..." #~ msgstr "Initialisieren..." #~ msgid "" #~ "Possible environment issues exist.\n" #~ "\n" #~ "The following environment variables are probably\n" #~ "going to be ignored by any Git subprocess run\n" #~ "by %s:\n" #~ "\n" #~ msgstr "" #~ "Möglicherweise gibt es Probleme mit manchen Umgebungsvariablen.\n" #~ "\n" #~ "Die folgenden Umgebungsvariablen können vermutlich nicht \n" #~ "von %s an Git weitergegeben werden:\n" #~ "\n" #~ msgid "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "Dies ist ein bekanntes Problem der Tcl-Version, die\n" #~ "in Cygwin mitgeliefert wird." #~ msgid "" #~ "\n" #~ "\n" #~ "A good replacement for %s\n" #~ "is placing values for the user.name and\n" #~ "user.email settings into your personal\n" #~ "~/.gitconfig file.\n" #~ msgstr "" #~ "\n" #~ "\n" #~ "Um den Namen »%s« zu ändern, sollten Sie die \n" #~ "gewünschten Werte für die Einstellung user.name und \n" #~ "user.email in Ihre Datei ~/.gitconfig einfügen.\n" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - eine grafische Oberfläche für Git." #~ msgid "File Viewer" #~ msgstr "Datei-Browser" #~ msgid "Reading %s..." #~ msgstr "%s lesen..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "Annotierungen für Kopieren/Verschieben werden geladen..." #~ msgid "lines annotated" #~ msgstr "Zeilen annotiert" #~ msgid "Loading original location annotations..." #~ msgstr "Annotierungen für ursprünglichen Ort werden geladen..." #~ msgid "Annotation complete." #~ msgstr "Annotierung vollständig." #~ msgid "Loading annotation..." #~ msgstr "Annotierung laden..." #~ msgid "Original File:" #~ msgstr "Ursprüngliche Datei:" #~ msgid "Originally By:" #~ msgstr "Ursprünglich von:" #~ msgid "In File:" #~ msgstr "In Datei:" #~ msgid "Copied Or Moved Here By:" #~ msgstr "Kopiert oder verschoben durch:" #~ msgid "Detach From Local Branch" #~ msgstr "Verbindung zu lokalem Zweig lösen" #~ msgid "Match Tracking Branch Name" #~ msgstr "Passend zu Übernahmezweig-Name" #~ msgid "Tracking branch %s is not a branch in the remote repository." #~ msgstr "Übernahmezweig »%s« ist kein Zweig im anderen Projektarchiv." #~ msgid "Please supply a branch name." #~ msgstr "Bitte geben Sie einen Zweignamen an." #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "»%s« ist kein zulässiger Zweigname." #~ msgid "Delete Local Branch" #~ msgstr "Lokalen Zweig löschen" #~ msgid "Local Branches" #~ msgstr "Lokale Zweige" #~ msgid "Delete Only If Merged Into" #~ msgstr "Nur löschen, wenn zusammengeführt nach" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "Immer (ohne Zusammenführungstest)" #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "Folgende Zweige sind noch nicht mit »%s« zusammengeführt:" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "Gelöschte Zweige können nur mit größerem Aufwand wiederhergestellt " #~ "werden.\n" #~ "\n" #~ "Gewählte Zweige jetzt löschen?" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "Fehler beim Löschen der Zweige:\n" #~ "%s" #~ msgid "New Name:" #~ msgstr "Neuer Name:" #~ msgid "Failed to rename '%s'." #~ msgstr "Fehler beim Umbenennen von »%s«." #~ msgid "[Up To Parent]" #~ msgstr "[Nach oben]" #~ msgid "Browse Branch Files" #~ msgstr "Dateien des Zweigs durchblättern" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "Fehler: »%s« kann nicht als Zweig oder Version erkannt werden" #~ msgid "Branch '%s' does not exist." #~ msgstr "Zweig »%s« existiert nicht." #~ msgid "" #~ "Branch '%s' already exists.\n" #~ "\n" #~ "It cannot fast-forward to %s.\n" #~ "A merge is required." #~ msgstr "" #~ "Zweig »%s« existiert bereits.\n" #~ "\n" #~ "Zweig kann nicht mit »%s« schnellzusammengeführt werden. Reguläres " #~ "Zusammenführen ist notwendig." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "Zusammenführungsmethode »%s« nicht unterstützt." #~ msgid "Failed to update '%s'." #~ msgstr "Aktualisieren von »%s« fehlgeschlagen." #~ msgid "Staging area (index) is already locked." #~ msgstr "Bereitstellung (»index«) ist zur Bearbeitung gesperrt (»locked«)." #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before the current branch can be changed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Der letzte geladene Status stimmt nicht mehr mit dem Projektarchiv " #~ "überein.\n" #~ "\n" #~ "Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden " #~ "geändert. Vor dem Wechseln des lokalen Zweigs muss neu geladen werden.\n" #~ "\n" #~ "Es wird gleich neu geladen.\n" #~ msgid "Updating working directory to '%s'..." #~ msgstr "Arbeitskopie umstellen auf »%s«..." #~ msgid "files checked out" #~ msgstr "Dateien aktualisiert" #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "" #~ "Auf Zweig »%s« umstellen abgebrochen (Zusammenführen der Dateien ist " #~ "notwendig)." #~ msgid "File level merge required." #~ msgstr "Zusammenführen der Dateien ist notwendig." #~ msgid "Staying on branch '%s'." #~ msgstr "Es wird auf Zweig »%s« verblieben." #~ msgid "" #~ "You are no longer on a local branch.\n" #~ "\n" #~ "If you wanted to be on a branch, create one now starting from 'This " #~ "Detached Checkout'." #~ msgstr "" #~ "Die Arbeitskopie ist nicht auf einem lokalen Zweig.\n" #~ "\n" #~ "Wenn Sie auf einem Zweig arbeiten möchten, erstellen Sie bitte jetzt " #~ "einen Zweig mit der Auswahl »Abgetrennte Arbeitskopie-Version«." #~ msgid "Checked out '%s'." #~ msgstr "Umgestellt auf »%s«." #~ msgid "Reset '%s'?" #~ msgstr "»%s« zurücksetzen?" #~ msgid "" #~ "Failed to set current branch.\n" #~ "\n" #~ "This working directory is only partially switched. We successfully " #~ "updated your files, but failed to update an internal Git file.\n" #~ "\n" #~ "This should not have occurred. %s will now close and give up." #~ msgstr "" #~ "Lokaler Zweig kann nicht gesetzt werden.\n" #~ "\n" #~ "Diese Arbeitskopie ist nur teilweise umgestellt. Die Dateien sind korrekt " #~ "aktualisiert, aber einige interne Git-Dateien konnten nicht geändert " #~ "werden.\n" #~ "\n" #~ "Dies ist ein interner Programmfehler von %s. Programm wird jetzt " #~ "abgebrochen." #~ msgid "Font Family" #~ msgstr "Schriftfamilie" #~ msgid "Font Example" #~ msgstr "Schriftbeispiel" #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "Dies ist ein Beispieltext.\n" #~ "Wenn Ihnen dieser Text gefällt, sollten Sie diese Schriftart wählen." #~ msgid "Git Gui" #~ msgstr "Git Gui" #~ msgid "Clone Existing Repository" #~ msgstr "Projektarchiv klonen" #~ msgid "Recent Repositories" #~ msgstr "Zuletzt benutzte Projektarchive" #~ msgid "Failed to create repository %s:" #~ msgstr "Projektarchiv »%s« konnte nicht erstellt werden:" #~ msgid "Directory:" #~ msgstr "Verzeichnis:" #~ msgid "Directory %s already exists." #~ msgstr "Verzeichnis »%s« existiert bereits." #~ msgid "Clone" #~ msgstr "Klonen" #~ msgid "Clone Type:" #~ msgstr "Art des Klonens:" #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "Standard (schnell, teilweise redundant, Hardlinks)" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "Alles kopieren (langsamer, volle Redundanz)" #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "Verknüpft (schnell, nicht empfohlen, kein Backup)" #~ msgid "Standard only available for local repository." #~ msgstr "Standard ist nur für lokale Projektarchive verfügbar." #~ msgid "Shared only available for local repository." #~ msgstr "Verknüpft ist nur für lokale Projektarchive verfügbar." #~ msgid "Location %s already exists." #~ msgstr "Projektarchiv »%s« existiert bereits." #~ msgid "Failed to configure origin" #~ msgstr "Der Ursprungsort konnte nicht eingerichtet werden" #~ msgid "Counting objects" #~ msgstr "Objekte werden gezählt" #~ msgid "buckets" #~ msgstr "Buckets" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "" #~ "Kopien von Objekten/Info/Alternates konnten nicht erstellt werden: %s" #~ msgid "The 'master' branch has not been initialized." #~ msgstr "Der »master«-Zweig wurde noch nicht initialisiert." #~ msgid "Hardlinks are unavailable. Falling back to copying." #~ msgstr "Hardlinks nicht verfügbar. Stattdessen wird kopiert." #~ msgid "Cloning from %s" #~ msgstr "Kopieren von »%s«" #~ msgid "Copying objects" #~ msgstr "Objektdatenbank kopieren" #~ msgid "KiB" #~ msgstr "KB" #~ msgid "Unable to copy object: %s" #~ msgstr "Objekt kann nicht kopiert werden: %s" #~ msgid "Linking objects" #~ msgstr "Objekte verlinken" #~ msgid "objects" #~ msgstr "Objekte" #~ msgid "Unable to hardlink object: %s" #~ msgstr "Für Objekt konnte kein Hardlink erstellt werden: %s" #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "" #~ "Zweige und Objekte konnten nicht angefordert werden. Kontrollieren Sie " #~ "die Ausgaben auf der Konsole für weitere Angaben." #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "" #~ "Markierungen konnten nicht angefordert werden. Kontrollieren Sie die " #~ "Ausgaben auf der Konsole für weitere Angaben." #~ msgid "Cannot determine HEAD. See console output for details." #~ msgstr "" #~ "Die Zweigspitze (HEAD) konnte nicht gefunden werden. Kontrollieren Sie " #~ "die Ausgaben auf der Konsole für weitere Angaben." #~ msgid "Unable to cleanup %s" #~ msgstr "Verzeichnis »%s« kann nicht aufgeräumt werden." #~ msgid "Clone failed." #~ msgstr "Klonen fehlgeschlagen." #~ msgid "No default branch obtained." #~ msgstr "Kein voreingestellter Zweig gefunden." #~ msgid "Cannot resolve %s as a commit." #~ msgstr "»%s« wurde nicht als Version gefunden." #~ msgid "Creating working directory" #~ msgstr "Arbeitskopie erstellen" #~ msgid "files" #~ msgstr "Dateien" #~ msgid "Initial file checkout failed." #~ msgstr "Erstellen der Arbeitskopie fehlgeschlagen." #~ msgid "Failed to open repository %s:" #~ msgstr "Projektarchiv »%s« konnte nicht geöffnet werden." #~ msgid "This Detached Checkout" #~ msgstr "Abgetrennte Arbeitskopie-Version" #~ msgid "Updated" #~ msgstr "Aktualisiert" #~ msgid "" #~ "There is nothing to amend.\n" #~ "\n" #~ "You are about to create the initial commit. There is no commit before " #~ "this to amend.\n" #~ msgstr "" #~ "Keine Version zur Nachbesserung vorhanden.\n" #~ "\n" #~ "Sie sind dabei, die erste Version zu übertragen. Es gibt keine " #~ "existierende Version, die Sie nachbessern könnten.\n" #~ msgid "" #~ "Cannot amend while merging.\n" #~ "\n" #~ "You are currently in the middle of a merge that has not been fully " #~ "completed. You cannot amend the prior commit unless you first abort the " #~ "current merge activity.\n" #~ msgstr "" #~ "Nachbesserung währen Zusammenführung nicht möglich.\n" #~ "\n" #~ "Sie haben das Zusammenführen von Versionen angefangen, aber noch nicht " #~ "beendet. Sie können keine vorige Übertragung nachbessern, solange eine " #~ "unfertige Zusammenführung existiert. Dazu müssen Sie die Zusammenführung " #~ "beenden oder abbrechen.\n" #~ msgid "Error loading commit data for amend:" #~ msgstr "Fehler beim Laden der Versionsdaten für Nachbessern:" #~ msgid "Unable to obtain your identity:" #~ msgstr "Benutzername konnte nicht bestimmt werden:" #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "Ungültiger Wert von GIT_COMMITTER_INDENT:" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before another commit can be created.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Der letzte geladene Status stimmt nicht mehr mit dem Projektarchiv " #~ "überein.\n" #~ "\n" #~ "Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden " #~ "geändert. Vor dem Eintragen einer neuen Version muss neu geladen " #~ "werden.\n" #~ "\n" #~ "Es wird gleich neu geladen.\n" #~ msgid "" #~ "Unmerged files cannot be committed.\n" #~ "\n" #~ "File %s has merge conflicts. You must resolve them and stage the file " #~ "before committing.\n" #~ msgstr "" #~ "Nicht zusammengeführte Dateien können nicht eingetragen werden.\n" #~ "\n" #~ "Die Datei »%s« hat noch nicht aufgelöste Zusammenführungs-Konflikte. Sie " #~ "müssen diese Konflikte auflösen, bevor Sie eintragen können.\n" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "Unbekannter Dateizustand »%s«.\n" #~ "\n" #~ "Datei »%s« kann nicht eingetragen werden.\n" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "Warning: Tcl/Tk unterstützt die Zeichencodierung »%s« nicht." #~ msgid "Calling pre-commit hook..." #~ msgstr "Aufrufen der Vor-Eintragen-Kontrolle..." #~ msgid "Commit declined by pre-commit hook." #~ msgstr "" #~ "Eintragen abgelehnt durch Vor-Eintragen-Kontrolle (»pre-commit hook«)." #~ msgid "Calling commit-msg hook..." #~ msgstr "Aufrufen der Versionsbeschreibungs-Kontrolle..." #~ msgid "Commit declined by commit-msg hook." #~ msgstr "" #~ "Eintragen abgelehnt durch Versionsbeschreibungs-Kontrolle (»commit-" #~ "message hook«)." #~ msgid "write-tree failed:" #~ msgstr "write-tree fehlgeschlagen:" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "Version »%s« scheint beschädigt zu sein" #~ msgid "" #~ "No changes to commit.\n" #~ "\n" #~ "No files were modified by this commit and it was not a merge commit.\n" #~ "\n" #~ "A rescan will be automatically started now.\n" #~ msgstr "" #~ "Keine Änderungen einzutragen.\n" #~ "\n" #~ "Es gibt keine geänderte Datei bei dieser Version und es wurde auch nichts " #~ "zusammengeführt.\n" #~ "\n" #~ "Das Arbeitsverzeichnis wird daher jetzt neu geladen.\n" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree fehlgeschlagen:" #~ msgid "update-ref failed:" #~ msgstr "update-ref fehlgeschlagen:" #~ msgid "Working... please wait..." #~ msgstr "Verarbeitung. Bitte warten..." #~ msgid "Error: Command Failed" #~ msgstr "Fehler: Kommando fehlgeschlagen" #~ msgid "Number of loose objects" #~ msgstr "Anzahl unverknüpfter Objekte" #~ msgid "Disk space used by loose objects" #~ msgstr "Festplattenplatz von unverknüpften Objekten" #~ msgid "Number of packed objects" #~ msgstr "Anzahl komprimierter Objekte" #~ msgid "Number of packs" #~ msgstr "Anzahl Komprimierungseinheiten" #~ msgid "Disk space used by packed objects" #~ msgstr "Festplattenplatz von komprimierten Objekten" #~ msgid "Packed objects waiting for pruning" #~ msgstr "Komprimierte Objekte, die zum Aufräumen vorgesehen sind" #~ msgid "Garbage files" #~ msgstr "Dateien im Mülleimer" #~ msgid "Compressing the object database" #~ msgstr "Objektdatenbank komprimieren" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "Die Objektdatenbank durch »fsck-objects« überprüfen lassen" #~ msgid "" #~ "This repository currently has approximately %i loose objects.\n" #~ "\n" #~ "To maintain optimal performance it is strongly recommended that you " #~ "compress the database when more than %i loose objects exist.\n" #~ "\n" #~ "Compress the database now?" #~ msgstr "" #~ "Dieses Projektarchiv enthält ungefähr %i nicht verknüpfte Objekte.\n" #~ "\n" #~ "Für eine optimale Performance wird empfohlen, die Datenbank des " #~ "Projektarchivs zu komprimieren, sobald mehr als %i nicht verknüpfte " #~ "Objekte vorliegen.\n" #~ "\n" #~ "Soll die Datenbank jetzt komprimiert werden?" #~ msgid "Invalid date from Git: %s" #~ msgstr "Ungültiges Datum von Git: %s" #~ msgid "" #~ "No differences detected.\n" #~ "\n" #~ "%s has no changes.\n" #~ "\n" #~ "The modification date of this file was updated by another application, " #~ "but the content within the file was not changed.\n" #~ "\n" #~ "A rescan will be automatically started to find other files which may have " #~ "the same state." #~ msgstr "" #~ "Keine Änderungen feststellbar.\n" #~ "\n" #~ "»%s« enthält keine Änderungen. Zwar wurde das Änderungsdatum dieser Datei " #~ "von einem anderen Programm modifiziert, aber der Inhalt der Datei ist " #~ "unverändert.\n" #~ "\n" #~ "Das Arbeitsverzeichnis wird jetzt neu geladen, um diese Änderung bei " #~ "allen Dateien zu prüfen." #~ msgid "Unable to display %s" #~ msgstr "Datei »%s« kann nicht angezeigt werden" #~ msgid "Git Repository (subproject)" #~ msgstr "Git-Projektarchiv (Unterprojekt)" #~ msgid "* Binary file (not showing content)." #~ msgstr "* Binärdatei (Inhalt wird nicht angezeigt)" #~ msgid "Failed to unstage selected hunk." #~ msgstr "" #~ "Fehler beim Herausnehmen des gewählten Kontexts aus der Bereitstellung." #~ msgid "Failed to stage selected hunk." #~ msgstr "Fehler beim Bereitstellen des gewählten Kontexts." #~ msgid "warning" #~ msgstr "Warnung" #~ msgid "You must correct the above errors before committing." #~ msgstr "" #~ "Sie müssen die obigen Fehler zuerst beheben, bevor Sie eintragen können." #~ msgid "Unable to unlock the index." #~ msgstr "Bereitstellung kann nicht wieder freigegeben werden." #~ msgid "Index Error" #~ msgstr "Fehler in Bereitstellung" #~ msgid "" #~ "Updating the Git index failed. A rescan will be automatically started to " #~ "resynchronize git-gui." #~ msgstr "" #~ "Das Aktualisieren der Git-Bereitstellung ist fehlgeschlagen. Eine " #~ "allgemeine Git-Aktualisierung wird jetzt gestartet, um git-gui wieder mit " #~ "git zu synchronisieren." #~ msgid "Unlock Index" #~ msgstr "Bereitstellung freigeben" #~ msgid "Ready to commit." #~ msgstr "Bereit zum Eintragen." #~ msgid "Revert changes in these %i files?" #~ msgstr "Änderungen in den gewählten %i Dateien verwerfen?" #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "" #~ "Alle nicht bereitgestellten Änderungen werden beim Verwerfen verloren " #~ "gehen." #~ msgid "Do Nothing" #~ msgstr "Nichts tun" #~ msgid "" #~ "Cannot merge while amending.\n" #~ "\n" #~ "You must finish amending this commit before starting any type of merge.\n" #~ msgstr "" #~ "Zusammenführen kann nicht gleichzeitig mit Nachbessern durchgeführt " #~ "werden.\n" #~ "\n" #~ "Sie müssen zuerst die Nachbesserungs-Version abschließen, bevor Sie " #~ "zusammenführen können.\n" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before a merge can be performed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Der letzte geladene Status stimmt nicht mehr mit dem Projektarchiv " #~ "überein.\n" #~ "\n" #~ "Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden " #~ "geändert. Vor einem Zusammenführen muss neu geladen werden.\n" #~ "\n" #~ "Es wird gleich neu geladen.\n" #~ msgid "" #~ "You are in the middle of a conflicted merge.\n" #~ "\n" #~ "File %s has merge conflicts.\n" #~ "\n" #~ "You must resolve them, stage the file, and commit to complete the current " #~ "merge. Only then can you begin another merge.\n" #~ msgstr "" #~ "Zusammenführung mit Konflikten.\n" #~ "\n" #~ "Die Datei »%s« enthält Konflikte beim Zusammenführen. Sie müssen diese " #~ "Konflikte per Hand auflösen. Anschließend müssen Sie die Datei wieder " #~ "bereitstellen und eintragen, um die Zusammenführung abzuschließen. Erst " #~ "danach kann eine neue Zusammenführung begonnen werden.\n" #~ msgid "" #~ "You are in the middle of a change.\n" #~ "\n" #~ "File %s is modified.\n" #~ "\n" #~ "You should complete the current commit before starting a merge. Doing so " #~ "will help you abort a failed merge, should the need arise.\n" #~ msgstr "" #~ "Es liegen Änderungen vor.\n" #~ "\n" #~ "Die Datei »%s« wurde geändert. Sie sollten zuerst die bereitgestellte " #~ "Version abschließen, bevor Sie eine Zusammenführung beginnen. Mit dieser " #~ "Reihenfolge können Sie mögliche Konflikte beim Zusammenführen wesentlich " #~ "einfacher beheben oder abbrechen.\n" #~ msgid "%s of %s" #~ msgstr "%s von %s" #~ msgid "Merging %s and %s..." #~ msgstr "Zusammenführen von %s und %s..." #~ msgid "Merge completed successfully." #~ msgstr "Zusammenführen erfolgreich abgeschlossen." #~ msgid "Merge failed. Conflict resolution is required." #~ msgstr "Zusammenführen fehlgeschlagen. Konfliktauflösung ist notwendig." #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\n" #~ msgstr "" #~ "Abbruch der Nachbesserung ist nicht möglich.\n" #~ "\n" #~ "Sie müssen die Nachbesserung der Version abschließen.\n" #~ msgid "" #~ "Reset changes?\n" #~ "\n" #~ "Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" #~ "\n" #~ "Continue with resetting the current changes?" #~ msgstr "" #~ "Änderungen zurücksetzen?\n" #~ "\n" #~ "Wenn Sie zurücksetzen, gehen alle noch nicht eingetragenen Änderungen " #~ "verloren.\n" #~ "\n" #~ "Änderungen jetzt zurücksetzen?" #~ msgid "files reset" #~ msgstr "Dateien zurückgesetzt" #~ msgid "Abort failed." #~ msgstr "Abbruch fehlgeschlagen." #~ msgid "Abort completed. Ready." #~ msgstr "Abbruch durchgeführt. Bereit." #~ msgid "Restore Defaults" #~ msgstr "Voreinstellungen wiederherstellen" #~ msgid "%s Repository" #~ msgstr "Projektarchiv %s" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "Übernahmezweige aufräumen während Anforderung" #~ msgid "Match Tracking Branches" #~ msgstr "Passend zu Übernahmezweig" #~ msgid "New Branch Name Template" #~ msgstr "Namensvorschlag für neue Zweige" #~ msgid "Spelling Dictionary:" #~ msgstr "Wörterbuch Rechtschreibprüfung:" #~ msgid "Change Font" #~ msgstr "Schriftart ändern" #~ msgid "pt." #~ msgstr "pt." #~ msgid "Failed to completely save options:" #~ msgstr "Optionen konnten nicht gespeichert werden:" #~ msgid "From Repository" #~ msgstr "In Projektarchiv" #~ msgid "Remote:" #~ msgstr "Anderes Archiv:" #~ msgid "Arbitrary URL:" #~ msgstr "Archiv-URL:" #~ msgid "Delete Only If" #~ msgstr "Nur löschen, wenn" #~ msgid "Merged Into:" #~ msgstr "Zusammengeführt mit:" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "Immer (Keine Zusammenführungsprüfung)" #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "Für »Zusammenführen mit« muss ein Zweig angegeben werden." #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "Folgende Zweige sind noch nicht mit »%s« zusammengeführt:\n" #~ "\n" #~ " - %s" #~ msgid "" #~ "One or more of the merge tests failed because you have not fetched the " #~ "necessary commits. Try fetching from %s first." #~ msgstr "" #~ "Ein oder mehrere Zusammenführungen sind fehlgeschlagen, da Sie nicht die " #~ "notwendigen Versionen vorher angefordert haben. Sie sollten versuchen, " #~ "zuerst von »%s« anzufordern." #~ msgid "Please select one or more branches to delete." #~ msgstr "Bitte wählen Sie mindestens einen Zweig, der gelöscht werden soll." #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "Das Wiederherstellen von gelöschten Zweigen ist nur mit größerem Aufwand " #~ "möglich.\n" #~ "\n" #~ "Sollen die ausgewählten Zweige gelöscht werden?" #~ msgid "Prune from" #~ msgstr "Aufräumen von" #~ msgid "Fetch from" #~ msgstr "Anfordern von" #~ msgid "Push to" #~ msgstr "Versenden nach" #~ msgid "Cannot write shortcut:" #~ msgstr "Fehler beim Schreiben der Verknüpfung:" #~ msgid "Unsupported spell checker" #~ msgstr "Rechtschreibprüfungsprogramm nicht unterstützt" #~ msgid "Spell checking is unavailable" #~ msgstr "Rechtschreibprüfung nicht verfügbar" #~ msgid "Invalid spell checking configuration" #~ msgstr "Unbenutzbare Konfiguration der Rechtschreibprüfung" #~ msgid "Reverting dictionary to %s." #~ msgstr "Wörterbuch auf %s zurückgesetzt." #~ msgid "Spell checker silently failed on startup" #~ msgstr "Rechtschreibprüfungsprogramm mit Fehler abgebrochen" #~ msgid "Unrecognized spell checker" #~ msgstr "Unbekanntes Rechtschreibprüfungsprogramm" #~ msgid "Unexpected EOF from spell checker" #~ msgstr "Unerwartetes EOF vom Rechtschreibprüfungsprogramm" #~ msgid "Spell Checker Failed" #~ msgstr "Rechtschreibprüfung fehlgeschlagen" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%s ... %*i von %*i %s (%3i%%)" #~ msgid "Fetching new changes from %s" #~ msgstr "Neue Änderungen von »%s« holen" #~ msgid "remote prune %s" #~ msgstr "Aufräumen von »%s«" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "" #~ "Übernahmezweige aufräumen und entfernen, die in »%s« gelöscht wurden" #~ msgid "push %s" #~ msgstr "»%s« versenden..." #~ msgid "Pushing %s %s to %s" #~ msgstr "%s %s nach %s versenden" #~ msgid "Push Branches" #~ msgstr "Zweige versenden" #~ msgid "Source Branches" #~ msgstr "Lokale Zweige" #~ msgid "Destination Repository" #~ msgstr "Ziel-Projektarchiv" #~ msgid "Transfer Options" #~ msgstr "Netzwerk-Einstellungen" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "" #~ "Überschreiben von existierenden Zweigen erzwingen (könnte Änderungen " #~ "löschen)" #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Kompaktes Datenformat benutzen (für langsame Netzverbindungen)" git-cola-1.9.3/po/fr.po000066400000000000000000002204721225156173500146260ustar00rootroot00000000000000# translation of fr.po to French # Translation of git-gui to French. # Copyright (C) 2008 Shawn Pearce, et al. # This file is distributed under the same license as the git package. # # Christian Couder , 2008. msgid "" msgstr "" "Project-Id-Version: fr\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-09-24 21:42-0700\n" "PO-Revision-Date: 2008-04-04 22:05+0200\n" "Last-Translator: Christian Couder \n" "Language-Team: French\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: cola/bookmarks.py:32 msgid "Bookmarks" msgstr "" #: cola/bookmarks.py:47 msgid "Open" msgstr "Ouvrir" #: cola/bookmarks.py:53 msgid "Add" msgstr "" #: cola/bookmarks.py:58 cola/guicmds.py:25 cola/guicmds.py:33 #: cola/widgets/editremotes.py:127 msgid "Delete" msgstr "Supprimer" #: cola/bookmarks.py:65 cola/stash/view.py:42 cola/widgets/archive.py:65 #: cola/widgets/browse.py:117 msgid "Save" msgstr "Sauvegarder" #: cola/bookmarks.py:71 cola/difftool.py:96 cola/qt.py:57 cola/qt.py:243 #: cola/prefs/view.py:241 cola/stash/view.py:50 cola/stash/view.py:51 #: cola/widgets/about.py:66 cola/widgets/about.py:126 #: cola/widgets/browse.py:116 cola/widgets/cfgactions.py:87 #: cola/widgets/cfgactions.py:239 cola/widgets/compare.py:94 #: cola/widgets/createbranch.py:159 cola/widgets/createtag.py:104 #: cola/widgets/editremotes.py:55 cola/widgets/grep.py:75 #: cola/widgets/recent.py:75 cola/widgets/remote.py:157 #: cola/widgets/search.py:81 cola/widgets/selectcommits.py:59 #: cola/widgets/startup.py:42 msgid "Close" msgstr "Fermer" #: cola/bookmarks.py:102 msgid "Bookmarks Saved" msgstr "" #: cola/bookmarks.py:103 msgid "Successfully saved bookmarks" msgstr "" #: cola/bookmarks.py:107 #, fuzzy msgid "Path to git repository" msgstr "'%s' n'est pas un référentiel Git." #: cola/bookmarks.py:108 #, fuzzy msgid "Enter Git Repository" msgstr "Référentiel Git" #: cola/cmds.py:105 msgid "Amend" msgstr "" #: cola/cmds.py:140 #, fuzzy msgid "Cannot Amend" msgstr "Impossible d'écrire l'icône :" #: cola/cmds.py:141 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" #: cola/cmds.py:204 #, python-format msgid "PATCH %(current)d/%(count)d" msgstr "" #: cola/cmds.py:208 msgid "Summary:" msgstr "" #: cola/cmds.py:217 msgid "Patch(es) Applied" msgstr "" #: cola/cmds.py:218 #, python-format msgid "%d patch(es) applied." msgstr "" #: cola/cmds.py:322 #, fuzzy, python-format msgid "Created commit: %s" msgstr "Commit créé %s : %s" #: cola/cmds.py:324 #, fuzzy, python-format msgid "Commit failed: %s" msgstr "Le commit a échoué." #: cola/cmds.py:369 cola/cmds.py:1186 #, fuzzy msgid "Error" msgstr "erreur" #: cola/cmds.py:370 #, python-format msgid "Deleting \"%s\" failed" msgstr "" #: cola/cmds.py:406 #, fuzzy msgid "Remote Branch Deleted" msgstr "Renommer branche" #: cola/cmds.py:407 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "" #: cola/cmds.py:411 cola/guicmds.py:108 cola/widgets/remote.py:472 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "" #: cola/cmds.py:414 #, fuzzy msgid "Error Deleting Remote Branch" msgstr "Créer branche" #: cola/cmds.py:493 cola/widgets/grep.py:60 cola/widgets/recent.py:69 msgid "Edit" msgstr "Editer" #: cola/cmds.py:529 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/cmds.py:531 #, fuzzy msgid "Error Editing File" msgstr "Erreur lors du chargement des différences :" #: cola/cmds.py:554 msgid "Launch Diff Tool" msgstr "" #: cola/cmds.py:577 msgid "Launch Editor" msgstr "" #: cola/cmds.py:598 msgid "Error: Cannot find commit template" msgstr "" #: cola/cmds.py:599 #, fuzzy, python-format msgid "%s: No such file or directory." msgstr "" "erreur fatale : pas d'infos sur le chemin %s : Fichier ou répertoire " "inexistant" #: cola/cmds.py:616 msgid "Error: Unconfigured commit template" msgstr "" #: cola/cmds.py:617 msgid "" "A commit template has not been configured.\n" "Use \"git config\" to define \"commit.template\"\n" "so that it points to a commit template." msgstr "" #: cola/cmds.py:669 msgid "Open Using Default Application" msgstr "" #: cola/cmds.py:692 #, fuzzy msgid "Open Parent Directory" msgstr "Ouvrir référentiel récent :" #: cola/cmds.py:732 #, python-format msgid "Error: could not clone \"%s\"" msgstr "" #: cola/cmds.py:733 #, python-format msgid "git clone returned exit code %s" msgstr "" #: cola/cmds.py:756 cola/widgets/action.py:19 cola/widgets/editremotes.py:49 #: cola/widgets/grep.py:65 cola/widgets/recent.py:52 #: cola/widgets/recent.py:121 msgid "Refresh" msgstr "Rafraichir" #: cola/cmds.py:784 #, python-format msgid "Run \"%s\"?" msgstr "" #: cola/cmds.py:791 #, fuzzy msgid "Please select a file" msgstr "Merci de choisir une branche de suivi" #: cola/cmds.py:792 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:804 #, fuzzy msgid "Invalid Revision" msgstr "Révision invalide : %s" #: cola/cmds.py:805 #, fuzzy msgid "The revision expression cannot be empty." msgstr "L'expression de révision est vide." #: cola/cmds.py:820 #, python-format msgid "Running command: %s" msgstr "" #: cola/cmds.py:829 cola/cmds.py:1006 cola/interaction.py:70 #, python-format msgid "Output: %s" msgstr "" #: cola/cmds.py:830 cola/guicmds.py:113 cola/interaction.py:71 #, python-format msgid "Errors: %s" msgstr "" #: cola/cmds.py:876 msgid "Sign Off" msgstr "Approuver" #: cola/cmds.py:897 msgid "unknown" msgstr "" #: cola/cmds.py:910 cola/widgets/action.py:17 #, fuzzy msgid "Stage" msgstr "Sauvegarder" #: cola/cmds.py:917 #, fuzzy, python-format msgid "Staging: %s" msgstr "Synchronisation de %s..." #: cola/cmds.py:934 msgid "Stage Modified" msgstr "" #: cola/cmds.py:948 #, fuzzy msgid "Stage Unmerged" msgstr "Pré-commit modifié" #: cola/cmds.py:962 #, fuzzy msgid "Stage Untracked" msgstr "Pré-commit modifié" #: cola/cmds.py:980 #, python-format msgid "Tagging \"%(revision)s\" as \"%(name)s\"" msgstr "" #: cola/cmds.py:988 msgid "GPG-signed" msgstr "" #: cola/cmds.py:1020 cola/widgets/action.py:18 #, fuzzy msgid "Unstage" msgstr "Modifications non pré-commitées" #: cola/cmds.py:1027 #, fuzzy, python-format msgid "Unstaging: %s" msgstr "Supprimer %s du commit" #: cola/cmds.py:1055 #, python-format msgid "Untracking: %s" msgstr "" #: cola/cmds.py:1137 #, fuzzy msgid "Error Launching History Browser" msgstr "Visionneur de fichier" #: cola/cmds.py:1138 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/difftool.py:76 msgid "git-cola diff" msgstr "" #: cola/difftool.py:92 cola/widgets/compare.py:90 msgid "Compare" msgstr "" #: cola/gitcmds.py:402 #, fuzzy msgid "Nothing to do" msgstr "Il n'y a rien à cloner depuis %s." #: cola/guicmds.py:25 msgid "Delete Branch" msgstr "Supprimer branche" #: cola/guicmds.py:33 #, fuzzy msgid "Delete Remote Branch" msgstr "Supprimer branche distante" #: cola/guicmds.py:53 #, fuzzy msgid "Browse Commits..." msgstr "Visionner" #: cola/guicmds.py:53 #, fuzzy msgid "Browse" msgstr "Visionner" #: cola/guicmds.py:61 msgid "Checkout Branch" msgstr "Emprunter branche" #: cola/guicmds.py:61 msgid "Checkout" msgstr "Emprunter" #: cola/guicmds.py:70 #, fuzzy msgid "Cherry-Pick Commit" msgstr "Copier commit" #: cola/guicmds.py:107 #, fuzzy msgid "Error Creating Repository" msgstr "Créer nouveau référentiel" #: cola/guicmds.py:110 #, python-format msgid "" "Output:\n" "%s" msgstr "" #: cola/guicmds.py:132 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/guicmds.py:153 #, fuzzy msgid "Error Cloning" msgstr "Erreur lors du chargement du fichier :" #: cola/guicmds.py:154 cola/guicmds.py:155 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/guicmds.py:159 msgid "Select a parent directory for the new clone" msgstr "" #: cola/guicmds.py:169 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/guicmds.py:185 cola/widgets/search.py:75 msgid "Export Patches" msgstr "" #: cola/guicmds.py:214 cola/widgets/startup.py:124 #, fuzzy msgid "Open Git Repository..." msgstr "Ouvrir référentiel existant" #: cola/guicmds.py:223 #, fuzzy msgid "Load Commit Message" msgstr "Message de commit :" #: cola/guicmds.py:251 #, fuzzy msgid "Select New Base" msgstr "Sélectionner" #: cola/guicmds.py:251 #, fuzzy msgid "Rebase" msgstr "Réinitialiser" #: cola/guicmds.py:261 #, fuzzy msgid "Select Branch to Review" msgstr "Supprimer branche" #: cola/guicmds.py:261 msgid "Review" msgstr "" #: cola/inotify.py:47 msgid "inotify is disabled because \"cola.inotify\" is false" msgstr "" #: cola/inotify.py:53 msgid "" "file notification: disabled\n" "Note: install pywin32 to enable.\n" msgstr "" #: cola/inotify.py:56 msgid "" "inotify: disabled\n" "Note: install python-pyinotify to enable inotify.\n" msgstr "" #: cola/inotify.py:62 msgid "On Debian systems try: sudo aptitude install python-pyinotify" msgstr "" #: cola/inotify.py:71 #, fuzzy msgid "File notification enabled." msgstr "Faire confiance aux dates de modification de fichiers " #: cola/inotify.py:73 msgid "inotify enabled." msgstr "" #: cola/interaction.py:53 msgid "Continue" msgstr "Continuer" #: cola/interaction.py:63 #, python-format msgid "Run %s?" msgstr "" #: cola/interaction.py:64 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/interaction.py:65 cola/widgets/cfgactions.py:240 msgid "Run" msgstr "" #: cola/interaction.py:72 #, python-format msgid "Exit code: %s" msgstr "" #: cola/qt.py:60 cola/qt.py:100 #, fuzzy msgid "Detach" msgstr "Supprimer branche" #: cola/qt.py:98 msgid "Attach" msgstr "" #: cola/qtutils.py:396 #, fuzzy msgid "Close..." msgstr "Cloner..." #: cola/classic/controller.py:69 msgid "Select Previous Version" msgstr "" #: cola/classic/model.py:37 cola/widgets/createtag.py:51 #: cola/widgets/editremotes.py:220 #, fuzzy msgid "Name" msgstr "Nom :" #: cola/classic/model.py:39 cola/main/view.py:91 msgid "Status" msgstr "" #: cola/classic/model.py:41 msgid "Age" msgstr "" #: cola/classic/model.py:43 cola/widgets/createtag.py:74 #, fuzzy msgid "Message" msgstr "Fusionner" #: cola/classic/model.py:45 cola/dag/view.py:371 #, fuzzy msgid "Author" msgstr "Auteur :" #: cola/classic/model.py:342 #, python-format msgid "%d minutes ago" msgstr "" #: cola/classic/model.py:345 #, python-format msgid "%d hours ago" msgstr "" #: cola/classic/model.py:346 #, python-format msgid "%d days ago" msgstr "" #: cola/classic/model.py:359 cola/widgets/status.py:73 #, fuzzy msgid "Unmerged" msgstr "Fusionner" #: cola/classic/model.py:361 msgid "Partially Staged" msgstr "" #: cola/classic/model.py:363 cola/widgets/status.py:74 #, fuzzy msgid "Modified" msgstr "Non modifié" #: cola/classic/model.py:365 cola/widgets/status.py:72 #, fuzzy msgid "Staged" msgstr "Pré-commit modifié" #: cola/classic/model.py:367 msgid "Changed Upstream" msgstr "" #: cola/classic/view.py:47 cola/main/view.py:545 #, fuzzy, python-format msgid "Repository: %s" msgstr "Référentiel :" #: cola/classic/view.py:49 cola/main/view.py:547 #, fuzzy, python-format msgid "Branch: %s" msgstr "Branche :" #: cola/classic/view.py:52 #, python-format msgid "%s: %s - Browse" msgstr "" #: cola/classic/view.py:54 cola/main/view.py:552 msgid "Amending" msgstr "" #: cola/classic/view.py:79 msgid "View History..." msgstr "" #: cola/classic/view.py:80 msgid "View history for selected path(s)." msgstr "" #: cola/classic/view.py:84 cola/widgets/status.py:506 #: cola/widgets/status.py:536 cola/widgets/status.py:593 #, fuzzy msgid "Stage Selected" msgstr "Sélectionner" #: cola/classic/view.py:85 #, fuzzy msgid "Stage selected path(s) for commit." msgstr "Pré-commité" #: cola/classic/view.py:90 cola/widgets/status.py:452 #: cola/widgets/status.py:494 msgid "Unstage Selected" msgstr "" #: cola/classic/view.py:91 msgid "Remove selected path(s) from the staging area." msgstr "" #: cola/classic/view.py:96 msgid "Untrack Selected" msgstr "" #: cola/classic/view.py:97 msgid "Stop tracking path(s)" msgstr "" #: cola/classic/view.py:102 msgid "Launch git-difftool on the current path." msgstr "" #: cola/classic/view.py:106 msgid "Diff Against Predecessor..." msgstr "" #: cola/classic/view.py:107 msgid "Launch git-difftool against previous versions." msgstr "" #: cola/classic/view.py:111 #, fuzzy msgid "Revert Uncommitted Changes..." msgstr "Inverser modification" #: cola/classic/view.py:112 #, fuzzy msgid "Revert changes to selected path(s)." msgstr "Inverser les modifications dans le fichier %s ? " #: cola/classic/view.py:117 msgid "Edit selected path(s)." msgstr "" #: cola/classic/view.py:293 cola/widgets/status.py:652 #, fuzzy msgid "Revert Uncommitted Changes?" msgstr "Inverser modification" #: cola/classic/view.py:294 cola/widgets/diff.py:246 cola/widgets/diff.py:259 #: cola/widgets/status.py:653 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/classic/view.py:296 cola/widgets/diff.py:248 cola/widgets/diff.py:261 #: cola/widgets/status.py:655 msgid "Revert the uncommitted changes?" msgstr "" #: cola/classic/view.py:297 cola/widgets/status.py:656 #, fuzzy msgid "Revert Uncommitted Changes" msgstr "Inverser modification" #: cola/dag/view.py:166 #, fuzzy msgid "Loading..." msgstr "Chargement de %s..." #: cola/dag/view.py:272 msgid "Diff this -> selected" msgstr "" #: cola/dag/view.py:275 msgid "Diff selected -> this" msgstr "" #: cola/dag/view.py:278 cola/widgets/createbranch.py:89 #: cola/widgets/createbranch.py:98 cola/widgets/createbranch.py:155 #: cola/widgets/createbranch.py:330 msgid "Create Branch" msgstr "Créer branche" #: cola/dag/view.py:281 #, fuzzy msgid "Create Patch" msgstr "Créer branche" #: cola/dag/view.py:284 cola/widgets/createtag.py:38 #: cola/widgets/createtag.py:99 #, fuzzy msgid "Create Tag" msgstr "Créer" #: cola/dag/view.py:287 cola/main/view.py:208 msgid "Save As Tarball/Zip..." msgstr "" #: cola/dag/view.py:290 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/dag/view.py:293 msgid "Grab File..." msgstr "" #: cola/dag/view.py:296 #, fuzzy msgid "Copy SHA-1" msgstr "Copier tout" #: cola/dag/view.py:371 msgid "Summary" msgstr "" #: cola/dag/view.py:371 msgid "Date, Time" msgstr "" #: cola/dag/view.py:378 msgid "Go Up" msgstr "" #: cola/dag/view.py:381 msgid "Go Down" msgstr "" #: cola/dag/view.py:511 cola/dag/view.py:1181 msgid "Zoom Out" msgstr "" #: cola/dag/view.py:514 cola/dag/view.py:1178 msgid "Zoom In" msgstr "" #: cola/dag/view.py:517 cola/dag/view.py:1184 msgid "Zoom to Fit" msgstr "" #: cola/dag/view.py:536 msgid "Log" msgstr "" #: cola/dag/view.py:541 cola/main/view.py:114 cola/main/view.py:384 msgid "Diff" msgstr "" #: cola/dag/view.py:554 msgid "Graph" msgstr "" #: cola/dag/view.py:563 msgid "View" msgstr "" #: cola/dag/view.py:636 #, python-format msgid "%s: %s - DAG" msgstr "" #: cola/dag/view.py:638 msgid " - DAG" msgstr "" #: cola/dag/view.py:1187 #, fuzzy msgid "Select Parent" msgstr "Sélectionner" #: cola/dag/view.py:1190 msgid "Select Oldest Parent" msgstr "" #: cola/dag/view.py:1193 #, fuzzy msgid "Select Child" msgstr "Tout sélectionner" #: cola/dag/view.py:1196 msgid "Select Newest Child" msgstr "" #: cola/main/view.py:78 #, fuzzy msgid "Browser" msgstr "Visionner" #: cola/main/view.py:83 #, fuzzy msgid "Action" msgstr "Options" #: cola/main/view.py:99 cola/merge/view.py:45 #, fuzzy msgid "Commit" msgstr "Commit :" #: cola/main/view.py:108 #, fuzzy msgid "Console" msgstr "Fermer" #: cola/main/view.py:120 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/main/view.py:125 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/main/view.py:130 msgid "Ignore all whitespace" msgstr "" #: cola/main/view.py:135 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/main/view.py:139 cola/widgets/createbranch.py:194 msgid "Options" msgstr "Options" #: cola/main/view.py:141 cola/main/view.py:142 #, fuzzy msgid "Diff Options" msgstr "Options" #: cola/main/view.py:157 cola/widgets/status.py:423 msgid "Unstage All" msgstr "" #: cola/main/view.py:161 msgid "Unstage From Commit" msgstr "Commit vers pré-commit" #: cola/main/view.py:165 msgid "Diffstat" msgstr "" #: cola/main/view.py:168 msgid "Stage Changed Files To Commit" msgstr "Commiter fichiers modifiés dans pré-commit" #: cola/main/view.py:173 msgid "Stage All Untracked" msgstr "" #: cola/main/view.py:178 msgid "Export Patches..." msgstr "" #: cola/main/view.py:181 #, fuzzy msgid "New Repository..." msgstr "Référentiel Git" #: cola/main/view.py:185 cola/prefs/view.py:220 msgid "Preferences" msgstr "Préférences" #: cola/main/view.py:189 msgid "Edit Remotes..." msgstr "" #: cola/main/view.py:197 #, fuzzy msgid "Recently Modified Files..." msgstr "Recherche de fichiers modifiés..." #: cola/main/view.py:201 #, fuzzy msgid "Cherry-Pick..." msgstr "Emprunter... " #: cola/main/view.py:205 #, fuzzy msgid "Load Commit Message..." msgstr "Message de commit :" #: cola/main/view.py:211 msgid "Quit" msgstr "Quitter" #: cola/main/view.py:213 msgid "Bookmarks..." msgstr "" #: cola/main/view.py:215 msgid "Grep" msgstr "" #: cola/main/view.py:217 #, fuzzy msgid "Merge..." msgstr "Fusionner" #: cola/main/view.py:220 cola/merge/__init__.py:20 msgid "Abort Merge..." msgstr "Abandonner fusion..." #: cola/main/view.py:223 cola/widgets/action.py:20 #, fuzzy msgid "Fetch..." msgstr "Réinitialiser..." #: cola/main/view.py:225 cola/widgets/action.py:21 msgid "Push..." msgstr "Pousser..." #: cola/main/view.py:227 cola/widgets/action.py:22 #, fuzzy msgid "Pull..." msgstr "Pousser..." #: cola/main/view.py:230 cola/widgets/startup.py:36 msgid "Open..." msgstr "Ouvrir..." #: cola/main/view.py:234 cola/widgets/action.py:23 #, fuzzy msgid "Stash..." msgstr "Pousser..." #: cola/main/view.py:237 cola/widgets/startup.py:39 msgid "Clone..." msgstr "Cloner..." #: cola/main/view.py:241 #, fuzzy msgid "Documentation" msgstr "Documentation en ligne" #: cola/main/view.py:245 msgid "Keyboard Shortcuts" msgstr "" #: cola/main/view.py:250 #, fuzzy msgid "Visualize Current Branch..." msgstr "Visualiser historique branche courante" #: cola/main/view.py:253 #, fuzzy msgid "Visualize All Branches..." msgstr "Visualiser historique toutes branches" #: cola/main/view.py:256 #, fuzzy msgid "Search..." msgstr "Lancement..." #: cola/main/view.py:258 #, fuzzy msgid "Browse Current Branch..." msgstr "Visionner fichiers dans branche courante" #: cola/main/view.py:260 #, fuzzy msgid "Browse Other Branch..." msgstr "Visionner fichiers de branche" #: cola/main/view.py:262 #, fuzzy msgid "Get Commit Message Template" msgstr "Largeur du texte de message de commit" #: cola/main/view.py:265 #, fuzzy msgid "About" msgstr "A propos de %s" #: cola/main/view.py:268 #, fuzzy msgid "Expression..." msgstr "Options..." #: cola/main/view.py:270 #, fuzzy msgid "Branches..." msgstr "Branches" #: cola/main/view.py:273 #, fuzzy msgid "Create Tag..." msgstr "Créer..." #: cola/main/view.py:276 msgid "Create..." msgstr "Créer..." #: cola/main/view.py:279 msgid "Delete..." msgstr "Supprimer..." #: cola/main/view.py:282 #, fuzzy msgid "Delete Remote Branch..." msgstr "Supprimer branche distante" #: cola/main/view.py:285 msgid "Checkout..." msgstr "Emprunter... " #: cola/main/view.py:287 #, fuzzy msgid "Rebase..." msgstr "Réinitialiser..." #: cola/main/view.py:289 #, fuzzy msgid "Review..." msgstr "Réinitialiser..." #: cola/main/view.py:292 #, fuzzy msgid "Browser..." msgstr "Visionner" #: cola/main/view.py:296 msgid "DAG..." msgstr "" #: cola/main/view.py:313 #, fuzzy msgid "File" msgstr "Fichier :" #: cola/main/view.py:316 #, fuzzy msgid "Open Recent" msgstr "Ouvrir référentiel récent :" #: cola/main/view.py:338 cola/main/view.py:339 #, fuzzy msgid "Index" msgstr "Erreur de pré-commit" #: cola/main/view.py:349 msgid "Branch" msgstr "Branche" #: cola/main/view.py:367 #, fuzzy msgid "Actions" msgstr "Options" #: cola/main/view.py:393 msgid "Tools" msgstr "" #: cola/main/view.py:404 msgid "Help" msgstr "Aide" #: cola/main/view.py:462 #, python-format msgid "git cola version %s" msgstr "" #: cola/merge/__init__.py:21 #, fuzzy msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Abandonner la fusion ?\n" "\n" "Abandonner la fusion courante entrainera la perte de TOUTES les " "modifications non commitées.\n" "\n" "Abandonner quand même la fusion courante ?" #: cola/merge/__init__.py:24 msgid "Aborting the current merge?" msgstr "" #: cola/merge/__init__.py:25 #, fuzzy msgid "Abort Merge" msgstr "Abandonner fusion..." #: cola/merge/view.py:23 msgid "Revision To Merge" msgstr "Révision à fusionner" #: cola/merge/view.py:28 cola/widgets/cfgactions.py:220 #: cola/widgets/remote.py:122 msgid "Local Branch" msgstr "Branche locale" #: cola/merge/view.py:31 cola/widgets/cfgactions.py:221 msgid "Tracking Branch" msgstr "Suivi de branche" #: cola/merge/view.py:33 cola/widgets/cfgactions.py:222 #: cola/widgets/createbranch.py:122 msgid "Tag" msgstr "Marque" #: cola/merge/view.py:39 msgid "Visualize" msgstr "Visualiser" #: cola/merge/view.py:42 #, fuzzy msgid "Squash" msgstr "Pousser" #: cola/merge/view.py:50 cola/widgets/archive.py:62 #: cola/widgets/editremotes.py:204 msgid "Cancel" msgstr "Annuler" #: cola/merge/view.py:53 msgid "Merge" msgstr "Fusionner" #: cola/merge/view.py:115 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/merge/view.py:118 #, fuzzy, python-format msgid "Merge into \"%s\"" msgstr "Fusion dans %s" #: cola/merge/view.py:162 cola/merge/view.py:171 #, fuzzy msgid "No Revision Specified" msgstr "Pas de révision selectionnée." #: cola/merge/view.py:163 msgid "You must specify a revision to view." msgstr "" #: cola/merge/view.py:172 msgid "You must specify a revision to merge." msgstr "" #: cola/prefs/view.py:116 msgid "User Name" msgstr "Nom d'utilisateur" #: cola/prefs/view.py:117 msgid "Email Address" msgstr "Adresse email" #: cola/prefs/view.py:118 msgid "Merge Verbosity" msgstr "Fusion bavarde" #: cola/prefs/view.py:119 msgid "Number of Diff Context Lines" msgstr "Nombre de lignes de contexte dans les diffs" #: cola/prefs/view.py:120 msgid "Summarize Merge Commits" msgstr "Résumer les commits de fusion" #: cola/prefs/view.py:121 msgid "Show Diffstat After Merge" msgstr "Montrer statistiques de diff après fusion" #: cola/prefs/view.py:122 msgid "Display Untracked Files" msgstr "" #: cola/prefs/view.py:163 msgid "Fixed-Width Font" msgstr "" #: cola/prefs/view.py:164 msgid "Font Size" msgstr "Taille de fonte" #: cola/prefs/view.py:165 msgid "Tab Width" msgstr "" #: cola/prefs/view.py:166 msgid "Text Width" msgstr "" #: cola/prefs/view.py:167 cola/widgets/commitmsg.py:99 msgid "Auto-Wrap Lines" msgstr "" #: cola/prefs/view.py:168 #, fuzzy msgid "Editor" msgstr "Editer" #: cola/prefs/view.py:169 #, fuzzy msgid "History Browser" msgstr "Visionneur de fichier" #: cola/prefs/view.py:170 msgid "Diff Tool" msgstr "" #: cola/prefs/view.py:171 #, fuzzy msgid "Merge Tool" msgstr "Fusionner" #: cola/prefs/view.py:172 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/prefs/view.py:173 msgid "Save GUI Settings" msgstr "" #: cola/prefs/view.py:227 #, fuzzy msgid "All Repositories" msgstr "Globales (tous les référentiels)" #: cola/prefs/view.py:228 #, fuzzy msgid "Current Repository" msgstr "Créer nouveau référentiel" #: cola/prefs/view.py:229 #, fuzzy msgid "Settings" msgstr "Lancement..." #: cola/stash/view.py:28 msgid "Stash" msgstr "" #: cola/stash/view.py:38 #, fuzzy msgid "Apply" msgstr "Pomme" #: cola/stash/view.py:39 msgid "Apply the selected stash" msgstr "" #: cola/stash/view.py:43 msgid "Save modified state to new stash" msgstr "" #: cola/stash/view.py:46 msgid "Drop" msgstr "" #: cola/stash/view.py:47 msgid "Drop the selected stash" msgstr "" #: cola/stash/view.py:54 msgid "Keep Index" msgstr "" #: cola/stash/view.py:175 msgid "Save Stash" msgstr "" #: cola/stash/view.py:176 msgid "Enter a name for the stash" msgstr "" #: cola/stash/view.py:182 msgid "Error: Stash exists" msgstr "" #: cola/stash/view.py:183 #, fuzzy, python-format msgid "A stash named \"%s\" already exists" msgstr "Le fichier %s existe déjà." #: cola/stash/view.py:198 msgid "Drop Stash?" msgstr "" #: cola/stash/view.py:199 #, fuzzy msgid "Recovering a dropped stash is not possible." msgstr "Récupérer les commits perdus ne sera peut être pas facile." #: cola/stash/view.py:200 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/stash/view.py:201 msgid "Drop Stash" msgstr "" #: cola/widgets/about.py:47 msgid "About git-cola" msgstr "" #: cola/widgets/about.py:97 msgid "" "This PyQt4 does not include QtWebKit.\n" "The keyboard shortcuts feature is unavailable." msgstr "" #: cola/widgets/about.py:104 msgid "hotkeys.html" msgstr "" #: cola/widgets/about.py:122 msgid "Shortcuts" msgstr "" #: cola/widgets/archive.py:46 msgid "Save Archive" msgstr "" #: cola/widgets/archive.py:69 msgid "Prefix" msgstr "" #: cola/widgets/archive.py:74 msgid "Advanced" msgstr "" #: cola/widgets/archive.py:141 cola/widgets/browse.py:49 msgid "File Saved" msgstr "" #: cola/widgets/archive.py:142 cola/widgets/browse.py:50 #, python-format msgid "File saved to \"%s\"" msgstr "" #: cola/widgets/archive.py:149 msgid "Overwrite File?" msgstr "" #: cola/widgets/archive.py:150 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/widgets/archive.py:151 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:152 msgid "Overwrite" msgstr "" #: cola/widgets/browse.py:42 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/browse.py:63 #, fuzzy, python-format msgid "Browsing %s" msgstr "Ajouter %s" #: cola/widgets/browse.py:81 #, fuzzy, python-format msgid "Select file from \"%s\"" msgstr "Supprimer les branches de %s" #: cola/widgets/browse.py:90 #, fuzzy msgid "Select File" msgstr "Tout sélectionner" #: cola/widgets/browse.py:117 cola/widgets/selectcommits.py:54 msgid "Select" msgstr "Sélectionner" #: cola/widgets/cfgactions.py:85 #, fuzzy msgid "Abort" msgstr "Abandon" #: cola/widgets/cfgactions.py:147 cola/widgets/cfgactions.py:151 #, fuzzy msgid "Abort Action" msgstr "Abandon" #: cola/widgets/cfgactions.py:148 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/widgets/cfgactions.py:150 msgid "Abort the action?" msgstr "" #: cola/widgets/cfgactions.py:201 msgid "Arguments" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/createtag.py:85 msgid "Revision" msgstr "Révision" #: cola/widgets/commitmsg.py:50 #, fuzzy msgid "Sign off on this commit" msgstr "Pré-commité" #: cola/widgets/commitmsg.py:53 cola/widgets/commitmsg.py:69 msgid "Commit@@verb" msgstr "Commiter" #: cola/widgets/commitmsg.py:56 #, fuzzy msgid "Commit staged changes" msgstr "Commit des modifications..." #: cola/widgets/commitmsg.py:67 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:75 #, fuzzy msgid "Actions..." msgstr "Options..." #: cola/widgets/commitmsg.py:85 msgid "Amend Last Commit" msgstr "Corriger dernier commit" #: cola/widgets/commitmsg.py:92 msgid "Check Spelling" msgstr "" #: cola/widgets/commitmsg.py:104 #, fuzzy msgid "Load Previous Commit Message" msgstr "Message de commit de fusion :" #: cola/widgets/commitmsg.py:135 cola/widgets/status.py:117 msgid "Move Down" msgstr "" #: cola/widgets/commitmsg.py:342 msgid "" "Please supply a commit message.\n" "\n" "A good commit message has the following format:\n" "\n" "- First line: Describe in one sentence what you did.\n" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" "Merci de fournir un message de commit.\n" "\n" "Un bon message de commit a le format suivant :\n" "\n" "- Première ligne : décrire en une phrase ce que vous avez fait.\n" "- Deuxième ligne : rien.\n" "- Lignes suivantes : Décrire pourquoi ces modifications sont bonnes.\n" #: cola/widgets/commitmsg.py:349 #, fuzzy msgid "Missing Commit Message" msgstr "Message de commit de fusion :" #: cola/widgets/commitmsg.py:355 #, fuzzy msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Pas de modification à commiter.\n" "\n" "Vous devez pré-commiter au moins 1 fichier avant de pouvoir commiter.\n" #: cola/widgets/commitmsg.py:359 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/commitmsg.py:361 #, fuzzy msgid "Stage and commit?" msgstr "Pré-commité" #: cola/widgets/commitmsg.py:364 #, fuzzy msgid "Stage and Commit" msgstr "Commiter un pré-commit" #: cola/widgets/commitmsg.py:369 #, fuzzy msgid "Nothing to commit" msgstr "Pas de modifications à commiter." #: cola/widgets/commitmsg.py:376 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/commitmsg.py:377 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" #: cola/widgets/commitmsg.py:380 msgid "Amend the published commit?" msgstr "" #: cola/widgets/commitmsg.py:381 #, fuzzy msgid "Amend Commit" msgstr "Corriger dernier commit" #: cola/widgets/commitmsg.py:386 #, fuzzy msgid "Commit failed" msgstr "Le commit a échoué." #: cola/widgets/commitmsg.py:387 #, python-format msgid "\"git commit\" returned exit code %s" msgstr "" #: cola/widgets/commitmsg.py:409 #, fuzzy msgid "More..." msgstr "Cloner..." #: cola/widgets/commitmsg.py:413 #, fuzzy msgid "Select Commit Message" msgstr "Message de commit de fusion :" #: cola/widgets/commitmsg.py:450 #, fuzzy msgid "Commit summary" msgstr "Message de commit :" #: cola/widgets/commitmsg.py:465 msgid "Extended description..." msgstr "" #: cola/widgets/compare.py:37 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:38 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/compare.py:39 cola/widgets/compare.py:62 #: cola/widgets/compare.py:68 msgid "Local" msgstr "" #: cola/widgets/compare.py:44 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/compare.py:63 cola/widgets/compare.py:69 #: cola/widgets/remote.py:129 msgid "Remote" msgstr "Référentiel distant" #: cola/widgets/compare.py:98 #, fuzzy msgid "File Differences" msgstr "Préférences" #: cola/widgets/createbranch.py:102 msgid "Branch Name" msgstr "Nom de branche" #: cola/widgets/createbranch.py:107 cola/widgets/createbranch.py:178 msgid "Starting Revision" msgstr "Début de révision" #: cola/widgets/createbranch.py:115 #, fuzzy msgid "Local branch" msgstr "Branche locale" #: cola/widgets/createbranch.py:119 #, fuzzy msgid "Tracking branch" msgstr "Suivi de branche" #: cola/widgets/createbranch.py:127 msgid "Update Existing Branch:" msgstr "Mettre à jour branche existante :" #: cola/widgets/createbranch.py:130 msgid "No" msgstr "Non" #: cola/widgets/createbranch.py:133 msgid "Fast Forward Only" msgstr "Avance rapide seulement" #: cola/widgets/createbranch.py:137 msgid "Reset" msgstr "Réinitialiser" #: cola/widgets/createbranch.py:143 msgid "Fetch Tracking Branch" msgstr "Branche suivant récupération" #: cola/widgets/createbranch.py:148 msgid "Checkout After Creation" msgstr "Emprunt après création" #: cola/widgets/createbranch.py:259 #, fuzzy msgid "Missing Data" msgstr "Manquant" #: cola/widgets/createbranch.py:260 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/widgets/createbranch.py:265 #, fuzzy, python-format msgid "Branch \"%s\" already exists." msgstr "La branche '%s' existe déjà." #: cola/widgets/createbranch.py:266 cola/widgets/createbranch.py:277 #, fuzzy msgid "Branch Exists" msgstr "Branches" #: cola/widgets/createbranch.py:273 #, fuzzy, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "Réinitialiser '%s' à '%s' va faire perdre les commits suivants :" #: cola/widgets/createbranch.py:288 #, python-format msgid "%d skipped" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Recovering lost commits may not be easy." msgstr "Récupérer les commits perdus ne sera peut être pas facile." #: cola/widgets/createbranch.py:292 #, fuzzy msgid "Reset Branch?" msgstr "Supprimer branche" #: cola/widgets/createbranch.py:294 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/widgets/createbranch.py:296 #, fuzzy msgid "Reset Branch" msgstr "Supprimer branche" #: cola/widgets/createbranch.py:305 #, fuzzy msgid "Updating..." msgstr "Lancement..." #: cola/widgets/createbranch.py:321 #, fuzzy msgid "Error Creating Branch" msgstr "Créer branche" #: cola/widgets/createbranch.py:322 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/widgets/createbranch.py:331 #, fuzzy msgid "Branch created" msgstr "Nom de branche" #: cola/widgets/createtag.py:55 msgid "vX.Y.Z" msgstr "" #: cola/widgets/createtag.py:56 msgid "Specifies the tag name" msgstr "" #: cola/widgets/createtag.py:62 #, fuzzy msgid "Sign Tag" msgstr "Approuver" #: cola/widgets/createtag.py:67 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:91 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:121 #, fuzzy msgid "Missing Revision" msgstr "Début de révision" #: cola/widgets/createtag.py:122 #, fuzzy msgid "Please specify a revision to tag." msgstr "Merci de sélectionner une branche à renommer." #: cola/widgets/createtag.py:125 #, fuzzy msgid "Missing Name" msgstr "Manquant" #: cola/widgets/createtag.py:126 msgid "Please specify a name for the new tag." msgstr "" #: cola/widgets/createtag.py:129 #, fuzzy msgid "Missing Tag Message" msgstr "Révision à fusionner" #: cola/widgets/createtag.py:130 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/createtag.py:132 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/createtag.py:135 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/createtag.py:142 #, fuzzy msgid "Tag Created" msgstr "Créer" #: cola/widgets/createtag.py:143 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/diff.py:22 msgid "Process Section" msgstr "" #: cola/widgets/diff.py:25 msgid "Process Selection" msgstr "" #: cola/widgets/diff.py:40 msgid "Stage &Selected Lines" msgstr "" #: cola/widgets/diff.py:46 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:51 #, fuzzy msgid "Unstage &Selected Lines" msgstr "Modifications non pré-commitées" #: cola/widgets/diff.py:57 msgid "Apply Diff Selection to Work Tree" msgstr "" #: cola/widgets/diff.py:86 cola/widgets/diff.py:108 cola/widgets/status.py:486 #: cola/widgets/status.py:584 msgid "Launch git-cola" msgstr "" #: cola/widgets/diff.py:91 #, fuzzy msgid "Stage Section" msgstr "Début de révision" #: cola/widgets/diff.py:97 msgid "Revert Section..." msgstr "" #: cola/widgets/diff.py:113 msgid "Unstage Section" msgstr "" #: cola/widgets/diff.py:125 msgid "Copy" msgstr "Copier" #: cola/widgets/diff.py:129 msgid "Select All" msgstr "Tout sélectionner" #: cola/widgets/diff.py:245 msgid "Revert Section?" msgstr "" #: cola/widgets/diff.py:249 msgid "Revert Section" msgstr "" #: cola/widgets/diff.py:258 #, fuzzy msgid "Revert Selected Lines?" msgstr "Inverser les modifications dans le fichier %s ? " #: cola/widgets/diff.py:262 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/editremotes.py:19 #, fuzzy msgid "Edit Remotes" msgstr "Référentiel distant" #: cola/widgets/editremotes.py:22 msgid "" "Add and remove remote repositories using the \n" "Add(+) and Delete(-) buttons on the left-hand side.\n" "\n" "Remotes can be renamed by selecting one from the list\n" "and pressing \"enter\", or by double-clicking." msgstr "" #: cola/widgets/editremotes.py:32 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/widgets/editremotes.py:45 #, fuzzy msgid "Add new remote git repository" msgstr "'%s' n'est pas un référentiel Git." #: cola/widgets/editremotes.py:53 #, fuzzy msgid "Delete remote" msgstr "Supprimer branche distante" #: cola/widgets/editremotes.py:116 #, python-format msgid "Error creating remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:124 #, fuzzy msgid "Delete Remote" msgstr "Supprimer branche distante" #: cola/widgets/editremotes.py:125 #, fuzzy msgid "Delete remote?" msgstr "Supprimer branche distante" #: cola/widgets/editremotes.py:126 #, fuzzy, python-format msgid "Delete remote \"%s\"" msgstr "Supprimer branche distante" #: cola/widgets/editremotes.py:134 #, python-format msgid "Error deleting remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:153 #, fuzzy msgid "Rename Remote" msgstr "Référentiel distant" #: cola/widgets/editremotes.py:154 #, fuzzy msgid "Rename remote?" msgstr "Référentiel distant" #: cola/widgets/editremotes.py:155 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/editremotes.py:157 msgid "Rename" msgstr "Renommer" #: cola/widgets/editremotes.py:169 #, fuzzy, python-format msgid "Gathering info for \"%s\"..." msgstr "Chargement des différences de %s..." #: cola/widgets/editremotes.py:201 #, fuzzy msgid "Add Remote" msgstr "Référentiel distant" #: cola/widgets/editremotes.py:213 #, fuzzy msgid "Add remote" msgstr "Référentiel distant" #: cola/widgets/editremotes.py:214 msgid "Name for the new remote" msgstr "" #: cola/widgets/editremotes.py:221 msgid "URL" msgstr "URL" #: cola/widgets/grep.py:47 cola/widgets/search.py:40 cola/widgets/search.py:58 msgid "Search" msgstr "" #: cola/widgets/grep.py:52 msgid "command-line arguments" msgstr "" #: cola/widgets/grep.py:56 msgid "grep result..." msgstr "" #: cola/widgets/grep.py:69 msgid "Shell arguments" msgstr "" #: cola/widgets/grep.py:71 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/widgets/log.py:34 #, fuzzy, python-format msgid "exit code %s" msgstr "récupérer %s" #: cola/widgets/recent.py:36 msgid "Recently Modified Files" msgstr "" #: cola/widgets/recent.py:46 msgid " commits ago" msgstr "" #: cola/widgets/recent.py:49 #, fuzzy msgid "Showing changes since" msgstr "Les modifications sont poussées vers %s" #: cola/widgets/recent.py:61 msgid "Expand" msgstr "" #: cola/widgets/recent.py:65 #, fuzzy msgid "Collapse" msgstr "Fermer" #: cola/widgets/remote.py:136 #, fuzzy msgid "Remote Branch" msgstr "Renommer branche" #: cola/widgets/remote.py:143 #, fuzzy msgid "Fast Forward Only " msgstr "Avance rapide seulement" #: cola/widgets/remote.py:147 #, fuzzy msgid "Include tags " msgstr "Inclure les marques" #: cola/widgets/remote.py:150 #, fuzzy msgid "Rebase " msgstr "Réinitialiser" #: cola/widgets/remote.py:314 #, fuzzy, python-format msgid "URL: %s" msgstr "URL :" #: cola/widgets/remote.py:393 msgid "No repository selected." msgstr "Aucun référentiel n'est sélectionné." #: cola/widgets/remote.py:406 msgid "Push" msgstr "Pousser" #: cola/widgets/remote.py:408 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/remote.py:410 #, fuzzy msgid "Create a new remote branch?" msgstr "Créer nouvelle branche" #: cola/widgets/remote.py:411 #, fuzzy msgid "Create Remote Branch" msgstr "Supprimer branche distante" #: cola/widgets/remote.py:419 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:420 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:421 #, fuzzy, python-format msgid "Force fetching from %s?" msgstr "Récupération de %s à partir de %s" #: cola/widgets/remote.py:422 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:424 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:425 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/remote.py:427 #, python-format msgid "Force push to %s?" msgstr "" #: cola/widgets/remote.py:428 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:462 msgid "Already up-to-date." msgstr "" #: cola/widgets/remote.py:485 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/widgets/search.py:44 #, fuzzy msgid "Browse..." msgstr "Visionner" #: cola/widgets/search.py:50 cola/widgets/search.py:55 msgid "yyyy-MM-dd" msgstr "" #: cola/widgets/search.py:220 #, fuzzy msgid "Search by Expression" msgstr "Expression de révision :" #: cola/widgets/search.py:221 msgid "Search by Path" msgstr "" #: cola/widgets/search.py:222 #, fuzzy msgid "Search Commit Messages" msgstr "Message de commit de fusion :" #: cola/widgets/search.py:223 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:224 msgid "Search Authors" msgstr "" #: cola/widgets/search.py:225 #, fuzzy msgid "Search Committers" msgstr "Commiteur :" #: cola/widgets/search.py:226 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:319 #, fuzzy msgid "Choose Path(s)" msgstr "Choisir %s" #: cola/widgets/selectcommits.py:50 msgid "Revision Expression:" msgstr "Expression de révision :" #: cola/widgets/selectcommits.py:101 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/spellcheck.py:139 #, fuzzy msgid "Spelling Suggestions" msgstr "Aucune suggestion" #: cola/widgets/startup.py:26 msgid "git-cola" msgstr "" #: cola/widgets/startup.py:33 msgid "New..." msgstr "Nouveau..." #: cola/widgets/startup.py:56 #, fuzzy msgid "Select Repository..." msgstr "Référentiel Git" #: cola/widgets/startup.py:61 #, fuzzy msgid "Select manually..." msgstr "Tout sélectionner" #: cola/widgets/status.py:75 #, fuzzy msgid "Untracked" msgstr "Non suivi, non pré-commité" #: cola/widgets/status.py:85 #, fuzzy msgid "Stage / Unstage" msgstr "Pré-commit modifié" #: cola/widgets/status.py:114 msgid "Move Up" msgstr "" #: cola/widgets/status.py:121 msgid "Copy Path to Clipboard" msgstr "" #: cola/widgets/status.py:474 cola/widgets/status.py:550 msgid "Revert Unstaged Edits..." msgstr "" #: cola/widgets/status.py:477 cola/widgets/status.py:553 msgid "Revert Uncommited Edits..." msgstr "" #: cola/widgets/status.py:572 #, fuzzy msgid "Delete File(s)..." msgstr "Supprimer..." #: cola/widgets/status.py:575 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:608 #, fuzzy msgid "Delete Files?" msgstr "Supprimer" #: cola/widgets/status.py:609 msgid "The following files will be deleted:" msgstr "" #: cola/widgets/status.py:616 #, python-format msgid "Delete %d file(s)?" msgstr "" #: cola/widgets/status.py:617 #, fuzzy msgid "Delete Files" msgstr "Supprimer" #: cola/widgets/status.py:633 #, fuzzy msgid "Revert Unstaged Changes?" msgstr "Modifications non pré-commitées" #: cola/widgets/status.py:634 msgid "" "This operation drops unstaged changes.\n" "These changes cannot be recovered." msgstr "" #: cola/widgets/status.py:636 #, fuzzy msgid "Revert the unstaged changes?" msgstr "Modifications non pré-commitées" #: cola/widgets/status.py:637 #, fuzzy msgid "Revert Unstaged Changes" msgstr "Modifications non pré-commitées" #: cola/widgets/status.py:646 cola/widgets/status.py:662 msgid "No files selected for checkout from HEAD." msgstr "" #~ msgid "Success" #~ msgstr "Succès" #~ msgid "Rescan" #~ msgstr "Resynchroniser" #, fuzzy #~ msgid "Browse Revision..." #~ msgstr "Révision" #, fuzzy #~ msgid "Rebase Branch" #~ msgstr "Renommer branche" #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: erreur fatale" #~ msgid "Invalid font specified in %s:" #~ msgstr "Invalide fonte spécifiée dans %s :" #~ msgid "Main Font" #~ msgstr "Fonte principale" #~ msgid "Diff/Console Font" #~ msgstr "Fonte diff/console" #~ msgid "Cannot find git in PATH." #~ msgstr "Impossible de trouver git dans PATH." #~ msgid "Cannot parse Git version string:" #~ msgstr "Impossible de parser la version de Git :" #~ msgid "" #~ "Git version cannot be determined.\n" #~ "\n" #~ "%s claims it is version '%s'.\n" #~ "\n" #~ "%s requires at least Git 1.5.0 or later.\n" #~ "\n" #~ "Assume '%s' is version 1.5.0?\n" #~ msgstr "" #~ "Impossible de déterminer la version de Git.\n" #~ "\n" #~ "%s affirme qu'il s'agit de la version '%s'.\n" #~ "\n" #~ "%s nécessite au moins Git 1.5.0.\n" #~ "\n" #~ "Peut'on considérer que '%s' est en version 1.5.0 ?\n" #~ msgid "Git directory not found:" #~ msgstr "Impossible de trouver le répertoire de Git :" #~ msgid "Cannot move to top of working directory:" #~ msgstr "Impossible d'aller à la racine du répertoire de travail :" #~ msgid "Cannot use funny .git directory:" #~ msgstr "Impossible d'utiliser un drôle de répertoire git :" #~ msgid "No working directory" #~ msgstr "Pas de répertoire de travail" #~ msgid "Refreshing file status..." #~ msgstr "Rafraichissement du status des fichiers..." #~ msgid "Ready." #~ msgstr "Prêt." #~ msgid "Modified, not staged" #~ msgstr "Modifié, non pré-commité" #~ msgid "Portions staged for commit" #~ msgstr "En partie pré-commité" #~ msgid "Staged for commit, missing" #~ msgstr "Pré-commité, manquant" #~ msgid "Staged for removal" #~ msgstr "Pré-commité pour suppression" #~ msgid "Staged for removal, still present" #~ msgstr "Pré-commité pour suppression, toujours présent" #~ msgid "Requires merge resolution" #~ msgstr "Nécessite la résolution d'une fusion" #~ msgid "Starting gitk... please wait..." #~ msgstr "Lancement de gitk... merci de patienter..." #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "Impossible de lancer gitk :\n" #~ "\n" #~ "%s inexistant" #~ msgid "Repository" #~ msgstr "Référentiel" #~ msgid "Commit@@noun" #~ msgstr "Commit" #~ msgid "Browse %s's Files" #~ msgstr "Visionner fichiers de %s" #~ msgid "Visualize %s's History" #~ msgstr "Visualiser historique de %s" #~ msgid "Database Statistics" #~ msgstr "Statistiques base de donnée" #~ msgid "Compress Database" #~ msgstr "Comprimer base de donnée" #~ msgid "Verify Database" #~ msgstr "Vérifier base de donnée" #~ msgid "Create Desktop Icon" #~ msgstr "Créer icône sur bureau" #~ msgid "Undo" #~ msgstr "Défaire" #~ msgid "Redo" #~ msgstr "Refaire" #~ msgid "Cut" #~ msgstr "Couper" #~ msgid "Paste" #~ msgstr "Coller" #~ msgid "Rename..." #~ msgstr "Renommer..." #~ msgid "New Commit" #~ msgstr "Nouveau commit" #~ msgid "Local Merge..." #~ msgstr "Fusion locale..." #~ msgid "Preferences..." #~ msgstr "Préférences..." #~ msgid "Current Branch:" #~ msgstr "Branche courante :" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "Modifications pré-commitées" #~ msgid "Initial Commit Message:" #~ msgstr "Message de commit initial :" #~ msgid "Amended Commit Message:" #~ msgstr "Message de commit corrigé :" #~ msgid "Amended Initial Commit Message:" #~ msgstr "Message de commit initial corrigé :" #~ msgid "Amended Merge Commit Message:" #~ msgstr "Message de commit de fusion corrigé :" #~ msgid "Apply/Reverse Hunk" #~ msgstr "Appliquer/Inverser section" #~ msgid "Show Less Context" #~ msgstr "Montrer moins de contexte" #~ msgid "Show More Context" #~ msgstr "Montrer plus de contexte" #~ msgid "Decrease Font Size" #~ msgstr "Réduire fonte" #~ msgid "Increase Font Size" #~ msgstr "Agrandir fonte" #~ msgid "Unstage Hunk From Commit" #~ msgstr "Enlever section pré-commitée" #~ msgid "Stage Hunk For Commit" #~ msgstr "Pré-commiter section" #~ msgid "Initializing..." #~ msgstr "Initialisation..." #~ msgid "" #~ "Possible environment issues exist.\n" #~ "\n" #~ "The following environment variables are probably\n" #~ "going to be ignored by any Git subprocess run\n" #~ "by %s:\n" #~ "\n" #~ msgstr "" #~ "Des problèmes d'environnement sont possibles.\n" #~ "\n" #~ "Les variables d'environnement suivantes seront\n" #~ "probablement ignorées par tous les\n" #~ "sous-processus de Git lancés par %s\n" #~ "\n" #~ msgid "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "Ceci est du à un problème connu avec\n" #~ "le binaire Tcl distribué par Cygwin." #~ msgid "" #~ "\n" #~ "\n" #~ "A good replacement for %s\n" #~ "is placing values for the user.name and\n" #~ "user.email settings into your personal\n" #~ "~/.gitconfig file.\n" #~ msgstr "" #~ "\n" #~ "\n" #~ "Un bon remplacement pour %s\n" #~ "est de mettre les valeurs pour 'user.name' (nom\n" #~ "de l'utilisateur) et 'user.email' (addresse email\n" #~ "de l'utilisateur) dans votre fichier '~/.gitconfig'.\n" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - une interface graphique utilisateur pour Git" #~ msgid "File Viewer" #~ msgstr "Visionneur de fichier" #~ msgid "Reading %s..." #~ msgstr "Lecture de %s..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "Chargement des annotations de suivi des copies/déplacements..." #~ msgid "lines annotated" #~ msgstr "lignes annotées" #~ msgid "Loading original location annotations..." #~ msgstr "Chargement des annotations d'emplacement original" #~ msgid "Annotation complete." #~ msgstr "Annotation terminée." #~ msgid "Loading annotation..." #~ msgstr "Chargement des annotations..." #~ msgid "Original File:" #~ msgstr "Fichier original :" #~ msgid "Originally By:" #~ msgstr "A l'origine par :" #~ msgid "In File:" #~ msgstr "Dans le fichier :" #~ msgid "Copied Or Moved Here By:" #~ msgstr "Copié ou déplacé ici par :" #~ msgid "Detach From Local Branch" #~ msgstr "Détacher de branche locale" #~ msgid "Match Tracking Branch Name" #~ msgstr "Trouver nom de branche de suivi" #~ msgid "Tracking branch %s is not a branch in the remote repository." #~ msgstr "" #~ "La branche de suivi %s n'est pas une branche dans le référentiel distant." #~ msgid "Please supply a branch name." #~ msgstr "Merci de fournir un nom de branche." #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "'%s' n'est pas un nom de branche acceptable." #~ msgid "Delete Local Branch" #~ msgstr "Supprimer branche locale" #~ msgid "Local Branches" #~ msgstr "Branches locales" #~ msgid "Delete Only If Merged Into" #~ msgstr "Supprimer ssi fusion dedans" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "Toujours (Ne pas faire de test de fusion.)" #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "" #~ "Les branches suivantes ne sont pas complètement fusionnées dans %s :" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "Récupérer des branches supprimées est difficile.\n" #~ "\n" #~ "Supprimer les branches sélectionnées ?" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "La suppression des branches suivantes a échouée :\n" #~ "%s" #~ msgid "New Name:" #~ msgstr "Nouveau nom :" #~ msgid "Failed to rename '%s'." #~ msgstr "Le renommage de '%s' a échoué." #~ msgid "[Up To Parent]" #~ msgstr "[Jusqu'au parent]" #~ msgid "Browse Branch Files" #~ msgstr "Visionner fichiers de branches" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "erreur fatale : Impossible de résoudre %s" #~ msgid "Branch '%s' does not exist." #~ msgstr "La branche '%s' n'existe pas." #~ msgid "" #~ "Branch '%s' already exists.\n" #~ "\n" #~ "It cannot fast-forward to %s.\n" #~ "A merge is required." #~ msgstr "" #~ "La branche '%s' existe déjà.\n" #~ "\n" #~ "Impossible d'avancer rapidement à %s.\n" #~ "Une fusion est nécessaire." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "La stratégie de fusion '%s' n'est pas supportée." #~ msgid "Failed to update '%s'." #~ msgstr "La mise à jour de '%s' a échouée." #~ msgid "Staging area (index) is already locked." #~ msgstr "L'espace de pré-commit ('index' ou 'staging') est déjà vérouillé." #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before the current branch can be changed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "L'état lors de la dernière synchronisation ne correspond plus à l'état du " #~ "référentiel.\n" #~ "\n" #~ "Un autre programme Git a modifié ce référentiel depuis la dernière " #~ "synchronisation. Une resynchronisation doit être effectuée avant de " #~ "pouvoir modifier la branche courante.\n" #~ "\n" #~ "Cela va être fait tout de suite automatiquement.\n" #~ msgid "Updating working directory to '%s'..." #~ msgstr "Mise à jour du répertoire courant avec '%s'..." #~ msgid "files checked out" #~ msgstr "fichiers empruntés" #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "" #~ "Emprunt de '%s' abandonné. (Il est nécessaire de fusionner des fichiers.)" #~ msgid "File level merge required." #~ msgstr "Il est nécessaire de fusionner des fichiers." #~ msgid "Staying on branch '%s'." #~ msgstr "Le répertoire de travail reste sur la branche '%s'." #~ msgid "" #~ "You are no longer on a local branch.\n" #~ "\n" #~ "If you wanted to be on a branch, create one now starting from 'This " #~ "Detached Checkout'." #~ msgstr "" #~ "Vous n'êtes plus ur une branche locale.\n" #~ "\n" #~ "Si vous vouliez être sur une branche, créez en une maintenant en partant " #~ "de 'Cet emprunt détaché'." #~ msgid "Checked out '%s'." #~ msgstr "'%s' emprunté." #~ msgid "Reset '%s'?" #~ msgstr "Réinitialiser '%s' ?" #~ msgid "" #~ "Failed to set current branch.\n" #~ "\n" #~ "This working directory is only partially switched. We successfully " #~ "updated your files, but failed to update an internal Git file.\n" #~ "\n" #~ "This should not have occurred. %s will now close and give up." #~ msgstr "" #~ "Le changement de la branche courante a échoué.\n" #~ "\n" #~ "Le répertoire courant n'est que partiellement modifié. Les fichiers ont " #~ "été mis à jour avec succès, mais la mise à jour d'un fichier interne à " #~ "Git a échouée.\n" #~ "\n" #~ "Cela n'aurait pas du se produire. %s va abandonner et se terminer." #~ msgid "Font Family" #~ msgstr "Famille de fonte" #~ msgid "Font Example" #~ msgstr "Exemple de fonte" #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "C'est un texte d'exemple.\n" #~ "Si vous aimez ce texte, vous pouvez choisir cette fonte." #~ msgid "Git Gui" #~ msgstr "Git Gui" #~ msgid "Clone Existing Repository" #~ msgstr "Cloner référentiel existant" #~ msgid "Recent Repositories" #~ msgstr "Référentiels récents" #~ msgid "Failed to create repository %s:" #~ msgstr "La création du référentiel %s a échouée :" #~ msgid "Directory:" #~ msgstr "Répertoire :" #~ msgid "Directory %s already exists." #~ msgstr "Le répertoire %s existe déjà." #~ msgid "Clone" #~ msgstr "Cloner" #~ msgid "Clone Type:" #~ msgstr "Type de clonage :" #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "Standard (rapide, semi-redondant, liens durs)" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "Copy complète (plus lent, sauvegarde redondante)" #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "Partagé (le plus rapide, non recommandé, pas de sauvegarde)" #~ msgid "Standard only available for local repository." #~ msgstr "Standard n'est disponible que pour un référentiel local." #~ msgid "Shared only available for local repository." #~ msgstr "Partagé n'est disponible que pour un référentiel local." #~ msgid "Location %s already exists." #~ msgstr "L'emplacement %s existe déjà." #~ msgid "Failed to configure origin" #~ msgstr "La configuration de l'origine a échouée." #~ msgid "Counting objects" #~ msgstr "Comptage des objets" #~ msgid "buckets" #~ msgstr "paniers" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "Impossible de copier 'objects/info/alternates' : %s" #~ msgid "The 'master' branch has not been initialized." #~ msgstr "Cette branche 'master' n'a pas été initialisée." #~ msgid "Hardlinks are unavailable. Falling back to copying." #~ msgstr "Les liens durs ne sont pas disponibles. On se résoud à copier." #~ msgid "Cloning from %s" #~ msgstr "Clonage depuis %s" #~ msgid "Copying objects" #~ msgstr "Copie des objets" #~ msgid "KiB" #~ msgstr "KiB" #~ msgid "Unable to copy object: %s" #~ msgstr "Impossible de copier l'objet : %s" #~ msgid "Linking objects" #~ msgstr "Liaison des objets" #~ msgid "objects" #~ msgstr "objets" #~ msgid "Unable to hardlink object: %s" #~ msgstr "Impossible créer un lien dur pour l'objet : %s" #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "" #~ "Impossible de récupérer les branches et objets. Voir la sortie console " #~ "pour plus de détails." #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "" #~ "Impossible de récupérer les marques. Voir la sortie console pour plus de " #~ "détails." #~ msgid "Cannot determine HEAD. See console output for details." #~ msgstr "" #~ "Impossible de déterminer HEAD. Voir la sortie console pour plus de " #~ "détails." #~ msgid "Unable to cleanup %s" #~ msgstr "Impossible de nettoyer %s" #~ msgid "Clone failed." #~ msgstr "Le clonage a échoué." #~ msgid "No default branch obtained." #~ msgstr "Aucune branche par défaut n'a été obtenue." #~ msgid "Cannot resolve %s as a commit." #~ msgstr "Impossible de résoudre %s comme commit." #~ msgid "Creating working directory" #~ msgstr "Création du répertoire de travail" #~ msgid "files" #~ msgstr "fichiers" #~ msgid "Initial file checkout failed." #~ msgstr "L'emprunt initial de fichier a échoué." #~ msgid "Failed to open repository %s:" #~ msgstr "Impossible d'ouvrir le référentiel %s :" #~ msgid "This Detached Checkout" #~ msgstr "Cet emprunt détaché" #~ msgid "Updated" #~ msgstr "Misa à jour" #~ msgid "" #~ "There is nothing to amend.\n" #~ "\n" #~ "You are about to create the initial commit. There is no commit before " #~ "this to amend.\n" #~ msgstr "" #~ "Il n'y a rien à corriger.\n" #~ "\n" #~ "Vous allez créer le commit initial. Il n'y a pas de commit avant celui-ci " #~ "à corriger.\n" #~ msgid "" #~ "Cannot amend while merging.\n" #~ "\n" #~ "You are currently in the middle of a merge that has not been fully " #~ "completed. You cannot amend the prior commit unless you first abort the " #~ "current merge activity.\n" #~ msgstr "" #~ "Impossible de corriger pendant une fusion.\n" #~ "\n" #~ "Vous êtes actuellement au milieu d'une fusion qui n'a pas été " #~ "completement terminée. Vous ne pouvez pas corriger le commit précédant " #~ "sauf si vous abandonnez la fusion courante.\n" #~ msgid "Error loading commit data for amend:" #~ msgstr "Erreur lors du chargement des données de commit pour correction :" #~ msgid "Unable to obtain your identity:" #~ msgstr "Impossible d'obtenir votre identité :" #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "GIT_COMMITTER_IDENT invalide :" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before another commit can be created.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "L'état lors de la dernière synchronisation ne correspond plus à l'état du " #~ "référentiel.\n" #~ "\n" #~ "Un autre programme Git a modifié ce référentiel depuis la dernière " #~ "synchronisation. Une resynshronisation doit être effectuée avant de " #~ "pouvoir créer un nouveau commit.\n" #~ "\n" #~ "Cela va être fait tout de suite automatiquement.\n" #~ msgid "" #~ "Unmerged files cannot be committed.\n" #~ "\n" #~ "File %s has merge conflicts. You must resolve them and stage the file " #~ "before committing.\n" #~ msgstr "" #~ "Des fichiers non fusionnés ne peuvent être commités.\n" #~ "\n" #~ "Le fichier %s a des conflicts de fusion. Vous devez les résoudre et pré-" #~ "commiter le fichier avant de pouvoir commiter.\n" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "Un état de fichier inconnu %s a été détecté.\n" #~ "\n" #~ "Le fichier %s ne peut pas être commité par ce programme.\n" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "attention : Tcl ne supporte pas l'encodage '%s'." #~ msgid "Calling pre-commit hook..." #~ msgstr "Appel du programme externe d'avant commit..." #~ msgid "Commit declined by pre-commit hook." #~ msgstr "Commit refusé par le programme externe d'avant commit." #~ msgid "Calling commit-msg hook..." #~ msgstr "Appel du programme externe de message de commit..." #~ msgid "Commit declined by commit-msg hook." #~ msgstr "Commit refusé par le programme externe de message de commit." #~ msgid "write-tree failed:" #~ msgstr "write-tree a échoué :" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "Le commit %s semble être corrompu" #~ msgid "" #~ "No changes to commit.\n" #~ "\n" #~ "No files were modified by this commit and it was not a merge commit.\n" #~ "\n" #~ "A rescan will be automatically started now.\n" #~ msgstr "" #~ "Pas de modification à commiter.\n" #~ "\n" #~ "Aucun fichier n'a été modifié par ce commit et il ne s'agit pas d'un " #~ "commit de fusion.\n" #~ "\n" #~ "Une resynchronisation va être lancée tout de suite automatiquement.\n" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree a échoué :" #~ msgid "update-ref failed:" #~ msgstr "update-ref a échoué" #~ msgid "Working... please wait..." #~ msgstr "Travail en cours... merci de patienter..." #~ msgid "Error: Command Failed" #~ msgstr "Erreur : échec de la commande" #~ msgid "Number of loose objects" #~ msgstr "Nombre d'objets en fichier particulier" #~ msgid "Disk space used by loose objects" #~ msgstr "Espace disque utilisé par les fichiers particuliers" #~ msgid "Number of packed objects" #~ msgstr "Nombre d'objets empaquetés" #~ msgid "Number of packs" #~ msgstr "Nombre de paquets d'objets" #~ msgid "Disk space used by packed objects" #~ msgstr "Espace disque utilisé par les objets empaquetés" #~ msgid "Packed objects waiting for pruning" #~ msgstr "Objets empaquetés attendant d'être supprimés" #~ msgid "Garbage files" #~ msgstr "Fichiers poubelle" #~ msgid "Compressing the object database" #~ msgstr "Compression de la base des objets" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "Vérification de la base des objets avec fsck-objects" #~ msgid "" #~ "This repository currently has approximately %i loose objects.\n" #~ "\n" #~ "To maintain optimal performance it is strongly recommended that you " #~ "compress the database when more than %i loose objects exist.\n" #~ "\n" #~ "Compress the database now?" #~ msgstr "" #~ "Ce référentiel comprend actuellement environ %i objets ayant leur fichier " #~ "particulier.\n" #~ "\n" #~ "Pour conserver une performance optimale, il est fortement recommandé de " #~ "comprimer la base quand plus de %i objets ayant leur fichier particulier " #~ "existent.\n" #~ "\n" #~ "Comprimer la base maintenant ?" #~ msgid "Invalid date from Git: %s" #~ msgstr "Date invalide de Git : %s" #~ msgid "" #~ "No differences detected.\n" #~ "\n" #~ "%s has no changes.\n" #~ "\n" #~ "The modification date of this file was updated by another application, " #~ "but the content within the file was not changed.\n" #~ "\n" #~ "A rescan will be automatically started to find other files which may have " #~ "the same state." #~ msgstr "" #~ "Aucune différence détectée.\n" #~ "\n" #~ "%s ne comporte aucune modification.\n" #~ "\n" #~ "La date de modification de ce fichier a été mise à jour par une autre " #~ "application, mais le contenu du fichier n'a pas changé.\n" #~ "\n" #~ "Une resynchronisation va être lancée automatiquement pour trouver " #~ "d'autres fichiers qui pourraient se trouver dans le même état." #~ msgid "Unable to display %s" #~ msgstr "Impossible d'afficher %s" #~ msgid "Git Repository (subproject)" #~ msgstr "Référentiel Git (sous projet)" #~ msgid "* Binary file (not showing content)." #~ msgstr "* Fichier binaire (pas d'apperçu du contenu)." #~ msgid "Failed to unstage selected hunk." #~ msgstr "" #~ "La suppression dans le pré-commit de la section sélectionnée a échouée." #~ msgid "Failed to stage selected hunk." #~ msgstr "Le pré-commit de la section sélectionnée a échoué." #~ msgid "warning" #~ msgstr "attention" #~ msgid "You must correct the above errors before committing." #~ msgstr "" #~ "Vous devez corriger les erreurs suivantes avant de pouvoir commiter." #~ msgid "Unable to unlock the index." #~ msgstr "Impossible de dévérouiller le pré-commit." #~ msgid "" #~ "Updating the Git index failed. A rescan will be automatically started to " #~ "resynchronize git-gui." #~ msgstr "" #~ "Le pré-commit a échoué. Une resynchronisation va être lancée " #~ "automatiquement." #~ msgid "Unlock Index" #~ msgstr "Dévérouiller le pré-commit" #~ msgid "Ready to commit." #~ msgstr "Prêt à être commité." #~ msgid "Revert changes in these %i files?" #~ msgstr "Inverser les modifications dans ces %i fichiers ?" #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "" #~ "Toutes les modifications non pré-commitées seront définitivement perdues " #~ "lors de l'inversion." #~ msgid "Do Nothing" #~ msgstr "Ne rien faire" #~ msgid "" #~ "Cannot merge while amending.\n" #~ "\n" #~ "You must finish amending this commit before starting any type of merge.\n" #~ msgstr "" #~ "Impossible de fucionner pendant une correction.\n" #~ "\n" #~ "Vous devez finir de corriger ce commit avant de lancer une quelconque " #~ "fusion.\n" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before a merge can be performed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "L'état lors de la dernière synchronisation ne correspond plus à l'état du " #~ "référentiel.\n" #~ "\n" #~ "Un autre programme Git a modifié ce référentiel depuis la dernière " #~ "synchronisation. Une resynchronisation doit être effectuée avant de " #~ "pouvoir fusionner de nouveau.\n" #~ "\n" #~ "Cela va être fait tout de suite automatiquement\n" #~ msgid "" #~ "You are in the middle of a conflicted merge.\n" #~ "\n" #~ "File %s has merge conflicts.\n" #~ "\n" #~ "You must resolve them, stage the file, and commit to complete the current " #~ "merge. Only then can you begin another merge.\n" #~ msgstr "" #~ "Vous êtes au milieu d'une fusion conflictuelle.\n" #~ "\n" #~ "Le fichier %s a des conflicts de fusion.\n" #~ "\n" #~ "Vous devez les résoudre, puis pré-commiter le fichier, et enfin commiter " #~ "pour terminer la fusion courante. Seulementà ce moment là, il sera " #~ "possible d'effectuer une nouvelle fusion.\n" #~ msgid "" #~ "You are in the middle of a change.\n" #~ "\n" #~ "File %s is modified.\n" #~ "\n" #~ "You should complete the current commit before starting a merge. Doing so " #~ "will help you abort a failed merge, should the need arise.\n" #~ msgstr "" #~ "Vous êtes au milieu d'une modification.\n" #~ "\n" #~ "Le fichier %s est modifié.\n" #~ "\n" #~ "Vous devriez terminer le commit courant avant de lancer une fusion. En " #~ "faisait comme cela, vous éviterez de devoir éventuellement abandonner une " #~ "fusion ayant échouée.\n" #~ msgid "%s of %s" #~ msgstr "%s de %s" #~ msgid "Merging %s and %s..." #~ msgstr "Fusion de %s et %s..." #~ msgid "Merge completed successfully." #~ msgstr "La fusion s'est faite avec succès." #~ msgid "Merge failed. Conflict resolution is required." #~ msgstr "La fusion a echouée. Il est nécessaire de résoudre les conflicts." #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\n" #~ msgstr "" #~ "Impossible d'abandonner en cours de correction.\n" #~ "\n" #~ "Vous devez finir de corriger ce commit.\n" #~ msgid "" #~ "Reset changes?\n" #~ "\n" #~ "Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" #~ "\n" #~ "Continue with resetting the current changes?" #~ msgstr "" #~ "Réinitialiser les modifications ?\n" #~ "\n" #~ "Réinitialiser les modifications va faire perdre TOUTES les modifications " #~ "non commitées.\n" #~ "\n" #~ "Réinitialiser quand même les modifications courantes ?" #~ msgid "files reset" #~ msgstr "fichiers réinitialisés" #~ msgid "Abort failed." #~ msgstr "L'abandon a échoué." #~ msgid "Abort completed. Ready." #~ msgstr "Abandon teminé. Prêt." #~ msgid "Restore Defaults" #~ msgstr "Remettre les valeurs par défaut" #~ msgid "%s Repository" #~ msgstr "Référentiel de %s" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "Nettoyer les branches de suivi pendant la récupération" #~ msgid "Match Tracking Branches" #~ msgstr "Faire correspondre les branches de suivi" #~ msgid "New Branch Name Template" #~ msgstr "Nouveau modèle de nom de branche" #~ msgid "Spelling Dictionary:" #~ msgstr "Dictionnaire d'orthographe :" #~ msgid "Change Font" #~ msgstr "Modifier les fontes" #~ msgid "pt." #~ msgstr "pt." #~ msgid "Failed to completely save options:" #~ msgstr "La sauvegarde complète des options a échouée :" #~ msgid "From Repository" #~ msgstr "Référentiel" #~ msgid "Remote:" #~ msgstr "Branche distante :" #~ msgid "Arbitrary URL:" #~ msgstr "URL arbitraire :" #~ msgid "Delete Only If" #~ msgstr "Supprimer seulement si" #~ msgid "Merged Into:" #~ msgstr "Fusionné dans :" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "Toujours (ne pas vérifier les fusions)" #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "Une branche est nécessaire pour 'Fusionné dans'." #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "Les branches suivantes ne sont pas complètement fusionnées dans %s :\n" #~ "\n" #~ " - %s" #~ msgid "" #~ "One or more of the merge tests failed because you have not fetched the " #~ "necessary commits. Try fetching from %s first." #~ msgstr "" #~ "Une ou plusieurs des tests de fusion ont échoués parce que vous n'avez " #~ "pas récupéré les commits nécessaires. Essayez de récupéré à partir de %s " #~ "d'abord." #~ msgid "Please select one or more branches to delete." #~ msgstr "Merci de sélectionner une ou plusieurs branches à supprimer." #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "Récupérer des branches supprimées est difficile.\n" #~ "\n" #~ "Souhaitez vous supprimer les branches sélectionnées ?" #~ msgid "Prune from" #~ msgstr "Nettoyer de" #~ msgid "Fetch from" #~ msgstr "Récupérer de" #~ msgid "Push to" #~ msgstr "Pousser vers" #~ msgid "Cannot write shortcut:" #~ msgstr "Impossible d'écrire le raccourcis :" #~ msgid "Unsupported spell checker" #~ msgstr "Vérificateur d'orthographe non supporté" #~ msgid "Spell checking is unavailable" #~ msgstr "La vérification d'orthographe n'est pas disponible" #~ msgid "Invalid spell checking configuration" #~ msgstr "Configuration de vérification d'orthographe invalide" #~ msgid "Reverting dictionary to %s." #~ msgstr "Réinitialisation du dictionnaire à %s." #~ msgid "Spell checker silently failed on startup" #~ msgstr "" #~ "La vérification d'orthographe a échouée silentieusement au démarrage" #~ msgid "Unrecognized spell checker" #~ msgstr "Vérificateur d'orthographe non reconnu" #~ msgid "Unexpected EOF from spell checker" #~ msgstr "Fin de fichier innatendue envoyée par le vérificateur d'orthographe" #~ msgid "Spell Checker Failed" #~ msgstr "Le vérificateur d'orthographe a échoué" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%s ... %*i de %*i %s (%3i%%)" #~ msgid "Fetching new changes from %s" #~ msgstr "Récupération des dernières modifications de %s" #~ msgid "remote prune %s" #~ msgstr "nettoyer à distance %s" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "Nettoyer les branches de suivi supprimées de %s" #~ msgid "push %s" #~ msgstr "pousser %s" #~ msgid "Pushing %s %s to %s" #~ msgstr "Pousse %s %s vers %s" #~ msgid "Push Branches" #~ msgstr "Pousser branches" #~ msgid "Source Branches" #~ msgstr "Branches source" #~ msgid "Destination Repository" #~ msgstr "Référentiel de destination" #~ msgid "Transfer Options" #~ msgstr "Transférer options" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "" #~ "Forcer l'écrasement d'une branche existante (peut supprimer des " #~ "modifications)" #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Utiliser des petits paquets (pour les connexions lentes)" git-cola-1.9.3/po/git-cola.pot000066400000000000000000001106211225156173500160740ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-09-24 21:42-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: cola/bookmarks.py:32 msgid "Bookmarks" msgstr "" #: cola/bookmarks.py:47 msgid "Open" msgstr "" #: cola/bookmarks.py:53 msgid "Add" msgstr "" #: cola/bookmarks.py:58 cola/guicmds.py:25 cola/guicmds.py:33 #: cola/widgets/editremotes.py:127 msgid "Delete" msgstr "" #: cola/bookmarks.py:65 cola/stash/view.py:42 cola/widgets/archive.py:65 #: cola/widgets/browse.py:117 msgid "Save" msgstr "" #: cola/bookmarks.py:71 cola/difftool.py:96 cola/qt.py:57 cola/qt.py:243 #: cola/prefs/view.py:241 cola/stash/view.py:50 cola/stash/view.py:51 #: cola/widgets/about.py:66 cola/widgets/about.py:126 #: cola/widgets/browse.py:116 cola/widgets/cfgactions.py:87 #: cola/widgets/cfgactions.py:239 cola/widgets/compare.py:94 #: cola/widgets/createbranch.py:159 cola/widgets/createtag.py:104 #: cola/widgets/editremotes.py:55 cola/widgets/grep.py:75 #: cola/widgets/recent.py:75 cola/widgets/remote.py:157 #: cola/widgets/search.py:81 cola/widgets/selectcommits.py:59 #: cola/widgets/startup.py:42 msgid "Close" msgstr "" #: cola/bookmarks.py:102 msgid "Bookmarks Saved" msgstr "" #: cola/bookmarks.py:103 msgid "Successfully saved bookmarks" msgstr "" #: cola/bookmarks.py:107 msgid "Path to git repository" msgstr "" #: cola/bookmarks.py:108 msgid "Enter Git Repository" msgstr "" #: cola/cmds.py:105 msgid "Amend" msgstr "" #: cola/cmds.py:140 msgid "Cannot Amend" msgstr "" #: cola/cmds.py:141 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" #: cola/cmds.py:204 #, python-format msgid "PATCH %(current)d/%(count)d" msgstr "" #: cola/cmds.py:208 msgid "Summary:" msgstr "" #: cola/cmds.py:217 msgid "Patch(es) Applied" msgstr "" #: cola/cmds.py:218 #, python-format msgid "%d patch(es) applied." msgstr "" #: cola/cmds.py:322 #, python-format msgid "Created commit: %s" msgstr "" #: cola/cmds.py:324 #, python-format msgid "Commit failed: %s" msgstr "" #: cola/cmds.py:369 cola/cmds.py:1186 msgid "Error" msgstr "" #: cola/cmds.py:370 #, python-format msgid "Deleting \"%s\" failed" msgstr "" #: cola/cmds.py:406 msgid "Remote Branch Deleted" msgstr "" #: cola/cmds.py:407 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "" #: cola/cmds.py:411 cola/guicmds.py:108 cola/widgets/remote.py:472 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "" #: cola/cmds.py:414 msgid "Error Deleting Remote Branch" msgstr "" #: cola/cmds.py:493 cola/widgets/grep.py:60 cola/widgets/recent.py:69 msgid "Edit" msgstr "" #: cola/cmds.py:529 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/cmds.py:531 msgid "Error Editing File" msgstr "" #: cola/cmds.py:554 msgid "Launch Diff Tool" msgstr "" #: cola/cmds.py:577 msgid "Launch Editor" msgstr "" #: cola/cmds.py:598 msgid "Error: Cannot find commit template" msgstr "" #: cola/cmds.py:599 #, python-format msgid "%s: No such file or directory." msgstr "" #: cola/cmds.py:616 msgid "Error: Unconfigured commit template" msgstr "" #: cola/cmds.py:617 msgid "" "A commit template has not been configured.\n" "Use \"git config\" to define \"commit.template\"\n" "so that it points to a commit template." msgstr "" #: cola/cmds.py:669 msgid "Open Using Default Application" msgstr "" #: cola/cmds.py:692 msgid "Open Parent Directory" msgstr "" #: cola/cmds.py:732 #, python-format msgid "Error: could not clone \"%s\"" msgstr "" #: cola/cmds.py:733 #, python-format msgid "git clone returned exit code %s" msgstr "" #: cola/cmds.py:756 cola/widgets/action.py:19 cola/widgets/editremotes.py:49 #: cola/widgets/grep.py:65 cola/widgets/recent.py:52 #: cola/widgets/recent.py:121 msgid "Refresh" msgstr "" #: cola/cmds.py:784 #, python-format msgid "Run \"%s\"?" msgstr "" #: cola/cmds.py:791 msgid "Please select a file" msgstr "" #: cola/cmds.py:792 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:804 msgid "Invalid Revision" msgstr "" #: cola/cmds.py:805 msgid "The revision expression cannot be empty." msgstr "" #: cola/cmds.py:820 #, python-format msgid "Running command: %s" msgstr "" #: cola/cmds.py:829 cola/cmds.py:1006 cola/interaction.py:70 #, python-format msgid "Output: %s" msgstr "" #: cola/cmds.py:830 cola/guicmds.py:113 cola/interaction.py:71 #, python-format msgid "Errors: %s" msgstr "" #: cola/cmds.py:876 msgid "Sign Off" msgstr "" #: cola/cmds.py:897 msgid "unknown" msgstr "" #: cola/cmds.py:910 cola/widgets/action.py:17 msgid "Stage" msgstr "" #: cola/cmds.py:917 #, python-format msgid "Staging: %s" msgstr "" #: cola/cmds.py:934 msgid "Stage Modified" msgstr "" #: cola/cmds.py:948 msgid "Stage Unmerged" msgstr "" #: cola/cmds.py:962 msgid "Stage Untracked" msgstr "" #: cola/cmds.py:980 #, python-format msgid "Tagging \"%(revision)s\" as \"%(name)s\"" msgstr "" #: cola/cmds.py:988 msgid "GPG-signed" msgstr "" #: cola/cmds.py:1020 cola/widgets/action.py:18 msgid "Unstage" msgstr "" #: cola/cmds.py:1027 #, python-format msgid "Unstaging: %s" msgstr "" #: cola/cmds.py:1055 #, python-format msgid "Untracking: %s" msgstr "" #: cola/cmds.py:1137 msgid "Error Launching History Browser" msgstr "" #: cola/cmds.py:1138 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/difftool.py:76 msgid "git-cola diff" msgstr "" #: cola/difftool.py:92 cola/widgets/compare.py:90 msgid "Compare" msgstr "" #: cola/gitcmds.py:402 msgid "Nothing to do" msgstr "" #: cola/guicmds.py:25 msgid "Delete Branch" msgstr "" #: cola/guicmds.py:33 msgid "Delete Remote Branch" msgstr "" #: cola/guicmds.py:53 msgid "Browse Commits..." msgstr "" #: cola/guicmds.py:53 msgid "Browse" msgstr "" #: cola/guicmds.py:61 msgid "Checkout Branch" msgstr "" #: cola/guicmds.py:61 msgid "Checkout" msgstr "" #: cola/guicmds.py:70 msgid "Cherry-Pick Commit" msgstr "" #: cola/guicmds.py:107 msgid "Error Creating Repository" msgstr "" #: cola/guicmds.py:110 #, python-format msgid "" "Output:\n" "%s" msgstr "" #: cola/guicmds.py:132 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/guicmds.py:153 msgid "Error Cloning" msgstr "" #: cola/guicmds.py:154 cola/guicmds.py:155 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/guicmds.py:159 msgid "Select a parent directory for the new clone" msgstr "" #: cola/guicmds.py:169 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/guicmds.py:185 cola/widgets/search.py:75 msgid "Export Patches" msgstr "" #: cola/guicmds.py:214 cola/widgets/startup.py:124 msgid "Open Git Repository..." msgstr "" #: cola/guicmds.py:223 msgid "Load Commit Message" msgstr "" #: cola/guicmds.py:251 msgid "Select New Base" msgstr "" #: cola/guicmds.py:251 msgid "Rebase" msgstr "" #: cola/guicmds.py:261 msgid "Select Branch to Review" msgstr "" #: cola/guicmds.py:261 msgid "Review" msgstr "" #: cola/inotify.py:47 msgid "inotify is disabled because \"cola.inotify\" is false" msgstr "" #: cola/inotify.py:53 msgid "" "file notification: disabled\n" "Note: install pywin32 to enable.\n" msgstr "" #: cola/inotify.py:56 msgid "" "inotify: disabled\n" "Note: install python-pyinotify to enable inotify.\n" msgstr "" #: cola/inotify.py:62 msgid "On Debian systems try: sudo aptitude install python-pyinotify" msgstr "" #: cola/inotify.py:71 msgid "File notification enabled." msgstr "" #: cola/inotify.py:73 msgid "inotify enabled." msgstr "" #: cola/interaction.py:53 msgid "Continue" msgstr "" #: cola/interaction.py:63 #, python-format msgid "Run %s?" msgstr "" #: cola/interaction.py:64 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/interaction.py:65 cola/widgets/cfgactions.py:240 msgid "Run" msgstr "" #: cola/interaction.py:72 #, python-format msgid "Exit code: %s" msgstr "" #: cola/qt.py:60 cola/qt.py:100 msgid "Detach" msgstr "" #: cola/qt.py:98 msgid "Attach" msgstr "" #: cola/qtutils.py:396 msgid "Close..." msgstr "" #: cola/classic/controller.py:69 msgid "Select Previous Version" msgstr "" #: cola/classic/model.py:37 cola/widgets/createtag.py:51 #: cola/widgets/editremotes.py:220 msgid "Name" msgstr "" #: cola/classic/model.py:39 cola/main/view.py:91 msgid "Status" msgstr "" #: cola/classic/model.py:41 msgid "Age" msgstr "" #: cola/classic/model.py:43 cola/widgets/createtag.py:74 msgid "Message" msgstr "" #: cola/classic/model.py:45 cola/dag/view.py:371 msgid "Author" msgstr "" #: cola/classic/model.py:342 #, python-format msgid "%d minutes ago" msgstr "" #: cola/classic/model.py:345 #, python-format msgid "%d hours ago" msgstr "" #: cola/classic/model.py:346 #, python-format msgid "%d days ago" msgstr "" #: cola/classic/model.py:359 cola/widgets/status.py:73 msgid "Unmerged" msgstr "" #: cola/classic/model.py:361 msgid "Partially Staged" msgstr "" #: cola/classic/model.py:363 cola/widgets/status.py:74 msgid "Modified" msgstr "" #: cola/classic/model.py:365 cola/widgets/status.py:72 msgid "Staged" msgstr "" #: cola/classic/model.py:367 msgid "Changed Upstream" msgstr "" #: cola/classic/view.py:47 cola/main/view.py:545 #, python-format msgid "Repository: %s" msgstr "" #: cola/classic/view.py:49 cola/main/view.py:547 #, python-format msgid "Branch: %s" msgstr "" #: cola/classic/view.py:52 #, python-format msgid "%s: %s - Browse" msgstr "" #: cola/classic/view.py:54 cola/main/view.py:552 msgid "Amending" msgstr "" #: cola/classic/view.py:79 msgid "View History..." msgstr "" #: cola/classic/view.py:80 msgid "View history for selected path(s)." msgstr "" #: cola/classic/view.py:84 cola/widgets/status.py:506 #: cola/widgets/status.py:536 cola/widgets/status.py:593 msgid "Stage Selected" msgstr "" #: cola/classic/view.py:85 msgid "Stage selected path(s) for commit." msgstr "" #: cola/classic/view.py:90 cola/widgets/status.py:452 #: cola/widgets/status.py:494 msgid "Unstage Selected" msgstr "" #: cola/classic/view.py:91 msgid "Remove selected path(s) from the staging area." msgstr "" #: cola/classic/view.py:96 msgid "Untrack Selected" msgstr "" #: cola/classic/view.py:97 msgid "Stop tracking path(s)" msgstr "" #: cola/classic/view.py:102 msgid "Launch git-difftool on the current path." msgstr "" #: cola/classic/view.py:106 msgid "Diff Against Predecessor..." msgstr "" #: cola/classic/view.py:107 msgid "Launch git-difftool against previous versions." msgstr "" #: cola/classic/view.py:111 msgid "Revert Uncommitted Changes..." msgstr "" #: cola/classic/view.py:112 msgid "Revert changes to selected path(s)." msgstr "" #: cola/classic/view.py:117 msgid "Edit selected path(s)." msgstr "" #: cola/classic/view.py:293 cola/widgets/status.py:652 msgid "Revert Uncommitted Changes?" msgstr "" #: cola/classic/view.py:294 cola/widgets/diff.py:246 cola/widgets/diff.py:259 #: cola/widgets/status.py:653 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/classic/view.py:296 cola/widgets/diff.py:248 cola/widgets/diff.py:261 #: cola/widgets/status.py:655 msgid "Revert the uncommitted changes?" msgstr "" #: cola/classic/view.py:297 cola/widgets/status.py:656 msgid "Revert Uncommitted Changes" msgstr "" #: cola/dag/view.py:166 msgid "Loading..." msgstr "" #: cola/dag/view.py:272 msgid "Diff this -> selected" msgstr "" #: cola/dag/view.py:275 msgid "Diff selected -> this" msgstr "" #: cola/dag/view.py:278 cola/widgets/createbranch.py:89 #: cola/widgets/createbranch.py:98 cola/widgets/createbranch.py:155 #: cola/widgets/createbranch.py:330 msgid "Create Branch" msgstr "" #: cola/dag/view.py:281 msgid "Create Patch" msgstr "" #: cola/dag/view.py:284 cola/widgets/createtag.py:38 #: cola/widgets/createtag.py:99 msgid "Create Tag" msgstr "" #: cola/dag/view.py:287 cola/main/view.py:208 msgid "Save As Tarball/Zip..." msgstr "" #: cola/dag/view.py:290 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/dag/view.py:293 msgid "Grab File..." msgstr "" #: cola/dag/view.py:296 msgid "Copy SHA-1" msgstr "" #: cola/dag/view.py:371 msgid "Summary" msgstr "" #: cola/dag/view.py:371 msgid "Date, Time" msgstr "" #: cola/dag/view.py:378 msgid "Go Up" msgstr "" #: cola/dag/view.py:381 msgid "Go Down" msgstr "" #: cola/dag/view.py:511 cola/dag/view.py:1181 msgid "Zoom Out" msgstr "" #: cola/dag/view.py:514 cola/dag/view.py:1178 msgid "Zoom In" msgstr "" #: cola/dag/view.py:517 cola/dag/view.py:1184 msgid "Zoom to Fit" msgstr "" #: cola/dag/view.py:536 msgid "Log" msgstr "" #: cola/dag/view.py:541 cola/main/view.py:114 cola/main/view.py:384 msgid "Diff" msgstr "" #: cola/dag/view.py:554 msgid "Graph" msgstr "" #: cola/dag/view.py:563 msgid "View" msgstr "" #: cola/dag/view.py:636 #, python-format msgid "%s: %s - DAG" msgstr "" #: cola/dag/view.py:638 msgid " - DAG" msgstr "" #: cola/dag/view.py:1187 msgid "Select Parent" msgstr "" #: cola/dag/view.py:1190 msgid "Select Oldest Parent" msgstr "" #: cola/dag/view.py:1193 msgid "Select Child" msgstr "" #: cola/dag/view.py:1196 msgid "Select Newest Child" msgstr "" #: cola/main/view.py:78 msgid "Browser" msgstr "" #: cola/main/view.py:83 msgid "Action" msgstr "" #: cola/main/view.py:99 cola/merge/view.py:45 msgid "Commit" msgstr "" #: cola/main/view.py:108 msgid "Console" msgstr "" #: cola/main/view.py:120 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/main/view.py:125 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/main/view.py:130 msgid "Ignore all whitespace" msgstr "" #: cola/main/view.py:135 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/main/view.py:139 cola/widgets/createbranch.py:194 msgid "Options" msgstr "" #: cola/main/view.py:141 cola/main/view.py:142 msgid "Diff Options" msgstr "" #: cola/main/view.py:157 cola/widgets/status.py:423 msgid "Unstage All" msgstr "" #: cola/main/view.py:161 msgid "Unstage From Commit" msgstr "" #: cola/main/view.py:165 msgid "Diffstat" msgstr "" #: cola/main/view.py:168 msgid "Stage Changed Files To Commit" msgstr "" #: cola/main/view.py:173 msgid "Stage All Untracked" msgstr "" #: cola/main/view.py:178 msgid "Export Patches..." msgstr "" #: cola/main/view.py:181 msgid "New Repository..." msgstr "" #: cola/main/view.py:185 cola/prefs/view.py:220 msgid "Preferences" msgstr "" #: cola/main/view.py:189 msgid "Edit Remotes..." msgstr "" #: cola/main/view.py:197 msgid "Recently Modified Files..." msgstr "" #: cola/main/view.py:201 msgid "Cherry-Pick..." msgstr "" #: cola/main/view.py:205 msgid "Load Commit Message..." msgstr "" #: cola/main/view.py:211 msgid "Quit" msgstr "" #: cola/main/view.py:213 msgid "Bookmarks..." msgstr "" #: cola/main/view.py:215 msgid "Grep" msgstr "" #: cola/main/view.py:217 msgid "Merge..." msgstr "" #: cola/main/view.py:220 cola/merge/__init__.py:20 msgid "Abort Merge..." msgstr "" #: cola/main/view.py:223 cola/widgets/action.py:20 msgid "Fetch..." msgstr "" #: cola/main/view.py:225 cola/widgets/action.py:21 msgid "Push..." msgstr "" #: cola/main/view.py:227 cola/widgets/action.py:22 msgid "Pull..." msgstr "" #: cola/main/view.py:230 cola/widgets/startup.py:36 msgid "Open..." msgstr "" #: cola/main/view.py:234 cola/widgets/action.py:23 msgid "Stash..." msgstr "" #: cola/main/view.py:237 cola/widgets/startup.py:39 msgid "Clone..." msgstr "" #: cola/main/view.py:241 msgid "Documentation" msgstr "" #: cola/main/view.py:245 msgid "Keyboard Shortcuts" msgstr "" #: cola/main/view.py:250 msgid "Visualize Current Branch..." msgstr "" #: cola/main/view.py:253 msgid "Visualize All Branches..." msgstr "" #: cola/main/view.py:256 msgid "Search..." msgstr "" #: cola/main/view.py:258 msgid "Browse Current Branch..." msgstr "" #: cola/main/view.py:260 msgid "Browse Other Branch..." msgstr "" #: cola/main/view.py:262 msgid "Get Commit Message Template" msgstr "" #: cola/main/view.py:265 msgid "About" msgstr "" #: cola/main/view.py:268 msgid "Expression..." msgstr "" #: cola/main/view.py:270 msgid "Branches..." msgstr "" #: cola/main/view.py:273 msgid "Create Tag..." msgstr "" #: cola/main/view.py:276 msgid "Create..." msgstr "" #: cola/main/view.py:279 msgid "Delete..." msgstr "" #: cola/main/view.py:282 msgid "Delete Remote Branch..." msgstr "" #: cola/main/view.py:285 msgid "Checkout..." msgstr "" #: cola/main/view.py:287 msgid "Rebase..." msgstr "" #: cola/main/view.py:289 msgid "Review..." msgstr "" #: cola/main/view.py:292 msgid "Browser..." msgstr "" #: cola/main/view.py:296 msgid "DAG..." msgstr "" #: cola/main/view.py:313 msgid "File" msgstr "" #: cola/main/view.py:316 msgid "Open Recent" msgstr "" #: cola/main/view.py:338 cola/main/view.py:339 msgid "Index" msgstr "" #: cola/main/view.py:349 msgid "Branch" msgstr "" #: cola/main/view.py:367 msgid "Actions" msgstr "" #: cola/main/view.py:393 msgid "Tools" msgstr "" #: cola/main/view.py:404 msgid "Help" msgstr "" #: cola/main/view.py:462 #, python-format msgid "git cola version %s" msgstr "" #: cola/merge/__init__.py:21 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/merge/__init__.py:24 msgid "Aborting the current merge?" msgstr "" #: cola/merge/__init__.py:25 msgid "Abort Merge" msgstr "" #: cola/merge/view.py:23 msgid "Revision To Merge" msgstr "" #: cola/merge/view.py:28 cola/widgets/cfgactions.py:220 #: cola/widgets/remote.py:122 msgid "Local Branch" msgstr "" #: cola/merge/view.py:31 cola/widgets/cfgactions.py:221 msgid "Tracking Branch" msgstr "" #: cola/merge/view.py:33 cola/widgets/cfgactions.py:222 #: cola/widgets/createbranch.py:122 msgid "Tag" msgstr "" #: cola/merge/view.py:39 msgid "Visualize" msgstr "" #: cola/merge/view.py:42 msgid "Squash" msgstr "" #: cola/merge/view.py:50 cola/widgets/archive.py:62 #: cola/widgets/editremotes.py:204 msgid "Cancel" msgstr "" #: cola/merge/view.py:53 msgid "Merge" msgstr "" #: cola/merge/view.py:115 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/merge/view.py:118 #, python-format msgid "Merge into \"%s\"" msgstr "" #: cola/merge/view.py:162 cola/merge/view.py:171 msgid "No Revision Specified" msgstr "" #: cola/merge/view.py:163 msgid "You must specify a revision to view." msgstr "" #: cola/merge/view.py:172 msgid "You must specify a revision to merge." msgstr "" #: cola/prefs/view.py:116 msgid "User Name" msgstr "" #: cola/prefs/view.py:117 msgid "Email Address" msgstr "" #: cola/prefs/view.py:118 msgid "Merge Verbosity" msgstr "" #: cola/prefs/view.py:119 msgid "Number of Diff Context Lines" msgstr "" #: cola/prefs/view.py:120 msgid "Summarize Merge Commits" msgstr "" #: cola/prefs/view.py:121 msgid "Show Diffstat After Merge" msgstr "" #: cola/prefs/view.py:122 msgid "Display Untracked Files" msgstr "" #: cola/prefs/view.py:163 msgid "Fixed-Width Font" msgstr "" #: cola/prefs/view.py:164 msgid "Font Size" msgstr "" #: cola/prefs/view.py:165 msgid "Tab Width" msgstr "" #: cola/prefs/view.py:166 msgid "Text Width" msgstr "" #: cola/prefs/view.py:167 cola/widgets/commitmsg.py:99 msgid "Auto-Wrap Lines" msgstr "" #: cola/prefs/view.py:168 msgid "Editor" msgstr "" #: cola/prefs/view.py:169 msgid "History Browser" msgstr "" #: cola/prefs/view.py:170 msgid "Diff Tool" msgstr "" #: cola/prefs/view.py:171 msgid "Merge Tool" msgstr "" #: cola/prefs/view.py:172 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/prefs/view.py:173 msgid "Save GUI Settings" msgstr "" #: cola/prefs/view.py:227 msgid "All Repositories" msgstr "" #: cola/prefs/view.py:228 msgid "Current Repository" msgstr "" #: cola/prefs/view.py:229 msgid "Settings" msgstr "" #: cola/stash/view.py:28 msgid "Stash" msgstr "" #: cola/stash/view.py:38 msgid "Apply" msgstr "" #: cola/stash/view.py:39 msgid "Apply the selected stash" msgstr "" #: cola/stash/view.py:43 msgid "Save modified state to new stash" msgstr "" #: cola/stash/view.py:46 msgid "Drop" msgstr "" #: cola/stash/view.py:47 msgid "Drop the selected stash" msgstr "" #: cola/stash/view.py:54 msgid "Keep Index" msgstr "" #: cola/stash/view.py:175 msgid "Save Stash" msgstr "" #: cola/stash/view.py:176 msgid "Enter a name for the stash" msgstr "" #: cola/stash/view.py:182 msgid "Error: Stash exists" msgstr "" #: cola/stash/view.py:183 #, python-format msgid "A stash named \"%s\" already exists" msgstr "" #: cola/stash/view.py:198 msgid "Drop Stash?" msgstr "" #: cola/stash/view.py:199 msgid "Recovering a dropped stash is not possible." msgstr "" #: cola/stash/view.py:200 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/stash/view.py:201 msgid "Drop Stash" msgstr "" #: cola/widgets/about.py:47 msgid "About git-cola" msgstr "" #: cola/widgets/about.py:97 msgid "" "This PyQt4 does not include QtWebKit.\n" "The keyboard shortcuts feature is unavailable." msgstr "" #: cola/widgets/about.py:104 msgid "hotkeys.html" msgstr "" #: cola/widgets/about.py:122 msgid "Shortcuts" msgstr "" #: cola/widgets/archive.py:46 msgid "Save Archive" msgstr "" #: cola/widgets/archive.py:69 msgid "Prefix" msgstr "" #: cola/widgets/archive.py:74 msgid "Advanced" msgstr "" #: cola/widgets/archive.py:141 cola/widgets/browse.py:49 msgid "File Saved" msgstr "" #: cola/widgets/archive.py:142 cola/widgets/browse.py:50 #, python-format msgid "File saved to \"%s\"" msgstr "" #: cola/widgets/archive.py:149 msgid "Overwrite File?" msgstr "" #: cola/widgets/archive.py:150 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/widgets/archive.py:151 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:152 msgid "Overwrite" msgstr "" #: cola/widgets/browse.py:42 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/browse.py:63 #, python-format msgid "Browsing %s" msgstr "" #: cola/widgets/browse.py:81 #, python-format msgid "Select file from \"%s\"" msgstr "" #: cola/widgets/browse.py:90 msgid "Select File" msgstr "" #: cola/widgets/browse.py:117 cola/widgets/selectcommits.py:54 msgid "Select" msgstr "" #: cola/widgets/cfgactions.py:85 msgid "Abort" msgstr "" #: cola/widgets/cfgactions.py:147 cola/widgets/cfgactions.py:151 msgid "Abort Action" msgstr "" #: cola/widgets/cfgactions.py:148 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/widgets/cfgactions.py:150 msgid "Abort the action?" msgstr "" #: cola/widgets/cfgactions.py:201 msgid "Arguments" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/createtag.py:85 msgid "Revision" msgstr "" #: cola/widgets/commitmsg.py:50 msgid "Sign off on this commit" msgstr "" #: cola/widgets/commitmsg.py:53 cola/widgets/commitmsg.py:69 msgid "Commit@@verb" msgstr "" #: cola/widgets/commitmsg.py:56 msgid "Commit staged changes" msgstr "" #: cola/widgets/commitmsg.py:67 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:75 msgid "Actions..." msgstr "" #: cola/widgets/commitmsg.py:85 msgid "Amend Last Commit" msgstr "" #: cola/widgets/commitmsg.py:92 msgid "Check Spelling" msgstr "" #: cola/widgets/commitmsg.py:104 msgid "Load Previous Commit Message" msgstr "" #: cola/widgets/commitmsg.py:135 cola/widgets/status.py:117 msgid "Move Down" msgstr "" #: cola/widgets/commitmsg.py:342 msgid "" "Please supply a commit message.\n" "\n" "A good commit message has the following format:\n" "\n" "- First line: Describe in one sentence what you did.\n" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" #: cola/widgets/commitmsg.py:349 msgid "Missing Commit Message" msgstr "" #: cola/widgets/commitmsg.py:355 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" #: cola/widgets/commitmsg.py:359 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/commitmsg.py:361 msgid "Stage and commit?" msgstr "" #: cola/widgets/commitmsg.py:364 msgid "Stage and Commit" msgstr "" #: cola/widgets/commitmsg.py:369 msgid "Nothing to commit" msgstr "" #: cola/widgets/commitmsg.py:376 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/commitmsg.py:377 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" #: cola/widgets/commitmsg.py:380 msgid "Amend the published commit?" msgstr "" #: cola/widgets/commitmsg.py:381 msgid "Amend Commit" msgstr "" #: cola/widgets/commitmsg.py:386 msgid "Commit failed" msgstr "" #: cola/widgets/commitmsg.py:387 #, python-format msgid "\"git commit\" returned exit code %s" msgstr "" #: cola/widgets/commitmsg.py:409 msgid "More..." msgstr "" #: cola/widgets/commitmsg.py:413 msgid "Select Commit Message" msgstr "" #: cola/widgets/commitmsg.py:450 msgid "Commit summary" msgstr "" #: cola/widgets/commitmsg.py:465 msgid "Extended description..." msgstr "" #: cola/widgets/compare.py:37 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:38 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/compare.py:39 cola/widgets/compare.py:62 #: cola/widgets/compare.py:68 msgid "Local" msgstr "" #: cola/widgets/compare.py:44 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/compare.py:63 cola/widgets/compare.py:69 #: cola/widgets/remote.py:129 msgid "Remote" msgstr "" #: cola/widgets/compare.py:98 msgid "File Differences" msgstr "" #: cola/widgets/createbranch.py:102 msgid "Branch Name" msgstr "" #: cola/widgets/createbranch.py:107 cola/widgets/createbranch.py:178 msgid "Starting Revision" msgstr "" #: cola/widgets/createbranch.py:115 msgid "Local branch" msgstr "" #: cola/widgets/createbranch.py:119 msgid "Tracking branch" msgstr "" #: cola/widgets/createbranch.py:127 msgid "Update Existing Branch:" msgstr "" #: cola/widgets/createbranch.py:130 msgid "No" msgstr "" #: cola/widgets/createbranch.py:133 msgid "Fast Forward Only" msgstr "" #: cola/widgets/createbranch.py:137 msgid "Reset" msgstr "" #: cola/widgets/createbranch.py:143 msgid "Fetch Tracking Branch" msgstr "" #: cola/widgets/createbranch.py:148 msgid "Checkout After Creation" msgstr "" #: cola/widgets/createbranch.py:259 msgid "Missing Data" msgstr "" #: cola/widgets/createbranch.py:260 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/widgets/createbranch.py:265 #, python-format msgid "Branch \"%s\" already exists." msgstr "" #: cola/widgets/createbranch.py:266 cola/widgets/createbranch.py:277 msgid "Branch Exists" msgstr "" #: cola/widgets/createbranch.py:273 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "" #: cola/widgets/createbranch.py:288 #, python-format msgid "%d skipped" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Recovering lost commits may not be easy." msgstr "" #: cola/widgets/createbranch.py:292 msgid "Reset Branch?" msgstr "" #: cola/widgets/createbranch.py:294 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/widgets/createbranch.py:296 msgid "Reset Branch" msgstr "" #: cola/widgets/createbranch.py:305 msgid "Updating..." msgstr "" #: cola/widgets/createbranch.py:321 msgid "Error Creating Branch" msgstr "" #: cola/widgets/createbranch.py:322 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/widgets/createbranch.py:331 msgid "Branch created" msgstr "" #: cola/widgets/createtag.py:55 msgid "vX.Y.Z" msgstr "" #: cola/widgets/createtag.py:56 msgid "Specifies the tag name" msgstr "" #: cola/widgets/createtag.py:62 msgid "Sign Tag" msgstr "" #: cola/widgets/createtag.py:67 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:91 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:121 msgid "Missing Revision" msgstr "" #: cola/widgets/createtag.py:122 msgid "Please specify a revision to tag." msgstr "" #: cola/widgets/createtag.py:125 msgid "Missing Name" msgstr "" #: cola/widgets/createtag.py:126 msgid "Please specify a name for the new tag." msgstr "" #: cola/widgets/createtag.py:129 msgid "Missing Tag Message" msgstr "" #: cola/widgets/createtag.py:130 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/createtag.py:132 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/createtag.py:135 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/createtag.py:142 msgid "Tag Created" msgstr "" #: cola/widgets/createtag.py:143 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/diff.py:22 msgid "Process Section" msgstr "" #: cola/widgets/diff.py:25 msgid "Process Selection" msgstr "" #: cola/widgets/diff.py:40 msgid "Stage &Selected Lines" msgstr "" #: cola/widgets/diff.py:46 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:51 msgid "Unstage &Selected Lines" msgstr "" #: cola/widgets/diff.py:57 msgid "Apply Diff Selection to Work Tree" msgstr "" #: cola/widgets/diff.py:86 cola/widgets/diff.py:108 cola/widgets/status.py:486 #: cola/widgets/status.py:584 msgid "Launch git-cola" msgstr "" #: cola/widgets/diff.py:91 msgid "Stage Section" msgstr "" #: cola/widgets/diff.py:97 msgid "Revert Section..." msgstr "" #: cola/widgets/diff.py:113 msgid "Unstage Section" msgstr "" #: cola/widgets/diff.py:125 msgid "Copy" msgstr "" #: cola/widgets/diff.py:129 msgid "Select All" msgstr "" #: cola/widgets/diff.py:245 msgid "Revert Section?" msgstr "" #: cola/widgets/diff.py:249 msgid "Revert Section" msgstr "" #: cola/widgets/diff.py:258 msgid "Revert Selected Lines?" msgstr "" #: cola/widgets/diff.py:262 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/editremotes.py:19 msgid "Edit Remotes" msgstr "" #: cola/widgets/editremotes.py:22 msgid "" "Add and remove remote repositories using the \n" "Add(+) and Delete(-) buttons on the left-hand side.\n" "\n" "Remotes can be renamed by selecting one from the list\n" "and pressing \"enter\", or by double-clicking." msgstr "" #: cola/widgets/editremotes.py:32 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/widgets/editremotes.py:45 msgid "Add new remote git repository" msgstr "" #: cola/widgets/editremotes.py:53 msgid "Delete remote" msgstr "" #: cola/widgets/editremotes.py:116 #, python-format msgid "Error creating remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:124 msgid "Delete Remote" msgstr "" #: cola/widgets/editremotes.py:125 msgid "Delete remote?" msgstr "" #: cola/widgets/editremotes.py:126 #, python-format msgid "Delete remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:134 #, python-format msgid "Error deleting remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:153 msgid "Rename Remote" msgstr "" #: cola/widgets/editremotes.py:154 msgid "Rename remote?" msgstr "" #: cola/widgets/editremotes.py:155 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/editremotes.py:157 msgid "Rename" msgstr "" #: cola/widgets/editremotes.py:169 #, python-format msgid "Gathering info for \"%s\"..." msgstr "" #: cola/widgets/editremotes.py:201 msgid "Add Remote" msgstr "" #: cola/widgets/editremotes.py:213 msgid "Add remote" msgstr "" #: cola/widgets/editremotes.py:214 msgid "Name for the new remote" msgstr "" #: cola/widgets/editremotes.py:221 msgid "URL" msgstr "" #: cola/widgets/grep.py:47 cola/widgets/search.py:40 cola/widgets/search.py:58 msgid "Search" msgstr "" #: cola/widgets/grep.py:52 msgid "command-line arguments" msgstr "" #: cola/widgets/grep.py:56 msgid "grep result..." msgstr "" #: cola/widgets/grep.py:69 msgid "Shell arguments" msgstr "" #: cola/widgets/grep.py:71 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/widgets/log.py:34 #, python-format msgid "exit code %s" msgstr "" #: cola/widgets/recent.py:36 msgid "Recently Modified Files" msgstr "" #: cola/widgets/recent.py:46 msgid " commits ago" msgstr "" #: cola/widgets/recent.py:49 msgid "Showing changes since" msgstr "" #: cola/widgets/recent.py:61 msgid "Expand" msgstr "" #: cola/widgets/recent.py:65 msgid "Collapse" msgstr "" #: cola/widgets/remote.py:136 msgid "Remote Branch" msgstr "" #: cola/widgets/remote.py:143 msgid "Fast Forward Only " msgstr "" #: cola/widgets/remote.py:147 msgid "Include tags " msgstr "" #: cola/widgets/remote.py:150 msgid "Rebase " msgstr "" #: cola/widgets/remote.py:314 #, python-format msgid "URL: %s" msgstr "" #: cola/widgets/remote.py:393 msgid "No repository selected." msgstr "" #: cola/widgets/remote.py:406 msgid "Push" msgstr "" #: cola/widgets/remote.py:408 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/remote.py:410 msgid "Create a new remote branch?" msgstr "" #: cola/widgets/remote.py:411 msgid "Create Remote Branch" msgstr "" #: cola/widgets/remote.py:419 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:420 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:421 #, python-format msgid "Force fetching from %s?" msgstr "" #: cola/widgets/remote.py:422 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:424 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:425 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/remote.py:427 #, python-format msgid "Force push to %s?" msgstr "" #: cola/widgets/remote.py:428 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:462 msgid "Already up-to-date." msgstr "" #: cola/widgets/remote.py:485 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/widgets/search.py:44 msgid "Browse..." msgstr "" #: cola/widgets/search.py:50 cola/widgets/search.py:55 msgid "yyyy-MM-dd" msgstr "" #: cola/widgets/search.py:220 msgid "Search by Expression" msgstr "" #: cola/widgets/search.py:221 msgid "Search by Path" msgstr "" #: cola/widgets/search.py:222 msgid "Search Commit Messages" msgstr "" #: cola/widgets/search.py:223 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:224 msgid "Search Authors" msgstr "" #: cola/widgets/search.py:225 msgid "Search Committers" msgstr "" #: cola/widgets/search.py:226 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:319 msgid "Choose Path(s)" msgstr "" #: cola/widgets/selectcommits.py:50 msgid "Revision Expression:" msgstr "" #: cola/widgets/selectcommits.py:101 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/spellcheck.py:139 msgid "Spelling Suggestions" msgstr "" #: cola/widgets/startup.py:26 msgid "git-cola" msgstr "" #: cola/widgets/startup.py:33 msgid "New..." msgstr "" #: cola/widgets/startup.py:56 msgid "Select Repository..." msgstr "" #: cola/widgets/startup.py:61 msgid "Select manually..." msgstr "" #: cola/widgets/status.py:75 msgid "Untracked" msgstr "" #: cola/widgets/status.py:85 msgid "Stage / Unstage" msgstr "" #: cola/widgets/status.py:114 msgid "Move Up" msgstr "" #: cola/widgets/status.py:121 msgid "Copy Path to Clipboard" msgstr "" #: cola/widgets/status.py:474 cola/widgets/status.py:550 msgid "Revert Unstaged Edits..." msgstr "" #: cola/widgets/status.py:477 cola/widgets/status.py:553 msgid "Revert Uncommited Edits..." msgstr "" #: cola/widgets/status.py:572 msgid "Delete File(s)..." msgstr "" #: cola/widgets/status.py:575 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:608 msgid "Delete Files?" msgstr "" #: cola/widgets/status.py:609 msgid "The following files will be deleted:" msgstr "" #: cola/widgets/status.py:616 #, python-format msgid "Delete %d file(s)?" msgstr "" #: cola/widgets/status.py:617 msgid "Delete Files" msgstr "" #: cola/widgets/status.py:633 msgid "Revert Unstaged Changes?" msgstr "" #: cola/widgets/status.py:634 msgid "" "This operation drops unstaged changes.\n" "These changes cannot be recovered." msgstr "" #: cola/widgets/status.py:636 msgid "Revert the unstaged changes?" msgstr "" #: cola/widgets/status.py:637 msgid "Revert Unstaged Changes" msgstr "" #: cola/widgets/status.py:646 cola/widgets/status.py:662 msgid "No files selected for checkout from HEAD." msgstr "" git-cola-1.9.3/po/glossary/000077500000000000000000000000001225156173500155135ustar00rootroot00000000000000git-cola-1.9.3/po/glossary/de.po000066400000000000000000000130121225156173500164400ustar00rootroot00000000000000# Translation of git-gui glossary to German # Copyright (C) 2007 Shawn Pearce, et al. # This file is distributed under the same license as the git package. # Christian Stimming , 2007 # msgid "" msgstr "" "Project-Id-Version: git-gui glossary\n" "POT-Creation-Date: 2007-10-19 21:43+0200\n" "PO-Revision-Date: 2007-10-20 15:24+0200\n" "Last-Translator: Christian Stimming \n" "Language-Team: German \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)" msgid "" "English Term (Dear translator: This file will never be visible to the user!)" msgstr "" "Deutsche Übersetzung.\n" "Andere deutsche SCM:\n" " http://tortoisesvn.net/docs/release/TortoiseSVN_de/index.html und http://" "tortoisesvn.tigris.org/svn/tortoisesvn/trunk/Languages/Tortoise_de.po " "(username=guest, password empty, gut),\n" " http://msdn.microsoft.com/de-de/library/ms181038(vs.80).aspx (MS Visual " "Source Safe, kommerziell),\n" " http://cvsbook.red-bean.com/translations/german/Kap_06.html " "(mittelmäßig),\n" " http://tortoisecvs.cvs.sourceforge.net/tortoisecvs/po/TortoiseCVS/de_DE.po?" "view=markup (mittelmäßig),\n" " http://rapidsvn.tigris.org/svn/rapidsvn/trunk/src/locale/de/rapidsvn.po " "(username=guest, password empty, schlecht)" #. "" msgid "amend" msgstr "nachbessern (ergänzen)" #. "" msgid "annotate" msgstr "annotieren" #. "A 'branch' is an active line of development." msgid "branch [noun]" msgstr "Zweig" #. "" msgid "branch [verb]" msgstr "verzweigen" #. "" msgid "checkout [noun]" msgstr "" "Arbeitskopie (Erstellung einer Arbeitskopie; Auscheck? Ausspielung? Abruf? " "Source Safe: Auscheckvorgang)" #. "The action of updating the working tree to a revision which was stored in the object database." msgid "checkout [verb]" msgstr "" "Arbeitskopie erstellen; Zweig umstellen [checkout a branch] (auschecken? " "ausspielen? abrufen? Source Safe: auschecken)" #. "" msgid "clone [verb]" msgstr "kopieren" #. "A single point in the git history." msgid "commit [noun]" msgstr "" "Version; Eintragung; Änderung (Buchung?, Eintragung?, Übertragung?, " "Sendung?, Übergabe?, Einspielung?, Ablagevorgang?)" #. "The action of storing a new snapshot of the project's state in the git history." msgid "commit [verb]" msgstr "" "eintragen (TortoiseSVN: übertragen; Source Safe: einchecken; senden?, " "übergeben?, einspielen?, einpflegen?, ablegen?)" #. "" msgid "diff [noun]" msgstr "Vergleich (Source Safe: Unterschiede)" #. "" msgid "diff [verb]" msgstr "vergleichen" #. "A fast-forward is a special type of merge where you have a revision and you are merging another branch's changes that happen to be a descendant of what you have." msgid "fast forward merge" msgstr "Schnellzusammenführung" #. "Fetching a branch means to get the branch's head from a remote repository, to find out which objects are missing from the local object database, and to get them, too." msgid "fetch" msgstr "anfordern (holen?)" #. "A collection of files. The index is a stored version of your working tree." msgid "index (in git-gui: staging area)" msgstr "Bereitstellung" #. "A successful merge results in the creation of a new commit representing the result of the merge." msgid "merge [noun]" msgstr "Zusammenführung" #. "To bring the contents of another branch into the current branch." msgid "merge [verb]" msgstr "zusammenführen" #. "" msgid "message" msgstr "Beschreibung (Meldung?, Nachricht?; Source Safe: Kommentar)" #. "Deletes all stale tracking branches under . These stale branches have already been removed from the remote repository referenced by , but are still locally available in 'remotes/'." msgid "prune" msgstr "entfernen" #. "Pulling a branch means to fetch it and merge it." msgid "pull" msgstr "übernehmen (ziehen?)" #. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" msgid "push" msgstr "versenden (ausliefern? hochladen? verschicken? schieben?)" #. "" msgid "redo" msgstr "wiederholen" #. "An other repository ('remote'). One might have a set of remotes whose branches one tracks." msgid "remote" msgstr "Andere Archive (Gegenseite?, Entfernte?, Server?)" #. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" msgid "repository" msgstr "Projektarchiv" #. "" msgid "reset" msgstr "zurücksetzen (zurückkehren?)" #. "" msgid "revert" msgstr "revidieren" #. "A particular state of files and directories which was stored in the object database." msgid "revision" msgstr "Version (TortoiseSVN: Revision; Source Safe: Version)" #. "" msgid "sign off" msgstr "abzeichnen (gegenzeichnen?, freizeichnen?, absegnen?)" #. "" msgid "staging area" msgstr "Bereitstellung" #. "" msgid "status" msgstr "Status" #. "A ref pointing to a tag or commit object" msgid "tag [noun]" msgstr "Markierung" #. "" msgid "tag [verb]" msgstr "markieren" #. "A regular git branch that is used to follow changes from another repository." msgid "tracking branch" msgstr "Übernahmezweig" #. "" msgid "undo" msgstr "rückgängig" #. "" msgid "update" msgstr "aktualisieren" #. "" msgid "verify" msgstr "überprüfen" #. "The tree of actual checked out files." msgid "working copy, working tree" msgstr "Arbeitskopie" git-cola-1.9.3/po/glossary/it.po000066400000000000000000000131201225156173500164640ustar00rootroot00000000000000# Translation of git-gui glossary to Italian # Copyright (C) 2007 Shawn Pearce, et al. # This file is distributed under the same license as the git package. # Christian Stimming , 2007 # msgid "" msgstr "" "Project-Id-Version: git-gui glossary\n" "POT-Creation-Date: 2007-10-19 21:43+0200\n" "PO-Revision-Date: 2007-10-10 15:24+0200\n" "Last-Translator: Michele Ballabio \n" "Language-Team: Italian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)" msgid "" "English Term (Dear translator: This file will never be visible to the user!)" msgstr "" "Traduzione italiana.\n" "Altri SCM in italiano:\n" " http://tortoisesvn.tigris.org/svn/tortoisesvn/trunk/Languages/Tortoise_it." "po (username=guest, password empty),\n" " http://tortoisecvs.cvs.sourceforge.net/tortoisecvs/po/TortoiseCVS/it_IT.po?" "view=markup ,\n" " http://rapidsvn.tigris.org/svn/rapidsvn/trunk/src/locale/it_IT/rapidsvn.po " "(username=guest, password empty)" #. "" msgid "amend" msgstr "correggere, correzione" #. "" msgid "annotate" msgstr "annotare, annotazione" #. "A 'branch' is an active line of development." msgid "branch [noun]" msgstr "ramo, diramazione, ramificazione" #. "" msgid "branch [verb]" msgstr "creare ramo, ramificare, diramare" #. "" msgid "checkout [noun]" msgstr "attivazione, checkout, revisione attiva, prelievo (TortoiseCVS)?" #. "The action of updating the working tree to a revision which was stored in the object database." msgid "checkout [verb]" msgstr "" "attivare, effettuare un checkout, attivare revisione, prelevare " "(TortoiseCVS), ritirare (TSVN)?" #. "" msgid "clone [verb]" msgstr "clonare" #. "A single point in the git history." msgid "commit [noun]" msgstr "revisione, commit, deposito (TortoiseCVS), invio (TSVN)?" #. "The action of storing a new snapshot of the project's state in the git history." msgid "commit [verb]" msgstr "" "creare una nuova revisione, archiviare, effettuare un commit, depositare " "(nel server), fare un deposito (TortoiseCVS), inviare (TSVN)?" #. "" msgid "diff [noun]" msgstr "differenza, confronto, comparazione, raffronto" #. "" msgid "diff [verb]" msgstr "confronta, mostra le differenze" #. "A fast-forward is a special type of merge where you have a revision and you are merging another branch's changes that happen to be a descendant of what you have." msgid "fast forward merge" msgstr "fusione in 'fast-forward', fusione in avanti veloce" #. "Fetching a branch means to get the branch's head from a remote repository, to find out which objects are missing from the local object database, and to get them, too." msgid "fetch" msgstr "recuperare, prelevare, prendere da, recuperare (TSVN)" #. "A collection of files. The index is a stored version of your working tree." msgid "index (in git-gui: staging area)" msgstr "indice" #. "A successful merge results in the creation of a new commit representing the result of the merge." msgid "merge [noun]" msgstr "fusione, unione" #. "To bring the contents of another branch into the current branch." msgid "merge [verb]" msgstr "effettuare la fusione, unire, fondere, eseguire la fusione" #. "" msgid "message" msgstr "messaggio, commento" #. "Deletes all stale tracking branches under . These stale branches have already been removed from the remote repository referenced by , but are still locally available in 'remotes/'." msgid "prune" msgstr "potatura" #. "Pulling a branch means to fetch it and merge it." msgid "pull" msgstr "" "prendi (recupera) e fondi (unisci)? (in pratica una traduzione di fetch + " "merge)" #. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" msgid "push" msgstr "propaga" #. "" msgid "redo" msgstr "ripeti, rifai" #. "An other repository ('remote'). One might have a set of remotes whose branches one tracks." msgid "remote" msgstr "remoto" #. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" msgid "repository" msgstr "archivio, repository, database? deposito (rapidsvn)?" #. "" msgid "reset" msgstr "ripristinare, annullare, azzerare, ripristinare" #. "" msgid "revert" msgstr "" "annullare, inverti (rapidsvn), ritorna allo stato precedente, annulla le " "modifiche della revisione" #. "A particular state of files and directories which was stored in the object database." msgid "revision" msgstr "revisione (TortoiseSVN)" #. "" msgid "sign off" msgstr "sign off, firma" #. "" msgid "staging area" msgstr "" "area di preparazione, zona di preparazione, modifiche in preparazione? " "modifiche in allestimento?" #. "" msgid "status" msgstr "stato" #. "A ref pointing to a tag or commit object" msgid "tag [noun]" msgstr "etichetta, etichettatura (TortoiseCVS)" #. "" msgid "tag [verb]" msgstr "etichettare" #. "A regular git branch that is used to follow changes from another repository." msgid "tracking branch" msgstr "" "duplicato locale di ramo remoto, ramo in 'tracking', ramo inseguitore? ramo " "di {inseguimento,allineamento,rilevamento,puntamento}?" #. "" msgid "undo" msgstr "annulla" #. "" msgid "update" msgstr "aggiornamento, aggiornare" #. "" msgid "verify" msgstr "verifica, verificare" #. "The tree of actual checked out files." msgid "working copy, working tree" msgstr "directory di lavoro, copia di lavoro" git-cola-1.9.3/po/glossary/zh_cn.po000066400000000000000000000122021225156173500171510ustar00rootroot00000000000000# Translation of git-gui glossary to Simplified Chinese # Copyright (C) 2007 Shawn Pearce, et al. # This file is distributed under the same license as the git package. # Xudong Guan and the zh-kernel.org mailing list, 2007 # msgid "" msgstr "" "Project-Id-Version: git-gui glossary\n" "PO-Revision-Date: 2007-07-23 22:07+0200\n" "Last-Translator: Xudong Guan \n" "Language-Team: Simplified Chinese \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)" msgid "" "English Term (Dear translator: This file will never be visible to the user!)" msgstr "注:这个文件是为了帮助翻译人员统一名词术语。最终用户不会关心这个文件。" #. "" #. amend指用户修改最近一次commit的操作,修订?修改?修正? #. [WANG Cong]: 根据我的了解,这个词似乎翻译成“修订”多一些。“修正”也可以,“修改”再次之。 #. [ZHANG Le]: 修订,感觉一般指对一些大型出版物的大规模升级,比如修订新华字典 # 修正,其实每次amend的结果也不一定就是最后结果,说不定还需要修改。所以不 # 如就叫修改 msgid "amend" msgstr "修订" #. "" #. git annotate 文件名:用来标注文件的每一行在什么时候被谁最后修改。 #. [WANG Cong]: "标记"一般是mark。;) #. [ZHANG Le]: 标注,或者干脆用原意:注解,或注释 msgid "annotate" msgstr "标注" #. "A 'branch' is an active line of development." msgid "branch [noun]" msgstr "分支" #. "" msgid "branch [verb]" msgstr "建立分支" #. "" #. [WANG Cong]: 网上有人翻译成“检出”,我感觉更好一些,毕竟把check的意思翻译出来了。 #. [ZHNAG Le]: 提取吧,提取分支/版本 #. [rae l]: 签出。subversion软件中的大多词汇已有翻译,既然git与subversion同是SCM管理,可以参考同类软件的翻译也不错。 msgid "checkout [noun]" msgstr "签出" #. "The action of updating the working tree to a revision which was stored in the object database." msgid "checkout [verb]" msgstr "签出" #. "A single point in the git history." msgid "commit [noun]" msgstr "提交" #. "The action of storing a new snapshot of the project's state in the git history." msgid "commit [verb]" msgstr "提交" #. "" #. 差异?差别? #. [ZHANG Le]: 个人感觉差别更加中性一些 msgid "diff [noun]" msgstr "差别" #. "" msgid "diff [verb]" msgstr "比较" #. "A fast-forward is a special type of merge where you have a revision and you are merging another branch's changes that happen to be a descendant of what you have." msgid "fast forward merge" msgstr "快进式合并" #. "Fetching a branch means to get the branch's head from a remote repository, to find out which objects are missing from the local object database, and to get them, too." #. 获取?取得?下载?更新?注意和update的区分 msgid "fetch" msgstr "获取" #. "A collection of files. The index is a stored version of your working tree." #. index是working tree和repository之间的缓存 msgid "index (in git-gui: staging area)" msgstr "工作缓存?" #. "A successful merge results in the creation of a new commit representing the result of the merge." msgid "merge [noun]" msgstr "合并" #. "To bring the contents of another branch into the current branch." msgid "merge [verb]" msgstr "合并" #. "" #. message是指commit中的文字信息 msgid "message" msgstr "描述" #. "Pulling a branch means to fetch it and merge it." msgid "pull" msgstr "获取+合并" #. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" msgid "push" msgstr "推入" #. "" msgid "redo" msgstr "重做" #. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" msgid "repository" msgstr "仓库" #. "" msgid "reset" msgstr "重置" #. "" msgid "revert" msgstr "恢复" #. "A particular state of files and directories which was stored in the object database." msgid "revision" msgstr "版本" #. "" msgid "sign off" msgstr "签名" #. "" #. 似乎是git-gui里面显示的本次提交的文件清单区域 msgid "staging area" msgstr "提交暂存区" #. "" msgid "status" msgstr "状态" #. "A ref pointing to a tag or commit object" msgid "tag [noun]" msgstr "标签" #. "" msgid "tag [verb]" msgstr "添加标签" #. "A regular git branch that is used to follow changes from another repository." msgid "tracking branch" msgstr "跟踪分支" #. "" msgid "undo" msgstr "撤销" #. "" msgid "update" msgstr "更新。注意和fetch的区分" #. "" msgid "verify" msgstr "验证" #. "The tree of actual checked out files." #. "工作副本?工作区域?工作目录" #. [LI Yang]: 当前副本, 当前源码树? msgid "working copy, working tree" msgstr "工作副本,工作源码树" git-cola-1.9.3/po/hu.po000066400000000000000000002211401225156173500146240ustar00rootroot00000000000000# Hungarian translations for git-gui-i package. # Copyright (C) 2007 THE git-gui-i'S COPYRIGHT HOLDER # This file is distributed under the same license as the git-gui-i package. # Miklos Vajna , 2007. # msgid "" msgstr "" "Project-Id-Version: git-gui-i 18n\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-09-24 21:42-0700\n" "PO-Revision-Date: 2008-03-14 17:24+0100\n" "Last-Translator: Miklos Vajna \n" "Language-Team: Hungarian\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: cola/bookmarks.py:32 msgid "Bookmarks" msgstr "" #: cola/bookmarks.py:47 msgid "Open" msgstr "Megnyitás" #: cola/bookmarks.py:53 msgid "Add" msgstr "" #: cola/bookmarks.py:58 cola/guicmds.py:25 cola/guicmds.py:33 #: cola/widgets/editremotes.py:127 msgid "Delete" msgstr "Törlés" #: cola/bookmarks.py:65 cola/stash/view.py:42 cola/widgets/archive.py:65 #: cola/widgets/browse.py:117 msgid "Save" msgstr "Mentés" #: cola/bookmarks.py:71 cola/difftool.py:96 cola/qt.py:57 cola/qt.py:243 #: cola/prefs/view.py:241 cola/stash/view.py:50 cola/stash/view.py:51 #: cola/widgets/about.py:66 cola/widgets/about.py:126 #: cola/widgets/browse.py:116 cola/widgets/cfgactions.py:87 #: cola/widgets/cfgactions.py:239 cola/widgets/compare.py:94 #: cola/widgets/createbranch.py:159 cola/widgets/createtag.py:104 #: cola/widgets/editremotes.py:55 cola/widgets/grep.py:75 #: cola/widgets/recent.py:75 cola/widgets/remote.py:157 #: cola/widgets/search.py:81 cola/widgets/selectcommits.py:59 #: cola/widgets/startup.py:42 msgid "Close" msgstr "Bezárás" #: cola/bookmarks.py:102 msgid "Bookmarks Saved" msgstr "" #: cola/bookmarks.py:103 msgid "Successfully saved bookmarks" msgstr "" #: cola/bookmarks.py:107 #, fuzzy msgid "Path to git repository" msgstr "Nem Git repó: %s" #: cola/bookmarks.py:108 #, fuzzy msgid "Enter Git Repository" msgstr "Git repó" #: cola/cmds.py:105 msgid "Amend" msgstr "" #: cola/cmds.py:140 #, fuzzy msgid "Cannot Amend" msgstr "Nem sikerült írni az ikont:" #: cola/cmds.py:141 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" #: cola/cmds.py:204 #, python-format msgid "PATCH %(current)d/%(count)d" msgstr "" #: cola/cmds.py:208 msgid "Summary:" msgstr "" #: cola/cmds.py:217 msgid "Patch(es) Applied" msgstr "" #: cola/cmds.py:218 #, python-format msgid "%d patch(es) applied." msgstr "" #: cola/cmds.py:322 #, fuzzy, python-format msgid "Created commit: %s" msgstr "Létrejött a %s commit: %s" #: cola/cmds.py:324 #, fuzzy, python-format msgid "Commit failed: %s" msgstr "A commit nem sikerült." #: cola/cmds.py:369 cola/cmds.py:1186 #, fuzzy msgid "Error" msgstr "hiba" #: cola/cmds.py:370 #, python-format msgid "Deleting \"%s\" failed" msgstr "" #: cola/cmds.py:406 #, fuzzy msgid "Remote Branch Deleted" msgstr "Branch átnevezése" #: cola/cmds.py:407 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "" #: cola/cmds.py:411 cola/guicmds.py:108 cola/widgets/remote.py:472 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "" #: cola/cmds.py:414 #, fuzzy msgid "Error Deleting Remote Branch" msgstr "Branch létrehozása" #: cola/cmds.py:493 cola/widgets/grep.py:60 cola/widgets/recent.py:69 msgid "Edit" msgstr "Szerkesztés" #: cola/cmds.py:529 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/cmds.py:531 #, fuzzy msgid "Error Editing File" msgstr "Hiba a diff betöltése közben:" #: cola/cmds.py:554 msgid "Launch Diff Tool" msgstr "" #: cola/cmds.py:577 msgid "Launch Editor" msgstr "" #: cola/cmds.py:598 msgid "Error: Cannot find commit template" msgstr "" #: cola/cmds.py:599 #, fuzzy, python-format msgid "%s: No such file or directory." msgstr "" "végzetes hiba: nem érhető el a(z) %s útvonal: Nincs ilyen fájl vagy könyvtár" #: cola/cmds.py:616 msgid "Error: Unconfigured commit template" msgstr "" #: cola/cmds.py:617 msgid "" "A commit template has not been configured.\n" "Use \"git config\" to define \"commit.template\"\n" "so that it points to a commit template." msgstr "" #: cola/cmds.py:669 msgid "Open Using Default Application" msgstr "" #: cola/cmds.py:692 #, fuzzy msgid "Open Parent Directory" msgstr "Legutóbbi repók megnyitása:" #: cola/cmds.py:732 #, python-format msgid "Error: could not clone \"%s\"" msgstr "" #: cola/cmds.py:733 #, python-format msgid "git clone returned exit code %s" msgstr "" #: cola/cmds.py:756 cola/widgets/action.py:19 cola/widgets/editremotes.py:49 #: cola/widgets/grep.py:65 cola/widgets/recent.py:52 #: cola/widgets/recent.py:121 msgid "Refresh" msgstr "Frissítés" #: cola/cmds.py:784 #, python-format msgid "Run \"%s\"?" msgstr "" #: cola/cmds.py:791 #, fuzzy msgid "Please select a file" msgstr "Válasszunk ki egy követő branchet." #: cola/cmds.py:792 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:804 #, fuzzy msgid "Invalid Revision" msgstr "Érvénytelen revízió: %s" #: cola/cmds.py:805 #, fuzzy msgid "The revision expression cannot be empty." msgstr "A revízió kifejezés üres." #: cola/cmds.py:820 #, python-format msgid "Running command: %s" msgstr "" #: cola/cmds.py:829 cola/cmds.py:1006 cola/interaction.py:70 #, python-format msgid "Output: %s" msgstr "" #: cola/cmds.py:830 cola/guicmds.py:113 cola/interaction.py:71 #, python-format msgid "Errors: %s" msgstr "" #: cola/cmds.py:876 msgid "Sign Off" msgstr "Aláír" #: cola/cmds.py:897 msgid "unknown" msgstr "" #: cola/cmds.py:910 cola/widgets/action.py:17 #, fuzzy msgid "Stage" msgstr "Mentés" #: cola/cmds.py:917 #, fuzzy, python-format msgid "Staging: %s" msgstr "Keresés itt: %s..." #: cola/cmds.py:934 msgid "Stage Modified" msgstr "" #: cola/cmds.py:948 #, fuzzy msgid "Stage Unmerged" msgstr "Változtatások kiválasztása" #: cola/cmds.py:962 #, fuzzy msgid "Stage Untracked" msgstr "Változtatások kiválasztása" #: cola/cmds.py:980 #, python-format msgid "Tagging \"%(revision)s\" as \"%(name)s\"" msgstr "" #: cola/cmds.py:988 msgid "GPG-signed" msgstr "" #: cola/cmds.py:1020 cola/widgets/action.py:18 #, fuzzy msgid "Unstage" msgstr "Kiválasztatlan változtatások" #: cola/cmds.py:1027 #, fuzzy, python-format msgid "Unstaging: %s" msgstr "A(z) %s commitba való kiválasztásának visszavonása" #: cola/cmds.py:1055 #, python-format msgid "Untracking: %s" msgstr "" #: cola/cmds.py:1137 #, fuzzy msgid "Error Launching History Browser" msgstr "Fájl böngésző" #: cola/cmds.py:1138 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/difftool.py:76 msgid "git-cola diff" msgstr "" #: cola/difftool.py:92 cola/widgets/compare.py:90 msgid "Compare" msgstr "" #: cola/gitcmds.py:402 #, fuzzy msgid "Nothing to do" msgstr "Semmi másolni való nincs innen: %s" #: cola/guicmds.py:25 msgid "Delete Branch" msgstr "Branch törlése" #: cola/guicmds.py:33 #, fuzzy msgid "Delete Remote Branch" msgstr "Távoli branch törlése" #: cola/guicmds.py:53 #, fuzzy msgid "Browse Commits..." msgstr "Böngészés" #: cola/guicmds.py:53 #, fuzzy msgid "Browse" msgstr "Böngészés" #: cola/guicmds.py:61 msgid "Checkout Branch" msgstr "Branch checkoutolása" #: cola/guicmds.py:61 msgid "Checkout" msgstr "Checkout" #: cola/guicmds.py:70 #, fuzzy msgid "Cherry-Pick Commit" msgstr "Commit másolása" #: cola/guicmds.py:107 #, fuzzy msgid "Error Creating Repository" msgstr "Új repó létrehozása" #: cola/guicmds.py:110 #, python-format msgid "" "Output:\n" "%s" msgstr "" #: cola/guicmds.py:132 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/guicmds.py:153 #, fuzzy msgid "Error Cloning" msgstr "Hiba a fájl betöltése közben:" #: cola/guicmds.py:154 cola/guicmds.py:155 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/guicmds.py:159 msgid "Select a parent directory for the new clone" msgstr "" #: cola/guicmds.py:169 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/guicmds.py:185 cola/widgets/search.py:75 msgid "Export Patches" msgstr "" #: cola/guicmds.py:214 cola/widgets/startup.py:124 #, fuzzy msgid "Open Git Repository..." msgstr "Létező könyvtár megnyitása" #: cola/guicmds.py:223 #, fuzzy msgid "Load Commit Message" msgstr "Commit üzenet:" #: cola/guicmds.py:251 #, fuzzy msgid "Select New Base" msgstr "Kiválaszt" #: cola/guicmds.py:251 #, fuzzy msgid "Rebase" msgstr "Visszaállítás" #: cola/guicmds.py:261 #, fuzzy msgid "Select Branch to Review" msgstr "Branch törlése" #: cola/guicmds.py:261 msgid "Review" msgstr "" #: cola/inotify.py:47 msgid "inotify is disabled because \"cola.inotify\" is false" msgstr "" #: cola/inotify.py:53 msgid "" "file notification: disabled\n" "Note: install pywin32 to enable.\n" msgstr "" #: cola/inotify.py:56 msgid "" "inotify: disabled\n" "Note: install python-pyinotify to enable inotify.\n" msgstr "" #: cola/inotify.py:62 msgid "On Debian systems try: sudo aptitude install python-pyinotify" msgstr "" #: cola/inotify.py:71 #, fuzzy msgid "File notification enabled." msgstr "A fájl módosítási dátumok megbízhatóak" #: cola/inotify.py:73 msgid "inotify enabled." msgstr "" #: cola/interaction.py:53 msgid "Continue" msgstr "Folytatás" #: cola/interaction.py:63 #, python-format msgid "Run %s?" msgstr "" #: cola/interaction.py:64 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/interaction.py:65 cola/widgets/cfgactions.py:240 msgid "Run" msgstr "" #: cola/interaction.py:72 #, python-format msgid "Exit code: %s" msgstr "" #: cola/qt.py:60 cola/qt.py:100 #, fuzzy msgid "Detach" msgstr "Branch törlése" #: cola/qt.py:98 msgid "Attach" msgstr "" #: cola/qtutils.py:396 #, fuzzy msgid "Close..." msgstr "Másolás..." #: cola/classic/controller.py:69 msgid "Select Previous Version" msgstr "" #: cola/classic/model.py:37 cola/widgets/createtag.py:51 #: cola/widgets/editremotes.py:220 #, fuzzy msgid "Name" msgstr "Név:" #: cola/classic/model.py:39 cola/main/view.py:91 msgid "Status" msgstr "" #: cola/classic/model.py:41 msgid "Age" msgstr "" #: cola/classic/model.py:43 cola/widgets/createtag.py:74 #, fuzzy msgid "Message" msgstr "Merge" #: cola/classic/model.py:45 cola/dag/view.py:371 #, fuzzy msgid "Author" msgstr "Szerző:" #: cola/classic/model.py:342 #, python-format msgid "%d minutes ago" msgstr "" #: cola/classic/model.py:345 #, python-format msgid "%d hours ago" msgstr "" #: cola/classic/model.py:346 #, python-format msgid "%d days ago" msgstr "" #: cola/classic/model.py:359 cola/widgets/status.py:73 #, fuzzy msgid "Unmerged" msgstr "Merge" #: cola/classic/model.py:361 msgid "Partially Staged" msgstr "" #: cola/classic/model.py:363 cola/widgets/status.py:74 #, fuzzy msgid "Modified" msgstr "Nem módosított" #: cola/classic/model.py:365 cola/widgets/status.py:72 #, fuzzy msgid "Staged" msgstr "Változtatások kiválasztása" #: cola/classic/model.py:367 msgid "Changed Upstream" msgstr "" #: cola/classic/view.py:47 cola/main/view.py:545 #, fuzzy, python-format msgid "Repository: %s" msgstr "Repó:" #: cola/classic/view.py:49 cola/main/view.py:547 #, fuzzy, python-format msgid "Branch: %s" msgstr "Branch:" #: cola/classic/view.py:52 #, python-format msgid "%s: %s - Browse" msgstr "" #: cola/classic/view.py:54 cola/main/view.py:552 msgid "Amending" msgstr "" #: cola/classic/view.py:79 msgid "View History..." msgstr "" #: cola/classic/view.py:80 msgid "View history for selected path(s)." msgstr "" #: cola/classic/view.py:84 cola/widgets/status.py:506 #: cola/widgets/status.py:536 cola/widgets/status.py:593 #, fuzzy msgid "Stage Selected" msgstr "Kiválaszt" #: cola/classic/view.py:85 #, fuzzy msgid "Stage selected path(s) for commit." msgstr "Kiválasztva commitolásra" #: cola/classic/view.py:90 cola/widgets/status.py:452 #: cola/widgets/status.py:494 msgid "Unstage Selected" msgstr "" #: cola/classic/view.py:91 msgid "Remove selected path(s) from the staging area." msgstr "" #: cola/classic/view.py:96 msgid "Untrack Selected" msgstr "" #: cola/classic/view.py:97 msgid "Stop tracking path(s)" msgstr "" #: cola/classic/view.py:102 msgid "Launch git-difftool on the current path." msgstr "" #: cola/classic/view.py:106 msgid "Diff Against Predecessor..." msgstr "" #: cola/classic/view.py:107 msgid "Launch git-difftool against previous versions." msgstr "" #: cola/classic/view.py:111 #, fuzzy msgid "Revert Uncommitted Changes..." msgstr "Változtatások visszaállítása" #: cola/classic/view.py:112 #, fuzzy msgid "Revert changes to selected path(s)." msgstr "Visszaállítja a változtatásokat a(z) %s fájlban?" #: cola/classic/view.py:117 msgid "Edit selected path(s)." msgstr "" #: cola/classic/view.py:293 cola/widgets/status.py:652 #, fuzzy msgid "Revert Uncommitted Changes?" msgstr "Változtatások visszaállítása" #: cola/classic/view.py:294 cola/widgets/diff.py:246 cola/widgets/diff.py:259 #: cola/widgets/status.py:653 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/classic/view.py:296 cola/widgets/diff.py:248 cola/widgets/diff.py:261 #: cola/widgets/status.py:655 msgid "Revert the uncommitted changes?" msgstr "" #: cola/classic/view.py:297 cola/widgets/status.py:656 #, fuzzy msgid "Revert Uncommitted Changes" msgstr "Változtatások visszaállítása" #: cola/dag/view.py:166 #, fuzzy msgid "Loading..." msgstr "A(z) %s betöltése..." #: cola/dag/view.py:272 msgid "Diff this -> selected" msgstr "" #: cola/dag/view.py:275 msgid "Diff selected -> this" msgstr "" #: cola/dag/view.py:278 cola/widgets/createbranch.py:89 #: cola/widgets/createbranch.py:98 cola/widgets/createbranch.py:155 #: cola/widgets/createbranch.py:330 msgid "Create Branch" msgstr "Branch létrehozása" #: cola/dag/view.py:281 #, fuzzy msgid "Create Patch" msgstr "Branch létrehozása" #: cola/dag/view.py:284 cola/widgets/createtag.py:38 #: cola/widgets/createtag.py:99 #, fuzzy msgid "Create Tag" msgstr "Létrehozás" #: cola/dag/view.py:287 cola/main/view.py:208 msgid "Save As Tarball/Zip..." msgstr "" #: cola/dag/view.py:290 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/dag/view.py:293 msgid "Grab File..." msgstr "" #: cola/dag/view.py:296 #, fuzzy msgid "Copy SHA-1" msgstr "Összes másolása" #: cola/dag/view.py:371 msgid "Summary" msgstr "" #: cola/dag/view.py:371 msgid "Date, Time" msgstr "" #: cola/dag/view.py:378 msgid "Go Up" msgstr "" #: cola/dag/view.py:381 msgid "Go Down" msgstr "" #: cola/dag/view.py:511 cola/dag/view.py:1181 msgid "Zoom Out" msgstr "" #: cola/dag/view.py:514 cola/dag/view.py:1178 msgid "Zoom In" msgstr "" #: cola/dag/view.py:517 cola/dag/view.py:1184 msgid "Zoom to Fit" msgstr "" #: cola/dag/view.py:536 msgid "Log" msgstr "" #: cola/dag/view.py:541 cola/main/view.py:114 cola/main/view.py:384 msgid "Diff" msgstr "" #: cola/dag/view.py:554 msgid "Graph" msgstr "" #: cola/dag/view.py:563 msgid "View" msgstr "" #: cola/dag/view.py:636 #, python-format msgid "%s: %s - DAG" msgstr "" #: cola/dag/view.py:638 msgid " - DAG" msgstr "" #: cola/dag/view.py:1187 #, fuzzy msgid "Select Parent" msgstr "Kiválaszt" #: cola/dag/view.py:1190 msgid "Select Oldest Parent" msgstr "" #: cola/dag/view.py:1193 #, fuzzy msgid "Select Child" msgstr "Mindent kiválaszt" #: cola/dag/view.py:1196 msgid "Select Newest Child" msgstr "" #: cola/main/view.py:78 #, fuzzy msgid "Browser" msgstr "Böngészés" #: cola/main/view.py:83 #, fuzzy msgid "Action" msgstr "Opciók" #: cola/main/view.py:99 cola/merge/view.py:45 #, fuzzy msgid "Commit" msgstr "Commit:" #: cola/main/view.py:108 #, fuzzy msgid "Console" msgstr "Bezárás" #: cola/main/view.py:120 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/main/view.py:125 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/main/view.py:130 msgid "Ignore all whitespace" msgstr "" #: cola/main/view.py:135 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/main/view.py:139 cola/widgets/createbranch.py:194 msgid "Options" msgstr "Opciók" #: cola/main/view.py:141 cola/main/view.py:142 #, fuzzy msgid "Diff Options" msgstr "Opciók" #: cola/main/view.py:157 cola/widgets/status.py:423 msgid "Unstage All" msgstr "" #: cola/main/view.py:161 msgid "Unstage From Commit" msgstr "Commitba való kiválasztás visszavonása" #: cola/main/view.py:165 msgid "Diffstat" msgstr "" #: cola/main/view.py:168 msgid "Stage Changed Files To Commit" msgstr "Módosított fájlok kiválasztása commitolásra" #: cola/main/view.py:173 msgid "Stage All Untracked" msgstr "" #: cola/main/view.py:178 msgid "Export Patches..." msgstr "" #: cola/main/view.py:181 #, fuzzy msgid "New Repository..." msgstr "Git repó" #: cola/main/view.py:185 cola/prefs/view.py:220 msgid "Preferences" msgstr "Beállítások" #: cola/main/view.py:189 msgid "Edit Remotes..." msgstr "" #: cola/main/view.py:197 #, fuzzy msgid "Recently Modified Files..." msgstr "Módosított fájlok keresése ..." #: cola/main/view.py:201 #, fuzzy msgid "Cherry-Pick..." msgstr "Checkout..." #: cola/main/view.py:205 #, fuzzy msgid "Load Commit Message..." msgstr "Commit üzenet:" #: cola/main/view.py:211 msgid "Quit" msgstr "Kilépés" #: cola/main/view.py:213 msgid "Bookmarks..." msgstr "" #: cola/main/view.py:215 msgid "Grep" msgstr "" #: cola/main/view.py:217 #, fuzzy msgid "Merge..." msgstr "Merge" #: cola/main/view.py:220 cola/merge/__init__.py:20 msgid "Abort Merge..." msgstr "Merge megszakítása..." #: cola/main/view.py:223 cola/widgets/action.py:20 #, fuzzy msgid "Fetch..." msgstr "Visszaállítás..." #: cola/main/view.py:225 cola/widgets/action.py:21 msgid "Push..." msgstr "Push..." #: cola/main/view.py:227 cola/widgets/action.py:22 #, fuzzy msgid "Pull..." msgstr "Push..." #: cola/main/view.py:230 cola/widgets/startup.py:36 msgid "Open..." msgstr "Meggyitás..." #: cola/main/view.py:234 cola/widgets/action.py:23 #, fuzzy msgid "Stash..." msgstr "Push..." #: cola/main/view.py:237 cola/widgets/startup.py:39 msgid "Clone..." msgstr "Másolás..." #: cola/main/view.py:241 #, fuzzy msgid "Documentation" msgstr "Online dokumentáció" #: cola/main/view.py:245 msgid "Keyboard Shortcuts" msgstr "" #: cola/main/view.py:250 #, fuzzy msgid "Visualize Current Branch..." msgstr "A jelenlegi branch történetének vizualizálása" #: cola/main/view.py:253 #, fuzzy msgid "Visualize All Branches..." msgstr "Az összes branch történetének vizualizálása" #: cola/main/view.py:256 #, fuzzy msgid "Search..." msgstr "Indítás..." #: cola/main/view.py:258 #, fuzzy msgid "Browse Current Branch..." msgstr "A jelenlegi branch fájljainak böngészése" #: cola/main/view.py:260 #, fuzzy msgid "Browse Other Branch..." msgstr "A branch fájljainak böngészése..." #: cola/main/view.py:262 #, fuzzy msgid "Get Commit Message Template" msgstr "Commit üzenet szövegének szélessége" #: cola/main/view.py:265 #, fuzzy msgid "About" msgstr "Névjegy: %s" #: cola/main/view.py:268 #, fuzzy msgid "Expression..." msgstr "Opciók..." #: cola/main/view.py:270 #, fuzzy msgid "Branches..." msgstr "Branchek" #: cola/main/view.py:273 #, fuzzy msgid "Create Tag..." msgstr "Létrehozás..." #: cola/main/view.py:276 msgid "Create..." msgstr "Létrehozás..." #: cola/main/view.py:279 msgid "Delete..." msgstr "Törlés..." #: cola/main/view.py:282 #, fuzzy msgid "Delete Remote Branch..." msgstr "Távoli branch törlése" #: cola/main/view.py:285 msgid "Checkout..." msgstr "Checkout..." #: cola/main/view.py:287 #, fuzzy msgid "Rebase..." msgstr "Visszaállítás..." #: cola/main/view.py:289 #, fuzzy msgid "Review..." msgstr "Visszaállítás..." #: cola/main/view.py:292 #, fuzzy msgid "Browser..." msgstr "Böngészés" #: cola/main/view.py:296 msgid "DAG..." msgstr "" #: cola/main/view.py:313 #, fuzzy msgid "File" msgstr "Fájl:" #: cola/main/view.py:316 #, fuzzy msgid "Open Recent" msgstr "Legutóbbi repók megnyitása:" #: cola/main/view.py:338 cola/main/view.py:339 #, fuzzy msgid "Index" msgstr "Index hiba" #: cola/main/view.py:349 msgid "Branch" msgstr "Branch" #: cola/main/view.py:367 #, fuzzy msgid "Actions" msgstr "Opciók" #: cola/main/view.py:393 msgid "Tools" msgstr "" #: cola/main/view.py:404 msgid "Help" msgstr "Segítség" #: cola/main/view.py:462 #, python-format msgid "git cola version %s" msgstr "" #: cola/merge/__init__.py:21 #, fuzzy msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Megszakítjuk a merge-t?\n" "\n" "A jelenlegi merge megszakítása *MINDEN* nem commitolt változtatás " "elvesztését jelenti.\n" "\n" "Folytatjuk a jelenlegi merge megszakítását?" #: cola/merge/__init__.py:24 msgid "Aborting the current merge?" msgstr "" #: cola/merge/__init__.py:25 #, fuzzy msgid "Abort Merge" msgstr "Merge megszakítása..." #: cola/merge/view.py:23 msgid "Revision To Merge" msgstr "Merge-ölni szándékozott revízió" #: cola/merge/view.py:28 cola/widgets/cfgactions.py:220 #: cola/widgets/remote.py:122 msgid "Local Branch" msgstr "Helyi branch" #: cola/merge/view.py:31 cola/widgets/cfgactions.py:221 msgid "Tracking Branch" msgstr "Követő branch" #: cola/merge/view.py:33 cola/widgets/cfgactions.py:222 #: cola/widgets/createbranch.py:122 msgid "Tag" msgstr "Tag" #: cola/merge/view.py:39 msgid "Visualize" msgstr "Vizualizálás" #: cola/merge/view.py:42 #, fuzzy msgid "Squash" msgstr "Push" #: cola/merge/view.py:50 cola/widgets/archive.py:62 #: cola/widgets/editremotes.py:204 msgid "Cancel" msgstr "Mégsem" #: cola/merge/view.py:53 msgid "Merge" msgstr "Merge" #: cola/merge/view.py:115 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/merge/view.py:118 #, fuzzy, python-format msgid "Merge into \"%s\"" msgstr "Merge-ölés a következőbe: %s" #: cola/merge/view.py:162 cola/merge/view.py:171 #, fuzzy msgid "No Revision Specified" msgstr "Nincs kiválasztva revízió." #: cola/merge/view.py:163 msgid "You must specify a revision to view." msgstr "" #: cola/merge/view.py:172 msgid "You must specify a revision to merge." msgstr "" #: cola/prefs/view.py:116 msgid "User Name" msgstr "Felhasználónév" #: cola/prefs/view.py:117 msgid "Email Address" msgstr "Email cím" #: cola/prefs/view.py:118 msgid "Merge Verbosity" msgstr "Merge beszédesség" #: cola/prefs/view.py:119 msgid "Number of Diff Context Lines" msgstr "A diff környezeti sorok száma" #: cola/prefs/view.py:120 msgid "Summarize Merge Commits" msgstr "A merge commitok összegzése" #: cola/prefs/view.py:121 msgid "Show Diffstat After Merge" msgstr "Diffstat mutatása merge után" #: cola/prefs/view.py:122 msgid "Display Untracked Files" msgstr "" #: cola/prefs/view.py:163 msgid "Fixed-Width Font" msgstr "" #: cola/prefs/view.py:164 msgid "Font Size" msgstr "Font méret" #: cola/prefs/view.py:165 msgid "Tab Width" msgstr "" #: cola/prefs/view.py:166 msgid "Text Width" msgstr "" #: cola/prefs/view.py:167 cola/widgets/commitmsg.py:99 msgid "Auto-Wrap Lines" msgstr "" #: cola/prefs/view.py:168 #, fuzzy msgid "Editor" msgstr "Szerkesztés" #: cola/prefs/view.py:169 #, fuzzy msgid "History Browser" msgstr "Fájl böngésző" #: cola/prefs/view.py:170 msgid "Diff Tool" msgstr "" #: cola/prefs/view.py:171 #, fuzzy msgid "Merge Tool" msgstr "Merge" #: cola/prefs/view.py:172 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/prefs/view.py:173 msgid "Save GUI Settings" msgstr "" #: cola/prefs/view.py:227 #, fuzzy msgid "All Repositories" msgstr "Globális (minden repó)" #: cola/prefs/view.py:228 #, fuzzy msgid "Current Repository" msgstr "Új repó létrehozása" #: cola/prefs/view.py:229 #, fuzzy msgid "Settings" msgstr "Indítás..." #: cola/stash/view.py:28 msgid "Stash" msgstr "" #: cola/stash/view.py:38 #, fuzzy msgid "Apply" msgstr "Apple" #: cola/stash/view.py:39 msgid "Apply the selected stash" msgstr "" #: cola/stash/view.py:43 msgid "Save modified state to new stash" msgstr "" #: cola/stash/view.py:46 msgid "Drop" msgstr "" #: cola/stash/view.py:47 msgid "Drop the selected stash" msgstr "" #: cola/stash/view.py:54 msgid "Keep Index" msgstr "" #: cola/stash/view.py:175 msgid "Save Stash" msgstr "" #: cola/stash/view.py:176 msgid "Enter a name for the stash" msgstr "" #: cola/stash/view.py:182 msgid "Error: Stash exists" msgstr "" #: cola/stash/view.py:183 #, fuzzy, python-format msgid "A stash named \"%s\" already exists" msgstr "A(z) '%s' fájl már létezik." #: cola/stash/view.py:198 msgid "Drop Stash?" msgstr "" #: cola/stash/view.py:199 #, fuzzy msgid "Recovering a dropped stash is not possible." msgstr "Az elveszett commitok helyreállítása nem biztos, hogy egyszerű." #: cola/stash/view.py:200 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/stash/view.py:201 msgid "Drop Stash" msgstr "" #: cola/widgets/about.py:47 msgid "About git-cola" msgstr "" #: cola/widgets/about.py:97 msgid "" "This PyQt4 does not include QtWebKit.\n" "The keyboard shortcuts feature is unavailable." msgstr "" #: cola/widgets/about.py:104 msgid "hotkeys.html" msgstr "" #: cola/widgets/about.py:122 msgid "Shortcuts" msgstr "" #: cola/widgets/archive.py:46 msgid "Save Archive" msgstr "" #: cola/widgets/archive.py:69 msgid "Prefix" msgstr "" #: cola/widgets/archive.py:74 msgid "Advanced" msgstr "" #: cola/widgets/archive.py:141 cola/widgets/browse.py:49 msgid "File Saved" msgstr "" #: cola/widgets/archive.py:142 cola/widgets/browse.py:50 #, python-format msgid "File saved to \"%s\"" msgstr "" #: cola/widgets/archive.py:149 msgid "Overwrite File?" msgstr "" #: cola/widgets/archive.py:150 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/widgets/archive.py:151 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:152 msgid "Overwrite" msgstr "" #: cola/widgets/browse.py:42 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/browse.py:63 #, fuzzy, python-format msgid "Browsing %s" msgstr "A(z) %s hozzáadása..." #: cola/widgets/browse.py:81 #, fuzzy, python-format msgid "Select file from \"%s\"" msgstr "Brancek törlése innen: %s" #: cola/widgets/browse.py:90 #, fuzzy msgid "Select File" msgstr "Mindent kiválaszt" #: cola/widgets/browse.py:117 cola/widgets/selectcommits.py:54 msgid "Select" msgstr "Kiválaszt" #: cola/widgets/cfgactions.py:85 #, fuzzy msgid "Abort" msgstr "Félbeszakítás" #: cola/widgets/cfgactions.py:147 cola/widgets/cfgactions.py:151 #, fuzzy msgid "Abort Action" msgstr "Félbeszakítás" #: cola/widgets/cfgactions.py:148 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/widgets/cfgactions.py:150 msgid "Abort the action?" msgstr "" #: cola/widgets/cfgactions.py:201 msgid "Arguments" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/createtag.py:85 msgid "Revision" msgstr "Revízió" #: cola/widgets/commitmsg.py:50 #, fuzzy msgid "Sign off on this commit" msgstr "Kiválasztva commitolásra" #: cola/widgets/commitmsg.py:53 cola/widgets/commitmsg.py:69 msgid "Commit@@verb" msgstr "Commit@@ige" #: cola/widgets/commitmsg.py:56 #, fuzzy msgid "Commit staged changes" msgstr "A változtatások commitolása..." #: cola/widgets/commitmsg.py:67 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:75 #, fuzzy msgid "Actions..." msgstr "Opciók..." #: cola/widgets/commitmsg.py:85 msgid "Amend Last Commit" msgstr "Utolsó commit javítása" #: cola/widgets/commitmsg.py:92 msgid "Check Spelling" msgstr "" #: cola/widgets/commitmsg.py:104 #, fuzzy msgid "Load Previous Commit Message" msgstr "Merge commit üzenet:" #: cola/widgets/commitmsg.py:135 cola/widgets/status.py:117 msgid "Move Down" msgstr "" #: cola/widgets/commitmsg.py:342 msgid "" "Please supply a commit message.\n" "\n" "A good commit message has the following format:\n" "\n" "- First line: Describe in one sentence what you did.\n" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" "Adjunk megy egy commit üzenetet.\n" "\n" "Egy jó commit üzenetnek a következő a formátuma:\n" "\n" "- Első sor: Egy mondatban leírja, hogy mit csináltunk.\n" "- Második sor: Üres\n" "- A többi sor: Leírja, hogy miért jó ez a változtatás.\n" #: cola/widgets/commitmsg.py:349 #, fuzzy msgid "Missing Commit Message" msgstr "Merge commit üzenet:" #: cola/widgets/commitmsg.py:355 #, fuzzy msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Nincs commitolandó változtatás.\n" "\n" "Legalább egy fájl ki kell választani, hogy commitolni lehessen.\n" #: cola/widgets/commitmsg.py:359 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/commitmsg.py:361 #, fuzzy msgid "Stage and commit?" msgstr "Kiválasztva commitolásra" #: cola/widgets/commitmsg.py:364 #, fuzzy msgid "Stage and Commit" msgstr "Kiválasztás commitolásra" #: cola/widgets/commitmsg.py:369 #, fuzzy msgid "Nothing to commit" msgstr "Nincs commitolandó változtatás." #: cola/widgets/commitmsg.py:376 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/commitmsg.py:377 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" #: cola/widgets/commitmsg.py:380 msgid "Amend the published commit?" msgstr "" #: cola/widgets/commitmsg.py:381 #, fuzzy msgid "Amend Commit" msgstr "Utolsó commit javítása" #: cola/widgets/commitmsg.py:386 #, fuzzy msgid "Commit failed" msgstr "A commit nem sikerült." #: cola/widgets/commitmsg.py:387 #, python-format msgid "\"git commit\" returned exit code %s" msgstr "" #: cola/widgets/commitmsg.py:409 #, fuzzy msgid "More..." msgstr "Másolás..." #: cola/widgets/commitmsg.py:413 #, fuzzy msgid "Select Commit Message" msgstr "Merge commit üzenet:" #: cola/widgets/commitmsg.py:450 #, fuzzy msgid "Commit summary" msgstr "Commit üzenet:" #: cola/widgets/commitmsg.py:465 msgid "Extended description..." msgstr "" #: cola/widgets/compare.py:37 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:38 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/compare.py:39 cola/widgets/compare.py:62 #: cola/widgets/compare.py:68 msgid "Local" msgstr "" #: cola/widgets/compare.py:44 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/compare.py:63 cola/widgets/compare.py:69 #: cola/widgets/remote.py:129 msgid "Remote" msgstr "Távoli" #: cola/widgets/compare.py:98 #, fuzzy msgid "File Differences" msgstr "Beállítások" #: cola/widgets/createbranch.py:102 msgid "Branch Name" msgstr "Branch neve" #: cola/widgets/createbranch.py:107 cola/widgets/createbranch.py:178 msgid "Starting Revision" msgstr "A következő revíziótól" #: cola/widgets/createbranch.py:115 #, fuzzy msgid "Local branch" msgstr "Helyi branch" #: cola/widgets/createbranch.py:119 #, fuzzy msgid "Tracking branch" msgstr "Követő branch" #: cola/widgets/createbranch.py:127 msgid "Update Existing Branch:" msgstr "Létező branch frissítése" #: cola/widgets/createbranch.py:130 msgid "No" msgstr "Nem" #: cola/widgets/createbranch.py:133 msgid "Fast Forward Only" msgstr "Csak fast forward" #: cola/widgets/createbranch.py:137 msgid "Reset" msgstr "Visszaállítás" #: cola/widgets/createbranch.py:143 msgid "Fetch Tracking Branch" msgstr "Követő branch letöltése" #: cola/widgets/createbranch.py:148 msgid "Checkout After Creation" msgstr "Checkout létrehozás után" #: cola/widgets/createbranch.py:259 #, fuzzy msgid "Missing Data" msgstr "Hiányzó" #: cola/widgets/createbranch.py:260 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/widgets/createbranch.py:265 #, fuzzy, python-format msgid "Branch \"%s\" already exists." msgstr "A(z) '%s' branch már létezik." #: cola/widgets/createbranch.py:266 cola/widgets/createbranch.py:277 #, fuzzy msgid "Branch Exists" msgstr "Branchek" #: cola/widgets/createbranch.py:273 #, fuzzy, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "" "A(z) '%s' -> '%s' visszaállítás a következő commitok elvesztését jelenti:" #: cola/widgets/createbranch.py:288 #, python-format msgid "%d skipped" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Recovering lost commits may not be easy." msgstr "Az elveszett commitok helyreállítása nem biztos, hogy egyszerű." #: cola/widgets/createbranch.py:292 #, fuzzy msgid "Reset Branch?" msgstr "Branch törlése" #: cola/widgets/createbranch.py:294 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/widgets/createbranch.py:296 #, fuzzy msgid "Reset Branch" msgstr "Branch törlése" #: cola/widgets/createbranch.py:305 #, fuzzy msgid "Updating..." msgstr "Indítás..." #: cola/widgets/createbranch.py:321 #, fuzzy msgid "Error Creating Branch" msgstr "Branch létrehozása" #: cola/widgets/createbranch.py:322 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/widgets/createbranch.py:331 #, fuzzy msgid "Branch created" msgstr "Branch neve" #: cola/widgets/createtag.py:55 msgid "vX.Y.Z" msgstr "" #: cola/widgets/createtag.py:56 msgid "Specifies the tag name" msgstr "" #: cola/widgets/createtag.py:62 #, fuzzy msgid "Sign Tag" msgstr "Aláír" #: cola/widgets/createtag.py:67 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:91 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:121 #, fuzzy msgid "Missing Revision" msgstr "A következő revíziótól" #: cola/widgets/createtag.py:122 #, fuzzy msgid "Please specify a revision to tag." msgstr "Válasszunk ki egy átnevezendő branchet." #: cola/widgets/createtag.py:125 #, fuzzy msgid "Missing Name" msgstr "Hiányzó" #: cola/widgets/createtag.py:126 msgid "Please specify a name for the new tag." msgstr "" #: cola/widgets/createtag.py:129 #, fuzzy msgid "Missing Tag Message" msgstr "Merge-ölni szándékozott revízió" #: cola/widgets/createtag.py:130 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/createtag.py:132 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/createtag.py:135 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/createtag.py:142 #, fuzzy msgid "Tag Created" msgstr "Létrehozás" #: cola/widgets/createtag.py:143 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/diff.py:22 msgid "Process Section" msgstr "" #: cola/widgets/diff.py:25 msgid "Process Selection" msgstr "" #: cola/widgets/diff.py:40 msgid "Stage &Selected Lines" msgstr "" #: cola/widgets/diff.py:46 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:51 #, fuzzy msgid "Unstage &Selected Lines" msgstr "Kiválasztatlan változtatások" #: cola/widgets/diff.py:57 msgid "Apply Diff Selection to Work Tree" msgstr "" #: cola/widgets/diff.py:86 cola/widgets/diff.py:108 cola/widgets/status.py:486 #: cola/widgets/status.py:584 msgid "Launch git-cola" msgstr "" #: cola/widgets/diff.py:91 #, fuzzy msgid "Stage Section" msgstr "A következő revíziótól" #: cola/widgets/diff.py:97 msgid "Revert Section..." msgstr "" #: cola/widgets/diff.py:113 msgid "Unstage Section" msgstr "" #: cola/widgets/diff.py:125 msgid "Copy" msgstr "Másolás" #: cola/widgets/diff.py:129 msgid "Select All" msgstr "Mindent kiválaszt" #: cola/widgets/diff.py:245 msgid "Revert Section?" msgstr "" #: cola/widgets/diff.py:249 msgid "Revert Section" msgstr "" #: cola/widgets/diff.py:258 #, fuzzy msgid "Revert Selected Lines?" msgstr "Visszaállítja a változtatásokat a(z) %s fájlban?" #: cola/widgets/diff.py:262 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/editremotes.py:19 #, fuzzy msgid "Edit Remotes" msgstr "Távoli" #: cola/widgets/editremotes.py:22 msgid "" "Add and remove remote repositories using the \n" "Add(+) and Delete(-) buttons on the left-hand side.\n" "\n" "Remotes can be renamed by selecting one from the list\n" "and pressing \"enter\", or by double-clicking." msgstr "" #: cola/widgets/editremotes.py:32 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/widgets/editremotes.py:45 #, fuzzy msgid "Add new remote git repository" msgstr "Nem Git repó: %s" #: cola/widgets/editremotes.py:53 #, fuzzy msgid "Delete remote" msgstr "Távoli branch törlése" #: cola/widgets/editremotes.py:116 #, python-format msgid "Error creating remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:124 #, fuzzy msgid "Delete Remote" msgstr "Távoli branch törlése" #: cola/widgets/editremotes.py:125 #, fuzzy msgid "Delete remote?" msgstr "Távoli branch törlése" #: cola/widgets/editremotes.py:126 #, fuzzy, python-format msgid "Delete remote \"%s\"" msgstr "Távoli branch törlése" #: cola/widgets/editremotes.py:134 #, python-format msgid "Error deleting remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:153 #, fuzzy msgid "Rename Remote" msgstr "Távoli" #: cola/widgets/editremotes.py:154 #, fuzzy msgid "Rename remote?" msgstr "Távoli" #: cola/widgets/editremotes.py:155 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/editremotes.py:157 msgid "Rename" msgstr "Átnevezés" #: cola/widgets/editremotes.py:169 #, fuzzy, python-format msgid "Gathering info for \"%s\"..." msgstr "A(z) %s diff-jének betöltése..." #: cola/widgets/editremotes.py:201 #, fuzzy msgid "Add Remote" msgstr "Távoli" #: cola/widgets/editremotes.py:213 #, fuzzy msgid "Add remote" msgstr "Távoli" #: cola/widgets/editremotes.py:214 msgid "Name for the new remote" msgstr "" #: cola/widgets/editremotes.py:221 msgid "URL" msgstr "URL" #: cola/widgets/grep.py:47 cola/widgets/search.py:40 cola/widgets/search.py:58 msgid "Search" msgstr "" #: cola/widgets/grep.py:52 msgid "command-line arguments" msgstr "" #: cola/widgets/grep.py:56 msgid "grep result..." msgstr "" #: cola/widgets/grep.py:69 msgid "Shell arguments" msgstr "" #: cola/widgets/grep.py:71 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/widgets/log.py:34 #, fuzzy, python-format msgid "exit code %s" msgstr "a(z) %s letöltése" #: cola/widgets/recent.py:36 msgid "Recently Modified Files" msgstr "" #: cola/widgets/recent.py:46 msgid " commits ago" msgstr "" #: cola/widgets/recent.py:49 #, fuzzy msgid "Showing changes since" msgstr "Változások pusholása ide: %s" #: cola/widgets/recent.py:61 msgid "Expand" msgstr "" #: cola/widgets/recent.py:65 #, fuzzy msgid "Collapse" msgstr "Bezárás" #: cola/widgets/remote.py:136 #, fuzzy msgid "Remote Branch" msgstr "Branch átnevezése" #: cola/widgets/remote.py:143 #, fuzzy msgid "Fast Forward Only " msgstr "Csak fast forward" #: cola/widgets/remote.py:147 #, fuzzy msgid "Include tags " msgstr "Tageket is" #: cola/widgets/remote.py:150 #, fuzzy msgid "Rebase " msgstr "Visszaállítás" #: cola/widgets/remote.py:314 #, fuzzy, python-format msgid "URL: %s" msgstr "URL:" #: cola/widgets/remote.py:393 msgid "No repository selected." msgstr "Nincs kiválasztott repó." #: cola/widgets/remote.py:406 msgid "Push" msgstr "Push" #: cola/widgets/remote.py:408 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/remote.py:410 #, fuzzy msgid "Create a new remote branch?" msgstr "Új branch létrehozása" #: cola/widgets/remote.py:411 #, fuzzy msgid "Create Remote Branch" msgstr "Távoli branch törlése" #: cola/widgets/remote.py:419 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:420 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:421 #, fuzzy, python-format msgid "Force fetching from %s?" msgstr "A(z) %s letöltése innen: %s" #: cola/widgets/remote.py:422 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:424 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:425 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/remote.py:427 #, fuzzy, python-format msgid "Force push to %s?" msgstr "Pusholás ide: %s..." #: cola/widgets/remote.py:428 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:462 msgid "Already up-to-date." msgstr "" #: cola/widgets/remote.py:485 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/widgets/search.py:44 #, fuzzy msgid "Browse..." msgstr "Böngészés" #: cola/widgets/search.py:50 cola/widgets/search.py:55 msgid "yyyy-MM-dd" msgstr "" #: cola/widgets/search.py:220 #, fuzzy msgid "Search by Expression" msgstr "Revízió kifejezés:" #: cola/widgets/search.py:221 msgid "Search by Path" msgstr "" #: cola/widgets/search.py:222 #, fuzzy msgid "Search Commit Messages" msgstr "Merge commit üzenet:" #: cola/widgets/search.py:223 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:224 msgid "Search Authors" msgstr "" #: cola/widgets/search.py:225 #, fuzzy msgid "Search Committers" msgstr "Commiter:" #: cola/widgets/search.py:226 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:319 #, fuzzy msgid "Choose Path(s)" msgstr "%s választása" #: cola/widgets/selectcommits.py:50 msgid "Revision Expression:" msgstr "Revízió kifejezés:" #: cola/widgets/selectcommits.py:101 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/spellcheck.py:139 #, fuzzy msgid "Spelling Suggestions" msgstr "Nincs javaslat" #: cola/widgets/startup.py:26 msgid "git-cola" msgstr "" #: cola/widgets/startup.py:33 msgid "New..." msgstr "Új..." #: cola/widgets/startup.py:56 #, fuzzy msgid "Select Repository..." msgstr "Git repó" #: cola/widgets/startup.py:61 #, fuzzy msgid "Select manually..." msgstr "Mindent kiválaszt" #: cola/widgets/status.py:75 #, fuzzy msgid "Untracked" msgstr "Nem követett, nem kiválasztott" #: cola/widgets/status.py:85 #, fuzzy msgid "Stage / Unstage" msgstr "Változtatások kiválasztása" #: cola/widgets/status.py:114 msgid "Move Up" msgstr "" #: cola/widgets/status.py:121 msgid "Copy Path to Clipboard" msgstr "" #: cola/widgets/status.py:474 cola/widgets/status.py:550 msgid "Revert Unstaged Edits..." msgstr "" #: cola/widgets/status.py:477 cola/widgets/status.py:553 msgid "Revert Uncommited Edits..." msgstr "" #: cola/widgets/status.py:572 #, fuzzy msgid "Delete File(s)..." msgstr "Törlés..." #: cola/widgets/status.py:575 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:608 #, fuzzy msgid "Delete Files?" msgstr "Törlés" #: cola/widgets/status.py:609 msgid "The following files will be deleted:" msgstr "" #: cola/widgets/status.py:616 #, python-format msgid "Delete %d file(s)?" msgstr "" #: cola/widgets/status.py:617 #, fuzzy msgid "Delete Files" msgstr "Törlés" #: cola/widgets/status.py:633 #, fuzzy msgid "Revert Unstaged Changes?" msgstr "Kiválasztatlan változtatások" #: cola/widgets/status.py:634 msgid "" "This operation drops unstaged changes.\n" "These changes cannot be recovered." msgstr "" #: cola/widgets/status.py:636 #, fuzzy msgid "Revert the unstaged changes?" msgstr "Kiválasztatlan változtatások" #: cola/widgets/status.py:637 #, fuzzy msgid "Revert Unstaged Changes" msgstr "Kiválasztatlan változtatások" #: cola/widgets/status.py:646 cola/widgets/status.py:662 msgid "No files selected for checkout from HEAD." msgstr "" #~ msgid "Success" #~ msgstr "Siker" #~ msgid "Rescan" #~ msgstr "Keresés újra" #, fuzzy #~ msgid "Browse Revision..." #~ msgstr "Revízió" #, fuzzy #~ msgid "Rebase Branch" #~ msgstr "Branch átnevezése" #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: végzetes hiba" #~ msgid "Invalid font specified in %s:" #~ msgstr "Érvénytelen font lett megadva itt: %s:" #~ msgid "Main Font" #~ msgstr "Fő betűtípus" #~ msgid "Diff/Console Font" #~ msgstr "Diff/konzol betűtípus" #~ msgid "Cannot find git in PATH." #~ msgstr "A git nem található a PATH-ban." #~ msgid "Cannot parse Git version string:" #~ msgstr "Nem értelmezhető a Git verzió sztring:" #~ msgid "" #~ "Git version cannot be determined.\n" #~ "\n" #~ "%s claims it is version '%s'.\n" #~ "\n" #~ "%s requires at least Git 1.5.0 or later.\n" #~ "\n" #~ "Assume '%s' is version 1.5.0?\n" #~ msgstr "" #~ "Nem állípítható meg a Git verziója.\n" #~ "\n" #~ "A(z) %s szerint a verzió '%s'.\n" #~ "\n" #~ "A(z) %s a Git 1.5.0 vagy későbbi verzióját igényli.\n" #~ "\n" #~ "Feltételezhetjük, hogy a(z) '%s' verziója legalább 1.5.0?\n" #~ msgid "Git directory not found:" #~ msgstr "A Git könyvtár nem található:" #~ msgid "Cannot move to top of working directory:" #~ msgstr "Nem lehet a munkakönyvtár tetejére lépni:" #~ msgid "Cannot use funny .git directory:" #~ msgstr "Nem használható vicces .git könyvtár:" #~ msgid "No working directory" #~ msgstr "Nincs munkakönyvtár" #~ msgid "Refreshing file status..." #~ msgstr "A fájlok státuszának frissítése..." #~ msgid "Ready." #~ msgstr "Kész." #~ msgid "Modified, not staged" #~ msgstr "Módosított, de nem kiválasztott" #~ msgid "Portions staged for commit" #~ msgstr "Részek kiválasztva commitolásra" #~ msgid "Staged for commit, missing" #~ msgstr "Kiválasztva commitolásra, hiányzó" #~ msgid "Staged for removal" #~ msgstr "Kiválasztva eltávolításra" #~ msgid "Staged for removal, still present" #~ msgstr "Kiválasztva eltávolításra, jelenleg is elérhető" #~ msgid "Requires merge resolution" #~ msgstr "Merge feloldás szükséges" #~ msgid "Starting gitk... please wait..." #~ msgstr "A gitk indítása... várjunk..." #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "A gitk indítása sikertelen:\n" #~ "\n" #~ "A(z) %s nem létezik" #~ msgid "Repository" #~ msgstr "Repó" #~ msgid "Commit@@noun" #~ msgstr "Commit@@főnév" #~ msgid "Browse %s's Files" #~ msgstr "A(z) %s branch fájljainak böngészése" #~ msgid "Visualize %s's History" #~ msgstr "A(z) %s branch történetének vizualizálása" #~ msgid "Database Statistics" #~ msgstr "Adatbázis statisztikák" #~ msgid "Compress Database" #~ msgstr "Adatbázis tömörítése" #~ msgid "Verify Database" #~ msgstr "Adatbázis ellenőrzése" #~ msgid "Create Desktop Icon" #~ msgstr "Asztal ikon létrehozása" #~ msgid "Undo" #~ msgstr "Visszavonás" #~ msgid "Redo" #~ msgstr "Mégis" #~ msgid "Cut" #~ msgstr "Kivágás" #~ msgid "Paste" #~ msgstr "Beillesztés" #~ msgid "Rename..." #~ msgstr "Átnevezés..." #~ msgid "New Commit" #~ msgstr "Új commit" #~ msgid "Local Merge..." #~ msgstr "Helyi merge..." #~ msgid "Preferences..." #~ msgstr "Beállítások..." #~ msgid "Current Branch:" #~ msgstr "Jelenlegi branch:" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "Kiválasztott változtatások (commitolva lesz)" #~ msgid "Initial Commit Message:" #~ msgstr "Kezdeti commit üzenet:" #~ msgid "Amended Commit Message:" #~ msgstr "Javító commit üzenet:" #~ msgid "Amended Initial Commit Message:" #~ msgstr "Kezdeti javító commit üzenet:" #~ msgid "Amended Merge Commit Message:" #~ msgstr "Javító merge commit üzenet:" #~ msgid "Apply/Reverse Hunk" #~ msgstr "Hunk alkalmazása/visszaállítása" #~ msgid "Show Less Context" #~ msgstr "Kevesebb környezet mutatása" #~ msgid "Show More Context" #~ msgstr "Több környezet mutatása" #~ msgid "Decrease Font Size" #~ msgstr "Font méret csökkentése" #~ msgid "Increase Font Size" #~ msgstr "Fönt méret növelése" #~ msgid "Unstage Hunk From Commit" #~ msgstr "Hunk törlése commitból" #~ msgid "Stage Hunk For Commit" #~ msgstr "Hunk kiválasztása commitba" #~ msgid "Initializing..." #~ msgstr "Inicializálás..." #~ msgid "" #~ "Possible environment issues exist.\n" #~ "\n" #~ "The following environment variables are probably\n" #~ "going to be ignored by any Git subprocess run\n" #~ "by %s:\n" #~ "\n" #~ msgstr "" #~ "Lehetséges, hogy környezeti problémák vannak.\n" #~ "\n" #~ "A következő környezeti változók valószínűleg\n" #~ "figyelmen kívül lesznek hagyva a(z) %s által\n" #~ "indított folyamatok által:\n" #~ "\n" #~ msgid "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "Ez a Cygwin által terjesztett Tcl binárisban\n" #~ "lévő ismert hiba miatt van." #~ msgid "" #~ "\n" #~ "\n" #~ "A good replacement for %s\n" #~ "is placing values for the user.name and\n" #~ "user.email settings into your personal\n" #~ "~/.gitconfig file.\n" #~ msgstr "" #~ "\n" #~ "\n" #~ "Egy jó helyettesítés a(z) %s számára\n" #~ "a user.name és user.email beállítások\n" #~ "elhelyezése a személyes\n" #~ "~/.gitconfig fájlba.\n" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - egy grafikus felület a Githez." #~ msgid "File Viewer" #~ msgstr "Fájl néző" #~ msgid "Reading %s..." #~ msgstr "A(z) %s olvasása..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "A másolást/átnevezést követő annotációk betöltése..." #~ msgid "lines annotated" #~ msgstr "sor annotálva" #~ msgid "Loading original location annotations..." #~ msgstr "Az eredeti hely annotációk betöltése..." #~ msgid "Annotation complete." #~ msgstr "Az annotáció kész." #~ msgid "Loading annotation..." #~ msgstr "Az annotáció betöltése..." #~ msgid "Original File:" #~ msgstr "Eredeti fájl:" #~ msgid "Originally By:" #~ msgstr "Eredeti szerző:" #~ msgid "In File:" #~ msgstr "Ebben a fájlban:" #~ msgid "Copied Or Moved Here By:" #~ msgstr "Ide másolta vagy helyezte:" #~ msgid "Detach From Local Branch" #~ msgstr "Helyi branch leválasztása" #~ msgid "Match Tracking Branch Name" #~ msgstr "Egyeztetendő követési branch név" #~ msgid "Tracking branch %s is not a branch in the remote repository." #~ msgstr "A(z) %s követő branch nem branch a távoli repóban." #~ msgid "Please supply a branch name." #~ msgstr "Adjunk megy egy branch nevet." #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "A(z) '%s' nem egy elfogadható branch név." #~ msgid "Delete Local Branch" #~ msgstr "Helyi branch törlése" #~ msgid "Local Branches" #~ msgstr "Helyi branchek" #~ msgid "Delete Only If Merged Into" #~ msgstr "Csak már merge-ölt törlése" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "Mindig (Ne legyen merge teszt.)" #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "A következő branchek nem teljesen lettek merge-ölve ebbe: %s:" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "A törölt branchek visszaállítása bonyolult. \n" #~ "\n" #~ " Biztosan törli a kiválasztott brancheket?" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "Nem sikerült törölni a következő brancheket:\n" #~ "%s" #~ msgid "New Name:" #~ msgstr "Új név:" #~ msgid "Failed to rename '%s'." #~ msgstr "Nem sikerült átnevezni: '%s'." #~ msgid "[Up To Parent]" #~ msgstr "[Fel a szülőhöz]" #~ msgid "Browse Branch Files" #~ msgstr "A branch fájljainak böngészése" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "végzetes: Nem lehet feloldani a következőt: %s" #~ msgid "Branch '%s' does not exist." #~ msgstr "A(z) '%s' branch nem létezik." #~ msgid "" #~ "Branch '%s' already exists.\n" #~ "\n" #~ "It cannot fast-forward to %s.\n" #~ "A merge is required." #~ msgstr "" #~ "A(z) '%s' branch már létezik.\n" #~ "\n" #~ "Nem lehet fast-forwardolni a következőhöz: %s.\n" #~ "Egy merge szükséges." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "A(z) '%s' merge strategy nem támogatott." #~ msgid "Failed to update '%s'." #~ msgstr "Nem sikerült frissíteni a következőt: '%s'." #~ msgid "Staging area (index) is already locked." #~ msgstr "A kiválasztási terület (index) már zárolva van." #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before the current branch can be changed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Az utolsó keresési állapot nem egyezik meg a repó állpotával.\n" #~ "\n" #~ "Egy másik Git program módosította ezt a repót az utolsó keresés óta. Egy " #~ "újrakeresés mindenképpen szükséges mielőtt a jelenlegi branchet " #~ "módosítani lehetne.\n" #~ "\n" #~ "Az újrakeresés most automatikusan el fog indulni.\n" #~ msgid "Updating working directory to '%s'..." #~ msgstr "A munkkönyvtár frissiítése a következőre: '%s'..." #~ msgid "files checked out" #~ msgstr "fájl frissítve" #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "A(z) '%s' checkoutja megszakítva (fájlszintű merge-ölés szükséges)." #~ msgid "File level merge required." #~ msgstr "Fájlszintű merge-ölés szükséges." #~ msgid "Staying on branch '%s'." #~ msgstr "Jelenleg a(z) '%s' branchen." #~ msgid "" #~ "You are no longer on a local branch.\n" #~ "\n" #~ "If you wanted to be on a branch, create one now starting from 'This " #~ "Detached Checkout'." #~ msgstr "" #~ "Már nem egy helyi branchen vagyunk.\n" #~ "\n" #~ "Ha egy branchen szeretnénk lenni, hozzunk létre egyet az 'Ez a " #~ "leválasztott checkout'-ból." #~ msgid "Checked out '%s'." #~ msgstr "'%s' kifejtve." #~ msgid "Reset '%s'?" #~ msgstr "Visszaállítjuk a következőt: '%s'?" #~ msgid "" #~ "Failed to set current branch.\n" #~ "\n" #~ "This working directory is only partially switched. We successfully " #~ "updated your files, but failed to update an internal Git file.\n" #~ "\n" #~ "This should not have occurred. %s will now close and give up." #~ msgstr "" #~ "Nem sikerült beállítani a jelenlegi branchet.\n" #~ "\n" #~ "A munkakönyvtár csak részben váltott át. A fájlok sikeresen frissítve " #~ "lettek, de nem sikerült frissíteni egy belső Git fájlt.\n" #~ "\n" #~ "Ennek nem szabad megtörténnie. A(z) %s most kilép és feladja." #~ msgid "Font Family" #~ msgstr "Font család" #~ msgid "Font Example" #~ msgstr "Font példa" #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "Ez egy példa szöveg.\n" #~ "Ha ez megfelel, ez lehet a betűtípus." #~ msgid "Git Gui" #~ msgstr "Git Gui" #~ msgid "Clone Existing Repository" #~ msgstr "Létező repó másolása" #~ msgid "Recent Repositories" #~ msgstr "Legutóbbi repók" #~ msgid "Failed to create repository %s:" #~ msgstr "Nem sikerült letrehozni a(z) %s repót:" #~ msgid "Directory:" #~ msgstr "Könyvtár:" #~ msgid "Directory %s already exists." #~ msgstr "A(z) '%s' könyvtár már létezik." #~ msgid "Clone" #~ msgstr "Bezárás" #~ msgid "Clone Type:" #~ msgstr "Másolás típusa:" #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "Általános (Gyors, félig-redundáns, hardlinkek)" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "Teljes másolás (Lassabb, redundáns biztonsági mentés)" #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "Megosztott (Leggyorsabb, nem ajánlott, nincs mentés)" #~ msgid "Standard only available for local repository." #~ msgstr "A standard csak helyi repókra érhető el." #~ msgid "Shared only available for local repository." #~ msgstr "A megosztott csak helyi repókra érhető el." #~ msgid "Location %s already exists." #~ msgstr "A(z) '%s' hely már létezik." #~ msgid "Failed to configure origin" #~ msgstr "Nem sikerült beállítani az origint" #~ msgid "Counting objects" #~ msgstr "Objektumok számolása" #~ msgid "buckets" #~ msgstr "vödrök" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "Nem sikerült másolni az objects/info/alternates-t: %s" #~ msgid "The 'master' branch has not been initialized." #~ msgstr "A 'master' branch nincs inicializálva." #~ msgid "Hardlinks are unavailable. Falling back to copying." #~ msgstr "Nem érhetőek el hardlinkek. Másolás használata." #~ msgid "Cloning from %s" #~ msgstr "Másolás innen: %s" #~ msgid "Copying objects" #~ msgstr "Objektumok másolása" #~ msgid "KiB" #~ msgstr "KiB" #~ msgid "Unable to copy object: %s" #~ msgstr "Nem sikerült másolni az objektumot: %s" #~ msgid "Linking objects" #~ msgstr "Objektumok összefűzése" #~ msgid "objects" #~ msgstr "objektum" #~ msgid "Unable to hardlink object: %s" #~ msgstr "Nem sikerült hardlinkelni az objektumot: %s" #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "" #~ "Nem sikerült letölteni a branch-eket és az objektumokat. Bővebben a " #~ "konzolos kimenetben." #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "Nem sikerült letölteni a tageket. Bővebben a konzolos kimenetben." #~ msgid "Cannot determine HEAD. See console output for details." #~ msgstr "" #~ "Nem sikerült megállapítani a HEAD-et. Bővebben a konzolos kimenetben." #~ msgid "Unable to cleanup %s" #~ msgstr "Nem sikerült tiszítani: %s." #~ msgid "Clone failed." #~ msgstr "A másolás nem sikerült." #~ msgid "No default branch obtained." #~ msgstr "Nincs alapértelmezett branch." #~ msgid "Cannot resolve %s as a commit." #~ msgstr "Nem sikerült felöldani a(z) %s objektumot commitként." #~ msgid "Creating working directory" #~ msgstr "Munkakönyvtár létrehozása" #~ msgid "files" #~ msgstr "fájl" #~ msgid "Initial file checkout failed." #~ msgstr "A kezdeti fájl-kibontás sikertelen." #~ msgid "Failed to open repository %s:" #~ msgstr "Nem sikerült megnyitni a(z) %s repót:" #~ msgid "This Detached Checkout" #~ msgstr "Ez a leválasztott checkout" #~ msgid "Updated" #~ msgstr "Frissítve" #~ msgid "" #~ "There is nothing to amend.\n" #~ "\n" #~ "You are about to create the initial commit. There is no commit before " #~ "this to amend.\n" #~ msgstr "" #~ "Nincs semmi javítanivaló.\n" #~ "\n" #~ "Az első commit létrehozása előtt nincs semmilyen commit amit javitani " #~ "lehetne.\n" #~ msgid "" #~ "Cannot amend while merging.\n" #~ "\n" #~ "You are currently in the middle of a merge that has not been fully " #~ "completed. You cannot amend the prior commit unless you first abort the " #~ "current merge activity.\n" #~ msgstr "" #~ "Nem lehet javítani merge alatt.\n" #~ "\n" #~ "A jelenlegi merge még nem teljesen fejeződött be. Csak akkor javíthat egy " #~ "előbbi commitot, hogyha megszakítja a jelenlegi merge folyamatot.\n" #~ msgid "Error loading commit data for amend:" #~ msgstr "Hiba a javítandó commit adat betöltése közben:" #~ msgid "Unable to obtain your identity:" #~ msgstr "Nem sikerült megállapítani az azonosítót:" #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "Érvénytelen GIT_COMMITTER_IDENT:" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before another commit can be created.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Az utolsó keresési állapot nem egyezik meg a repó állapotával.\n" #~ "\n" #~ "Egy másik Git program módosította ezt a repót az utolsó keresés óta. Egy " #~ "újrakeresés mindenképpen szükséges mielőtt a jelenlegi branchet " #~ "módosítani lehetne.\n" #~ "\n" #~ "Az újrakeresés most automatikusan el fog indulni.\n" #~ msgid "" #~ "Unmerged files cannot be committed.\n" #~ "\n" #~ "File %s has merge conflicts. You must resolve them and stage the file " #~ "before committing.\n" #~ msgstr "" #~ "Nem commitolhatunk fájlokat merge előtt.\n" #~ "\n" #~ "A(z) %s fájlban ütközések vannak. Egyszer azokat ki kell javítani, majd " #~ "hozzá ki kell választani a fájlt mielőtt commitolni lehetne.\n" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "Ismeretlen fájl típus %s érzékelve.\n" #~ "\n" #~ "A(z) %s fájlt nem tudja ez a program commitolni.\n" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "figyelmeztetés: a Tcl nem támogatja a(z) '%s' kódolást." #~ msgid "Calling pre-commit hook..." #~ msgstr "A pre-commit hurok meghívása..." #~ msgid "Commit declined by pre-commit hook." #~ msgstr "A commitot megakadályozta a pre-commit hurok. " #~ msgid "Calling commit-msg hook..." #~ msgstr "A commit-msg hurok meghívása..." #~ msgid "Commit declined by commit-msg hook." #~ msgstr "A commiot megakadályozta a commit-msg hurok." #~ msgid "write-tree failed:" #~ msgstr "a write-tree sikertelen:" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "A(z) %s commit sérültnek tűnik" #~ msgid "" #~ "No changes to commit.\n" #~ "\n" #~ "No files were modified by this commit and it was not a merge commit.\n" #~ "\n" #~ "A rescan will be automatically started now.\n" #~ msgstr "" #~ "Nincs commitolandó változtatás.\n" #~ "\n" #~ "Egyetlen fájlt se módosított ez a commit és merge commit se volt.\n" #~ "\n" #~ "Az újrakeresés most automatikusan el fog indulni.\n" #~ msgid "commit-tree failed:" #~ msgstr "a commit-tree sikertelen:" #~ msgid "update-ref failed:" #~ msgstr "az update-ref sikertelen:" #~ msgid "Working... please wait..." #~ msgstr "Munka folyamatban.. Várjunk..." #~ msgid "Error: Command Failed" #~ msgstr "Hiba: a parancs sikertelen" #~ msgid "Number of loose objects" #~ msgstr "Elvesztett objektumok száma" #~ msgid "Disk space used by loose objects" #~ msgstr "Elveszett objektumok által elfoglalt lemezterület" #~ msgid "Number of packed objects" #~ msgstr "Csomagolt objektumok számra" #~ msgid "Number of packs" #~ msgstr "Csomagok száma" #~ msgid "Disk space used by packed objects" #~ msgstr "A csomagolt objektumok által használt lemezterület" #~ msgid "Packed objects waiting for pruning" #~ msgstr "Eltávolításra váró csomagolt objektumok számra" #~ msgid "Garbage files" #~ msgstr "Hulladék fájlok" #~ msgid "Compressing the object database" #~ msgstr "Az objektum adatbázis tömörítése" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "Az objektum adatbázis ellenőrzése az fsck-objects használatával" #~ msgid "" #~ "This repository currently has approximately %i loose objects.\n" #~ "\n" #~ "To maintain optimal performance it is strongly recommended that you " #~ "compress the database when more than %i loose objects exist.\n" #~ "\n" #~ "Compress the database now?" #~ msgstr "" #~ "Ennek a repónak jelenleg %i különálló objektuma van.\n" #~ "\n" #~ "Az optimális teljesítményhez erősen ajánlott az adatbázis tömörítése, ha " #~ "több mint %i objektum létezik.\n" #~ "\n" #~ "Lehet most tömöríteni az adatbázist?" #~ msgid "Invalid date from Git: %s" #~ msgstr "Érvénytelen dátum a Git-től: %s" #~ msgid "" #~ "No differences detected.\n" #~ "\n" #~ "%s has no changes.\n" #~ "\n" #~ "The modification date of this file was updated by another application, " #~ "but the content within the file was not changed.\n" #~ "\n" #~ "A rescan will be automatically started to find other files which may have " #~ "the same state." #~ msgstr "" #~ "Nincsenek változások.\n" #~ "\n" #~ "A(z) %s módosítatlan.\n" #~ "\n" #~ "A fájl módosítási dátumát frissítette egy másik alkalmazás, de a fájl " #~ "tartalma változatlan.\n" #~ "\n" #~ "Egy újrakeresés fog indulni a hasonló állapotú fájlok megtalálása " #~ "érdekében." #~ msgid "Unable to display %s" #~ msgstr "Nem lehet megjeleníteni a következőt: %s" #~ msgid "Git Repository (subproject)" #~ msgstr "Git repó (alprojekt)" #~ msgid "* Binary file (not showing content)." #~ msgstr "* Bináris fájl (tartalom elrejtése)." #~ msgid "Failed to unstage selected hunk." #~ msgstr "Nem visszavonni a hunk kiválasztását." #~ msgid "Failed to stage selected hunk." #~ msgstr "Nem sikerült kiválasztani a hunkot." #~ msgid "warning" #~ msgstr "figyelmeztetés" #~ msgid "You must correct the above errors before committing." #~ msgstr "Ki kell javítanunk a fenti hibákat commit előtt." #~ msgid "Unable to unlock the index." #~ msgstr "Nem sikerült az index zárolásának feloldása." #~ msgid "" #~ "Updating the Git index failed. A rescan will be automatically started to " #~ "resynchronize git-gui." #~ msgstr "" #~ "A Git index frissítése sikertelen volt. Egy újraolvasás automatikusan " #~ "elindult, hogy a git-gui újra szinkonban legyen." #~ msgid "Unlock Index" #~ msgstr "Index zárolásának feloldása" #~ msgid "Ready to commit." #~ msgstr "Commitolásra kész." #~ msgid "Revert changes in these %i files?" #~ msgstr "Visszaállítja a változtatásokat ebben e %i fájlban?" #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "" #~ "Minden nem kiválasztott változtatás el fog veszni ezáltal a visszaállítás " #~ "által." #~ msgid "Do Nothing" #~ msgstr "Ne csináljunk semmit" #~ msgid "" #~ "Cannot merge while amending.\n" #~ "\n" #~ "You must finish amending this commit before starting any type of merge.\n" #~ msgstr "" #~ "Javítás közben nem lehetséges a merge.\n" #~ "\n" #~ "Egyszer be kell fejezni ennek a commitnak a javítását, majd kezdődhet egy " #~ "merge.\n" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before a merge can be performed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Az utolsó keresési állapot nem egyezik meg a repó állapotával.\n" #~ "\n" #~ "Egy másik Git program módosította ezt a repót az utolsó keresés óta. Egy " #~ "újrakeresés mindenképpen szükséges mielőtt a jelenlegi branchet " #~ "módosítani lehetne.\n" #~ "\n" #~ "Az újrakeresés most automatikusan el fog indulni.\n" #~ msgid "" #~ "You are in the middle of a conflicted merge.\n" #~ "\n" #~ "File %s has merge conflicts.\n" #~ "\n" #~ "You must resolve them, stage the file, and commit to complete the current " #~ "merge. Only then can you begin another merge.\n" #~ msgstr "" #~ "Jelenleg egy ütközés feloldása közben vagyunk.\n" #~ "\n" #~ "A(z) %s fájlban ütközések vannak.\n" #~ "\n" #~ "Fel kell oldanunk őket, kiválasztani a fájlt, és commitolni hogy " #~ "befejezzük a jelenlegi merge-t. Csak ezután kezdhetünk el egy újabbat.\n" #~ msgid "" #~ "You are in the middle of a change.\n" #~ "\n" #~ "File %s is modified.\n" #~ "\n" #~ "You should complete the current commit before starting a merge. Doing so " #~ "will help you abort a failed merge, should the need arise.\n" #~ msgstr "" #~ "Jelenleg egy változtatás közben vagyunk.\n" #~ "\n" #~ "A(z) %s fájl megváltozott.\n" #~ "\n" #~ "Először be kell fejeznünk a jelenlegi commitot, hogy elkezdhessünk egy " #~ "merge-t. Ez segíteni fog, hogy félbeszakíthassunk egy merge-t.\n" #~ msgid "%s of %s" #~ msgstr "%s / %s" #~ msgid "Merging %s and %s..." #~ msgstr "A(z) %s és a(z) %s merge-ölése..." #~ msgid "Merge completed successfully." #~ msgstr "A merge sikeresen befejeződött." #~ msgid "Merge failed. Conflict resolution is required." #~ msgstr "A merge sikertelen. Fel kell oldanunk az ütközéseket." #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\n" #~ msgstr "" #~ "A commit javítás közben megszakítva.\n" #~ "\n" #~ "Be kell fejeznünk ennek a commitnak a javítását.\n" #~ msgid "" #~ "Reset changes?\n" #~ "\n" #~ "Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" #~ "\n" #~ "Continue with resetting the current changes?" #~ msgstr "" #~ "Visszavonjuk a módosításokat?\n" #~ "\n" #~ "A módosítások visszavonása *MINDEN* nem commitolt változtatás elvesztését " #~ "jelenti.\n" #~ "\n" #~ "Folytatjuk a jelenlegi módosítások visszavonását?" #~ msgid "files reset" #~ msgstr "fájl visszaállítva" #~ msgid "Abort failed." #~ msgstr "A félbeszakítás nem sikerült." #~ msgid "Abort completed. Ready." #~ msgstr "A megkeszakítás befejeződött. Kész." #~ msgid "Restore Defaults" #~ msgstr "Alapértelmezés visszaállítása" #~ msgid "%s Repository" #~ msgstr "%s Repó" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "A követő branchek eltávolítása letöltés alatt" #~ msgid "Match Tracking Branches" #~ msgstr "A követő branchek egyeztetése" #~ msgid "New Branch Name Template" #~ msgstr "Új branch név sablon" #~ msgid "Spelling Dictionary:" #~ msgstr "Helyesírás-ellenőrző szótár:" #~ msgid "Change Font" #~ msgstr "Betűtípus megváltoztatása" #~ msgid "pt." #~ msgstr "pt." #~ msgid "Failed to completely save options:" #~ msgstr "Nem sikerült teljesen elmenteni a beállításokat:" #~ msgid "From Repository" #~ msgstr "Forrás repó" #~ msgid "Remote:" #~ msgstr "Távoli:" #~ msgid "Arbitrary URL:" #~ msgstr "Tetszőleges URL:" #~ msgid "Delete Only If" #~ msgstr "Törlés csak akkor ha" #~ msgid "Merged Into:" #~ msgstr "Merge-ölt a következőbe:" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "Mindig (Ne végezzen merge vizsgálatokat)" #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "Egy branch szükséges a 'Merge-ölt a következőbe'-hez." #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "A következő branchek nem teljesen lettek merge-ölve ebbe: %s:\n" #~ " - %s" #~ msgid "" #~ "One or more of the merge tests failed because you have not fetched the " #~ "necessary commits. Try fetching from %s first." #~ msgstr "" #~ "Egy vagy több merge teszt hibát jelzett, mivel nem töltöttük le a " #~ "megfelelő commitokat. Próbáljunk meg letölteni a következőből: %s először." #~ msgid "Please select one or more branches to delete." #~ msgstr "Válasszunk ki egy vagy több branchet törlésre." #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "A törölt branchek visszaállítása nehéz.\n" #~ "\n" #~ "Töröljük a kiválasztott brancheket?" #~ msgid "Prune from" #~ msgstr "Törlés innen" # tcl-format #~ msgid "Fetch from" #~ msgstr "Letöltés innen" #~ msgid "Push to" #~ msgstr "Push ide" #~ msgid "Cannot write shortcut:" #~ msgstr "Nem sikerült írni a gyorsbillentyűt:" #~ msgid "Unsupported spell checker" #~ msgstr "Nem támogatott helyesírás-ellenőrző" #~ msgid "Spell checking is unavailable" #~ msgstr "A helyesírás-ellenőrzés nem elérhető" #~ msgid "Invalid spell checking configuration" #~ msgstr "Érvénytelen a helyesírás-ellenőrző beállítása" #~ msgid "Reverting dictionary to %s." #~ msgstr "Szótár visszaállítása a következőre: %s." #~ msgid "Spell checker silently failed on startup" #~ msgstr "A helyesírás-ellenőrő indítása sikertelen" #~ msgid "Unrecognized spell checker" #~ msgstr "Ismeretlen helyesírás-ellenőrző" #~ msgid "Unexpected EOF from spell checker" #~ msgstr "Nem várt EOF a helyesírás-ellenőrzőtől" #~ msgid "Spell Checker Failed" #~ msgstr "A helyesírás-ellenőrzés sikertelen" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%s ... %*i / %*i %s (%3i%%)" #~ msgid "Fetching new changes from %s" #~ msgstr "Új változások letöltése innen: %s" #~ msgid "remote prune %s" #~ msgstr "a(z) %s távoli törlése" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "A %s repóból törölt követő branchek törlése" #~ msgid "push %s" #~ msgstr "%s push-olása" #~ msgid "Pushing %s %s to %s" #~ msgstr "Pusholás: %s %s, ide: %s" #~ msgid "Push Branches" #~ msgstr "Branchek pusholása" #~ msgid "Source Branches" #~ msgstr "Forrás branchek" #~ msgid "Destination Repository" #~ msgstr "Cél repó" #~ msgid "Transfer Options" #~ msgstr "Átviteli opciók" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "" #~ "Létező branch felülírásának erőltetése (lehet, hogy el fog dobni " #~ "változtatásokat)" #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Vékony csomagok használata (lassú hálózati kapcsolatok számára)" #~ msgid "Not connected to aspell" #~ msgstr "Nincs kapcsolat az aspellhez" #~ msgid "Cannot find the git directory:" #~ msgstr "Nem található a git könyvtár:" #~ msgid "Unstaged Changes (Will Not Be Committed)" #~ msgstr "Nem kiválasztott változtatások (nem lesz commitolva)" #~ msgid "Add To Commit" #~ msgstr "Hozzáadás a commithoz" #~ msgid "Add Existing To Commit" #~ msgstr "Hozzáadás létező commithoz" #~ msgid "Running miga..." #~ msgstr "A miga futtatása..." #~ msgid "Add Existing" #~ msgstr "Létező hozzáadása" #~ msgid "" #~ "Abort commit?\n" #~ "\n" #~ "Aborting the current commit will cause *ALL* uncommitted changes to be " #~ "lost.\n" #~ "\n" #~ "Continue with aborting the current commit?" #~ msgstr "" #~ "Megszakítjuk a commitot?\n" #~ "\n" #~ "A jelenlegi commit megszakítása *MINDEN* nem commitolt változtatás " #~ "elvesztését jelenti.\n" #~ "\n" #~ "Folytatjuk a jelenlegi commit megszakítását?" #~ msgid "Aborting... please wait..." #~ msgstr "Megszakítás... várjunk..." git-cola-1.9.3/po/it.po000066400000000000000000002162511225156173500146330ustar00rootroot00000000000000# Translation of git-gui to Italian # Copyright (C) 2007 Shawn Pearce # This file is distributed under the same license as the git-gui package. # Paolo Ciarrocchi , 2007 # Michele Ballabio , 2007. # # msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-09-24 21:42-0700\n" "PO-Revision-Date: 2008-03-12 22:12+0100\n" "Last-Translator: Michele Ballabio \n" "Language-Team: Italian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: cola/bookmarks.py:32 msgid "Bookmarks" msgstr "" #: cola/bookmarks.py:47 msgid "Open" msgstr "Apri" #: cola/bookmarks.py:53 msgid "Add" msgstr "" #: cola/bookmarks.py:58 cola/guicmds.py:25 cola/guicmds.py:33 #: cola/widgets/editremotes.py:127 msgid "Delete" msgstr "Elimina" #: cola/bookmarks.py:65 cola/stash/view.py:42 cola/widgets/archive.py:65 #: cola/widgets/browse.py:117 msgid "Save" msgstr "Salva" #: cola/bookmarks.py:71 cola/difftool.py:96 cola/qt.py:57 cola/qt.py:243 #: cola/prefs/view.py:241 cola/stash/view.py:50 cola/stash/view.py:51 #: cola/widgets/about.py:66 cola/widgets/about.py:126 #: cola/widgets/browse.py:116 cola/widgets/cfgactions.py:87 #: cola/widgets/cfgactions.py:239 cola/widgets/compare.py:94 #: cola/widgets/createbranch.py:159 cola/widgets/createtag.py:104 #: cola/widgets/editremotes.py:55 cola/widgets/grep.py:75 #: cola/widgets/recent.py:75 cola/widgets/remote.py:157 #: cola/widgets/search.py:81 cola/widgets/selectcommits.py:59 #: cola/widgets/startup.py:42 msgid "Close" msgstr "Chiudi" #: cola/bookmarks.py:102 msgid "Bookmarks Saved" msgstr "" #: cola/bookmarks.py:103 msgid "Successfully saved bookmarks" msgstr "" #: cola/bookmarks.py:107 #, fuzzy msgid "Path to git repository" msgstr "%s non è un archivio Git." #: cola/bookmarks.py:108 #, fuzzy msgid "Enter Git Repository" msgstr "Archivio Git" #: cola/cmds.py:105 msgid "Amend" msgstr "" #: cola/cmds.py:140 #, fuzzy msgid "Cannot Amend" msgstr "Impossibile scrivere icona:" #: cola/cmds.py:141 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" #: cola/cmds.py:204 #, python-format msgid "PATCH %(current)d/%(count)d" msgstr "" #: cola/cmds.py:208 msgid "Summary:" msgstr "" #: cola/cmds.py:217 msgid "Patch(es) Applied" msgstr "" #: cola/cmds.py:218 #, python-format msgid "%d patch(es) applied." msgstr "" #: cola/cmds.py:322 #, fuzzy, python-format msgid "Created commit: %s" msgstr "Creata revisione %s: %s" #: cola/cmds.py:324 #, fuzzy, python-format msgid "Commit failed: %s" msgstr "Impossibile creare una nuova revisione." #: cola/cmds.py:369 cola/cmds.py:1186 #, fuzzy msgid "Error" msgstr "errore" #: cola/cmds.py:370 #, python-format msgid "Deleting \"%s\" failed" msgstr "" #: cola/cmds.py:406 #, fuzzy msgid "Remote Branch Deleted" msgstr "Rinomina ramo" #: cola/cmds.py:407 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "" #: cola/cmds.py:411 cola/guicmds.py:108 cola/widgets/remote.py:472 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "" #: cola/cmds.py:414 #, fuzzy msgid "Error Deleting Remote Branch" msgstr "Crea ramo" #: cola/cmds.py:493 cola/widgets/grep.py:60 cola/widgets/recent.py:69 msgid "Edit" msgstr "Modifica" #: cola/cmds.py:529 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/cmds.py:531 #, fuzzy msgid "Error Editing File" msgstr "Errore nel caricamento delle differenze:" #: cola/cmds.py:554 msgid "Launch Diff Tool" msgstr "" #: cola/cmds.py:577 msgid "Launch Editor" msgstr "" #: cola/cmds.py:598 msgid "Error: Cannot find commit template" msgstr "" #: cola/cmds.py:599 #, fuzzy, python-format msgid "%s: No such file or directory." msgstr "" "errore grave: impossibile effettuare lo stat del path %s: file o directory " "non trovata" #: cola/cmds.py:616 msgid "Error: Unconfigured commit template" msgstr "" #: cola/cmds.py:617 msgid "" "A commit template has not been configured.\n" "Use \"git config\" to define \"commit.template\"\n" "so that it points to a commit template." msgstr "" #: cola/cmds.py:669 msgid "Open Using Default Application" msgstr "" #: cola/cmds.py:692 #, fuzzy msgid "Open Parent Directory" msgstr "Apri archivio recente:" #: cola/cmds.py:732 #, python-format msgid "Error: could not clone \"%s\"" msgstr "" #: cola/cmds.py:733 #, python-format msgid "git clone returned exit code %s" msgstr "" #: cola/cmds.py:756 cola/widgets/action.py:19 cola/widgets/editremotes.py:49 #: cola/widgets/grep.py:65 cola/widgets/recent.py:52 #: cola/widgets/recent.py:121 msgid "Refresh" msgstr "Rinfresca" #: cola/cmds.py:784 #, python-format msgid "Run \"%s\"?" msgstr "" #: cola/cmds.py:791 #, fuzzy msgid "Please select a file" msgstr "Scegliere un duplicato locale di ramo remoto" #: cola/cmds.py:792 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:804 #, fuzzy msgid "Invalid Revision" msgstr "Revisione non valida: %s" #: cola/cmds.py:805 #, fuzzy msgid "The revision expression cannot be empty." msgstr "L'espressione di revisione è vuota." #: cola/cmds.py:820 #, python-format msgid "Running command: %s" msgstr "" #: cola/cmds.py:829 cola/cmds.py:1006 cola/interaction.py:70 #, python-format msgid "Output: %s" msgstr "" #: cola/cmds.py:830 cola/guicmds.py:113 cola/interaction.py:71 #, python-format msgid "Errors: %s" msgstr "" #: cola/cmds.py:876 msgid "Sign Off" msgstr "Sign Off" #: cola/cmds.py:897 msgid "unknown" msgstr "" #: cola/cmds.py:910 cola/widgets/action.py:17 #, fuzzy msgid "Stage" msgstr "Salva" #: cola/cmds.py:917 #, fuzzy, python-format msgid "Staging: %s" msgstr "Analisi in corso %s..." #: cola/cmds.py:934 msgid "Stage Modified" msgstr "" #: cola/cmds.py:948 #, fuzzy msgid "Stage Unmerged" msgstr "Prepara modificati" #: cola/cmds.py:962 #, fuzzy msgid "Stage Untracked" msgstr "Prepara modificati" #: cola/cmds.py:980 #, python-format msgid "Tagging \"%(revision)s\" as \"%(name)s\"" msgstr "" #: cola/cmds.py:988 msgid "GPG-signed" msgstr "" #: cola/cmds.py:1020 cola/widgets/action.py:18 #, fuzzy msgid "Unstage" msgstr "Modifiche non preparate" #: cola/cmds.py:1027 #, fuzzy, python-format msgid "Unstaging: %s" msgstr "%s non farà parte della prossima revisione" #: cola/cmds.py:1055 #, python-format msgid "Untracking: %s" msgstr "" #: cola/cmds.py:1137 #, fuzzy msgid "Error Launching History Browser" msgstr "File browser" #: cola/cmds.py:1138 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/difftool.py:76 msgid "git-cola diff" msgstr "" #: cola/difftool.py:92 cola/widgets/compare.py:90 msgid "Compare" msgstr "" #: cola/gitcmds.py:402 #, fuzzy msgid "Nothing to do" msgstr "Niente da clonare da %s." #: cola/guicmds.py:25 msgid "Delete Branch" msgstr "Elimina ramo" #: cola/guicmds.py:33 #, fuzzy msgid "Delete Remote Branch" msgstr "Cancella ramo remoto" #: cola/guicmds.py:53 #, fuzzy msgid "Browse Commits..." msgstr "Esplora" #: cola/guicmds.py:53 #, fuzzy msgid "Browse" msgstr "Esplora" #: cola/guicmds.py:61 msgid "Checkout Branch" msgstr "Attiva ramo" #: cola/guicmds.py:61 msgid "Checkout" msgstr "Attiva" #: cola/guicmds.py:70 #, fuzzy msgid "Cherry-Pick Commit" msgstr "Copia revisione" #: cola/guicmds.py:107 #, fuzzy msgid "Error Creating Repository" msgstr "Crea nuovo archivio" #: cola/guicmds.py:110 #, python-format msgid "" "Output:\n" "%s" msgstr "" #: cola/guicmds.py:132 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/guicmds.py:153 #, fuzzy msgid "Error Cloning" msgstr "Errore nel caricamento del file:" #: cola/guicmds.py:154 cola/guicmds.py:155 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/guicmds.py:159 msgid "Select a parent directory for the new clone" msgstr "" #: cola/guicmds.py:169 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/guicmds.py:185 cola/widgets/search.py:75 msgid "Export Patches" msgstr "" #: cola/guicmds.py:214 cola/widgets/startup.py:124 #, fuzzy msgid "Open Git Repository..." msgstr "Apri archivio esistente" #: cola/guicmds.py:223 #, fuzzy msgid "Load Commit Message" msgstr "Messaggio di revisione:" #: cola/guicmds.py:251 #, fuzzy msgid "Select New Base" msgstr "Seleziona" #: cola/guicmds.py:251 #, fuzzy msgid "Rebase" msgstr "Ripristina" #: cola/guicmds.py:261 #, fuzzy msgid "Select Branch to Review" msgstr "Elimina ramo" #: cola/guicmds.py:261 msgid "Review" msgstr "" #: cola/inotify.py:47 msgid "inotify is disabled because \"cola.inotify\" is false" msgstr "" #: cola/inotify.py:53 msgid "" "file notification: disabled\n" "Note: install pywin32 to enable.\n" msgstr "" #: cola/inotify.py:56 msgid "" "inotify: disabled\n" "Note: install python-pyinotify to enable inotify.\n" msgstr "" #: cola/inotify.py:62 msgid "On Debian systems try: sudo aptitude install python-pyinotify" msgstr "" #: cola/inotify.py:71 #, fuzzy msgid "File notification enabled." msgstr "Fidati delle date di modifica dei file" #: cola/inotify.py:73 msgid "inotify enabled." msgstr "" #: cola/interaction.py:53 msgid "Continue" msgstr "Continua" #: cola/interaction.py:63 #, python-format msgid "Run %s?" msgstr "" #: cola/interaction.py:64 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/interaction.py:65 cola/widgets/cfgactions.py:240 msgid "Run" msgstr "" #: cola/interaction.py:72 #, python-format msgid "Exit code: %s" msgstr "" #: cola/qt.py:60 cola/qt.py:100 #, fuzzy msgid "Detach" msgstr "Elimina ramo" #: cola/qt.py:98 msgid "Attach" msgstr "" #: cola/qtutils.py:396 #, fuzzy msgid "Close..." msgstr "Clona..." #: cola/classic/controller.py:69 msgid "Select Previous Version" msgstr "" #: cola/classic/model.py:37 cola/widgets/createtag.py:51 #: cola/widgets/editremotes.py:220 #, fuzzy msgid "Name" msgstr "Nome:" #: cola/classic/model.py:39 cola/main/view.py:91 msgid "Status" msgstr "" #: cola/classic/model.py:41 msgid "Age" msgstr "" #: cola/classic/model.py:43 cola/widgets/createtag.py:74 #, fuzzy msgid "Message" msgstr "Fusione (Merge)" #: cola/classic/model.py:45 cola/dag/view.py:371 #, fuzzy msgid "Author" msgstr "Autore:" #: cola/classic/model.py:342 #, python-format msgid "%d minutes ago" msgstr "" #: cola/classic/model.py:345 #, python-format msgid "%d hours ago" msgstr "" #: cola/classic/model.py:346 #, python-format msgid "%d days ago" msgstr "" #: cola/classic/model.py:359 cola/widgets/status.py:73 #, fuzzy msgid "Unmerged" msgstr "Fusione (Merge)" #: cola/classic/model.py:361 msgid "Partially Staged" msgstr "" #: cola/classic/model.py:363 cola/widgets/status.py:74 #, fuzzy msgid "Modified" msgstr "Non modificato" #: cola/classic/model.py:365 cola/widgets/status.py:72 #, fuzzy msgid "Staged" msgstr "Prepara modificati" #: cola/classic/model.py:367 msgid "Changed Upstream" msgstr "" #: cola/classic/view.py:47 cola/main/view.py:545 #, fuzzy, python-format msgid "Repository: %s" msgstr "Archivio:" #: cola/classic/view.py:49 cola/main/view.py:547 #, fuzzy, python-format msgid "Branch: %s" msgstr "Ramo:" #: cola/classic/view.py:52 #, python-format msgid "%s: %s - Browse" msgstr "" #: cola/classic/view.py:54 cola/main/view.py:552 msgid "Amending" msgstr "" #: cola/classic/view.py:79 msgid "View History..." msgstr "" #: cola/classic/view.py:80 msgid "View history for selected path(s)." msgstr "" #: cola/classic/view.py:84 cola/widgets/status.py:506 #: cola/widgets/status.py:536 cola/widgets/status.py:593 #, fuzzy msgid "Stage Selected" msgstr "Seleziona" #: cola/classic/view.py:85 #, fuzzy msgid "Stage selected path(s) for commit." msgstr "Preparato per una nuova revisione" #: cola/classic/view.py:90 cola/widgets/status.py:452 #: cola/widgets/status.py:494 msgid "Unstage Selected" msgstr "" #: cola/classic/view.py:91 msgid "Remove selected path(s) from the staging area." msgstr "" #: cola/classic/view.py:96 msgid "Untrack Selected" msgstr "" #: cola/classic/view.py:97 msgid "Stop tracking path(s)" msgstr "" #: cola/classic/view.py:102 msgid "Launch git-difftool on the current path." msgstr "" #: cola/classic/view.py:106 msgid "Diff Against Predecessor..." msgstr "" #: cola/classic/view.py:107 msgid "Launch git-difftool against previous versions." msgstr "" #: cola/classic/view.py:111 #, fuzzy msgid "Revert Uncommitted Changes..." msgstr "Annulla modifiche" #: cola/classic/view.py:112 #, fuzzy msgid "Revert changes to selected path(s)." msgstr "Annullare le modifiche nel file %s?" #: cola/classic/view.py:117 msgid "Edit selected path(s)." msgstr "" #: cola/classic/view.py:293 cola/widgets/status.py:652 #, fuzzy msgid "Revert Uncommitted Changes?" msgstr "Annulla modifiche" #: cola/classic/view.py:294 cola/widgets/diff.py:246 cola/widgets/diff.py:259 #: cola/widgets/status.py:653 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/classic/view.py:296 cola/widgets/diff.py:248 cola/widgets/diff.py:261 #: cola/widgets/status.py:655 msgid "Revert the uncommitted changes?" msgstr "" #: cola/classic/view.py:297 cola/widgets/status.py:656 #, fuzzy msgid "Revert Uncommitted Changes" msgstr "Annulla modifiche" #: cola/dag/view.py:166 #, fuzzy msgid "Loading..." msgstr "Caricamento %s..." #: cola/dag/view.py:272 msgid "Diff this -> selected" msgstr "" #: cola/dag/view.py:275 msgid "Diff selected -> this" msgstr "" #: cola/dag/view.py:278 cola/widgets/createbranch.py:89 #: cola/widgets/createbranch.py:98 cola/widgets/createbranch.py:155 #: cola/widgets/createbranch.py:330 msgid "Create Branch" msgstr "Crea ramo" #: cola/dag/view.py:281 #, fuzzy msgid "Create Patch" msgstr "Crea ramo" #: cola/dag/view.py:284 cola/widgets/createtag.py:38 #: cola/widgets/createtag.py:99 #, fuzzy msgid "Create Tag" msgstr "Crea" #: cola/dag/view.py:287 cola/main/view.py:208 msgid "Save As Tarball/Zip..." msgstr "" #: cola/dag/view.py:290 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/dag/view.py:293 msgid "Grab File..." msgstr "" #: cola/dag/view.py:296 #, fuzzy msgid "Copy SHA-1" msgstr "Copia tutto" #: cola/dag/view.py:371 msgid "Summary" msgstr "" #: cola/dag/view.py:371 msgid "Date, Time" msgstr "" #: cola/dag/view.py:378 msgid "Go Up" msgstr "" #: cola/dag/view.py:381 msgid "Go Down" msgstr "" #: cola/dag/view.py:511 cola/dag/view.py:1181 msgid "Zoom Out" msgstr "" #: cola/dag/view.py:514 cola/dag/view.py:1178 msgid "Zoom In" msgstr "" #: cola/dag/view.py:517 cola/dag/view.py:1184 msgid "Zoom to Fit" msgstr "" #: cola/dag/view.py:536 msgid "Log" msgstr "" #: cola/dag/view.py:541 cola/main/view.py:114 cola/main/view.py:384 msgid "Diff" msgstr "" #: cola/dag/view.py:554 msgid "Graph" msgstr "" #: cola/dag/view.py:563 msgid "View" msgstr "" #: cola/dag/view.py:636 #, python-format msgid "%s: %s - DAG" msgstr "" #: cola/dag/view.py:638 msgid " - DAG" msgstr "" #: cola/dag/view.py:1187 #, fuzzy msgid "Select Parent" msgstr "Seleziona" #: cola/dag/view.py:1190 msgid "Select Oldest Parent" msgstr "" #: cola/dag/view.py:1193 #, fuzzy msgid "Select Child" msgstr "Seleziona tutto" #: cola/dag/view.py:1196 msgid "Select Newest Child" msgstr "" #: cola/main/view.py:78 #, fuzzy msgid "Browser" msgstr "Esplora" #: cola/main/view.py:83 #, fuzzy msgid "Action" msgstr "Opzioni" #: cola/main/view.py:99 cola/merge/view.py:45 #, fuzzy msgid "Commit" msgstr "Revisione:" #: cola/main/view.py:108 #, fuzzy msgid "Console" msgstr "Chiudi" #: cola/main/view.py:120 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/main/view.py:125 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/main/view.py:130 msgid "Ignore all whitespace" msgstr "" #: cola/main/view.py:135 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/main/view.py:139 cola/widgets/createbranch.py:194 msgid "Options" msgstr "Opzioni" #: cola/main/view.py:141 cola/main/view.py:142 #, fuzzy msgid "Diff Options" msgstr "Opzioni" #: cola/main/view.py:157 cola/widgets/status.py:423 msgid "Unstage All" msgstr "" #: cola/main/view.py:161 msgid "Unstage From Commit" msgstr "Annulla preparazione" #: cola/main/view.py:165 msgid "Diffstat" msgstr "" #: cola/main/view.py:168 msgid "Stage Changed Files To Commit" msgstr "Prepara i file modificati per una nuova revisione" #: cola/main/view.py:173 msgid "Stage All Untracked" msgstr "" #: cola/main/view.py:178 msgid "Export Patches..." msgstr "" #: cola/main/view.py:181 #, fuzzy msgid "New Repository..." msgstr "Archivio Git" #: cola/main/view.py:185 cola/prefs/view.py:220 msgid "Preferences" msgstr "Preferenze" #: cola/main/view.py:189 msgid "Edit Remotes..." msgstr "" #: cola/main/view.py:197 #, fuzzy msgid "Recently Modified Files..." msgstr "Ricerca di file modificati in corso..." #: cola/main/view.py:201 #, fuzzy msgid "Cherry-Pick..." msgstr "Attiva..." #: cola/main/view.py:205 #, fuzzy msgid "Load Commit Message..." msgstr "Messaggio di revisione:" #: cola/main/view.py:211 msgid "Quit" msgstr "Esci" #: cola/main/view.py:213 msgid "Bookmarks..." msgstr "" #: cola/main/view.py:215 msgid "Grep" msgstr "" #: cola/main/view.py:217 #, fuzzy msgid "Merge..." msgstr "Fusione (Merge)" #: cola/main/view.py:220 cola/merge/__init__.py:20 msgid "Abort Merge..." msgstr "Interrompi fusione..." #: cola/main/view.py:223 cola/widgets/action.py:20 #, fuzzy msgid "Fetch..." msgstr "Ripristina..." #: cola/main/view.py:225 cola/widgets/action.py:21 msgid "Push..." msgstr "Propaga..." #: cola/main/view.py:227 cola/widgets/action.py:22 #, fuzzy msgid "Pull..." msgstr "Propaga..." #: cola/main/view.py:230 cola/widgets/startup.py:36 msgid "Open..." msgstr "Apri..." #: cola/main/view.py:234 cola/widgets/action.py:23 #, fuzzy msgid "Stash..." msgstr "Propaga..." #: cola/main/view.py:237 cola/widgets/startup.py:39 msgid "Clone..." msgstr "Clona..." #: cola/main/view.py:241 #, fuzzy msgid "Documentation" msgstr "Documentazione sul web" #: cola/main/view.py:245 msgid "Keyboard Shortcuts" msgstr "" #: cola/main/view.py:250 #, fuzzy msgid "Visualize Current Branch..." msgstr "Visualizza la cronologia del ramo attuale" #: cola/main/view.py:253 #, fuzzy msgid "Visualize All Branches..." msgstr "Visualizza la cronologia di tutti i rami" #: cola/main/view.py:256 #, fuzzy msgid "Search..." msgstr "Avvio in corso..." #: cola/main/view.py:258 #, fuzzy msgid "Browse Current Branch..." msgstr "Esplora i file del ramo attuale" #: cola/main/view.py:260 #, fuzzy msgid "Browse Other Branch..." msgstr "Esplora i file del ramo..." #: cola/main/view.py:262 #, fuzzy msgid "Get Commit Message Template" msgstr "Larghezza del messaggio di revisione" #: cola/main/view.py:265 #, fuzzy msgid "About" msgstr "Informazioni su %s" #: cola/main/view.py:268 #, fuzzy msgid "Expression..." msgstr "Opzioni..." #: cola/main/view.py:270 #, fuzzy msgid "Branches..." msgstr "Rami" #: cola/main/view.py:273 #, fuzzy msgid "Create Tag..." msgstr "Crea..." #: cola/main/view.py:276 msgid "Create..." msgstr "Crea..." #: cola/main/view.py:279 msgid "Delete..." msgstr "Elimina..." #: cola/main/view.py:282 #, fuzzy msgid "Delete Remote Branch..." msgstr "Cancella ramo remoto" #: cola/main/view.py:285 msgid "Checkout..." msgstr "Attiva..." #: cola/main/view.py:287 #, fuzzy msgid "Rebase..." msgstr "Ripristina..." #: cola/main/view.py:289 #, fuzzy msgid "Review..." msgstr "Ripristina..." #: cola/main/view.py:292 #, fuzzy msgid "Browser..." msgstr "Esplora" #: cola/main/view.py:296 msgid "DAG..." msgstr "" #: cola/main/view.py:313 #, fuzzy msgid "File" msgstr "File:" #: cola/main/view.py:316 #, fuzzy msgid "Open Recent" msgstr "Apri archivio recente:" #: cola/main/view.py:338 cola/main/view.py:339 #, fuzzy msgid "Index" msgstr "Errore nell'indice" #: cola/main/view.py:349 msgid "Branch" msgstr "Ramo" #: cola/main/view.py:367 #, fuzzy msgid "Actions" msgstr "Opzioni" #: cola/main/view.py:393 msgid "Tools" msgstr "" #: cola/main/view.py:404 msgid "Help" msgstr "Aiuto" #: cola/main/view.py:462 #, python-format msgid "git cola version %s" msgstr "" #: cola/merge/__init__.py:21 #, fuzzy msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Interrompere fusione?\n" "\n" "L'interruzione della fusione attuale causerà la perdita di *TUTTE* le " "modifiche non ancora presenti nell'archivio.\n" "\n" "Continuare con l'interruzione della fusione attuale?" #: cola/merge/__init__.py:24 msgid "Aborting the current merge?" msgstr "" #: cola/merge/__init__.py:25 #, fuzzy msgid "Abort Merge" msgstr "Interrompi fusione..." #: cola/merge/view.py:23 msgid "Revision To Merge" msgstr "Revisione da fondere" #: cola/merge/view.py:28 cola/widgets/cfgactions.py:220 #: cola/widgets/remote.py:122 msgid "Local Branch" msgstr "Ramo locale" #: cola/merge/view.py:31 cola/widgets/cfgactions.py:221 msgid "Tracking Branch" msgstr "Duplicato locale di ramo remoto" #: cola/merge/view.py:33 cola/widgets/cfgactions.py:222 #: cola/widgets/createbranch.py:122 msgid "Tag" msgstr "Etichetta" #: cola/merge/view.py:39 msgid "Visualize" msgstr "Visualizza" #: cola/merge/view.py:42 #, fuzzy msgid "Squash" msgstr "Propaga (Push)" #: cola/merge/view.py:50 cola/widgets/archive.py:62 #: cola/widgets/editremotes.py:204 msgid "Cancel" msgstr "Annulla" #: cola/merge/view.py:53 msgid "Merge" msgstr "Fusione (Merge)" #: cola/merge/view.py:115 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/merge/view.py:118 #, fuzzy, python-format msgid "Merge into \"%s\"" msgstr "Fusione in %s" #: cola/merge/view.py:162 cola/merge/view.py:171 #, fuzzy msgid "No Revision Specified" msgstr "Nessuna revisione selezionata." #: cola/merge/view.py:163 msgid "You must specify a revision to view." msgstr "" #: cola/merge/view.py:172 msgid "You must specify a revision to merge." msgstr "" #: cola/prefs/view.py:116 msgid "User Name" msgstr "Nome utente" #: cola/prefs/view.py:117 msgid "Email Address" msgstr "Indirizzo Email" #: cola/prefs/view.py:118 msgid "Merge Verbosity" msgstr "Prolissità della fusione" #: cola/prefs/view.py:119 msgid "Number of Diff Context Lines" msgstr "Numero di linee di contesto nelle differenze" #: cola/prefs/view.py:120 msgid "Summarize Merge Commits" msgstr "Riepilogo nelle revisioni di fusione" #: cola/prefs/view.py:121 msgid "Show Diffstat After Merge" msgstr "Mostra statistiche delle differenze dopo la fusione" #: cola/prefs/view.py:122 msgid "Display Untracked Files" msgstr "" #: cola/prefs/view.py:163 msgid "Fixed-Width Font" msgstr "" #: cola/prefs/view.py:164 msgid "Font Size" msgstr "Dimensione caratteri" #: cola/prefs/view.py:165 msgid "Tab Width" msgstr "" #: cola/prefs/view.py:166 msgid "Text Width" msgstr "" #: cola/prefs/view.py:167 cola/widgets/commitmsg.py:99 msgid "Auto-Wrap Lines" msgstr "" #: cola/prefs/view.py:168 #, fuzzy msgid "Editor" msgstr "Modifica" #: cola/prefs/view.py:169 #, fuzzy msgid "History Browser" msgstr "File browser" #: cola/prefs/view.py:170 msgid "Diff Tool" msgstr "" #: cola/prefs/view.py:171 #, fuzzy msgid "Merge Tool" msgstr "Fusione (Merge)" #: cola/prefs/view.py:172 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/prefs/view.py:173 msgid "Save GUI Settings" msgstr "" #: cola/prefs/view.py:227 #, fuzzy msgid "All Repositories" msgstr "Tutti gli archivi" #: cola/prefs/view.py:228 #, fuzzy msgid "Current Repository" msgstr "Crea nuovo archivio" #: cola/prefs/view.py:229 #, fuzzy msgid "Settings" msgstr "Avvio in corso..." #: cola/stash/view.py:28 msgid "Stash" msgstr "" #: cola/stash/view.py:38 #, fuzzy msgid "Apply" msgstr "Apple" #: cola/stash/view.py:39 msgid "Apply the selected stash" msgstr "" #: cola/stash/view.py:43 msgid "Save modified state to new stash" msgstr "" #: cola/stash/view.py:46 msgid "Drop" msgstr "" #: cola/stash/view.py:47 msgid "Drop the selected stash" msgstr "" #: cola/stash/view.py:54 msgid "Keep Index" msgstr "" #: cola/stash/view.py:175 msgid "Save Stash" msgstr "" #: cola/stash/view.py:176 msgid "Enter a name for the stash" msgstr "" #: cola/stash/view.py:182 msgid "Error: Stash exists" msgstr "" #: cola/stash/view.py:183 #, fuzzy, python-format msgid "A stash named \"%s\" already exists" msgstr "Il file %s esiste già." #: cola/stash/view.py:198 msgid "Drop Stash?" msgstr "" #: cola/stash/view.py:199 #, fuzzy msgid "Recovering a dropped stash is not possible." msgstr "Ricomporre le revisioni perdute potrebbe non essere semplice." #: cola/stash/view.py:200 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/stash/view.py:201 msgid "Drop Stash" msgstr "" #: cola/widgets/about.py:47 msgid "About git-cola" msgstr "" #: cola/widgets/about.py:97 msgid "" "This PyQt4 does not include QtWebKit.\n" "The keyboard shortcuts feature is unavailable." msgstr "" #: cola/widgets/about.py:104 msgid "hotkeys.html" msgstr "" #: cola/widgets/about.py:122 msgid "Shortcuts" msgstr "" #: cola/widgets/archive.py:46 msgid "Save Archive" msgstr "" #: cola/widgets/archive.py:69 msgid "Prefix" msgstr "" #: cola/widgets/archive.py:74 msgid "Advanced" msgstr "" #: cola/widgets/archive.py:141 cola/widgets/browse.py:49 msgid "File Saved" msgstr "" #: cola/widgets/archive.py:142 cola/widgets/browse.py:50 #, python-format msgid "File saved to \"%s\"" msgstr "" #: cola/widgets/archive.py:149 msgid "Overwrite File?" msgstr "" #: cola/widgets/archive.py:150 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/widgets/archive.py:151 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:152 msgid "Overwrite" msgstr "" #: cola/widgets/browse.py:42 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/browse.py:63 #, fuzzy, python-format msgid "Browsing %s" msgstr "Aggiunta di %s in corso" #: cola/widgets/browse.py:81 #, fuzzy, python-format msgid "Select file from \"%s\"" msgstr "Cancellazione rami da %s" #: cola/widgets/browse.py:90 #, fuzzy msgid "Select File" msgstr "Seleziona tutto" #: cola/widgets/browse.py:117 cola/widgets/selectcommits.py:54 msgid "Select" msgstr "Seleziona" #: cola/widgets/cfgactions.py:85 #, fuzzy msgid "Abort" msgstr "Interruzione" #: cola/widgets/cfgactions.py:147 cola/widgets/cfgactions.py:151 #, fuzzy msgid "Abort Action" msgstr "Interruzione" #: cola/widgets/cfgactions.py:148 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/widgets/cfgactions.py:150 msgid "Abort the action?" msgstr "" #: cola/widgets/cfgactions.py:201 msgid "Arguments" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/createtag.py:85 msgid "Revision" msgstr "Revisione" #: cola/widgets/commitmsg.py:50 #, fuzzy msgid "Sign off on this commit" msgstr "Preparato per una nuova revisione" #: cola/widgets/commitmsg.py:53 cola/widgets/commitmsg.py:69 msgid "Commit@@verb" msgstr "Nuova revisione" #: cola/widgets/commitmsg.py:56 #, fuzzy msgid "Commit staged changes" msgstr "Archiviazione modifiche..." #: cola/widgets/commitmsg.py:67 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:75 #, fuzzy msgid "Actions..." msgstr "Opzioni..." #: cola/widgets/commitmsg.py:85 msgid "Amend Last Commit" msgstr "Correggi l'ultima revisione" #: cola/widgets/commitmsg.py:92 msgid "Check Spelling" msgstr "" #: cola/widgets/commitmsg.py:104 #, fuzzy msgid "Load Previous Commit Message" msgstr "Messaggio di fusione:" #: cola/widgets/commitmsg.py:135 cola/widgets/status.py:117 msgid "Move Down" msgstr "" #: cola/widgets/commitmsg.py:342 msgid "" "Please supply a commit message.\n" "\n" "A good commit message has the following format:\n" "\n" "- First line: Describe in one sentence what you did.\n" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" "Bisogna fornire un messaggio di revisione.\n" "\n" "Un buon messaggio di revisione ha il seguente formato:\n" "\n" "- Prima linea: descrivi in una frase ciò che hai fatto.\n" "- Seconda linea: vuota.\n" "- Terza linea: spiega a cosa serve la tua modifica.\n" #: cola/widgets/commitmsg.py:349 #, fuzzy msgid "Missing Commit Message" msgstr "Messaggio di fusione:" #: cola/widgets/commitmsg.py:355 #, fuzzy msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Nessuna modifica per la nuova revisione.\n" "\n" "Devi preparare per una nuova revisione almeno 1 file prima di effettuare " "questa operazione.\n" #: cola/widgets/commitmsg.py:359 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/commitmsg.py:361 #, fuzzy msgid "Stage and commit?" msgstr "Preparato per una nuova revisione" #: cola/widgets/commitmsg.py:364 #, fuzzy msgid "Stage and Commit" msgstr "Prepara per una nuova revisione" #: cola/widgets/commitmsg.py:369 #, fuzzy msgid "Nothing to commit" msgstr "Nessuna modifica per la nuova revisione." #: cola/widgets/commitmsg.py:376 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/commitmsg.py:377 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" #: cola/widgets/commitmsg.py:380 msgid "Amend the published commit?" msgstr "" #: cola/widgets/commitmsg.py:381 #, fuzzy msgid "Amend Commit" msgstr "Correggi l'ultima revisione" #: cola/widgets/commitmsg.py:386 #, fuzzy msgid "Commit failed" msgstr "Impossibile creare una nuova revisione." #: cola/widgets/commitmsg.py:387 #, python-format msgid "\"git commit\" returned exit code %s" msgstr "" #: cola/widgets/commitmsg.py:409 #, fuzzy msgid "More..." msgstr "Clona..." #: cola/widgets/commitmsg.py:413 #, fuzzy msgid "Select Commit Message" msgstr "Messaggio di fusione:" #: cola/widgets/commitmsg.py:450 #, fuzzy msgid "Commit summary" msgstr "Messaggio di revisione:" #: cola/widgets/commitmsg.py:465 msgid "Extended description..." msgstr "" #: cola/widgets/compare.py:37 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:38 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/compare.py:39 cola/widgets/compare.py:62 #: cola/widgets/compare.py:68 msgid "Local" msgstr "" #: cola/widgets/compare.py:44 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/compare.py:63 cola/widgets/compare.py:69 #: cola/widgets/remote.py:129 msgid "Remote" msgstr "Remoto" #: cola/widgets/compare.py:98 #, fuzzy msgid "File Differences" msgstr "Preferenze" #: cola/widgets/createbranch.py:102 msgid "Branch Name" msgstr "Nome del ramo" #: cola/widgets/createbranch.py:107 cola/widgets/createbranch.py:178 msgid "Starting Revision" msgstr "Revisione iniziale" #: cola/widgets/createbranch.py:115 #, fuzzy msgid "Local branch" msgstr "Ramo locale" #: cola/widgets/createbranch.py:119 #, fuzzy msgid "Tracking branch" msgstr "Duplicato locale di ramo remoto" #: cola/widgets/createbranch.py:127 msgid "Update Existing Branch:" msgstr "Aggiorna ramo esistente:" #: cola/widgets/createbranch.py:130 msgid "No" msgstr "No" #: cola/widgets/createbranch.py:133 msgid "Fast Forward Only" msgstr "Solo fast forward" #: cola/widgets/createbranch.py:137 msgid "Reset" msgstr "Ripristina" #: cola/widgets/createbranch.py:143 msgid "Fetch Tracking Branch" msgstr "Recupera duplicato locale di ramo remoto" #: cola/widgets/createbranch.py:148 msgid "Checkout After Creation" msgstr "Attiva dopo la creazione" #: cola/widgets/createbranch.py:259 #, fuzzy msgid "Missing Data" msgstr "Mancante" #: cola/widgets/createbranch.py:260 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/widgets/createbranch.py:265 #, fuzzy, python-format msgid "Branch \"%s\" already exists." msgstr "Il ramo '%s' esiste già." #: cola/widgets/createbranch.py:266 cola/widgets/createbranch.py:277 #, fuzzy msgid "Branch Exists" msgstr "Rami" #: cola/widgets/createbranch.py:273 #, fuzzy, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "" "Ripristinare '%s' a '%s' comporterà la perdita delle seguenti revisioni:" #: cola/widgets/createbranch.py:288 #, python-format msgid "%d skipped" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Recovering lost commits may not be easy." msgstr "Ricomporre le revisioni perdute potrebbe non essere semplice." #: cola/widgets/createbranch.py:292 #, fuzzy msgid "Reset Branch?" msgstr "Elimina ramo" #: cola/widgets/createbranch.py:294 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/widgets/createbranch.py:296 #, fuzzy msgid "Reset Branch" msgstr "Elimina ramo" #: cola/widgets/createbranch.py:305 #, fuzzy msgid "Updating..." msgstr "Avvio in corso..." #: cola/widgets/createbranch.py:321 #, fuzzy msgid "Error Creating Branch" msgstr "Crea ramo" #: cola/widgets/createbranch.py:322 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/widgets/createbranch.py:331 #, fuzzy msgid "Branch created" msgstr "Nome del ramo" #: cola/widgets/createtag.py:55 msgid "vX.Y.Z" msgstr "" #: cola/widgets/createtag.py:56 msgid "Specifies the tag name" msgstr "" #: cola/widgets/createtag.py:62 #, fuzzy msgid "Sign Tag" msgstr "Sign Off" #: cola/widgets/createtag.py:67 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:91 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:121 #, fuzzy msgid "Missing Revision" msgstr "Revisione iniziale" #: cola/widgets/createtag.py:122 #, fuzzy msgid "Please specify a revision to tag." msgstr "Scegliere un ramo da rinominare." #: cola/widgets/createtag.py:125 #, fuzzy msgid "Missing Name" msgstr "Mancante" #: cola/widgets/createtag.py:126 msgid "Please specify a name for the new tag." msgstr "" #: cola/widgets/createtag.py:129 #, fuzzy msgid "Missing Tag Message" msgstr "Revisione da fondere" #: cola/widgets/createtag.py:130 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/createtag.py:132 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/createtag.py:135 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/createtag.py:142 #, fuzzy msgid "Tag Created" msgstr "Crea" #: cola/widgets/createtag.py:143 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/diff.py:22 msgid "Process Section" msgstr "" #: cola/widgets/diff.py:25 msgid "Process Selection" msgstr "" #: cola/widgets/diff.py:40 msgid "Stage &Selected Lines" msgstr "" #: cola/widgets/diff.py:46 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:51 #, fuzzy msgid "Unstage &Selected Lines" msgstr "Modifiche non preparate" #: cola/widgets/diff.py:57 msgid "Apply Diff Selection to Work Tree" msgstr "" #: cola/widgets/diff.py:86 cola/widgets/diff.py:108 cola/widgets/status.py:486 #: cola/widgets/status.py:584 msgid "Launch git-cola" msgstr "" #: cola/widgets/diff.py:91 #, fuzzy msgid "Stage Section" msgstr "Revisione iniziale" #: cola/widgets/diff.py:97 msgid "Revert Section..." msgstr "" #: cola/widgets/diff.py:113 msgid "Unstage Section" msgstr "" #: cola/widgets/diff.py:125 msgid "Copy" msgstr "Copia" #: cola/widgets/diff.py:129 msgid "Select All" msgstr "Seleziona tutto" #: cola/widgets/diff.py:245 msgid "Revert Section?" msgstr "" #: cola/widgets/diff.py:249 msgid "Revert Section" msgstr "" #: cola/widgets/diff.py:258 #, fuzzy msgid "Revert Selected Lines?" msgstr "Annullare le modifiche nel file %s?" #: cola/widgets/diff.py:262 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/editremotes.py:19 #, fuzzy msgid "Edit Remotes" msgstr "Remoto" #: cola/widgets/editremotes.py:22 msgid "" "Add and remove remote repositories using the \n" "Add(+) and Delete(-) buttons on the left-hand side.\n" "\n" "Remotes can be renamed by selecting one from the list\n" "and pressing \"enter\", or by double-clicking." msgstr "" #: cola/widgets/editremotes.py:32 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/widgets/editremotes.py:45 #, fuzzy msgid "Add new remote git repository" msgstr "%s non è un archivio Git." #: cola/widgets/editremotes.py:53 #, fuzzy msgid "Delete remote" msgstr "Cancella ramo remoto" #: cola/widgets/editremotes.py:116 #, python-format msgid "Error creating remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:124 #, fuzzy msgid "Delete Remote" msgstr "Cancella ramo remoto" #: cola/widgets/editremotes.py:125 #, fuzzy msgid "Delete remote?" msgstr "Cancella ramo remoto" #: cola/widgets/editremotes.py:126 #, fuzzy, python-format msgid "Delete remote \"%s\"" msgstr "Cancella ramo remoto" #: cola/widgets/editremotes.py:134 #, python-format msgid "Error deleting remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:153 #, fuzzy msgid "Rename Remote" msgstr "Remoto" #: cola/widgets/editremotes.py:154 #, fuzzy msgid "Rename remote?" msgstr "Remoto" #: cola/widgets/editremotes.py:155 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/editremotes.py:157 msgid "Rename" msgstr "Rinomina" #: cola/widgets/editremotes.py:169 #, fuzzy, python-format msgid "Gathering info for \"%s\"..." msgstr "Caricamento delle differenze di %s..." #: cola/widgets/editremotes.py:201 #, fuzzy msgid "Add Remote" msgstr "Remoto" #: cola/widgets/editremotes.py:213 #, fuzzy msgid "Add remote" msgstr "Remoto" #: cola/widgets/editremotes.py:214 msgid "Name for the new remote" msgstr "" #: cola/widgets/editremotes.py:221 msgid "URL" msgstr "URL" #: cola/widgets/grep.py:47 cola/widgets/search.py:40 cola/widgets/search.py:58 msgid "Search" msgstr "" #: cola/widgets/grep.py:52 msgid "command-line arguments" msgstr "" #: cola/widgets/grep.py:56 msgid "grep result..." msgstr "" #: cola/widgets/grep.py:69 msgid "Shell arguments" msgstr "" #: cola/widgets/grep.py:71 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/widgets/log.py:34 #, fuzzy, python-format msgid "exit code %s" msgstr "recupera da %s" #: cola/widgets/recent.py:36 msgid "Recently Modified Files" msgstr "" #: cola/widgets/recent.py:46 msgid " commits ago" msgstr "" #: cola/widgets/recent.py:49 #, fuzzy msgid "Showing changes since" msgstr "Propagazione modifiche a %s" #: cola/widgets/recent.py:61 msgid "Expand" msgstr "" #: cola/widgets/recent.py:65 #, fuzzy msgid "Collapse" msgstr "Chiudi" #: cola/widgets/remote.py:136 #, fuzzy msgid "Remote Branch" msgstr "Rinomina ramo" #: cola/widgets/remote.py:143 #, fuzzy msgid "Fast Forward Only " msgstr "Solo fast forward" #: cola/widgets/remote.py:147 #, fuzzy msgid "Include tags " msgstr "Includi etichette" #: cola/widgets/remote.py:150 #, fuzzy msgid "Rebase " msgstr "Ripristina" #: cola/widgets/remote.py:314 #, fuzzy, python-format msgid "URL: %s" msgstr "URL:" #: cola/widgets/remote.py:393 msgid "No repository selected." msgstr "Nessun archivio selezionato." #: cola/widgets/remote.py:406 msgid "Push" msgstr "Propaga (Push)" #: cola/widgets/remote.py:408 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/remote.py:410 #, fuzzy msgid "Create a new remote branch?" msgstr "Crea nuovo ramo" #: cola/widgets/remote.py:411 #, fuzzy msgid "Create Remote Branch" msgstr "Cancella ramo remoto" #: cola/widgets/remote.py:419 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:420 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:421 #, fuzzy, python-format msgid "Force fetching from %s?" msgstr "Recupero %s da %s" #: cola/widgets/remote.py:422 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:424 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:425 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/remote.py:427 #, python-format msgid "Force push to %s?" msgstr "" #: cola/widgets/remote.py:428 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:462 msgid "Already up-to-date." msgstr "" #: cola/widgets/remote.py:485 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/widgets/search.py:44 #, fuzzy msgid "Browse..." msgstr "Esplora" #: cola/widgets/search.py:50 cola/widgets/search.py:55 msgid "yyyy-MM-dd" msgstr "" #: cola/widgets/search.py:220 #, fuzzy msgid "Search by Expression" msgstr "Espressione di revisione:" #: cola/widgets/search.py:221 msgid "Search by Path" msgstr "" #: cola/widgets/search.py:222 #, fuzzy msgid "Search Commit Messages" msgstr "Messaggio di fusione:" #: cola/widgets/search.py:223 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:224 msgid "Search Authors" msgstr "" #: cola/widgets/search.py:225 #, fuzzy msgid "Search Committers" msgstr "Revisione creata da:" #: cola/widgets/search.py:226 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:319 #, fuzzy msgid "Choose Path(s)" msgstr "Scegli %s" #: cola/widgets/selectcommits.py:50 msgid "Revision Expression:" msgstr "Espressione di revisione:" #: cola/widgets/selectcommits.py:101 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/spellcheck.py:139 #, fuzzy msgid "Spelling Suggestions" msgstr "Nessun suggerimento" #: cola/widgets/startup.py:26 msgid "git-cola" msgstr "" #: cola/widgets/startup.py:33 msgid "New..." msgstr "Nuovo..." #: cola/widgets/startup.py:56 #, fuzzy msgid "Select Repository..." msgstr "Archivio Git" #: cola/widgets/startup.py:61 #, fuzzy msgid "Select manually..." msgstr "Seleziona tutto" #: cola/widgets/status.py:75 #, fuzzy msgid "Untracked" msgstr "Non tracciato, non preparato per una nuova revisione" #: cola/widgets/status.py:85 #, fuzzy msgid "Stage / Unstage" msgstr "Prepara modificati" #: cola/widgets/status.py:114 msgid "Move Up" msgstr "" #: cola/widgets/status.py:121 msgid "Copy Path to Clipboard" msgstr "" #: cola/widgets/status.py:474 cola/widgets/status.py:550 msgid "Revert Unstaged Edits..." msgstr "" #: cola/widgets/status.py:477 cola/widgets/status.py:553 msgid "Revert Uncommited Edits..." msgstr "" #: cola/widgets/status.py:572 #, fuzzy msgid "Delete File(s)..." msgstr "Elimina..." #: cola/widgets/status.py:575 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:608 #, fuzzy msgid "Delete Files?" msgstr "Elimina" #: cola/widgets/status.py:609 msgid "The following files will be deleted:" msgstr "" #: cola/widgets/status.py:616 #, python-format msgid "Delete %d file(s)?" msgstr "" #: cola/widgets/status.py:617 #, fuzzy msgid "Delete Files" msgstr "Elimina" #: cola/widgets/status.py:633 #, fuzzy msgid "Revert Unstaged Changes?" msgstr "Modifiche non preparate" #: cola/widgets/status.py:634 msgid "" "This operation drops unstaged changes.\n" "These changes cannot be recovered." msgstr "" #: cola/widgets/status.py:636 #, fuzzy msgid "Revert the unstaged changes?" msgstr "Modifiche non preparate" #: cola/widgets/status.py:637 #, fuzzy msgid "Revert Unstaged Changes" msgstr "Modifiche non preparate" #: cola/widgets/status.py:646 cola/widgets/status.py:662 msgid "No files selected for checkout from HEAD." msgstr "" #~ msgid "Success" #~ msgstr "Successo" #~ msgid "Rescan" #~ msgstr "Analizza nuovamente" #, fuzzy #~ msgid "Browse Revision..." #~ msgstr "Revisione" #, fuzzy #~ msgid "Rebase Branch" #~ msgstr "Rinomina ramo" #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: errore grave" #~ msgid "Invalid font specified in %s:" #~ msgstr "Caratteri non validi specificati in %s:" #~ msgid "Main Font" #~ msgstr "Caratteri principali" #~ msgid "Diff/Console Font" #~ msgstr "Caratteri per confronti e terminale" #~ msgid "Cannot find git in PATH." #~ msgstr "Impossibile trovare git nel PATH" #~ msgid "Cannot parse Git version string:" #~ msgstr "Impossibile determinare la versione di Git:" #~ msgid "" #~ "Git version cannot be determined.\n" #~ "\n" #~ "%s claims it is version '%s'.\n" #~ "\n" #~ "%s requires at least Git 1.5.0 or later.\n" #~ "\n" #~ "Assume '%s' is version 1.5.0?\n" #~ msgstr "" #~ "La versione di Git non può essere determinata.\n" #~ "\n" #~ "%s riporta che la versione è '%s'.\n" #~ "\n" #~ "%s richiede almeno Git 1.5.0 o superiore.\n" #~ "\n" #~ "Assumere che '%s' sia alla versione 1.5.0?\n" #~ msgid "Git directory not found:" #~ msgstr "Non trovo la directory di git: " #~ msgid "Cannot move to top of working directory:" #~ msgstr "Impossibile spostarsi sulla directory principale del progetto:" #~ msgid "Cannot use funny .git directory:" #~ msgstr "Impossibile usare una .git directory strana:" #~ msgid "No working directory" #~ msgstr "Nessuna directory di lavoro" #~ msgid "Refreshing file status..." #~ msgstr "Controllo dello stato dei file in corso..." #~ msgid "Ready." #~ msgstr "Pronto." #~ msgid "Modified, not staged" #~ msgstr "Modificato, non preparato per una nuova revisione" #~ msgid "Portions staged for commit" #~ msgstr "Parti preparate per una nuova revisione" #~ msgid "Staged for commit, missing" #~ msgstr "Preparato per una nuova revisione, mancante" #~ msgid "Staged for removal" #~ msgstr "Preparato per la rimozione" #~ msgid "Staged for removal, still present" #~ msgstr "Preparato alla rimozione, ancora presente" #~ msgid "Requires merge resolution" #~ msgstr "Richiede risoluzione dei conflitti" #~ msgid "Starting gitk... please wait..." #~ msgstr "Avvio di gitk... attendere..." #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "Impossibile avviare gitk:\n" #~ "\n" #~ "%s non esiste" #~ msgid "Repository" #~ msgstr "Archivio" #~ msgid "Commit@@noun" #~ msgstr "Revisione" #~ msgid "Browse %s's Files" #~ msgstr "Esplora i file di %s" #~ msgid "Visualize %s's History" #~ msgstr "Visualizza la cronologia di %s" #~ msgid "Database Statistics" #~ msgstr "Statistiche dell'archivio" #~ msgid "Compress Database" #~ msgstr "Comprimi l'archivio" #~ msgid "Verify Database" #~ msgstr "Verifica l'archivio" #~ msgid "Create Desktop Icon" #~ msgstr "Crea icona desktop" #~ msgid "Undo" #~ msgstr "Annulla" #~ msgid "Redo" #~ msgstr "Ripeti" #~ msgid "Cut" #~ msgstr "Taglia" #~ msgid "Paste" #~ msgstr "Incolla" #~ msgid "Rename..." #~ msgstr "Rinomina" #~ msgid "New Commit" #~ msgstr "Nuova revisione" #~ msgid "Local Merge..." #~ msgstr "Fusione locale..." #~ msgid "Preferences..." #~ msgstr "Preferenze..." #~ msgid "Current Branch:" #~ msgstr "Ramo attuale:" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "Modifiche preparate (saranno nella nuova revisione)" #~ msgid "Initial Commit Message:" #~ msgstr "Messaggio di revisione iniziale:" #~ msgid "Amended Commit Message:" #~ msgstr "Messaggio di revisione corretto:" #~ msgid "Amended Initial Commit Message:" #~ msgstr "Messaggio iniziale di revisione corretto:" #~ msgid "Amended Merge Commit Message:" #~ msgstr "Messaggio di fusione corretto:" #~ msgid "Apply/Reverse Hunk" #~ msgstr "Applica/Inverti sezione" #~ msgid "Show Less Context" #~ msgstr "Mostra meno contesto" #~ msgid "Show More Context" #~ msgstr "Mostra più contesto" #~ msgid "Decrease Font Size" #~ msgstr "Diminuisci dimensione caratteri" #~ msgid "Increase Font Size" #~ msgstr "Aumenta dimensione caratteri" #~ msgid "Unstage Hunk From Commit" #~ msgstr "Sezione non preparata per una nuova revisione" #~ msgid "Stage Hunk For Commit" #~ msgstr "Prepara sezione per una nuova revisione" #~ msgid "Initializing..." #~ msgstr "Inizializzazione..." #~ msgid "" #~ "Possible environment issues exist.\n" #~ "\n" #~ "The following environment variables are probably\n" #~ "going to be ignored by any Git subprocess run\n" #~ "by %s:\n" #~ "\n" #~ msgstr "" #~ "Possibili problemi con le variabili d'ambiente.\n" #~ "\n" #~ "Le seguenti variabili d'ambiente saranno probabilmente\n" #~ "ignorate da tutti i sottoprocessi di Git avviati\n" #~ "da %s:\n" #~ "\n" #~ msgid "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "Ciò è dovuto a un problema conosciuto\n" #~ "causato dall'eseguibile Tcl distribuito da Cygwin." #~ msgid "" #~ "\n" #~ "\n" #~ "A good replacement for %s\n" #~ "is placing values for the user.name and\n" #~ "user.email settings into your personal\n" #~ "~/.gitconfig file.\n" #~ msgstr "" #~ "\n" #~ "\n" #~ "Una buona alternativa a %s\n" #~ "consiste nell'assegnare valori alle variabili di configurazione\n" #~ "user.name e user.email nel tuo file ~/.gitconfig personale.\n" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - un'interfaccia grafica per Git." #~ msgid "File Viewer" #~ msgstr "Mostra file" #~ msgid "Reading %s..." #~ msgstr "Lettura di %s..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "Caricamento annotazioni per copie/spostamenti..." #~ msgid "lines annotated" #~ msgstr "linee annotate" #~ msgid "Loading original location annotations..." #~ msgstr "Caricamento annotazioni per posizione originaria..." #~ msgid "Annotation complete." #~ msgstr "Annotazione completata." #~ msgid "Loading annotation..." #~ msgstr "Caricamento annotazioni..." #~ msgid "Original File:" #~ msgstr "File originario:" #~ msgid "Originally By:" #~ msgstr "In origine da:" #~ msgid "In File:" #~ msgstr "Nel file:" #~ msgid "Copied Or Moved Here By:" #~ msgstr "Copiato o spostato qui da:" #~ msgid "Detach From Local Branch" #~ msgstr "Stacca da ramo locale" #~ msgid "Match Tracking Branch Name" #~ msgstr "Appaia nome del duplicato locale di ramo remoto" #~ msgid "Tracking branch %s is not a branch in the remote repository." #~ msgstr "" #~ "Il duplicato locale del ramo remoto %s non è un ramo nell'archivio remoto." #~ msgid "Please supply a branch name." #~ msgstr "Inserire un nome per il ramo." #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "'%s' non è utilizzabile come nome di ramo." #~ msgid "Delete Local Branch" #~ msgstr "Elimina ramo locale" #~ msgid "Local Branches" #~ msgstr "Rami locali" #~ msgid "Delete Only If Merged Into" #~ msgstr "Cancella solo se fuso con un altro ramo" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "Sempre (Non effettuare verifiche di fusione)." #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "I rami seguenti non sono stati fusi completamente in %s:" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "Ricomporre rami cancellati può essere complicato. \n" #~ "\n" #~ " Eliminare i rami selezionati?" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "Impossibile cancellare i rami:\n" #~ "%s" #~ msgid "New Name:" #~ msgstr "Nuovo Nome:" #~ msgid "Failed to rename '%s'." #~ msgstr "Impossibile rinominare '%s'." #~ msgid "[Up To Parent]" #~ msgstr "[Directory superiore]" #~ msgid "Browse Branch Files" #~ msgstr "Esplora i file del ramo" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "errore grave: impossibile risolvere %s" #~ msgid "Branch '%s' does not exist." #~ msgstr "Il ramo '%s' non esiste." #~ msgid "" #~ "Branch '%s' already exists.\n" #~ "\n" #~ "It cannot fast-forward to %s.\n" #~ "A merge is required." #~ msgstr "" #~ "Il ramo '%s' esiste già.\n" #~ "\n" #~ "Non può effettuare un 'fast-forward' a %s.\n" #~ "E' necessaria una fusione." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "La strategia di fusione '%s' non è supportata." #~ msgid "Failed to update '%s'." #~ msgstr "Impossibile aggiornare '%s'." #~ msgid "Staging area (index) is already locked." #~ msgstr "" #~ "L'area di preparazione per una nuova revisione (indice) è già bloccata." #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before the current branch can be changed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "L'ultimo stato analizzato non corrisponde allo stato dell'archivio.\n" #~ "\n" #~ "Un altro programma Git ha modificato questo archivio dall'ultima analisi. " #~ "Bisogna effettuare una nuova analisi prima di poter cambiare il ramo " #~ "attuale.\n" #~ "\n" #~ "La nuova analisi comincerà ora.\n" #~ msgid "Updating working directory to '%s'..." #~ msgstr "Aggiornamento della directory di lavoro a '%s' in corso..." #~ msgid "files checked out" #~ msgstr "file presenti nella directory di lavoro" #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "Attivazione di '%s' fallita (richiesta una fusione a livello file)." #~ msgid "File level merge required." #~ msgstr "E' richiesta una fusione a livello file." #~ msgid "Staying on branch '%s'." #~ msgstr "Si rimarrà sul ramo '%s'." #~ msgid "" #~ "You are no longer on a local branch.\n" #~ "\n" #~ "If you wanted to be on a branch, create one now starting from 'This " #~ "Detached Checkout'." #~ msgstr "" #~ "Non si è più su un ramo locale\n" #~ "\n" #~ "Se si vuole rimanere su un ramo, crearne uno ora a partire da 'Questa " #~ "revisione attiva staccata'." #~ msgid "Checked out '%s'." #~ msgstr "Attivazione di '%s' completata." #~ msgid "Reset '%s'?" #~ msgstr "Ripristinare '%s'?" #~ msgid "" #~ "Failed to set current branch.\n" #~ "\n" #~ "This working directory is only partially switched. We successfully " #~ "updated your files, but failed to update an internal Git file.\n" #~ "\n" #~ "This should not have occurred. %s will now close and give up." #~ msgstr "" #~ "Impossibile preparare il ramo attuale.\n" #~ "\n" #~ "Questa directory di lavoro è stata convertita solo parzialmente. I file " #~ "sono stati aggiornati correttamente, ma l'aggiornamento di un file di Git " #~ "ha prodotto degli errori.\n" #~ "\n" #~ "Questo non sarebbe dovuto succedere. %s ora terminerà senza altre azioni." #~ msgid "Font Family" #~ msgstr "Famiglia di caratteri" #~ msgid "Font Example" #~ msgstr "Esempio caratteri" #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "Questo è un testo d'esempio.\n" #~ "Se ti piace questo testo, scegli questo carattere." #~ msgid "Git Gui" #~ msgstr "Git Gui" #~ msgid "Clone Existing Repository" #~ msgstr "Clona archivio esistente" #~ msgid "Recent Repositories" #~ msgstr "Archivi recenti" #~ msgid "Failed to create repository %s:" #~ msgstr "Impossibile creare l'archivio %s:" #~ msgid "Directory:" #~ msgstr "Directory:" #~ msgid "Directory %s already exists." #~ msgstr "La directory %s esiste già." #~ msgid "Clone" #~ msgstr "Clona" #~ msgid "Clone Type:" #~ msgstr "Tipo di clone:" #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "Standard (veloce, semi-ridondante, con hardlink)" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "Copia completa (più lento, backup ridondante)" #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "Shared (il più veloce, non raccomandato, nessun backup)" #~ msgid "Standard only available for local repository." #~ msgstr "Standard è disponibile solo per archivi locali." #~ msgid "Shared only available for local repository." #~ msgstr "Shared è disponibile solo per archivi locali." #~ msgid "Location %s already exists." #~ msgstr "Il file/directory %s esiste già." #~ msgid "Failed to configure origin" #~ msgstr "Impossibile configurare origin" #~ msgid "Counting objects" #~ msgstr "Calcolo oggetti" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "Impossibile copiare oggetti/info/alternate: %s" #~ msgid "The 'master' branch has not been initialized." #~ msgstr "Il ramo 'master' non è stato inizializzato." #~ msgid "Hardlinks are unavailable. Falling back to copying." #~ msgstr "Impossibile utilizzare gli hardlink. Si ricorrerà alla copia." #~ msgid "Cloning from %s" #~ msgstr "Clonazione da %s" #~ msgid "Copying objects" #~ msgstr "Copia degli oggetti" #~ msgid "KiB" #~ msgstr "KiB" #~ msgid "Unable to copy object: %s" #~ msgstr "Impossibile copiare oggetto: %s" #~ msgid "Linking objects" #~ msgstr "Collegamento oggetti" #~ msgid "objects" #~ msgstr "oggetti" #~ msgid "Unable to hardlink object: %s" #~ msgstr "Hardlink impossibile sull'oggetto: %s" #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "" #~ "Impossibile recuperare rami e oggetti. Controllare i dettagli forniti " #~ "dalla console." #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "" #~ "Impossibile recuperare le etichette. Controllare i dettagli forniti dalla " #~ "console." #~ msgid "Cannot determine HEAD. See console output for details." #~ msgstr "" #~ "Impossibile determinare HEAD. Controllare i dettagli forniti dalla " #~ "console." #~ msgid "Unable to cleanup %s" #~ msgstr "Impossibile ripulire %s" #~ msgid "Clone failed." #~ msgstr "Clonazione non riuscita." #~ msgid "No default branch obtained." #~ msgstr "Non è stato trovato un ramo predefinito." #~ msgid "Cannot resolve %s as a commit." #~ msgstr "Impossibile risolvere %s come una revisione." #~ msgid "Creating working directory" #~ msgstr "Creazione directory di lavoro" #~ msgid "files" #~ msgstr "file" #~ msgid "Initial file checkout failed." #~ msgstr "Attivazione iniziale non riuscita." #~ msgid "Failed to open repository %s:" #~ msgstr "Impossibile accedere all'archivio %s:" #~ msgid "This Detached Checkout" #~ msgstr "Questa revisione attiva staccata" #~ msgid "Updated" #~ msgstr "Aggiornato" #~ msgid "" #~ "There is nothing to amend.\n" #~ "\n" #~ "You are about to create the initial commit. There is no commit before " #~ "this to amend.\n" #~ msgstr "" #~ "Non c'è niente da correggere.\n" #~ "\n" #~ "Stai per creare la revisione iniziale. Non esiste una revisione " #~ "precedente da correggere.\n" #~ msgid "" #~ "Cannot amend while merging.\n" #~ "\n" #~ "You are currently in the middle of a merge that has not been fully " #~ "completed. You cannot amend the prior commit unless you first abort the " #~ "current merge activity.\n" #~ msgstr "" #~ "Non è possibile effettuare una correzione durante una fusione.\n" #~ "\n" #~ "In questo momento si sta effettuando una fusione che non è stata del " #~ "tutto completata. Non puoi correggere la revisione precedente a meno che " #~ "prima tu non interrompa l'operazione di fusione in corso.\n" #~ msgid "Error loading commit data for amend:" #~ msgstr "" #~ "Errore durante il caricamento dei dati della revisione da correggere:" #~ msgid "Unable to obtain your identity:" #~ msgstr "Impossibile ottenere la tua identità:" #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "GIT_COMMITTER_IDENT non valida:" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before another commit can be created.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "L'ultimo stato analizzato non corrisponde allo stato dell'archivio.\n" #~ "\n" #~ "Un altro programma Git ha modificato questo archivio dall'ultima analisi. " #~ "Bisogna effettuare una nuova analisi prima di poter creare una nuova " #~ "revisione.\n" #~ "\n" #~ "La nuova analisi comincerà ora.\n" #~ msgid "" #~ "Unmerged files cannot be committed.\n" #~ "\n" #~ "File %s has merge conflicts. You must resolve them and stage the file " #~ "before committing.\n" #~ msgstr "" #~ "Non è possibile creare una revisione con file non sottoposti a fusione.\n" #~ "\n" #~ "Il file %s presenta dei conflitti. Devi risolverli e preparare il file " #~ "per creare una nuova revisione prima di effettuare questa azione.\n" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "Stato di file %s sconosciuto.\n" #~ "\n" #~ "Questo programma non può creare una revisione contenente il file %s.\n" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "attenzione: Tcl non supporta la codifica '%s'." #~ msgid "Calling pre-commit hook..." #~ msgstr "Avvio pre-commit hook..." #~ msgid "Commit declined by pre-commit hook." #~ msgstr "Revisione rifiutata dal pre-commit hook." #~ msgid "Calling commit-msg hook..." #~ msgstr "Avvio commit-msg hook..." #~ msgid "Commit declined by commit-msg hook." #~ msgstr "Revisione rifiutata dal commit-msg hook." #~ msgid "write-tree failed:" #~ msgstr "write-tree non riuscito:" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "La revisione %s sembra essere danneggiata" #~ msgid "" #~ "No changes to commit.\n" #~ "\n" #~ "No files were modified by this commit and it was not a merge commit.\n" #~ "\n" #~ "A rescan will be automatically started now.\n" #~ msgstr "" #~ "Nessuna modifica per la nuova revisione.\n" #~ "\n" #~ "Questa revisione non modifica alcun file e non effettua alcuna fusione.\n" #~ "\n" #~ "Si procederà subito ad una nuova analisi.\n" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree non riuscito:" #~ msgid "update-ref failed:" #~ msgstr "update-ref non riuscito:" #~ msgid "Working... please wait..." #~ msgstr "Elaborazione in corso... attendere..." #~ msgid "Error: Command Failed" #~ msgstr "Errore: comando non riuscito" #~ msgid "Number of loose objects" #~ msgstr "Numero di oggetti slegati" #~ msgid "Disk space used by loose objects" #~ msgstr "Spazio su disco utilizzato da oggetti slegati" #~ msgid "Number of packed objects" #~ msgstr "Numero di oggetti impacchettati" #~ msgid "Number of packs" #~ msgstr "Numero di pacchetti" #~ msgid "Disk space used by packed objects" #~ msgstr "Spazio su disco utilizzato da oggetti impacchettati" #~ msgid "Packed objects waiting for pruning" #~ msgstr "Oggetti impacchettati che attendono la potatura" #~ msgid "Garbage files" #~ msgstr "File inutili" #~ msgid "Compressing the object database" #~ msgstr "Compressione dell'archivio in corso" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "Verifica dell'archivio con fsck-objects in corso" #~ msgid "" #~ "This repository currently has approximately %i loose objects.\n" #~ "\n" #~ "To maintain optimal performance it is strongly recommended that you " #~ "compress the database when more than %i loose objects exist.\n" #~ "\n" #~ "Compress the database now?" #~ msgstr "" #~ "Questo archivio attualmente ha circa %i oggetti slegati.\n" #~ "\n" #~ "Per mantenere buone prestazioni si raccomanda di comprimere l'archivio " #~ "quando sono presenti più di %i oggetti slegati.\n" #~ "\n" #~ "Comprimere l'archivio ora?" #~ msgid "Invalid date from Git: %s" #~ msgstr "Git ha restituito una data non valida: %s" #~ msgid "" #~ "No differences detected.\n" #~ "\n" #~ "%s has no changes.\n" #~ "\n" #~ "The modification date of this file was updated by another application, " #~ "but the content within the file was not changed.\n" #~ "\n" #~ "A rescan will be automatically started to find other files which may have " #~ "the same state." #~ msgstr "" #~ "Non sono state trovate differenze.\n" #~ "\n" #~ "%s non ha modifiche.\n" #~ "\n" #~ "La data di modifica di questo file è stata cambiata da un'altra " #~ "applicazione, ma il contenuto del file è rimasto invariato.\n" #~ "\n" #~ "Si procederà automaticamente ad una nuova analisi per trovare altri file " #~ "che potrebbero avere lo stesso stato." #~ msgid "Unable to display %s" #~ msgstr "Impossibile visualizzare %s" #~ msgid "Git Repository (subproject)" #~ msgstr "Archivio Git (sottoprogetto)" #~ msgid "* Binary file (not showing content)." #~ msgstr "* File binario (il contenuto non sarà mostrato)." #~ msgid "Failed to unstage selected hunk." #~ msgstr "Impossibile rimuovere la sezione scelta dalla nuova revisione." #~ msgid "Failed to stage selected hunk." #~ msgstr "Impossibile preparare la sezione scelta per una nuova revisione." #~ msgid "warning" #~ msgstr "attenzione" #~ msgid "You must correct the above errors before committing." #~ msgstr "" #~ "Bisogna correggere gli errori suddetti prima di creare una nuova " #~ "revisione." #~ msgid "Unable to unlock the index." #~ msgstr "Impossibile sbloccare l'accesso all'indice" #~ msgid "" #~ "Updating the Git index failed. A rescan will be automatically started to " #~ "resynchronize git-gui." #~ msgstr "" #~ "Impossibile aggiornare l'indice. Ora sarà avviata una nuova analisi che " #~ "aggiornerà git-gui." #~ msgid "Unlock Index" #~ msgstr "Sblocca l'accesso all'indice" #~ msgid "Ready to commit." #~ msgstr "Pronto per creare una nuova revisione." #~ msgid "Revert changes in these %i files?" #~ msgstr "Annullare le modifiche in questi %i file?" #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "" #~ "Tutte le modifiche non preparate per una nuova revisione saranno perse " #~ "per sempre." #~ msgid "Do Nothing" #~ msgstr "Non fare niente" #~ msgid "" #~ "Cannot merge while amending.\n" #~ "\n" #~ "You must finish amending this commit before starting any type of merge.\n" #~ msgstr "" #~ "Non posso effettuare fusioni durante una correzione.\n" #~ "\n" #~ "Bisogna finire di correggere questa revisione prima di iniziare una " #~ "qualunque fusione.\n" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before a merge can be performed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "L'ultimo stato analizzato non corrisponde allo stato dell'archivio.\n" #~ "\n" #~ "Un altro programma Git ha modificato questo archivio dall'ultima analisi." #~ "Bisogna effettuare una nuova analisi prima di poter effettuare una " #~ "fusione.\n" #~ "\n" #~ "La nuova analisi comincerà ora.\n" #~ msgid "" #~ "You are in the middle of a conflicted merge.\n" #~ "\n" #~ "File %s has merge conflicts.\n" #~ "\n" #~ "You must resolve them, stage the file, and commit to complete the current " #~ "merge. Only then can you begin another merge.\n" #~ msgstr "" #~ "Sei nel mezzo di una fusione con conflitti.\n" #~ "\n" #~ "Il file %s ha dei conflitti.\n" #~ "\n" #~ "Bisogna risolvere i conflitti, preparare il file per una nuova revisione " #~ "ed infine crearla per completare la fusione attuale. Solo a questo punto " #~ "potrai iniziare un'altra fusione.\n" #~ msgid "" #~ "You are in the middle of a change.\n" #~ "\n" #~ "File %s is modified.\n" #~ "\n" #~ "You should complete the current commit before starting a merge. Doing so " #~ "will help you abort a failed merge, should the need arise.\n" #~ msgstr "" #~ "Sei nel mezzo di una modifica.\n" #~ "\n" #~ "Il file %s è stato modificato.\n" #~ "\n" #~ "Bisogna completare la creazione della revisione attuale prima di iniziare " #~ "una fusione. In questo modo sarà più facile interrompere una fusione non " #~ "riuscita, nel caso ce ne fosse bisogno.\n" #~ msgid "%s of %s" #~ msgstr "%s di %s" #~ msgid "Merging %s and %s..." #~ msgstr "Fusione di %s e %s in corso..." #~ msgid "Merge completed successfully." #~ msgstr "Fusione completata con successo." #~ msgid "Merge failed. Conflict resolution is required." #~ msgstr "Fusione non riuscita. Bisogna risolvere i conflitti." #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\n" #~ msgstr "" #~ "Interruzione impossibile durante una correzione.\n" #~ "\n" #~ "Bisogna finire di correggere questa revisione.\n" #~ msgid "" #~ "Reset changes?\n" #~ "\n" #~ "Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" #~ "\n" #~ "Continue with resetting the current changes?" #~ msgstr "" #~ "Ripristinare la revisione corrente e annullare le modifiche?\n" #~ "\n" #~ "L'annullamento delle modifiche causerà la perdita di *TUTTE* le modifiche " #~ "non ancora presenti nell'archivio.\n" #~ "\n" #~ "Continuare con l'annullamento delle modifiche attuali?" #~ msgid "files reset" #~ msgstr "ripristino file" #~ msgid "Abort failed." #~ msgstr "Interruzione non riuscita." #~ msgid "Abort completed. Ready." #~ msgstr "Interruzione completata. Pronto." #~ msgid "Restore Defaults" #~ msgstr "Ripristina valori predefiniti" #~ msgid "%s Repository" #~ msgstr "Archivio di %s" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "" #~ "Effettua potatura dei duplicati locali di rami remoti durante il recupero" #~ msgid "Match Tracking Branches" #~ msgstr "Appaia duplicati locali di rami remoti" #~ msgid "New Branch Name Template" #~ msgstr "Modello per il nome di un nuovo ramo" #~ msgid "Spelling Dictionary:" #~ msgstr "Lingua dizionario:" #~ msgid "Change Font" #~ msgstr "Cambia caratteri" #~ msgid "pt." #~ msgstr "pt." #~ msgid "Failed to completely save options:" #~ msgstr "Impossibile salvare completamente le opzioni:" #~ msgid "From Repository" #~ msgstr "Da archivio" #~ msgid "Remote:" #~ msgstr "Remoto:" #~ msgid "Arbitrary URL:" #~ msgstr "URL specifico:" #~ msgid "Delete Only If" #~ msgstr "Elimina solo se" #~ msgid "Merged Into:" #~ msgstr "Fuso in:" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "Sempre (non verificare le fusioni)" #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "Si richiede un ramo per 'Fuso in'." #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "I rami seguenti non sono stati fusi completamente in %s:\n" #~ "\n" #~ " - %s" #~ msgid "" #~ "One or more of the merge tests failed because you have not fetched the " #~ "necessary commits. Try fetching from %s first." #~ msgstr "" #~ "Impossibile verificare una o più fusioni: mancano le revisioni " #~ "necessarie. Prova prima a recuperarle da %s." #~ msgid "Please select one or more branches to delete." #~ msgstr "Scegliere uno o più rami da cancellare." #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "Ricomporre rami cancellati è difficile.\n" #~ "\n" #~ "Cancellare i rami selezionati?" #~ msgid "Prune from" #~ msgstr "Effettua potatura da" #~ msgid "Fetch from" #~ msgstr "Recupera da" #~ msgid "Push to" #~ msgstr "Propaga verso" #~ msgid "Cannot write shortcut:" #~ msgstr "Impossibile scrivere shortcut:" #~ msgid "Unsupported spell checker" #~ msgstr "Correttore ortografico non supportato" #~ msgid "Spell checking is unavailable" #~ msgstr "Correzione ortografica indisponibile" #~ msgid "Invalid spell checking configuration" #~ msgstr "La configurazione del correttore ortografico non è valida" #~ msgid "Reverting dictionary to %s." #~ msgstr "Il dizionario è stato reimpostato su %s." #~ msgid "Spell checker silently failed on startup" #~ msgstr "Il correttore ortografico ha riportato un errore all'avvio" #~ msgid "Unrecognized spell checker" #~ msgstr "Correttore ortografico sconosciuto" #~ msgid "Unexpected EOF from spell checker" #~ msgstr "Il correttore ortografico ha mandato un EOF inaspettato" #~ msgid "Spell Checker Failed" #~ msgstr "Errore nel correttore ortografico" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%1$s ... %6$s: %2$*i di %4$*i (%7$3i%%)" #~ msgid "Fetching new changes from %s" #~ msgstr "Recupero nuove modifiche da %s" #~ msgid "remote prune %s" #~ msgstr "potatura remota di %s" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "" #~ "Effettua potatura dei duplicati locali di rami remoti cancellati da %s" #~ msgid "push %s" #~ msgstr "propaga verso %s" #~ msgid "Pushing %s %s to %s" #~ msgstr "Propagazione %s %s a %s" #~ msgid "Push Branches" #~ msgstr "Propaga rami" #~ msgid "Source Branches" #~ msgstr "Rami di origine" #~ msgid "Destination Repository" #~ msgstr "Archivio di destinazione" #~ msgid "Transfer Options" #~ msgstr "Opzioni di trasferimento" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "" #~ "Sovrascrivi ramo esistente (alcune modifiche potrebbero essere perse)" #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Utilizza 'thin pack' (per connessioni lente)" git-cola-1.9.3/po/ja.po000066400000000000000000002247711225156173500146170ustar00rootroot00000000000000# Translation of git-gui to Japanese # Copyright (C) 2007 Shawn Pearce # This file is distributed under the same license as the git-gui package. # しらいし ななこ , 2007. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-09-24 21:42-0700\n" "PO-Revision-Date: 2008-03-15 20:12+0900\n" "Last-Translator: しらいし ななこ \n" "Language-Team: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: cola/bookmarks.py:32 msgid "Bookmarks" msgstr "" #: cola/bookmarks.py:47 msgid "Open" msgstr "開く" #: cola/bookmarks.py:53 msgid "Add" msgstr "" #: cola/bookmarks.py:58 cola/guicmds.py:25 cola/guicmds.py:33 #: cola/widgets/editremotes.py:127 msgid "Delete" msgstr "削除" #: cola/bookmarks.py:65 cola/stash/view.py:42 cola/widgets/archive.py:65 #: cola/widgets/browse.py:117 msgid "Save" msgstr "保存" #: cola/bookmarks.py:71 cola/difftool.py:96 cola/qt.py:57 cola/qt.py:243 #: cola/prefs/view.py:241 cola/stash/view.py:50 cola/stash/view.py:51 #: cola/widgets/about.py:66 cola/widgets/about.py:126 #: cola/widgets/browse.py:116 cola/widgets/cfgactions.py:87 #: cola/widgets/cfgactions.py:239 cola/widgets/compare.py:94 #: cola/widgets/createbranch.py:159 cola/widgets/createtag.py:104 #: cola/widgets/editremotes.py:55 cola/widgets/grep.py:75 #: cola/widgets/recent.py:75 cola/widgets/remote.py:157 #: cola/widgets/search.py:81 cola/widgets/selectcommits.py:59 #: cola/widgets/startup.py:42 msgid "Close" msgstr "閉じる" #: cola/bookmarks.py:102 msgid "Bookmarks Saved" msgstr "" #: cola/bookmarks.py:103 msgid "Successfully saved bookmarks" msgstr "" #: cola/bookmarks.py:107 #, fuzzy msgid "Path to git repository" msgstr "Git リポジトリではありません: %s" #: cola/bookmarks.py:108 #, fuzzy msgid "Enter Git Repository" msgstr "GIT リポジトリ" #: cola/cmds.py:105 msgid "Amend" msgstr "" #: cola/cmds.py:140 #, fuzzy msgid "Cannot Amend" msgstr "アイコンが書けません:" #: cola/cmds.py:141 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" #: cola/cmds.py:204 #, python-format msgid "PATCH %(current)d/%(count)d" msgstr "" #: cola/cmds.py:208 msgid "Summary:" msgstr "" #: cola/cmds.py:217 msgid "Patch(es) Applied" msgstr "" #: cola/cmds.py:218 #, python-format msgid "%d patch(es) applied." msgstr "" #: cola/cmds.py:322 #, fuzzy, python-format msgid "Created commit: %s" msgstr "コミット %s を作成しました: %s" #: cola/cmds.py:324 #, fuzzy, python-format msgid "Commit failed: %s" msgstr "コミットに失敗しました。" #: cola/cmds.py:369 cola/cmds.py:1186 #, fuzzy msgid "Error" msgstr "エラー" #: cola/cmds.py:370 #, python-format msgid "Deleting \"%s\" failed" msgstr "" #: cola/cmds.py:406 #, fuzzy msgid "Remote Branch Deleted" msgstr "ブランチの名前変更" #: cola/cmds.py:407 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "" #: cola/cmds.py:411 cola/guicmds.py:108 cola/widgets/remote.py:472 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "" #: cola/cmds.py:414 #, fuzzy msgid "Error Deleting Remote Branch" msgstr "ブランチを作成" #: cola/cmds.py:493 cola/widgets/grep.py:60 cola/widgets/recent.py:69 msgid "Edit" msgstr "編集" #: cola/cmds.py:529 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/cmds.py:531 #, fuzzy msgid "Error Editing File" msgstr "diff を読む際のエラーです:" #: cola/cmds.py:554 msgid "Launch Diff Tool" msgstr "" #: cola/cmds.py:577 msgid "Launch Editor" msgstr "" #: cola/cmds.py:598 msgid "Error: Cannot find commit template" msgstr "" #: cola/cmds.py:599 #, fuzzy, python-format msgid "%s: No such file or directory." msgstr "" "致命的: パス %s が stat できません。そのようなファイルやディレクトリはありま" "せん" #: cola/cmds.py:616 msgid "Error: Unconfigured commit template" msgstr "" #: cola/cmds.py:617 msgid "" "A commit template has not been configured.\n" "Use \"git config\" to define \"commit.template\"\n" "so that it points to a commit template." msgstr "" #: cola/cmds.py:669 msgid "Open Using Default Application" msgstr "" #: cola/cmds.py:692 #, fuzzy msgid "Open Parent Directory" msgstr "最近使ったリポジトリを開く" #: cola/cmds.py:732 #, python-format msgid "Error: could not clone \"%s\"" msgstr "" #: cola/cmds.py:733 #, python-format msgid "git clone returned exit code %s" msgstr "" #: cola/cmds.py:756 cola/widgets/action.py:19 cola/widgets/editremotes.py:49 #: cola/widgets/grep.py:65 cola/widgets/recent.py:52 #: cola/widgets/recent.py:121 msgid "Refresh" msgstr "再読み込み" #: cola/cmds.py:784 #, python-format msgid "Run \"%s\"?" msgstr "" #: cola/cmds.py:791 #, fuzzy msgid "Please select a file" msgstr "トラッキング・ブランチを選択して下さい。" #: cola/cmds.py:792 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:804 #, fuzzy msgid "Invalid Revision" msgstr "無効なリビジョン: %s" #: cola/cmds.py:805 #, fuzzy msgid "The revision expression cannot be empty." msgstr "リビジョン式が空です。" #: cola/cmds.py:820 #, python-format msgid "Running command: %s" msgstr "" #: cola/cmds.py:829 cola/cmds.py:1006 cola/interaction.py:70 #, python-format msgid "Output: %s" msgstr "" #: cola/cmds.py:830 cola/guicmds.py:113 cola/interaction.py:71 #, python-format msgid "Errors: %s" msgstr "" #: cola/cmds.py:876 msgid "Sign Off" msgstr "署名" #: cola/cmds.py:897 msgid "unknown" msgstr "" #: cola/cmds.py:910 cola/widgets/action.py:17 #, fuzzy msgid "Stage" msgstr "保存" #: cola/cmds.py:917 #, fuzzy, python-format msgid "Staging: %s" msgstr "%s をスキャンしています…" #: cola/cmds.py:934 msgid "Stage Modified" msgstr "" #: cola/cmds.py:948 #, fuzzy msgid "Stage Unmerged" msgstr "変更をコミット予定に入れる" #: cola/cmds.py:962 #, fuzzy msgid "Stage Untracked" msgstr "変更をコミット予定に入れる" #: cola/cmds.py:980 #, python-format msgid "Tagging \"%(revision)s\" as \"%(name)s\"" msgstr "" #: cola/cmds.py:988 msgid "GPG-signed" msgstr "" #: cola/cmds.py:1020 cola/widgets/action.py:18 #, fuzzy msgid "Unstage" msgstr "コミット予定に入っていない変更" #: cola/cmds.py:1027 #, fuzzy, python-format msgid "Unstaging: %s" msgstr "コミットから '%s' を降ろす" #: cola/cmds.py:1055 #, python-format msgid "Untracking: %s" msgstr "" #: cola/cmds.py:1137 #, fuzzy msgid "Error Launching History Browser" msgstr "ファイル・ブラウザ" #: cola/cmds.py:1138 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/difftool.py:76 msgid "git-cola diff" msgstr "" #: cola/difftool.py:92 cola/widgets/compare.py:90 msgid "Compare" msgstr "" #: cola/gitcmds.py:402 #, fuzzy msgid "Nothing to do" msgstr "%s から複製する内容はありません" #: cola/guicmds.py:25 msgid "Delete Branch" msgstr "ブランチ削除" #: cola/guicmds.py:33 #, fuzzy msgid "Delete Remote Branch" msgstr "リモート・ブランチを削除" #: cola/guicmds.py:53 #, fuzzy msgid "Browse Commits..." msgstr "ブラウズ" #: cola/guicmds.py:53 #, fuzzy msgid "Browse" msgstr "ブラウズ" #: cola/guicmds.py:61 msgid "Checkout Branch" msgstr "ブランチをチェックアウト" #: cola/guicmds.py:61 msgid "Checkout" msgstr "チェックアウト" #: cola/guicmds.py:70 #, fuzzy msgid "Cherry-Pick Commit" msgstr "コミットをコピー" #: cola/guicmds.py:107 #, fuzzy msgid "Error Creating Repository" msgstr "新しいリポジトリを作る" #: cola/guicmds.py:110 #, python-format msgid "" "Output:\n" "%s" msgstr "" #: cola/guicmds.py:132 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/guicmds.py:153 #, fuzzy msgid "Error Cloning" msgstr "ファイルを読む際のエラーです:" #: cola/guicmds.py:154 cola/guicmds.py:155 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/guicmds.py:159 msgid "Select a parent directory for the new clone" msgstr "" #: cola/guicmds.py:169 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/guicmds.py:185 cola/widgets/search.py:75 msgid "Export Patches" msgstr "" #: cola/guicmds.py:214 cola/widgets/startup.py:124 #, fuzzy msgid "Open Git Repository..." msgstr "既存リポジトリを開く" #: cola/guicmds.py:223 #, fuzzy msgid "Load Commit Message" msgstr "コミットメッセージ:" #: cola/guicmds.py:251 #, fuzzy msgid "Select New Base" msgstr "選択" #: cola/guicmds.py:251 #, fuzzy msgid "Rebase" msgstr "リセット" #: cola/guicmds.py:261 #, fuzzy msgid "Select Branch to Review" msgstr "ブランチ削除" #: cola/guicmds.py:261 msgid "Review" msgstr "" #: cola/inotify.py:47 msgid "inotify is disabled because \"cola.inotify\" is false" msgstr "" #: cola/inotify.py:53 msgid "" "file notification: disabled\n" "Note: install pywin32 to enable.\n" msgstr "" #: cola/inotify.py:56 msgid "" "inotify: disabled\n" "Note: install python-pyinotify to enable inotify.\n" msgstr "" #: cola/inotify.py:62 msgid "On Debian systems try: sudo aptitude install python-pyinotify" msgstr "" #: cola/inotify.py:71 #, fuzzy msgid "File notification enabled." msgstr "ファイル変更時刻を信頼する" #: cola/inotify.py:73 msgid "inotify enabled." msgstr "" #: cola/interaction.py:53 msgid "Continue" msgstr "続行" #: cola/interaction.py:63 #, python-format msgid "Run %s?" msgstr "" #: cola/interaction.py:64 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/interaction.py:65 cola/widgets/cfgactions.py:240 msgid "Run" msgstr "" #: cola/interaction.py:72 #, python-format msgid "Exit code: %s" msgstr "" #: cola/qt.py:60 cola/qt.py:100 #, fuzzy msgid "Detach" msgstr "ブランチ削除" #: cola/qt.py:98 msgid "Attach" msgstr "" #: cola/qtutils.py:396 #, fuzzy msgid "Close..." msgstr "複製…" #: cola/classic/controller.py:69 msgid "Select Previous Version" msgstr "" #: cola/classic/model.py:37 cola/widgets/createtag.py:51 #: cola/widgets/editremotes.py:220 #, fuzzy msgid "Name" msgstr "名前:" #: cola/classic/model.py:39 cola/main/view.py:91 msgid "Status" msgstr "" #: cola/classic/model.py:41 msgid "Age" msgstr "" #: cola/classic/model.py:43 cola/widgets/createtag.py:74 #, fuzzy msgid "Message" msgstr "マージ" #: cola/classic/model.py:45 cola/dag/view.py:371 #, fuzzy msgid "Author" msgstr "作者:" #: cola/classic/model.py:342 #, python-format msgid "%d minutes ago" msgstr "" #: cola/classic/model.py:345 #, python-format msgid "%d hours ago" msgstr "" #: cola/classic/model.py:346 #, python-format msgid "%d days ago" msgstr "" #: cola/classic/model.py:359 cola/widgets/status.py:73 #, fuzzy msgid "Unmerged" msgstr "マージ" #: cola/classic/model.py:361 msgid "Partially Staged" msgstr "" #: cola/classic/model.py:363 cola/widgets/status.py:74 #, fuzzy msgid "Modified" msgstr "変更無し" #: cola/classic/model.py:365 cola/widgets/status.py:72 #, fuzzy msgid "Staged" msgstr "変更をコミット予定に入れる" #: cola/classic/model.py:367 msgid "Changed Upstream" msgstr "" #: cola/classic/view.py:47 cola/main/view.py:545 #, fuzzy, python-format msgid "Repository: %s" msgstr "リポジトリ:" #: cola/classic/view.py:49 cola/main/view.py:547 #, fuzzy, python-format msgid "Branch: %s" msgstr "ブランチ:" #: cola/classic/view.py:52 #, python-format msgid "%s: %s - Browse" msgstr "" #: cola/classic/view.py:54 cola/main/view.py:552 msgid "Amending" msgstr "" #: cola/classic/view.py:79 msgid "View History..." msgstr "" #: cola/classic/view.py:80 msgid "View history for selected path(s)." msgstr "" #: cola/classic/view.py:84 cola/widgets/status.py:506 #: cola/widgets/status.py:536 cola/widgets/status.py:593 #, fuzzy msgid "Stage Selected" msgstr "選択" #: cola/classic/view.py:85 #, fuzzy msgid "Stage selected path(s) for commit." msgstr "コミット予定済" #: cola/classic/view.py:90 cola/widgets/status.py:452 #: cola/widgets/status.py:494 msgid "Unstage Selected" msgstr "" #: cola/classic/view.py:91 msgid "Remove selected path(s) from the staging area." msgstr "" #: cola/classic/view.py:96 msgid "Untrack Selected" msgstr "" #: cola/classic/view.py:97 msgid "Stop tracking path(s)" msgstr "" #: cola/classic/view.py:102 msgid "Launch git-difftool on the current path." msgstr "" #: cola/classic/view.py:106 msgid "Diff Against Predecessor..." msgstr "" #: cola/classic/view.py:107 msgid "Launch git-difftool against previous versions." msgstr "" #: cola/classic/view.py:111 #, fuzzy msgid "Revert Uncommitted Changes..." msgstr "変更を元に戻す" #: cola/classic/view.py:112 #, fuzzy msgid "Revert changes to selected path(s)." msgstr "ファイル %s にした変更を元に戻しますか?" #: cola/classic/view.py:117 msgid "Edit selected path(s)." msgstr "" #: cola/classic/view.py:293 cola/widgets/status.py:652 #, fuzzy msgid "Revert Uncommitted Changes?" msgstr "変更を元に戻す" #: cola/classic/view.py:294 cola/widgets/diff.py:246 cola/widgets/diff.py:259 #: cola/widgets/status.py:653 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/classic/view.py:296 cola/widgets/diff.py:248 cola/widgets/diff.py:261 #: cola/widgets/status.py:655 msgid "Revert the uncommitted changes?" msgstr "" #: cola/classic/view.py:297 cola/widgets/status.py:656 #, fuzzy msgid "Revert Uncommitted Changes" msgstr "変更を元に戻す" #: cola/dag/view.py:166 #, fuzzy msgid "Loading..." msgstr "%s をロード中…" #: cola/dag/view.py:272 msgid "Diff this -> selected" msgstr "" #: cola/dag/view.py:275 msgid "Diff selected -> this" msgstr "" #: cola/dag/view.py:278 cola/widgets/createbranch.py:89 #: cola/widgets/createbranch.py:98 cola/widgets/createbranch.py:155 #: cola/widgets/createbranch.py:330 msgid "Create Branch" msgstr "ブランチを作成" #: cola/dag/view.py:281 #, fuzzy msgid "Create Patch" msgstr "ブランチを作成" #: cola/dag/view.py:284 cola/widgets/createtag.py:38 #: cola/widgets/createtag.py:99 #, fuzzy msgid "Create Tag" msgstr "作成" #: cola/dag/view.py:287 cola/main/view.py:208 msgid "Save As Tarball/Zip..." msgstr "" #: cola/dag/view.py:290 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/dag/view.py:293 msgid "Grab File..." msgstr "" #: cola/dag/view.py:296 #, fuzzy msgid "Copy SHA-1" msgstr "全てコピー" #: cola/dag/view.py:371 msgid "Summary" msgstr "" #: cola/dag/view.py:371 msgid "Date, Time" msgstr "" #: cola/dag/view.py:378 msgid "Go Up" msgstr "" #: cola/dag/view.py:381 msgid "Go Down" msgstr "" #: cola/dag/view.py:511 cola/dag/view.py:1181 msgid "Zoom Out" msgstr "" #: cola/dag/view.py:514 cola/dag/view.py:1178 msgid "Zoom In" msgstr "" #: cola/dag/view.py:517 cola/dag/view.py:1184 msgid "Zoom to Fit" msgstr "" #: cola/dag/view.py:536 msgid "Log" msgstr "" #: cola/dag/view.py:541 cola/main/view.py:114 cola/main/view.py:384 msgid "Diff" msgstr "" #: cola/dag/view.py:554 msgid "Graph" msgstr "" #: cola/dag/view.py:563 msgid "View" msgstr "" #: cola/dag/view.py:636 #, python-format msgid "%s: %s - DAG" msgstr "" #: cola/dag/view.py:638 msgid " - DAG" msgstr "" #: cola/dag/view.py:1187 #, fuzzy msgid "Select Parent" msgstr "選択" #: cola/dag/view.py:1190 msgid "Select Oldest Parent" msgstr "" #: cola/dag/view.py:1193 #, fuzzy msgid "Select Child" msgstr "全て選択" #: cola/dag/view.py:1196 msgid "Select Newest Child" msgstr "" #: cola/main/view.py:78 #, fuzzy msgid "Browser" msgstr "ブラウズ" #: cola/main/view.py:83 #, fuzzy msgid "Action" msgstr "オプション" #: cola/main/view.py:99 cola/merge/view.py:45 #, fuzzy msgid "Commit" msgstr "コミット:" #: cola/main/view.py:108 #, fuzzy msgid "Console" msgstr "閉じる" #: cola/main/view.py:120 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/main/view.py:125 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/main/view.py:130 msgid "Ignore all whitespace" msgstr "" #: cola/main/view.py:135 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/main/view.py:139 cola/widgets/createbranch.py:194 msgid "Options" msgstr "オプション" #: cola/main/view.py:141 cola/main/view.py:142 #, fuzzy msgid "Diff Options" msgstr "オプション" #: cola/main/view.py:157 cola/widgets/status.py:423 msgid "Unstage All" msgstr "" #: cola/main/view.py:161 msgid "Unstage From Commit" msgstr "コミットから降ろす" #: cola/main/view.py:165 msgid "Diffstat" msgstr "" #: cola/main/view.py:168 msgid "Stage Changed Files To Commit" msgstr "変更されたファイルをコミット予定" #: cola/main/view.py:173 msgid "Stage All Untracked" msgstr "" #: cola/main/view.py:178 msgid "Export Patches..." msgstr "" #: cola/main/view.py:181 #, fuzzy msgid "New Repository..." msgstr "GIT リポジトリ" #: cola/main/view.py:185 cola/prefs/view.py:220 msgid "Preferences" msgstr "設定" #: cola/main/view.py:189 msgid "Edit Remotes..." msgstr "" #: cola/main/view.py:197 #, fuzzy msgid "Recently Modified Files..." msgstr "変更されたファイルをスキャンしています…" #: cola/main/view.py:201 #, fuzzy msgid "Cherry-Pick..." msgstr "チェックアウト" #: cola/main/view.py:205 #, fuzzy msgid "Load Commit Message..." msgstr "コミットメッセージ:" #: cola/main/view.py:211 msgid "Quit" msgstr "終了" #: cola/main/view.py:213 msgid "Bookmarks..." msgstr "" #: cola/main/view.py:215 msgid "Grep" msgstr "" #: cola/main/view.py:217 #, fuzzy msgid "Merge..." msgstr "マージ" #: cola/main/view.py:220 cola/merge/__init__.py:20 msgid "Abort Merge..." msgstr "マージ中止…" #: cola/main/view.py:223 cola/widgets/action.py:20 #, fuzzy msgid "Fetch..." msgstr "リセット…" #: cola/main/view.py:225 cola/widgets/action.py:21 msgid "Push..." msgstr "プッシュ…" #: cola/main/view.py:227 cola/widgets/action.py:22 #, fuzzy msgid "Pull..." msgstr "プッシュ…" #: cola/main/view.py:230 cola/widgets/startup.py:36 msgid "Open..." msgstr "開く…" #: cola/main/view.py:234 cola/widgets/action.py:23 #, fuzzy msgid "Stash..." msgstr "プッシュ…" #: cola/main/view.py:237 cola/widgets/startup.py:39 msgid "Clone..." msgstr "複製…" #: cola/main/view.py:241 #, fuzzy msgid "Documentation" msgstr "オンライン・ドキュメント" #: cola/main/view.py:245 msgid "Keyboard Shortcuts" msgstr "" #: cola/main/view.py:250 #, fuzzy msgid "Visualize Current Branch..." msgstr "現在のブランチの履歴を見る" #: cola/main/view.py:253 #, fuzzy msgid "Visualize All Branches..." msgstr "全てのブランチの履歴を見る" #: cola/main/view.py:256 #, fuzzy msgid "Search..." msgstr "起動中…" #: cola/main/view.py:258 #, fuzzy msgid "Browse Current Branch..." msgstr "現在のブランチのファイルを見る" #: cola/main/view.py:260 #, fuzzy msgid "Browse Other Branch..." msgstr "ブランチのファイルを見る…" #: cola/main/view.py:262 #, fuzzy msgid "Get Commit Message Template" msgstr "コミットメッセージのテキスト幅" #: cola/main/view.py:265 #, fuzzy msgid "About" msgstr "%s について" #: cola/main/view.py:268 #, fuzzy msgid "Expression..." msgstr "オプション…" #: cola/main/view.py:270 #, fuzzy msgid "Branches..." msgstr "ブランチ" #: cola/main/view.py:273 #, fuzzy msgid "Create Tag..." msgstr "作成…" #: cola/main/view.py:276 msgid "Create..." msgstr "作成…" #: cola/main/view.py:279 msgid "Delete..." msgstr "削除…" #: cola/main/view.py:282 #, fuzzy msgid "Delete Remote Branch..." msgstr "リモート・ブランチを削除" #: cola/main/view.py:285 msgid "Checkout..." msgstr "チェックアウト" #: cola/main/view.py:287 #, fuzzy msgid "Rebase..." msgstr "リセット…" #: cola/main/view.py:289 #, fuzzy msgid "Review..." msgstr "リセット…" #: cola/main/view.py:292 #, fuzzy msgid "Browser..." msgstr "ブラウズ" #: cola/main/view.py:296 msgid "DAG..." msgstr "" #: cola/main/view.py:313 #, fuzzy msgid "File" msgstr "ファイル:" #: cola/main/view.py:316 #, fuzzy msgid "Open Recent" msgstr "最近使ったリポジトリを開く" #: cola/main/view.py:338 cola/main/view.py:339 #, fuzzy msgid "Index" msgstr "索引エラー" #: cola/main/view.py:349 msgid "Branch" msgstr "ブランチ" #: cola/main/view.py:367 #, fuzzy msgid "Actions" msgstr "オプション" #: cola/main/view.py:393 msgid "Tools" msgstr "" #: cola/main/view.py:404 msgid "Help" msgstr "ヘルプ" #: cola/main/view.py:462 #, python-format msgid "git cola version %s" msgstr "" #: cola/merge/__init__.py:21 #, fuzzy msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "マージを中断しますか?\n" "\n" "現在のマージを中断すると、コミットしていない全ての変更が失われます。\n" "\n" "マージを中断してよろしいですか?" #: cola/merge/__init__.py:24 msgid "Aborting the current merge?" msgstr "" #: cola/merge/__init__.py:25 #, fuzzy msgid "Abort Merge" msgstr "マージ中止…" #: cola/merge/view.py:23 msgid "Revision To Merge" msgstr "マージするリビジョン" #: cola/merge/view.py:28 cola/widgets/cfgactions.py:220 #: cola/widgets/remote.py:122 msgid "Local Branch" msgstr "ローカル・ブランチ" #: cola/merge/view.py:31 cola/widgets/cfgactions.py:221 msgid "Tracking Branch" msgstr "トラッキング・ブランチ" #: cola/merge/view.py:33 cola/widgets/cfgactions.py:222 #: cola/widgets/createbranch.py:122 msgid "Tag" msgstr "タグ" #: cola/merge/view.py:39 msgid "Visualize" msgstr "可視化" #: cola/merge/view.py:42 #, fuzzy msgid "Squash" msgstr "プッシュ" #: cola/merge/view.py:50 cola/widgets/archive.py:62 #: cola/widgets/editremotes.py:204 msgid "Cancel" msgstr "中止" #: cola/merge/view.py:53 msgid "Merge" msgstr "マージ" #: cola/merge/view.py:115 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/merge/view.py:118 #, fuzzy, python-format msgid "Merge into \"%s\"" msgstr "%s にマージ" #: cola/merge/view.py:162 cola/merge/view.py:171 #, fuzzy msgid "No Revision Specified" msgstr "リビジョンが未選択です。" #: cola/merge/view.py:163 msgid "You must specify a revision to view." msgstr "" #: cola/merge/view.py:172 msgid "You must specify a revision to merge." msgstr "" #: cola/prefs/view.py:116 msgid "User Name" msgstr "ユーザ名" #: cola/prefs/view.py:117 msgid "Email Address" msgstr "電子メールアドレス" #: cola/prefs/view.py:118 msgid "Merge Verbosity" msgstr "マージの冗長度" #: cola/prefs/view.py:119 msgid "Number of Diff Context Lines" msgstr "diff の文脈行数" #: cola/prefs/view.py:120 msgid "Summarize Merge Commits" msgstr "マージコミットの要約" #: cola/prefs/view.py:121 msgid "Show Diffstat After Merge" msgstr "マージ後に diffstat を表示" #: cola/prefs/view.py:122 msgid "Display Untracked Files" msgstr "" #: cola/prefs/view.py:163 msgid "Fixed-Width Font" msgstr "" #: cola/prefs/view.py:164 msgid "Font Size" msgstr "フォントの大きさ" #: cola/prefs/view.py:165 msgid "Tab Width" msgstr "" #: cola/prefs/view.py:166 msgid "Text Width" msgstr "" #: cola/prefs/view.py:167 cola/widgets/commitmsg.py:99 msgid "Auto-Wrap Lines" msgstr "" #: cola/prefs/view.py:168 #, fuzzy msgid "Editor" msgstr "編集" #: cola/prefs/view.py:169 #, fuzzy msgid "History Browser" msgstr "ファイル・ブラウザ" #: cola/prefs/view.py:170 msgid "Diff Tool" msgstr "" #: cola/prefs/view.py:171 #, fuzzy msgid "Merge Tool" msgstr "マージ" #: cola/prefs/view.py:172 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/prefs/view.py:173 msgid "Save GUI Settings" msgstr "" #: cola/prefs/view.py:227 #, fuzzy msgid "All Repositories" msgstr "大域(全てのリポジトリ)" #: cola/prefs/view.py:228 #, fuzzy msgid "Current Repository" msgstr "新しいリポジトリを作る" #: cola/prefs/view.py:229 #, fuzzy msgid "Settings" msgstr "起動中…" #: cola/stash/view.py:28 msgid "Stash" msgstr "" #: cola/stash/view.py:38 #, fuzzy msgid "Apply" msgstr "りんご" #: cola/stash/view.py:39 msgid "Apply the selected stash" msgstr "" #: cola/stash/view.py:43 msgid "Save modified state to new stash" msgstr "" #: cola/stash/view.py:46 msgid "Drop" msgstr "" #: cola/stash/view.py:47 msgid "Drop the selected stash" msgstr "" #: cola/stash/view.py:54 msgid "Keep Index" msgstr "" #: cola/stash/view.py:175 msgid "Save Stash" msgstr "" #: cola/stash/view.py:176 msgid "Enter a name for the stash" msgstr "" #: cola/stash/view.py:182 msgid "Error: Stash exists" msgstr "" #: cola/stash/view.py:183 #, fuzzy, python-format msgid "A stash named \"%s\" already exists" msgstr "ファイル '%s' は既に存在します。" #: cola/stash/view.py:198 msgid "Drop Stash?" msgstr "" #: cola/stash/view.py:199 #, fuzzy msgid "Recovering a dropped stash is not possible." msgstr "失なわれたコミットを回復するのは簡単ではありません。" #: cola/stash/view.py:200 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/stash/view.py:201 msgid "Drop Stash" msgstr "" #: cola/widgets/about.py:47 msgid "About git-cola" msgstr "" #: cola/widgets/about.py:97 msgid "" "This PyQt4 does not include QtWebKit.\n" "The keyboard shortcuts feature is unavailable." msgstr "" #: cola/widgets/about.py:104 msgid "hotkeys.html" msgstr "" #: cola/widgets/about.py:122 msgid "Shortcuts" msgstr "" #: cola/widgets/archive.py:46 msgid "Save Archive" msgstr "" #: cola/widgets/archive.py:69 msgid "Prefix" msgstr "" #: cola/widgets/archive.py:74 msgid "Advanced" msgstr "" #: cola/widgets/archive.py:141 cola/widgets/browse.py:49 msgid "File Saved" msgstr "" #: cola/widgets/archive.py:142 cola/widgets/browse.py:50 #, python-format msgid "File saved to \"%s\"" msgstr "" #: cola/widgets/archive.py:149 msgid "Overwrite File?" msgstr "" #: cola/widgets/archive.py:150 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/widgets/archive.py:151 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:152 msgid "Overwrite" msgstr "" #: cola/widgets/browse.py:42 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/browse.py:63 #, fuzzy, python-format msgid "Browsing %s" msgstr "コミットに %s を加えています" #: cola/widgets/browse.py:81 #, fuzzy, python-format msgid "Select file from \"%s\"" msgstr "%s からブランチを削除しています。" #: cola/widgets/browse.py:90 #, fuzzy msgid "Select File" msgstr "全て選択" #: cola/widgets/browse.py:117 cola/widgets/selectcommits.py:54 msgid "Select" msgstr "選択" #: cola/widgets/cfgactions.py:85 #, fuzzy msgid "Abort" msgstr "中断しています" #: cola/widgets/cfgactions.py:147 cola/widgets/cfgactions.py:151 #, fuzzy msgid "Abort Action" msgstr "中断しています" #: cola/widgets/cfgactions.py:148 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/widgets/cfgactions.py:150 msgid "Abort the action?" msgstr "" #: cola/widgets/cfgactions.py:201 msgid "Arguments" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/createtag.py:85 msgid "Revision" msgstr "リビジョン" #: cola/widgets/commitmsg.py:50 #, fuzzy msgid "Sign off on this commit" msgstr "コミット予定済" #: cola/widgets/commitmsg.py:53 cola/widgets/commitmsg.py:69 msgid "Commit@@verb" msgstr "コミット" #: cola/widgets/commitmsg.py:56 #, fuzzy msgid "Commit staged changes" msgstr "変更点をコミット中・・・" #: cola/widgets/commitmsg.py:67 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:75 #, fuzzy msgid "Actions..." msgstr "オプション…" #: cola/widgets/commitmsg.py:85 msgid "Amend Last Commit" msgstr "最新コミットを訂正" #: cola/widgets/commitmsg.py:92 msgid "Check Spelling" msgstr "" #: cola/widgets/commitmsg.py:104 #, fuzzy msgid "Load Previous Commit Message" msgstr "マージコミットメッセージ:" #: cola/widgets/commitmsg.py:135 cola/widgets/status.py:117 msgid "Move Down" msgstr "" #: cola/widgets/commitmsg.py:342 msgid "" "Please supply a commit message.\n" "\n" "A good commit message has the following format:\n" "\n" "- First line: Describe in one sentence what you did.\n" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" "コミット・メッセージを入力して下さい。\n" "\n" "正しいコミット・メッセージは:\n" "\n" "- 第1行: 何をしたか、を1行で要約。\n" "- 第2行: 空白\n" "- 残りの行: なぜ、この変更が良い変更か、の説明。\n" #: cola/widgets/commitmsg.py:349 #, fuzzy msgid "Missing Commit Message" msgstr "マージコミットメッセージ:" #: cola/widgets/commitmsg.py:355 #, fuzzy msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "コミットする変更がありません。\n" "\n" "最低一つの変更をコミット予定に加えてからコミットして下さい。\n" #: cola/widgets/commitmsg.py:359 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/commitmsg.py:361 #, fuzzy msgid "Stage and commit?" msgstr "コミット予定済" #: cola/widgets/commitmsg.py:364 #, fuzzy msgid "Stage and Commit" msgstr "コミット予定する" #: cola/widgets/commitmsg.py:369 #, fuzzy msgid "Nothing to commit" msgstr "コミットする変更がありません。" #: cola/widgets/commitmsg.py:376 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/commitmsg.py:377 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" #: cola/widgets/commitmsg.py:380 msgid "Amend the published commit?" msgstr "" #: cola/widgets/commitmsg.py:381 #, fuzzy msgid "Amend Commit" msgstr "最新コミットを訂正" #: cola/widgets/commitmsg.py:386 #, fuzzy msgid "Commit failed" msgstr "コミットに失敗しました。" #: cola/widgets/commitmsg.py:387 #, python-format msgid "\"git commit\" returned exit code %s" msgstr "" #: cola/widgets/commitmsg.py:409 #, fuzzy msgid "More..." msgstr "複製…" #: cola/widgets/commitmsg.py:413 #, fuzzy msgid "Select Commit Message" msgstr "マージコミットメッセージ:" #: cola/widgets/commitmsg.py:450 #, fuzzy msgid "Commit summary" msgstr "コミットメッセージ:" #: cola/widgets/commitmsg.py:465 msgid "Extended description..." msgstr "" #: cola/widgets/compare.py:37 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:38 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/compare.py:39 cola/widgets/compare.py:62 #: cola/widgets/compare.py:68 msgid "Local" msgstr "" #: cola/widgets/compare.py:44 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/compare.py:63 cola/widgets/compare.py:69 #: cola/widgets/remote.py:129 msgid "Remote" msgstr "リモート" #: cola/widgets/compare.py:98 #, fuzzy msgid "File Differences" msgstr "設定" #: cola/widgets/createbranch.py:102 msgid "Branch Name" msgstr "ブランチ名" #: cola/widgets/createbranch.py:107 cola/widgets/createbranch.py:178 msgid "Starting Revision" msgstr "初期リビジョン" #: cola/widgets/createbranch.py:115 #, fuzzy msgid "Local branch" msgstr "ローカル・ブランチ" #: cola/widgets/createbranch.py:119 #, fuzzy msgid "Tracking branch" msgstr "トラッキング・ブランチ" #: cola/widgets/createbranch.py:127 msgid "Update Existing Branch:" msgstr "既存のブランチを更新:" #: cola/widgets/createbranch.py:130 msgid "No" msgstr "いいえ" #: cola/widgets/createbranch.py:133 msgid "Fast Forward Only" msgstr "早送りのみ" #: cola/widgets/createbranch.py:137 msgid "Reset" msgstr "リセット" #: cola/widgets/createbranch.py:143 msgid "Fetch Tracking Branch" msgstr "トラッキング・ブランチをフェッチ" #: cola/widgets/createbranch.py:148 msgid "Checkout After Creation" msgstr "作成してすぐチェックアウト" #: cola/widgets/createbranch.py:259 #, fuzzy msgid "Missing Data" msgstr "ファイル無し" #: cola/widgets/createbranch.py:260 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/widgets/createbranch.py:265 #, fuzzy, python-format msgid "Branch \"%s\" already exists." msgstr "'%s'というブランチは既に存在します。" #: cola/widgets/createbranch.py:266 cola/widgets/createbranch.py:277 #, fuzzy msgid "Branch Exists" msgstr "ブランチ" #: cola/widgets/createbranch.py:273 #, fuzzy, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "'%s' を '%s' にリセットすると、以下のコミットが失なわれます:" #: cola/widgets/createbranch.py:288 #, python-format msgid "%d skipped" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Recovering lost commits may not be easy." msgstr "失なわれたコミットを回復するのは簡単ではありません。" #: cola/widgets/createbranch.py:292 #, fuzzy msgid "Reset Branch?" msgstr "ブランチ削除" #: cola/widgets/createbranch.py:294 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/widgets/createbranch.py:296 #, fuzzy msgid "Reset Branch" msgstr "ブランチ削除" #: cola/widgets/createbranch.py:305 #, fuzzy msgid "Updating..." msgstr "起動中…" #: cola/widgets/createbranch.py:321 #, fuzzy msgid "Error Creating Branch" msgstr "ブランチを作成" #: cola/widgets/createbranch.py:322 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/widgets/createbranch.py:331 #, fuzzy msgid "Branch created" msgstr "ブランチ名" #: cola/widgets/createtag.py:55 msgid "vX.Y.Z" msgstr "" #: cola/widgets/createtag.py:56 msgid "Specifies the tag name" msgstr "" #: cola/widgets/createtag.py:62 #, fuzzy msgid "Sign Tag" msgstr "署名" #: cola/widgets/createtag.py:67 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:91 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:121 #, fuzzy msgid "Missing Revision" msgstr "初期リビジョン" #: cola/widgets/createtag.py:122 #, fuzzy msgid "Please specify a revision to tag." msgstr "名前を変更するブランチを選んで下さい。" #: cola/widgets/createtag.py:125 #, fuzzy msgid "Missing Name" msgstr "ファイル無し" #: cola/widgets/createtag.py:126 msgid "Please specify a name for the new tag." msgstr "" #: cola/widgets/createtag.py:129 #, fuzzy msgid "Missing Tag Message" msgstr "マージするリビジョン" #: cola/widgets/createtag.py:130 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/createtag.py:132 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/createtag.py:135 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/createtag.py:142 #, fuzzy msgid "Tag Created" msgstr "作成" #: cola/widgets/createtag.py:143 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/diff.py:22 msgid "Process Section" msgstr "" #: cola/widgets/diff.py:25 msgid "Process Selection" msgstr "" #: cola/widgets/diff.py:40 msgid "Stage &Selected Lines" msgstr "" #: cola/widgets/diff.py:46 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:51 #, fuzzy msgid "Unstage &Selected Lines" msgstr "コミット予定に入っていない変更" #: cola/widgets/diff.py:57 msgid "Apply Diff Selection to Work Tree" msgstr "" #: cola/widgets/diff.py:86 cola/widgets/diff.py:108 cola/widgets/status.py:486 #: cola/widgets/status.py:584 msgid "Launch git-cola" msgstr "" #: cola/widgets/diff.py:91 #, fuzzy msgid "Stage Section" msgstr "初期リビジョン" #: cola/widgets/diff.py:97 msgid "Revert Section..." msgstr "" #: cola/widgets/diff.py:113 msgid "Unstage Section" msgstr "" #: cola/widgets/diff.py:125 msgid "Copy" msgstr "コピー" #: cola/widgets/diff.py:129 msgid "Select All" msgstr "全て選択" #: cola/widgets/diff.py:245 msgid "Revert Section?" msgstr "" #: cola/widgets/diff.py:249 msgid "Revert Section" msgstr "" #: cola/widgets/diff.py:258 #, fuzzy msgid "Revert Selected Lines?" msgstr "ファイル %s にした変更を元に戻しますか?" #: cola/widgets/diff.py:262 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/editremotes.py:19 #, fuzzy msgid "Edit Remotes" msgstr "リモート" #: cola/widgets/editremotes.py:22 msgid "" "Add and remove remote repositories using the \n" "Add(+) and Delete(-) buttons on the left-hand side.\n" "\n" "Remotes can be renamed by selecting one from the list\n" "and pressing \"enter\", or by double-clicking." msgstr "" #: cola/widgets/editremotes.py:32 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/widgets/editremotes.py:45 #, fuzzy msgid "Add new remote git repository" msgstr "Git リポジトリではありません: %s" #: cola/widgets/editremotes.py:53 #, fuzzy msgid "Delete remote" msgstr "リモート・ブランチを削除" #: cola/widgets/editremotes.py:116 #, python-format msgid "Error creating remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:124 #, fuzzy msgid "Delete Remote" msgstr "リモート・ブランチを削除" #: cola/widgets/editremotes.py:125 #, fuzzy msgid "Delete remote?" msgstr "リモート・ブランチを削除" #: cola/widgets/editremotes.py:126 #, fuzzy, python-format msgid "Delete remote \"%s\"" msgstr "リモート・ブランチを削除" #: cola/widgets/editremotes.py:134 #, python-format msgid "Error deleting remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:153 #, fuzzy msgid "Rename Remote" msgstr "リモート" #: cola/widgets/editremotes.py:154 #, fuzzy msgid "Rename remote?" msgstr "リモート" #: cola/widgets/editremotes.py:155 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/editremotes.py:157 msgid "Rename" msgstr "名前変更" #: cola/widgets/editremotes.py:169 #, fuzzy, python-format msgid "Gathering info for \"%s\"..." msgstr "%s の変更点をロード中…" #: cola/widgets/editremotes.py:201 #, fuzzy msgid "Add Remote" msgstr "リモート" #: cola/widgets/editremotes.py:213 #, fuzzy msgid "Add remote" msgstr "リモート" #: cola/widgets/editremotes.py:214 msgid "Name for the new remote" msgstr "" #: cola/widgets/editremotes.py:221 msgid "URL" msgstr "URL" #: cola/widgets/grep.py:47 cola/widgets/search.py:40 cola/widgets/search.py:58 msgid "Search" msgstr "" #: cola/widgets/grep.py:52 msgid "command-line arguments" msgstr "" #: cola/widgets/grep.py:56 msgid "grep result..." msgstr "" #: cola/widgets/grep.py:69 msgid "Shell arguments" msgstr "" #: cola/widgets/grep.py:71 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/widgets/log.py:34 #, fuzzy, python-format msgid "exit code %s" msgstr "%s を取得" #: cola/widgets/recent.py:36 msgid "Recently Modified Files" msgstr "" #: cola/widgets/recent.py:46 msgid " commits ago" msgstr "" #: cola/widgets/recent.py:49 #, fuzzy msgid "Showing changes since" msgstr "%s へ変更をプッシュしています" #: cola/widgets/recent.py:61 msgid "Expand" msgstr "" #: cola/widgets/recent.py:65 #, fuzzy msgid "Collapse" msgstr "閉じる" #: cola/widgets/remote.py:136 #, fuzzy msgid "Remote Branch" msgstr "ブランチの名前変更" #: cola/widgets/remote.py:143 #, fuzzy msgid "Fast Forward Only " msgstr "早送りのみ" #: cola/widgets/remote.py:147 #, fuzzy msgid "Include tags " msgstr "タグを含める" #: cola/widgets/remote.py:150 #, fuzzy msgid "Rebase " msgstr "リセット" #: cola/widgets/remote.py:314 #, fuzzy, python-format msgid "URL: %s" msgstr "URL:" #: cola/widgets/remote.py:393 msgid "No repository selected." msgstr "リポジトリが選択されていません。" #: cola/widgets/remote.py:406 msgid "Push" msgstr "プッシュ" #: cola/widgets/remote.py:408 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/remote.py:410 #, fuzzy msgid "Create a new remote branch?" msgstr "ブランチを新規作成" #: cola/widgets/remote.py:411 #, fuzzy msgid "Create Remote Branch" msgstr "リモート・ブランチを削除" #: cola/widgets/remote.py:419 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:420 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:421 #, fuzzy, python-format msgid "Force fetching from %s?" msgstr "%s から %s をフェッチしています" #: cola/widgets/remote.py:422 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:424 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:425 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/remote.py:427 #, python-format msgid "Force push to %s?" msgstr "" #: cola/widgets/remote.py:428 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:462 msgid "Already up-to-date." msgstr "" #: cola/widgets/remote.py:485 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/widgets/search.py:44 #, fuzzy msgid "Browse..." msgstr "ブラウズ" #: cola/widgets/search.py:50 cola/widgets/search.py:55 msgid "yyyy-MM-dd" msgstr "" #: cola/widgets/search.py:220 #, fuzzy msgid "Search by Expression" msgstr "リビジョン式:" #: cola/widgets/search.py:221 msgid "Search by Path" msgstr "" #: cola/widgets/search.py:222 #, fuzzy msgid "Search Commit Messages" msgstr "マージコミットメッセージ:" #: cola/widgets/search.py:223 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:224 msgid "Search Authors" msgstr "" #: cola/widgets/search.py:225 #, fuzzy msgid "Search Committers" msgstr "コミット者:" #: cola/widgets/search.py:226 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:319 #, fuzzy msgid "Choose Path(s)" msgstr "%s を選択" #: cola/widgets/selectcommits.py:50 msgid "Revision Expression:" msgstr "リビジョン式:" #: cola/widgets/selectcommits.py:101 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/spellcheck.py:139 #, fuzzy msgid "Spelling Suggestions" msgstr "提案なし" #: cola/widgets/startup.py:26 msgid "git-cola" msgstr "" #: cola/widgets/startup.py:33 msgid "New..." msgstr "新規…" #: cola/widgets/startup.py:56 #, fuzzy msgid "Select Repository..." msgstr "GIT リポジトリ" #: cola/widgets/startup.py:61 #, fuzzy msgid "Select manually..." msgstr "全て選択" #: cola/widgets/status.py:75 #, fuzzy msgid "Untracked" msgstr "管理外、コミット未予定" #: cola/widgets/status.py:85 #, fuzzy msgid "Stage / Unstage" msgstr "変更をコミット予定に入れる" #: cola/widgets/status.py:114 msgid "Move Up" msgstr "" #: cola/widgets/status.py:121 msgid "Copy Path to Clipboard" msgstr "" #: cola/widgets/status.py:474 cola/widgets/status.py:550 msgid "Revert Unstaged Edits..." msgstr "" #: cola/widgets/status.py:477 cola/widgets/status.py:553 msgid "Revert Uncommited Edits..." msgstr "" #: cola/widgets/status.py:572 #, fuzzy msgid "Delete File(s)..." msgstr "削除…" #: cola/widgets/status.py:575 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:608 #, fuzzy msgid "Delete Files?" msgstr "削除" #: cola/widgets/status.py:609 msgid "The following files will be deleted:" msgstr "" #: cola/widgets/status.py:616 #, python-format msgid "Delete %d file(s)?" msgstr "" #: cola/widgets/status.py:617 #, fuzzy msgid "Delete Files" msgstr "削除" #: cola/widgets/status.py:633 #, fuzzy msgid "Revert Unstaged Changes?" msgstr "コミット予定に入っていない変更" #: cola/widgets/status.py:634 msgid "" "This operation drops unstaged changes.\n" "These changes cannot be recovered." msgstr "" #: cola/widgets/status.py:636 #, fuzzy msgid "Revert the unstaged changes?" msgstr "コミット予定に入っていない変更" #: cola/widgets/status.py:637 #, fuzzy msgid "Revert Unstaged Changes" msgstr "コミット予定に入っていない変更" #: cola/widgets/status.py:646 cola/widgets/status.py:662 msgid "No files selected for checkout from HEAD." msgstr "" #~ msgid "Success" #~ msgstr "成功" #~ msgid "Rescan" #~ msgstr "再スキャン" #, fuzzy #~ msgid "Browse Revision..." #~ msgstr "リビジョン" #, fuzzy #~ msgid "Rebase Branch" #~ msgstr "ブランチの名前変更" #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: 致命的なエラー" #~ msgid "Invalid font specified in %s:" #~ msgstr "%s に無効なフォントが指定されています:" #~ msgid "Main Font" #~ msgstr "主フォント" #~ msgid "Diff/Console Font" #~ msgstr "diff/コンソール・フォント" #~ msgid "Cannot find git in PATH." #~ msgstr "PATH 中に git が見つかりません" #~ msgid "Cannot parse Git version string:" #~ msgstr "Git バージョン名が理解できません:" #~ msgid "" #~ "Git version cannot be determined.\n" #~ "\n" #~ "%s claims it is version '%s'.\n" #~ "\n" #~ "%s requires at least Git 1.5.0 or later.\n" #~ "\n" #~ "Assume '%s' is version 1.5.0?\n" #~ msgstr "" #~ "Git のバージョンが確認できません。\n" #~ "\n" #~ "%s はバージョン '%s' とのことです。\n" #~ "\n" #~ "%s は最低でも 1.5.0 かそれ以降の Git が必要です\n" #~ "\n" #~ "'%s' はバージョン 1.5.0 と思って良いですか?\n" #~ msgid "Git directory not found:" #~ msgstr "Git ディレクトリが見つかりません:" #~ msgid "Cannot move to top of working directory:" #~ msgstr "作業ディレクトリの最上位に移動できません" #~ msgid "Cannot use funny .git directory:" #~ msgstr "変な .git ディレクトリは使えません" #~ msgid "No working directory" #~ msgstr "作業ディレクトリがありません" #~ msgid "Refreshing file status..." #~ msgstr "ファイル状態を更新しています…" #~ msgid "Ready." #~ msgstr "準備完了" #~ msgid "Modified, not staged" #~ msgstr "変更あり、コミット未予定" #~ msgid "Portions staged for commit" #~ msgstr "部分的にコミット予定済" #~ msgid "Staged for commit, missing" #~ msgstr "コミット予定済、ファイル無し" #~ msgid "Staged for removal" #~ msgstr "削除予定済" #~ msgid "Staged for removal, still present" #~ msgstr "削除予定済、ファイル未削除" #~ msgid "Requires merge resolution" #~ msgstr "要マージ解決" #~ msgid "Starting gitk... please wait..." #~ msgstr "gitk を起動中…お待ち下さい…" #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "gitk を起動できません:\n" #~ "\n" #~ "%s がありません" #~ msgid "Repository" #~ msgstr "リポジトリ" #~ msgid "Commit@@noun" #~ msgstr "コミット" #~ msgid "Browse %s's Files" #~ msgstr "ブランチ %s のファイルを見る" #~ msgid "Visualize %s's History" #~ msgstr "ブランチ %s の履歴を見る" #~ msgid "Database Statistics" #~ msgstr "データベース統計" #~ msgid "Compress Database" #~ msgstr "データベース圧縮" #~ msgid "Verify Database" #~ msgstr "データベース検証" #~ msgid "Create Desktop Icon" #~ msgstr "デスクトップ・アイコンを作る" #~ msgid "Undo" #~ msgstr "元に戻す" #~ msgid "Redo" #~ msgstr "やり直し" #~ msgid "Cut" #~ msgstr "切り取り" #~ msgid "Paste" #~ msgstr "貼り付け" #~ msgid "Rename..." #~ msgstr "名前変更…" #~ msgid "New Commit" #~ msgstr "新規コミット" #~ msgid "Local Merge..." #~ msgstr "ローカル・マージ…" #~ msgid "Preferences..." #~ msgstr "設定…" #~ msgid "Current Branch:" #~ msgstr "現在のブランチ" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "ステージングされた(コミット予定済の)変更" #~ msgid "Initial Commit Message:" #~ msgstr "最初のコミットメッセージ:" #~ msgid "Amended Commit Message:" #~ msgstr "訂正したコミットメッセージ:" #~ msgid "Amended Initial Commit Message:" #~ msgstr "訂正した最初のコミットメッセージ:" #~ msgid "Amended Merge Commit Message:" #~ msgstr "訂正したマージコミットメッセージ:" #~ msgid "Apply/Reverse Hunk" #~ msgstr "パッチを適用/取り消す" #~ msgid "Show Less Context" #~ msgstr "文脈を少なく" #~ msgid "Show More Context" #~ msgstr "文脈を多く" #~ msgid "Decrease Font Size" #~ msgstr "フォントを小さく" #~ msgid "Increase Font Size" #~ msgstr "フォントを大きく" #~ msgid "Unstage Hunk From Commit" #~ msgstr "パッチをコミット予定から外す" #~ msgid "Stage Hunk For Commit" #~ msgstr "パッチをコミット予定に加える" #~ msgid "Initializing..." #~ msgstr "初期化しています…" #~ msgid "" #~ "Possible environment issues exist.\n" #~ "\n" #~ "The following environment variables are probably\n" #~ "going to be ignored by any Git subprocess run\n" #~ "by %s:\n" #~ "\n" #~ msgstr "" #~ "環境に問題がある可能性があります\n" #~ "\n" #~ "以下の環境変数は %s が起動する Git サブプロセスによって無視されるでしょ" #~ "う:\n" #~ "\n" #~ msgid "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "これは Cygwin で配布されている Tcl バイナリに\n" #~ "関しての既知の問題によります" #~ msgid "" #~ "\n" #~ "\n" #~ "A good replacement for %s\n" #~ "is placing values for the user.name and\n" #~ "user.email settings into your personal\n" #~ "~/.gitconfig file.\n" #~ msgstr "" #~ "\n" #~ "\n" #~ "個人的な ~/.gitconfig ファイル内で user.name と user.email の値を設定\n" #~ "するのが、%s の良い代用となります\n" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "Git のグラフィカルUI git-gui" #~ msgid "File Viewer" #~ msgstr "ファイルピューワ" #~ msgid "Reading %s..." #~ msgstr "%s を読んでいます…" #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "コピー・移動追跡データを読んでいます…" #~ msgid "lines annotated" #~ msgstr "行を注釈しました" #~ msgid "Loading original location annotations..." #~ msgstr "元位置行の注釈データを読んでいます…" #~ msgid "Annotation complete." #~ msgstr "注釈完了しました" #~ msgid "Loading annotation..." #~ msgstr "注釈を読み込んでいます…" #~ msgid "Original File:" #~ msgstr "元ファイル" #~ msgid "Originally By:" #~ msgstr "原作者:" #~ msgid "In File:" #~ msgstr "ファイル:" #~ msgid "Copied Or Moved Here By:" #~ msgstr "複写・移動者:" #~ msgid "Detach From Local Branch" #~ msgstr "ローカル・ブランチから削除" #~ msgid "Match Tracking Branch Name" #~ msgstr "トラッキング・ブランチ名を合わせる" #~ msgid "Tracking branch %s is not a branch in the remote repository." #~ msgstr "" #~ "トラッキング・ブランチ %s は遠隔リポジトリのブランチではありません。" #~ msgid "Please supply a branch name." #~ msgstr "ブランチ名を指定して下さい。" #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "'%s' はブランチ名に使えません。" #~ msgid "Delete Local Branch" #~ msgstr "ローカル・ブランチを削除" #~ msgid "Local Branches" #~ msgstr "ローカル・ブランチ" #~ msgid "Delete Only If Merged Into" #~ msgstr "マージ済みの時のみ削除" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "無条件(マージテストしない)" #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "以下のブランチは %s に完全にマージされていません:" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "ブランチを削除すると元に戻すのは困難です。 \n" #~ "\n" #~ " 選択したブランチを削除しますか?" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "以下のブランチを削除できません:\n" #~ "%s" #~ msgid "New Name:" #~ msgstr "新しい名前:" #~ msgid "Failed to rename '%s'." #~ msgstr "'%s'の名前変更に失敗しました。" #~ msgid "[Up To Parent]" #~ msgstr "[上位フォルダへ]" #~ msgid "Browse Branch Files" #~ msgstr "現在のブランチのファイルを見る" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "致命的エラー: %s を解決できません" #~ msgid "Branch '%s' does not exist." #~ msgstr "ブランチ'%s'は存在しません。" #~ msgid "" #~ "Branch '%s' already exists.\n" #~ "\n" #~ "It cannot fast-forward to %s.\n" #~ "A merge is required." #~ msgstr "" #~ "ブランチ '%s' は既に存在します。\n" #~ "\n" #~ "%s に早送りできません。\n" #~ "マージが必要です。" #~ msgid "Merge strategy '%s' not supported." #~ msgstr "'%s' マージ戦略はサポートされていません。" #~ msgid "Failed to update '%s'." #~ msgstr "'%s' の更新に失敗しました。" #~ msgid "Staging area (index) is already locked." #~ msgstr "インデックスは既にロックされています。" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before the current branch can be changed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "最後にスキャンした状態はリポジトリの状態と合致しません。\n" #~ "\n" #~ "最後にスキャンして以後、別の Git プログラムがリポジトリを変更しています。" #~ "現在のブランチを変更する前に、再スキャンが必要です。\n" #~ "\n" #~ "自動的に再スキャンを開始します。\n" #~ msgid "Updating working directory to '%s'..." #~ msgstr "作業ディレクトリを '%s' に更新しています…" #~ msgid "files checked out" #~ msgstr "チェックアウトされたファイル" #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "" #~ "'%s' のチェックアウトを中止しました(ファイル毎のマージが必要です)。" #~ msgid "File level merge required." #~ msgstr "ファイル毎のマージが必要です。" #~ msgid "Staying on branch '%s'." #~ msgstr "ブランチ '%s' に滞まります。" #~ msgid "" #~ "You are no longer on a local branch.\n" #~ "\n" #~ "If you wanted to be on a branch, create one now starting from 'This " #~ "Detached Checkout'." #~ msgstr "" #~ "ローカル・ブランチから離れます。\n" #~ "\n" #~ "ブランチ上に滞まりたいときは、この「分離されたチェックアウト」から新規ブラ" #~ "ンチを開始してください。" #~ msgid "Checked out '%s'." #~ msgstr "'%s' をチェックアウトしました" #~ msgid "Reset '%s'?" #~ msgstr "'%s' をリセットしますか?" #~ msgid "" #~ "Failed to set current branch.\n" #~ "\n" #~ "This working directory is only partially switched. We successfully " #~ "updated your files, but failed to update an internal Git file.\n" #~ "\n" #~ "This should not have occurred. %s will now close and give up." #~ msgstr "" #~ "現在のブランチを設定できません。\n" #~ "\n" #~ "作業ディレクトリは部分的にしか切り替わっていません。ファイルの更新には成功" #~ "しましたが、 Git の内部データを更新できませんでした。\n" #~ "起こるはずのないエラーです。あきらめて %s を終了します。" #~ msgid "Font Family" #~ msgstr "フォント・ファミリー" #~ msgid "Font Example" #~ msgstr "フォント・サンプル" #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "これはサンプル文です。\n" #~ "このフォントが気に入ればお使いになれます。" #~ msgid "Git Gui" #~ msgstr "Git GUI" #~ msgid "Clone Existing Repository" #~ msgstr "既存リポジトリを複製する" #~ msgid "Recent Repositories" #~ msgstr "最近使ったリポジトリ" #~ msgid "Failed to create repository %s:" #~ msgstr "リポジトリ %s を作製できません:" #~ msgid "Directory:" #~ msgstr "ディレクトリ:" #~ msgid "Directory %s already exists." #~ msgstr "ディレクトリ '%s' は既に存在します。" #~ msgid "Clone" #~ msgstr "複製" #~ msgid "Clone Type:" #~ msgstr "複製方式:" #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "標準(高速・中冗長度・ハードリンク)" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "全複写(低速・冗長バックアップ)" #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "共有(最高速・非推奨・バックアップ無し)" #~ msgid "Standard only available for local repository." #~ msgstr "標準方式は同一計算機上のリポジトリにのみ使えます。" #~ msgid "Shared only available for local repository." #~ msgstr "共有方式は同一計算機上のリポジトリにのみ使えます。" #~ msgid "Location %s already exists." #~ msgstr "'%s' は既に存在します。" #~ msgid "Failed to configure origin" #~ msgstr "origin を設定できませんでした" #~ msgid "Counting objects" #~ msgstr "オブジェクトを数えています" #~ msgid "buckets" #~ msgstr "バケツ" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "objects/info/alternates を複写できません: %s" #~ msgid "The 'master' branch has not been initialized." #~ msgstr "'master' ブランチが初期化されていません" #~ msgid "Hardlinks are unavailable. Falling back to copying." #~ msgstr "ハードリンクが作れないので、コピーします" #~ msgid "Cloning from %s" #~ msgstr "%s から複製しています" #~ msgid "Copying objects" #~ msgstr "オブジェクトを複写しています" #~ msgid "KiB" #~ msgstr "KiB" #~ msgid "Unable to copy object: %s" #~ msgstr "オブジェクトを複写できません: %s" #~ msgid "Linking objects" #~ msgstr "オブジェクトを連結しています" #~ msgid "objects" #~ msgstr "オブジェクト" #~ msgid "Unable to hardlink object: %s" #~ msgstr "オブジェクトをハードリンクできません: %s" #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "ブランチやオブジェクトを取得できません。コンソール出力を見て下さい" #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "タグを取得できません。コンソール出力を見て下さい" #~ msgid "Cannot determine HEAD. See console output for details." #~ msgstr "HEAD を確定できません。コンソール出力を見て下さい" #~ msgid "Unable to cleanup %s" #~ msgstr "%s を掃除できません" #~ msgid "Clone failed." #~ msgstr "複写に失敗しました。" #~ msgid "No default branch obtained." #~ msgstr "デフォールト・ブランチが取得されませんでした" #~ msgid "Cannot resolve %s as a commit." #~ msgstr "%s をコミットとして解釈できません" #~ msgid "Creating working directory" #~ msgstr "作業ディレクトリを作成しています" #~ msgid "files" #~ msgstr "ファイル" #~ msgid "Initial file checkout failed." #~ msgstr "初期チェックアウトに失敗しました" #~ msgid "Failed to open repository %s:" #~ msgstr "リポジトリ %s を開けません:" #~ msgid "This Detached Checkout" #~ msgstr "分離されたチェックアウト" #~ msgid "Updated" #~ msgstr "更新しました" #~ msgid "" #~ "There is nothing to amend.\n" #~ "\n" #~ "You are about to create the initial commit. There is no commit before " #~ "this to amend.\n" #~ msgstr "" #~ "訂正するコミットがそもそもありません。\n" #~ "\n" #~ "これから作るのは最初のコミットです。その前にはまだ訂正するようなコミットは" #~ "ありません。\n" #~ msgid "" #~ "Cannot amend while merging.\n" #~ "\n" #~ "You are currently in the middle of a merge that has not been fully " #~ "completed. You cannot amend the prior commit unless you first abort the " #~ "current merge activity.\n" #~ msgstr "" #~ "マージ中にコミットの訂正はできません。\n" #~ "\n" #~ "現在はまだマージの途中です。先にこのマージを中止しないと、前のコミットの訂" #~ "正はできません\n" #~ msgid "Error loading commit data for amend:" #~ msgstr "訂正するコミットのデータを読めません:" #~ msgid "Unable to obtain your identity:" #~ msgstr "ユーザの正体を確認できません:" #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "GIT_COMMITTER_IDENT が無効です:" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before another commit can be created.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "最後にスキャンした状態はリポジトリの状態と合致しません。\n" #~ "\n" #~ "最後にスキャンして以後、別の Git プログラムがリポジトリを変更しています。" #~ "新しくコミットする前に、再スキャンが必要です。\n" #~ "\n" #~ "自動的に再スキャンを開始します。\n" #~ msgid "" #~ "Unmerged files cannot be committed.\n" #~ "\n" #~ "File %s has merge conflicts. You must resolve them and stage the file " #~ "before committing.\n" #~ msgstr "" #~ "マージしていないファイルはコミットできません。\n" #~ "\n" #~ "ファイル %s にはマージ衝突が残っています。まず解決してコミット予定に加える" #~ "必要があります。\n" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "不明なファイル状態 %s です。\n" #~ "\n" #~ "ファイル %s は本プログラムではコミットできません。\n" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "警告: Tcl はエンコーディング '%s' をサポートしていません" #~ msgid "Calling pre-commit hook..." #~ msgstr "コミット前フックを実行中・・・" #~ msgid "Commit declined by pre-commit hook." #~ msgstr "コミット前フックがコミットを拒否しました" #~ msgid "Calling commit-msg hook..." #~ msgstr "コミット・メッセージ・フックを実行中・・・" #~ msgid "Commit declined by commit-msg hook." #~ msgstr "コミット・メッセージ・フックがコミットを拒否しました" #~ msgid "write-tree failed:" #~ msgstr "write-tree が失敗しました:" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "コミット %s は壊れています" #~ msgid "" #~ "No changes to commit.\n" #~ "\n" #~ "No files were modified by this commit and it was not a merge commit.\n" #~ "\n" #~ "A rescan will be automatically started now.\n" #~ msgstr "" #~ "コミットする変更がありません。\n" #~ "\n" #~ "マージでなく、また、一つも変更点がありません。\n" #~ "\n" #~ "自動的に再スキャンを開始します。\n" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree が失敗しました:" #~ msgid "update-ref failed:" #~ msgstr "update-ref が失敗しました:" #~ msgid "Working... please wait..." #~ msgstr "実行中…お待ち下さい…" #~ msgid "Error: Command Failed" #~ msgstr "エラー: コマンドが失敗しました" #~ msgid "Number of loose objects" #~ msgstr "ばらばらなオブジェクトの数" #~ msgid "Disk space used by loose objects" #~ msgstr "ばらばらなオブジェクトの使用するディスク量" #~ msgid "Number of packed objects" #~ msgstr "パックされたオブジェクトの数" #~ msgid "Number of packs" #~ msgstr "パックの数" #~ msgid "Disk space used by packed objects" #~ msgstr "パックされたオブジェクトの使用するディスク量" #~ msgid "Packed objects waiting for pruning" #~ msgstr "パックに存在するので捨てて良いオブジェクトの数" #~ msgid "Garbage files" #~ msgstr "ゴミファイル" #~ msgid "Compressing the object database" #~ msgstr "データベース圧縮" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "fsck-objects でオブジェクト・データベースを検証しています" #~ msgid "" #~ "This repository currently has approximately %i loose objects.\n" #~ "\n" #~ "To maintain optimal performance it is strongly recommended that you " #~ "compress the database when more than %i loose objects exist.\n" #~ "\n" #~ "Compress the database now?" #~ msgstr "" #~ "このリポジトリにはおおよそ %i 個の個別オブジェクトがあります\n" #~ "\n" #~ "最適な性能を保つために、%i 個以上の個別オブジェクトを作る毎にデータベース" #~ "を圧縮することを推奨します\n" #~ "\n" #~ "データベースを圧縮しますか?" #~ msgid "Invalid date from Git: %s" #~ msgstr "Git から出た無効な日付: %s" #~ msgid "" #~ "No differences detected.\n" #~ "\n" #~ "%s has no changes.\n" #~ "\n" #~ "The modification date of this file was updated by another application, " #~ "but the content within the file was not changed.\n" #~ "\n" #~ "A rescan will be automatically started to find other files which may have " #~ "the same state." #~ msgstr "" #~ "変更がありません。\n" #~ "\n" #~ "%s には変更がありません。\n" #~ "\n" #~ "このファイルの変更時刻は他のアプリケーションによって更新されていますがファ" #~ "イル内容には変更がありません。\n" #~ "\n" #~ "同様な状態のファイルを探すために、自動的に再スキャンを開始します。" #~ msgid "Unable to display %s" #~ msgstr "%s を表示できません" #~ msgid "Git Repository (subproject)" #~ msgstr "Git リポジトリ(サブプロジェクト)" #~ msgid "* Binary file (not showing content)." #~ msgstr "* バイナリファイル(内容は表示しません)" #~ msgid "Failed to unstage selected hunk." #~ msgstr "選択されたパッチをコミット予定から外せません。" #~ msgid "Failed to stage selected hunk." #~ msgstr "選択されたパッチをコミット予定に加えられません。" #~ msgid "warning" #~ msgstr "警告" #~ msgid "You must correct the above errors before committing." #~ msgstr "コミットする前に、以上のエラーを修正して下さい" #~ msgid "Unable to unlock the index." #~ msgstr "インデックスをロックできません" #~ msgid "" #~ "Updating the Git index failed. A rescan will be automatically started to " #~ "resynchronize git-gui." #~ msgstr "" #~ "GIT インデックスの更新が失敗しました。git-gui と同期をとるために再スキャン" #~ "します。" #~ msgid "Unlock Index" #~ msgstr "インデックスのロック解除" #~ msgid "Ready to commit." #~ msgstr "コミット準備完了" #~ msgid "Revert changes in these %i files?" #~ msgstr "これら %i 個のファイルにした変更を元に戻しますか?" #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "変更を元に戻すとコミット予定していない変更は全て失われます。" #~ msgid "Do Nothing" #~ msgstr "何もしない" #~ msgid "" #~ "Cannot merge while amending.\n" #~ "\n" #~ "You must finish amending this commit before starting any type of merge.\n" #~ msgstr "" #~ "訂正中にはマージできません。\n" #~ "\n" #~ "訂正処理を完了するまでは新たにマージを開始できません。\n" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before a merge can be performed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "最後にスキャンした状態はリポジトリの状態と合致しません。\n" #~ "\n" #~ "最後にスキャンして以後、別の Git プログラムがリポジトリを変更しています。" #~ "マージを開始する前に、再スキャンが必要です。\n" #~ "\n" #~ "自動的に再スキャンを開始します。\n" #~ msgid "" #~ "You are in the middle of a conflicted merge.\n" #~ "\n" #~ "File %s has merge conflicts.\n" #~ "\n" #~ "You must resolve them, stage the file, and commit to complete the current " #~ "merge. Only then can you begin another merge.\n" #~ msgstr "" #~ "衝突のあったマージの途中です。\n" #~ "\n" #~ "ファイル %s にはマージ中の衝突が残っています。\n" #~ "\n" #~ "このファイルの衝突を解決し、コミット予定に加えて、コミットすることでマージ" #~ "を完了します。そうやって始めて、新たなマージを開始できるようになります。\n" #~ msgid "" #~ "You are in the middle of a change.\n" #~ "\n" #~ "File %s is modified.\n" #~ "\n" #~ "You should complete the current commit before starting a merge. Doing so " #~ "will help you abort a failed merge, should the need arise.\n" #~ msgstr "" #~ "変更の途中です。\n" #~ "\n" #~ "ファイル %s は変更中です。\n" #~ "\n" #~ "現在のコミットを完了してからマージを開始して下さい。そうする方がマージに失" #~ "敗したときの回復が楽です。\n" #~ msgid "%s of %s" #~ msgstr "%s の %s ブランチ" #~ msgid "Merging %s and %s..." #~ msgstr "%s と %s をマージ中・・・" #~ msgid "Merge completed successfully." #~ msgstr "マージが完了しました" #~ msgid "Merge failed. Conflict resolution is required." #~ msgstr "マージが失敗しました。衝突の解決が必要です。" #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\n" #~ msgstr "" #~ "訂正中には中止できません。\n" #~ "\n" #~ "まず今のコミット訂正を完了させて下さい。\n" #~ msgid "" #~ "Reset changes?\n" #~ "\n" #~ "Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" #~ "\n" #~ "Continue with resetting the current changes?" #~ msgstr "" #~ "変更点をリセットしますか?\n" #~ "\n" #~ "変更点をリセットすると、コミットしていない全ての変更が失われます。\n" #~ "\n" #~ "リセットしてよろしいですか?" #~ msgid "files reset" #~ msgstr "リセットしたファイル" #~ msgid "Abort failed." #~ msgstr "中断に失敗しました。" #~ msgid "Abort completed. Ready." #~ msgstr "中断完了。" #~ msgid "Restore Defaults" #~ msgstr "既定値に戻す" #~ msgid "%s Repository" #~ msgstr "%s リポジトリ" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "フェッチ中にトラッキングブランチを刈る" #~ msgid "Match Tracking Branches" #~ msgstr "トラッキングブランチを合わせる" #~ msgid "New Branch Name Template" #~ msgstr "新しいブランチ名のテンプレート" #~ msgid "Spelling Dictionary:" #~ msgstr "スペルチェック辞書" #~ msgid "Change Font" #~ msgstr "フォントを変更" #~ msgid "pt." #~ msgstr "ポイント" #~ msgid "Failed to completely save options:" #~ msgstr "完全にオプションを保存できません:" #~ msgid "From Repository" #~ msgstr "元のリポジトリ" #~ msgid "Remote:" #~ msgstr "リモート:" #~ msgid "Arbitrary URL:" #~ msgstr "任意の URL:" #~ msgid "Delete Only If" #~ msgstr "条件付で削除" #~ msgid "Merged Into:" #~ msgstr "マージ先:" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "無条件(マージ検査をしない)" #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "'マージ先' にはブランチが必要です。" #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "以下のブランチは %s に完全にマージされていません:\n" #~ "\n" #~ " - %s" #~ msgid "" #~ "One or more of the merge tests failed because you have not fetched the " #~ "necessary commits. Try fetching from %s first." #~ msgstr "" #~ "必要なコミットが不足しているために、マージ検査が失敗しました。まず %s から" #~ "フェッチして下さい。" #~ msgid "Please select one or more branches to delete." #~ msgstr "削除するブランチを選択して下さい。" #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "削除したブランチを回復するのは困難です。\n" #~ "\n" #~ "選択したブランチを削除して良いですか?" #~ msgid "Prune from" #~ msgstr "から刈込む…" #~ msgid "Fetch from" #~ msgstr "取得元" #~ msgid "Push to" #~ msgstr "プッシュ先" #~ msgid "Cannot write shortcut:" #~ msgstr "ショートカットが書けません:" #~ msgid "Unsupported spell checker" #~ msgstr "サポートされていないスペルチェッカーです" #~ msgid "Spell checking is unavailable" #~ msgstr "スペルチェック機能は使えません" #~ msgid "Invalid spell checking configuration" #~ msgstr "スペルチェックの設定が不正です" #~ msgid "Reverting dictionary to %s." #~ msgstr "辞書を %s に巻き戻します" #~ msgid "Spell checker silently failed on startup" #~ msgstr "スペルチェッカーの起動に失敗しました" #~ msgid "Unrecognized spell checker" #~ msgstr "スペルチェッカーが判別できません" #~ msgid "Unexpected EOF from spell checker" #~ msgstr "スペルチェッカーが予想外の EOF を返しました" #~ msgid "Spell Checker Failed" #~ msgstr "スペルチェック失敗" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%1$s ... %4$*i %6$s 中の %2$*i (%7$3i%%)" #~ msgid "Fetching new changes from %s" #~ msgstr "%s から新しい変更をフェッチしています" #~ msgid "remote prune %s" #~ msgstr "遠隔刈込 %s" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "%s から削除されたトラッキング・ブランチを刈っています" #~ msgid "push %s" #~ msgstr "%s をプッシュ" #~ msgid "Pushing %s %s to %s" #~ msgstr "%3$s へ %1$s %2$s をプッシュしています" #~ msgid "Push Branches" #~ msgstr "ブランチをプッシュ" #~ msgid "Source Branches" #~ msgstr "元のブランチ" #~ msgid "Destination Repository" #~ msgstr "送り先リポジトリ" #~ msgid "Transfer Options" #~ msgstr "通信オプション" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "既存ブランチを上書き(変更を破棄する可能性があります)" #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Thin Pack を使う(遅いネットワーク接続)" #~ msgid "Not connected to aspell" #~ msgstr "aspell に接続していません" git-cola-1.9.3/po/ru.po000066400000000000000000002444741225156173500146550ustar00rootroot00000000000000# Translation of git-gui to russian # Copyright (C) 2007 Shawn Pearce # This file is distributed under the same license as the git-gui package. # Irina Riesen , 2007. # msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-09-24 21:42-0700\n" "PO-Revision-Date: 2007-10-22 22:30-0200\n" "Last-Translator: Alex Riesen \n" "Language-Team: Russian Translation \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: cola/bookmarks.py:32 msgid "Bookmarks" msgstr "" #: cola/bookmarks.py:47 msgid "Open" msgstr "Открыть" #: cola/bookmarks.py:53 msgid "Add" msgstr "" #: cola/bookmarks.py:58 cola/guicmds.py:25 cola/guicmds.py:33 #: cola/widgets/editremotes.py:127 msgid "Delete" msgstr "Удалить" #: cola/bookmarks.py:65 cola/stash/view.py:42 cola/widgets/archive.py:65 #: cola/widgets/browse.py:117 msgid "Save" msgstr "Сохранить" #: cola/bookmarks.py:71 cola/difftool.py:96 cola/qt.py:57 cola/qt.py:243 #: cola/prefs/view.py:241 cola/stash/view.py:50 cola/stash/view.py:51 #: cola/widgets/about.py:66 cola/widgets/about.py:126 #: cola/widgets/browse.py:116 cola/widgets/cfgactions.py:87 #: cola/widgets/cfgactions.py:239 cola/widgets/compare.py:94 #: cola/widgets/createbranch.py:159 cola/widgets/createtag.py:104 #: cola/widgets/editremotes.py:55 cola/widgets/grep.py:75 #: cola/widgets/recent.py:75 cola/widgets/remote.py:157 #: cola/widgets/search.py:81 cola/widgets/selectcommits.py:59 #: cola/widgets/startup.py:42 msgid "Close" msgstr "Закрыть" #: cola/bookmarks.py:102 msgid "Bookmarks Saved" msgstr "" #: cola/bookmarks.py:103 msgid "Successfully saved bookmarks" msgstr "" #: cola/bookmarks.py:107 #, fuzzy msgid "Path to git repository" msgstr "Каталог не является репозиторием: %s" #: cola/bookmarks.py:108 #, fuzzy msgid "Enter Git Repository" msgstr "Репозиторий" #: cola/cmds.py:105 msgid "Amend" msgstr "" #: cola/cmds.py:140 #, fuzzy msgid "Cannot Amend" msgstr "Невозможно записать значок:" #: cola/cmds.py:141 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" #: cola/cmds.py:204 #, python-format msgid "PATCH %(current)d/%(count)d" msgstr "" #: cola/cmds.py:208 msgid "Summary:" msgstr "" #: cola/cmds.py:217 msgid "Patch(es) Applied" msgstr "" #: cola/cmds.py:218 #, python-format msgid "%d patch(es) applied." msgstr "" #: cola/cmds.py:322 #, fuzzy, python-format msgid "Created commit: %s" msgstr "Создано состояние %s: %s " #: cola/cmds.py:324 #, fuzzy, python-format msgid "Commit failed: %s" msgstr "Сохранить состояние не удалось." #: cola/cmds.py:369 cola/cmds.py:1186 #, fuzzy msgid "Error" msgstr "ошибка" #: cola/cmds.py:370 #, python-format msgid "Deleting \"%s\" failed" msgstr "" #: cola/cmds.py:406 #, fuzzy msgid "Remote Branch Deleted" msgstr "Переименование ветви" #: cola/cmds.py:407 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "" #: cola/cmds.py:411 cola/guicmds.py:108 cola/widgets/remote.py:472 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "" #: cola/cmds.py:414 #, fuzzy msgid "Error Deleting Remote Branch" msgstr "Создание ветви" #: cola/cmds.py:493 cola/widgets/grep.py:60 cola/widgets/recent.py:69 msgid "Edit" msgstr "Редактировать" #: cola/cmds.py:529 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/cmds.py:531 #, fuzzy msgid "Error Editing File" msgstr "Ошибка загрузки diff:" #: cola/cmds.py:554 msgid "Launch Diff Tool" msgstr "" #: cola/cmds.py:577 msgid "Launch Editor" msgstr "" #: cola/cmds.py:598 msgid "Error: Cannot find commit template" msgstr "" #: cola/cmds.py:599 #, fuzzy, python-format msgid "%s: No such file or directory." msgstr "критическая ошибка: %s: нет такого файла или каталога" #: cola/cmds.py:616 msgid "Error: Unconfigured commit template" msgstr "" #: cola/cmds.py:617 msgid "" "A commit template has not been configured.\n" "Use \"git config\" to define \"commit.template\"\n" "so that it points to a commit template." msgstr "" #: cola/cmds.py:669 msgid "Open Using Default Application" msgstr "" #: cola/cmds.py:692 #, fuzzy msgid "Open Parent Directory" msgstr "Открыть последний репозиторий" #: cola/cmds.py:732 #, python-format msgid "Error: could not clone \"%s\"" msgstr "" #: cola/cmds.py:733 #, python-format msgid "git clone returned exit code %s" msgstr "" #: cola/cmds.py:756 cola/widgets/action.py:19 cola/widgets/editremotes.py:49 #: cola/widgets/grep.py:65 cola/widgets/recent.py:52 #: cola/widgets/recent.py:121 msgid "Refresh" msgstr "Обновить" #: cola/cmds.py:784 #, python-format msgid "Run \"%s\"?" msgstr "" #: cola/cmds.py:791 #, fuzzy msgid "Please select a file" msgstr "Укажите ветвь слежения." #: cola/cmds.py:792 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:804 #, fuzzy msgid "Invalid Revision" msgstr "Неверная версия: %s" #: cola/cmds.py:805 #, fuzzy msgid "The revision expression cannot be empty." msgstr "Пустое выражение для определения версии." #: cola/cmds.py:820 #, python-format msgid "Running command: %s" msgstr "" #: cola/cmds.py:829 cola/cmds.py:1006 cola/interaction.py:70 #, python-format msgid "Output: %s" msgstr "" #: cola/cmds.py:830 cola/guicmds.py:113 cola/interaction.py:71 #, python-format msgid "Errors: %s" msgstr "" #: cola/cmds.py:876 msgid "Sign Off" msgstr "Подписать" #: cola/cmds.py:897 msgid "unknown" msgstr "" #: cola/cmds.py:910 cola/widgets/action.py:17 #, fuzzy msgid "Stage" msgstr "Сохранить" #: cola/cmds.py:917 #, fuzzy, python-format msgid "Staging: %s" msgstr "Перечитывание %s... " #: cola/cmds.py:934 msgid "Stage Modified" msgstr "" #: cola/cmds.py:948 #, fuzzy msgid "Stage Unmerged" msgstr "Подготовить все" #: cola/cmds.py:962 #, fuzzy msgid "Stage Untracked" msgstr "Подготовить все" #: cola/cmds.py:980 #, python-format msgid "Tagging \"%(revision)s\" as \"%(name)s\"" msgstr "" #: cola/cmds.py:988 msgid "GPG-signed" msgstr "" #: cola/cmds.py:1020 cola/widgets/action.py:18 #, fuzzy msgid "Unstage" msgstr "Изменено (не будет сохранено)" #: cola/cmds.py:1027 #, fuzzy, python-format msgid "Unstaging: %s" msgstr "Удаление %s из подготовленного" #: cola/cmds.py:1055 #, python-format msgid "Untracking: %s" msgstr "" #: cola/cmds.py:1137 #, fuzzy msgid "Error Launching History Browser" msgstr "Просмотр списка файлов" #: cola/cmds.py:1138 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/difftool.py:76 msgid "git-cola diff" msgstr "" #: cola/difftool.py:92 cola/widgets/compare.py:90 msgid "Compare" msgstr "" #: cola/gitcmds.py:402 #, fuzzy msgid "Nothing to do" msgstr "Нечего клонировать с %s." #: cola/guicmds.py:25 msgid "Delete Branch" msgstr "Удаление ветви" #: cola/guicmds.py:33 #, fuzzy msgid "Delete Remote Branch" msgstr "Удалить внешнюю ветвь" #: cola/guicmds.py:53 #, fuzzy msgid "Browse Commits..." msgstr "Показать" #: cola/guicmds.py:53 #, fuzzy msgid "Browse" msgstr "Показать" #: cola/guicmds.py:61 msgid "Checkout Branch" msgstr "Перейти на ветвь" #: cola/guicmds.py:61 msgid "Checkout" msgstr "Перейти" #: cola/guicmds.py:70 #, fuzzy msgid "Cherry-Pick Commit" msgstr "Скопировать SHA-1" #: cola/guicmds.py:107 #, fuzzy msgid "Error Creating Repository" msgstr "Создать новый репозиторий" #: cola/guicmds.py:110 #, python-format msgid "" "Output:\n" "%s" msgstr "" #: cola/guicmds.py:132 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/guicmds.py:153 #, fuzzy msgid "Error Cloning" msgstr "Ошибка загрузки файла:" #: cola/guicmds.py:154 cola/guicmds.py:155 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/guicmds.py:159 msgid "Select a parent directory for the new clone" msgstr "" #: cola/guicmds.py:169 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/guicmds.py:185 cola/widgets/search.py:75 msgid "Export Patches" msgstr "" #: cola/guicmds.py:214 cola/widgets/startup.py:124 #, fuzzy msgid "Open Git Repository..." msgstr "Выбрать существующий репозиторий" #: cola/guicmds.py:223 #, fuzzy msgid "Load Commit Message" msgstr "Комментарий к состоянию:" #: cola/guicmds.py:251 #, fuzzy msgid "Select New Base" msgstr "Выбрать" #: cola/guicmds.py:251 #, fuzzy msgid "Rebase" msgstr "Сброс" #: cola/guicmds.py:261 #, fuzzy msgid "Select Branch to Review" msgstr "Удаление ветви" #: cola/guicmds.py:261 msgid "Review" msgstr "" #: cola/inotify.py:47 msgid "inotify is disabled because \"cola.inotify\" is false" msgstr "" #: cola/inotify.py:53 msgid "" "file notification: disabled\n" "Note: install pywin32 to enable.\n" msgstr "" #: cola/inotify.py:56 msgid "" "inotify: disabled\n" "Note: install python-pyinotify to enable inotify.\n" msgstr "" #: cola/inotify.py:62 msgid "On Debian systems try: sudo aptitude install python-pyinotify" msgstr "" #: cola/inotify.py:71 #, fuzzy msgid "File notification enabled." msgstr "Доверять времени модификации файла" #: cola/inotify.py:73 msgid "inotify enabled." msgstr "" #: cola/interaction.py:53 msgid "Continue" msgstr "Продолжить" #: cola/interaction.py:63 #, python-format msgid "Run %s?" msgstr "" #: cola/interaction.py:64 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/interaction.py:65 cola/widgets/cfgactions.py:240 msgid "Run" msgstr "" #: cola/interaction.py:72 #, python-format msgid "Exit code: %s" msgstr "" #: cola/qt.py:60 cola/qt.py:100 #, fuzzy msgid "Detach" msgstr "Удаление ветви" #: cola/qt.py:98 msgid "Attach" msgstr "" #: cola/qtutils.py:396 #, fuzzy msgid "Close..." msgstr "Склонировать..." #: cola/classic/controller.py:69 msgid "Select Previous Version" msgstr "" #: cola/classic/model.py:37 cola/widgets/createtag.py:51 #: cola/widgets/editremotes.py:220 #, fuzzy msgid "Name" msgstr "Название:" #: cola/classic/model.py:39 cola/main/view.py:91 msgid "Status" msgstr "" #: cola/classic/model.py:41 msgid "Age" msgstr "" #: cola/classic/model.py:43 cola/widgets/createtag.py:74 #, fuzzy msgid "Message" msgstr "Объединить" #: cola/classic/model.py:45 cola/dag/view.py:371 #, fuzzy msgid "Author" msgstr "Автор:" #: cola/classic/model.py:342 #, python-format msgid "%d minutes ago" msgstr "" #: cola/classic/model.py:345 #, python-format msgid "%d hours ago" msgstr "" #: cola/classic/model.py:346 #, python-format msgid "%d days ago" msgstr "" #: cola/classic/model.py:359 cola/widgets/status.py:73 #, fuzzy msgid "Unmerged" msgstr "Объединить" #: cola/classic/model.py:361 msgid "Partially Staged" msgstr "" #: cola/classic/model.py:363 cola/widgets/status.py:74 #, fuzzy msgid "Modified" msgstr "Не изменено" #: cola/classic/model.py:365 cola/widgets/status.py:72 #, fuzzy msgid "Staged" msgstr "Подготовить все" #: cola/classic/model.py:367 msgid "Changed Upstream" msgstr "" #: cola/classic/view.py:47 cola/main/view.py:545 #, fuzzy, python-format msgid "Repository: %s" msgstr "Репозиторий:" #: cola/classic/view.py:49 cola/main/view.py:547 #, fuzzy, python-format msgid "Branch: %s" msgstr "Ветвь:" #: cola/classic/view.py:52 #, python-format msgid "%s: %s - Browse" msgstr "" #: cola/classic/view.py:54 cola/main/view.py:552 msgid "Amending" msgstr "" #: cola/classic/view.py:79 msgid "View History..." msgstr "" #: cola/classic/view.py:80 msgid "View history for selected path(s)." msgstr "" #: cola/classic/view.py:84 cola/widgets/status.py:506 #: cola/widgets/status.py:536 cola/widgets/status.py:593 #, fuzzy msgid "Stage Selected" msgstr "Выбрать" #: cola/classic/view.py:85 #, fuzzy msgid "Stage selected path(s) for commit." msgstr "Подготовлено для сохранения" #: cola/classic/view.py:90 cola/widgets/status.py:452 #: cola/widgets/status.py:494 msgid "Unstage Selected" msgstr "" #: cola/classic/view.py:91 msgid "Remove selected path(s) from the staging area." msgstr "" #: cola/classic/view.py:96 msgid "Untrack Selected" msgstr "" #: cola/classic/view.py:97 msgid "Stop tracking path(s)" msgstr "" #: cola/classic/view.py:102 msgid "Launch git-difftool on the current path." msgstr "" #: cola/classic/view.py:106 msgid "Diff Against Predecessor..." msgstr "" #: cola/classic/view.py:107 msgid "Launch git-difftool against previous versions." msgstr "" #: cola/classic/view.py:111 #, fuzzy msgid "Revert Uncommitted Changes..." msgstr "Отменить изменения" #: cola/classic/view.py:112 #, fuzzy msgid "Revert changes to selected path(s)." msgstr "Отменить изменения в файле %s?" #: cola/classic/view.py:117 msgid "Edit selected path(s)." msgstr "" #: cola/classic/view.py:293 cola/widgets/status.py:652 #, fuzzy msgid "Revert Uncommitted Changes?" msgstr "Отменить изменения" #: cola/classic/view.py:294 cola/widgets/diff.py:246 cola/widgets/diff.py:259 #: cola/widgets/status.py:653 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/classic/view.py:296 cola/widgets/diff.py:248 cola/widgets/diff.py:261 #: cola/widgets/status.py:655 msgid "Revert the uncommitted changes?" msgstr "" #: cola/classic/view.py:297 cola/widgets/status.py:656 #, fuzzy msgid "Revert Uncommitted Changes" msgstr "Отменить изменения" #: cola/dag/view.py:166 #, fuzzy msgid "Loading..." msgstr "Загрузка %s..." #: cola/dag/view.py:272 msgid "Diff this -> selected" msgstr "" #: cola/dag/view.py:275 msgid "Diff selected -> this" msgstr "" #: cola/dag/view.py:278 cola/widgets/createbranch.py:89 #: cola/widgets/createbranch.py:98 cola/widgets/createbranch.py:155 #: cola/widgets/createbranch.py:330 msgid "Create Branch" msgstr "Создание ветви" #: cola/dag/view.py:281 #, fuzzy msgid "Create Patch" msgstr "Создание ветви" #: cola/dag/view.py:284 cola/widgets/createtag.py:38 #: cola/widgets/createtag.py:99 #, fuzzy msgid "Create Tag" msgstr "Создать" #: cola/dag/view.py:287 cola/main/view.py:208 msgid "Save As Tarball/Zip..." msgstr "" #: cola/dag/view.py:290 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/dag/view.py:293 msgid "Grab File..." msgstr "" #: cola/dag/view.py:296 #, fuzzy msgid "Copy SHA-1" msgstr "Копировать все" #: cola/dag/view.py:371 msgid "Summary" msgstr "" #: cola/dag/view.py:371 msgid "Date, Time" msgstr "" #: cola/dag/view.py:378 msgid "Go Up" msgstr "" #: cola/dag/view.py:381 msgid "Go Down" msgstr "" #: cola/dag/view.py:511 cola/dag/view.py:1181 msgid "Zoom Out" msgstr "" #: cola/dag/view.py:514 cola/dag/view.py:1178 msgid "Zoom In" msgstr "" #: cola/dag/view.py:517 cola/dag/view.py:1184 msgid "Zoom to Fit" msgstr "" #: cola/dag/view.py:536 msgid "Log" msgstr "" #: cola/dag/view.py:541 cola/main/view.py:114 cola/main/view.py:384 msgid "Diff" msgstr "" #: cola/dag/view.py:554 msgid "Graph" msgstr "" #: cola/dag/view.py:563 msgid "View" msgstr "" #: cola/dag/view.py:636 #, python-format msgid "%s: %s - DAG" msgstr "" #: cola/dag/view.py:638 msgid " - DAG" msgstr "" #: cola/dag/view.py:1187 #, fuzzy msgid "Select Parent" msgstr "Выбрать" #: cola/dag/view.py:1190 msgid "Select Oldest Parent" msgstr "" #: cola/dag/view.py:1193 #, fuzzy msgid "Select Child" msgstr "Выделить все" #: cola/dag/view.py:1196 msgid "Select Newest Child" msgstr "" #: cola/main/view.py:78 #, fuzzy msgid "Browser" msgstr "Показать" #: cola/main/view.py:83 #, fuzzy msgid "Action" msgstr "Настройки" #: cola/main/view.py:99 cola/merge/view.py:45 #, fuzzy msgid "Commit" msgstr "Сохраненное состояние:" #: cola/main/view.py:108 #, fuzzy msgid "Console" msgstr "Закрыть" #: cola/main/view.py:120 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/main/view.py:125 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/main/view.py:130 msgid "Ignore all whitespace" msgstr "" #: cola/main/view.py:135 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/main/view.py:139 cola/widgets/createbranch.py:194 msgid "Options" msgstr "Настройки" #: cola/main/view.py:141 cola/main/view.py:142 #, fuzzy msgid "Diff Options" msgstr "Настройки" #: cola/main/view.py:157 cola/widgets/status.py:423 msgid "Unstage All" msgstr "" #: cola/main/view.py:161 msgid "Unstage From Commit" msgstr "Убрать из подготовленного" #: cola/main/view.py:165 msgid "Diffstat" msgstr "" #: cola/main/view.py:168 msgid "Stage Changed Files To Commit" msgstr "Подготовить измененные файлы для сохранения" #: cola/main/view.py:173 msgid "Stage All Untracked" msgstr "" #: cola/main/view.py:178 msgid "Export Patches..." msgstr "" #: cola/main/view.py:181 #, fuzzy msgid "New Repository..." msgstr "Репозиторий" #: cola/main/view.py:185 cola/prefs/view.py:220 msgid "Preferences" msgstr "Настройки" #: cola/main/view.py:189 msgid "Edit Remotes..." msgstr "" #: cola/main/view.py:197 #, fuzzy msgid "Recently Modified Files..." msgstr "Поиск измененных файлов..." #: cola/main/view.py:201 #, fuzzy msgid "Cherry-Pick..." msgstr "Перейти..." #: cola/main/view.py:205 #, fuzzy msgid "Load Commit Message..." msgstr "Комментарий к состоянию:" #: cola/main/view.py:211 msgid "Quit" msgstr "Выход" #: cola/main/view.py:213 msgid "Bookmarks..." msgstr "" #: cola/main/view.py:215 msgid "Grep" msgstr "" #: cola/main/view.py:217 #, fuzzy msgid "Merge..." msgstr "Объединить" #: cola/main/view.py:220 cola/merge/__init__.py:20 msgid "Abort Merge..." msgstr "Прервать объединение..." #: cola/main/view.py:223 cola/widgets/action.py:20 #, fuzzy msgid "Fetch..." msgstr "Сбросить..." #: cola/main/view.py:225 cola/widgets/action.py:21 msgid "Push..." msgstr "Отправить..." #: cola/main/view.py:227 cola/widgets/action.py:22 #, fuzzy msgid "Pull..." msgstr "Отправить..." #: cola/main/view.py:230 cola/widgets/startup.py:36 msgid "Open..." msgstr "Открыть..." #: cola/main/view.py:234 cola/widgets/action.py:23 #, fuzzy msgid "Stash..." msgstr "Отправить..." #: cola/main/view.py:237 cola/widgets/startup.py:39 msgid "Clone..." msgstr "Склонировать..." #: cola/main/view.py:241 #, fuzzy msgid "Documentation" msgstr "Документация в интернете" #: cola/main/view.py:245 msgid "Keyboard Shortcuts" msgstr "" #: cola/main/view.py:250 #, fuzzy msgid "Visualize Current Branch..." msgstr "История текущей ветви наглядно" #: cola/main/view.py:253 #, fuzzy msgid "Visualize All Branches..." msgstr "История всех ветвей наглядно" #: cola/main/view.py:256 #, fuzzy msgid "Search..." msgstr "Запуск..." #: cola/main/view.py:258 #, fuzzy msgid "Browse Current Branch..." msgstr "Просмотреть файлы текущей ветви" #: cola/main/view.py:260 #, fuzzy msgid "Browse Other Branch..." msgstr "Показать файлы ветви..." #: cola/main/view.py:262 #, fuzzy msgid "Get Commit Message Template" msgstr "Ширина комментария к состоянию:" #: cola/main/view.py:265 #, fuzzy msgid "About" msgstr "О %s" #: cola/main/view.py:268 #, fuzzy msgid "Expression..." msgstr "Настройки..." #: cola/main/view.py:270 #, fuzzy msgid "Branches..." msgstr "Ветви" #: cola/main/view.py:273 #, fuzzy msgid "Create Tag..." msgstr "Создать..." #: cola/main/view.py:276 msgid "Create..." msgstr "Создать..." #: cola/main/view.py:279 msgid "Delete..." msgstr "Удалить..." #: cola/main/view.py:282 #, fuzzy msgid "Delete Remote Branch..." msgstr "Удалить внешнюю ветвь" #: cola/main/view.py:285 msgid "Checkout..." msgstr "Перейти..." #: cola/main/view.py:287 #, fuzzy msgid "Rebase..." msgstr "Сбросить..." #: cola/main/view.py:289 #, fuzzy msgid "Review..." msgstr "Сбросить..." #: cola/main/view.py:292 #, fuzzy msgid "Browser..." msgstr "Показать" #: cola/main/view.py:296 msgid "DAG..." msgstr "" #: cola/main/view.py:313 #, fuzzy msgid "File" msgstr "Файл:" #: cola/main/view.py:316 #, fuzzy msgid "Open Recent" msgstr "Открыть последний репозиторий" #: cola/main/view.py:338 cola/main/view.py:339 #, fuzzy msgid "Index" msgstr "Ошибка индекса" #: cola/main/view.py:349 msgid "Branch" msgstr "Ветвь" #: cola/main/view.py:367 #, fuzzy msgid "Actions" msgstr "Настройки" #: cola/main/view.py:393 msgid "Tools" msgstr "" #: cola/main/view.py:404 msgid "Help" msgstr "Помощь" #: cola/main/view.py:462 #, python-format msgid "git cola version %s" msgstr "" #: cola/merge/__init__.py:21 #, fuzzy msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Прервать объединение?\n" "\n" "Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n" "\n" "Продолжить?" #: cola/merge/__init__.py:24 msgid "Aborting the current merge?" msgstr "" #: cola/merge/__init__.py:25 #, fuzzy msgid "Abort Merge" msgstr "Прервать объединение..." #: cola/merge/view.py:23 msgid "Revision To Merge" msgstr "Версия для объединения" #: cola/merge/view.py:28 cola/widgets/cfgactions.py:220 #: cola/widgets/remote.py:122 msgid "Local Branch" msgstr "Локальная ветвь:" #: cola/merge/view.py:31 cola/widgets/cfgactions.py:221 msgid "Tracking Branch" msgstr "Ветвь слежения" #: cola/merge/view.py:33 cola/widgets/cfgactions.py:222 #: cola/widgets/createbranch.py:122 msgid "Tag" msgstr "Таг" #: cola/merge/view.py:39 msgid "Visualize" msgstr "Наглядно" #: cola/merge/view.py:42 #, fuzzy msgid "Squash" msgstr "Отправить" #: cola/merge/view.py:50 cola/widgets/archive.py:62 #: cola/widgets/editremotes.py:204 msgid "Cancel" msgstr "Отменить" #: cola/merge/view.py:53 msgid "Merge" msgstr "Объединить" #: cola/merge/view.py:115 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/merge/view.py:118 #, fuzzy, python-format msgid "Merge into \"%s\"" msgstr "Объединить с %s" #: cola/merge/view.py:162 cola/merge/view.py:171 #, fuzzy msgid "No Revision Specified" msgstr "Версия не указана." #: cola/merge/view.py:163 msgid "You must specify a revision to view." msgstr "" #: cola/merge/view.py:172 msgid "You must specify a revision to merge." msgstr "" #: cola/prefs/view.py:116 msgid "User Name" msgstr "Имя пользователя" #: cola/prefs/view.py:117 msgid "Email Address" msgstr "Адрес электронной почты" #: cola/prefs/view.py:118 msgid "Merge Verbosity" msgstr "Уровень детальности сообщений при объединении" #: cola/prefs/view.py:119 msgid "Number of Diff Context Lines" msgstr "Число строк в контексте diff" #: cola/prefs/view.py:120 msgid "Summarize Merge Commits" msgstr "Суммарный комментарий при объединении" #: cola/prefs/view.py:121 msgid "Show Diffstat After Merge" msgstr "Показать отчет об изменениях после объединения" #: cola/prefs/view.py:122 msgid "Display Untracked Files" msgstr "" #: cola/prefs/view.py:163 msgid "Fixed-Width Font" msgstr "" #: cola/prefs/view.py:164 msgid "Font Size" msgstr "Размер шрифта" #: cola/prefs/view.py:165 msgid "Tab Width" msgstr "" #: cola/prefs/view.py:166 msgid "Text Width" msgstr "" #: cola/prefs/view.py:167 cola/widgets/commitmsg.py:99 msgid "Auto-Wrap Lines" msgstr "" #: cola/prefs/view.py:168 #, fuzzy msgid "Editor" msgstr "Редактировать" #: cola/prefs/view.py:169 #, fuzzy msgid "History Browser" msgstr "Просмотр списка файлов" #: cola/prefs/view.py:170 msgid "Diff Tool" msgstr "" #: cola/prefs/view.py:171 #, fuzzy msgid "Merge Tool" msgstr "Объединить" #: cola/prefs/view.py:172 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/prefs/view.py:173 msgid "Save GUI Settings" msgstr "" #: cola/prefs/view.py:227 #, fuzzy msgid "All Repositories" msgstr "Общие (для всех репозиториев)" #: cola/prefs/view.py:228 #, fuzzy msgid "Current Repository" msgstr "Создать новый репозиторий" #: cola/prefs/view.py:229 #, fuzzy msgid "Settings" msgstr "Запуск..." #: cola/stash/view.py:28 msgid "Stash" msgstr "" #: cola/stash/view.py:38 msgid "Apply" msgstr "" #: cola/stash/view.py:39 msgid "Apply the selected stash" msgstr "" #: cola/stash/view.py:43 msgid "Save modified state to new stash" msgstr "" #: cola/stash/view.py:46 msgid "Drop" msgstr "" #: cola/stash/view.py:47 msgid "Drop the selected stash" msgstr "" #: cola/stash/view.py:54 msgid "Keep Index" msgstr "" #: cola/stash/view.py:175 msgid "Save Stash" msgstr "" #: cola/stash/view.py:176 msgid "Enter a name for the stash" msgstr "" #: cola/stash/view.py:182 msgid "Error: Stash exists" msgstr "" #: cola/stash/view.py:183 #, fuzzy, python-format msgid "A stash named \"%s\" already exists" msgstr "Файл '%s' уже существует." #: cola/stash/view.py:198 msgid "Drop Stash?" msgstr "" #: cola/stash/view.py:199 #, fuzzy msgid "Recovering a dropped stash is not possible." msgstr "Восстановить потерянные сохраненные состояния будет сложно." #: cola/stash/view.py:200 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/stash/view.py:201 msgid "Drop Stash" msgstr "" #: cola/widgets/about.py:47 msgid "About git-cola" msgstr "" #: cola/widgets/about.py:97 msgid "" "This PyQt4 does not include QtWebKit.\n" "The keyboard shortcuts feature is unavailable." msgstr "" #: cola/widgets/about.py:104 msgid "hotkeys.html" msgstr "" #: cola/widgets/about.py:122 msgid "Shortcuts" msgstr "" #: cola/widgets/archive.py:46 msgid "Save Archive" msgstr "" #: cola/widgets/archive.py:69 msgid "Prefix" msgstr "" #: cola/widgets/archive.py:74 msgid "Advanced" msgstr "" #: cola/widgets/archive.py:141 cola/widgets/browse.py:49 msgid "File Saved" msgstr "" #: cola/widgets/archive.py:142 cola/widgets/browse.py:50 #, python-format msgid "File saved to \"%s\"" msgstr "" #: cola/widgets/archive.py:149 msgid "Overwrite File?" msgstr "" #: cola/widgets/archive.py:150 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/widgets/archive.py:151 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:152 msgid "Overwrite" msgstr "" #: cola/widgets/browse.py:42 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/browse.py:63 #, fuzzy, python-format msgid "Browsing %s" msgstr "Добавление %s..." #: cola/widgets/browse.py:81 #, fuzzy, python-format msgid "Select file from \"%s\"" msgstr "Удаление ветвей из %s" #: cola/widgets/browse.py:90 #, fuzzy msgid "Select File" msgstr "Выделить все" #: cola/widgets/browse.py:117 cola/widgets/selectcommits.py:54 msgid "Select" msgstr "Выбрать" #: cola/widgets/cfgactions.py:85 #, fuzzy msgid "Abort" msgstr "Прерываю" #: cola/widgets/cfgactions.py:147 cola/widgets/cfgactions.py:151 #, fuzzy msgid "Abort Action" msgstr "Прерываю" #: cola/widgets/cfgactions.py:148 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/widgets/cfgactions.py:150 msgid "Abort the action?" msgstr "" #: cola/widgets/cfgactions.py:201 msgid "Arguments" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/createtag.py:85 msgid "Revision" msgstr "Версия" #: cola/widgets/commitmsg.py:50 #, fuzzy msgid "Sign off on this commit" msgstr "Подготовлено для сохранения" #: cola/widgets/commitmsg.py:53 cola/widgets/commitmsg.py:69 msgid "Commit@@verb" msgstr "Сохранить" #: cola/widgets/commitmsg.py:56 #, fuzzy msgid "Commit staged changes" msgstr "Сохранение изменений..." #: cola/widgets/commitmsg.py:67 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:75 #, fuzzy msgid "Actions..." msgstr "Настройки..." #: cola/widgets/commitmsg.py:85 msgid "Amend Last Commit" msgstr "Исправить последнее состояние" #: cola/widgets/commitmsg.py:92 msgid "Check Spelling" msgstr "" #: cola/widgets/commitmsg.py:104 #, fuzzy msgid "Load Previous Commit Message" msgstr "Комментарий к объединению:" #: cola/widgets/commitmsg.py:135 cola/widgets/status.py:117 msgid "Move Down" msgstr "" #: cola/widgets/commitmsg.py:342 msgid "" "Please supply a commit message.\n" "\n" "A good commit message has the following format:\n" "\n" "- First line: Describe in one sentence what you did.\n" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" "Напишите комментарий к сохраненному состоянию.\n" "\n" "Рекомендуется следующий формат комментария:\n" "\n" "- первая строка: краткое описание сделанных изменений.\n" "- вторая строка пустая\n" "- оставшиеся строки: опишите, что дают ваши изменения.\n" #: cola/widgets/commitmsg.py:349 #, fuzzy msgid "Missing Commit Message" msgstr "Комментарий к объединению:" #: cola/widgets/commitmsg.py:355 #, fuzzy msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Отсутствуют изменения для сохранения.\n" "\n" "Подготовьте хотя бы один файл до создания сохраненного состояния.\n" #: cola/widgets/commitmsg.py:359 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/commitmsg.py:361 #, fuzzy msgid "Stage and commit?" msgstr "Подготовлено для сохранения" #: cola/widgets/commitmsg.py:364 #, fuzzy msgid "Stage and Commit" msgstr "Подготовить для сохранения" #: cola/widgets/commitmsg.py:369 #, fuzzy msgid "Nothing to commit" msgstr "Отуствуют измения для сохранения." #: cola/widgets/commitmsg.py:376 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/commitmsg.py:377 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" #: cola/widgets/commitmsg.py:380 msgid "Amend the published commit?" msgstr "" #: cola/widgets/commitmsg.py:381 #, fuzzy msgid "Amend Commit" msgstr "Исправить последнее состояние" #: cola/widgets/commitmsg.py:386 #, fuzzy msgid "Commit failed" msgstr "Сохранить состояние не удалось." #: cola/widgets/commitmsg.py:387 #, python-format msgid "\"git commit\" returned exit code %s" msgstr "" #: cola/widgets/commitmsg.py:409 #, fuzzy msgid "More..." msgstr "Склонировать..." #: cola/widgets/commitmsg.py:413 #, fuzzy msgid "Select Commit Message" msgstr "Комментарий к объединению:" #: cola/widgets/commitmsg.py:450 #, fuzzy msgid "Commit summary" msgstr "Комментарий к состоянию:" #: cola/widgets/commitmsg.py:465 msgid "Extended description..." msgstr "" #: cola/widgets/compare.py:37 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:38 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/compare.py:39 cola/widgets/compare.py:62 #: cola/widgets/compare.py:68 msgid "Local" msgstr "" #: cola/widgets/compare.py:44 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/compare.py:63 cola/widgets/compare.py:69 #: cola/widgets/remote.py:129 msgid "Remote" msgstr "Внешние репозитории" #: cola/widgets/compare.py:98 #, fuzzy msgid "File Differences" msgstr "Настройки" #: cola/widgets/createbranch.py:102 msgid "Branch Name" msgstr "Название ветви" #: cola/widgets/createbranch.py:107 cola/widgets/createbranch.py:178 msgid "Starting Revision" msgstr "Начальная версия" #: cola/widgets/createbranch.py:115 #, fuzzy msgid "Local branch" msgstr "Локальная ветвь:" #: cola/widgets/createbranch.py:119 #, fuzzy msgid "Tracking branch" msgstr "Ветвь слежения" #: cola/widgets/createbranch.py:127 msgid "Update Existing Branch:" msgstr "Обновить имеющуюся ветвь:" #: cola/widgets/createbranch.py:130 msgid "No" msgstr "Нет" #: cola/widgets/createbranch.py:133 msgid "Fast Forward Only" msgstr "Только Fast Forward" #: cola/widgets/createbranch.py:137 msgid "Reset" msgstr "Сброс" #: cola/widgets/createbranch.py:143 msgid "Fetch Tracking Branch" msgstr "Получить изменения из внешней ветви" #: cola/widgets/createbranch.py:148 msgid "Checkout After Creation" msgstr "После создания сделать текущей" #: cola/widgets/createbranch.py:259 #, fuzzy msgid "Missing Data" msgstr "Отсутствует" #: cola/widgets/createbranch.py:260 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/widgets/createbranch.py:265 #, fuzzy, python-format msgid "Branch \"%s\" already exists." msgstr "Ветвь '%s' уже существует." #: cola/widgets/createbranch.py:266 cola/widgets/createbranch.py:277 #, fuzzy msgid "Branch Exists" msgstr "Ветви" #: cola/widgets/createbranch.py:273 #, fuzzy, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "Сброс '%s' в '%s' приведет к потере следующих сохраненных состояний: " #: cola/widgets/createbranch.py:288 #, python-format msgid "%d skipped" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Recovering lost commits may not be easy." msgstr "Восстановить потерянные сохраненные состояния будет сложно." #: cola/widgets/createbranch.py:292 #, fuzzy msgid "Reset Branch?" msgstr "Удаление ветви" #: cola/widgets/createbranch.py:294 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/widgets/createbranch.py:296 #, fuzzy msgid "Reset Branch" msgstr "Удаление ветви" #: cola/widgets/createbranch.py:305 #, fuzzy msgid "Updating..." msgstr "Запуск..." #: cola/widgets/createbranch.py:321 #, fuzzy msgid "Error Creating Branch" msgstr "Создание ветви" #: cola/widgets/createbranch.py:322 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/widgets/createbranch.py:331 #, fuzzy msgid "Branch created" msgstr "Название ветви" #: cola/widgets/createtag.py:55 msgid "vX.Y.Z" msgstr "" #: cola/widgets/createtag.py:56 msgid "Specifies the tag name" msgstr "" #: cola/widgets/createtag.py:62 #, fuzzy msgid "Sign Tag" msgstr "Подписать" #: cola/widgets/createtag.py:67 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:91 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:121 #, fuzzy msgid "Missing Revision" msgstr "Начальная версия" #: cola/widgets/createtag.py:122 #, fuzzy msgid "Please specify a revision to tag." msgstr "Укажите ветвь для переименования." #: cola/widgets/createtag.py:125 #, fuzzy msgid "Missing Name" msgstr "Отсутствует" #: cola/widgets/createtag.py:126 msgid "Please specify a name for the new tag." msgstr "" #: cola/widgets/createtag.py:129 #, fuzzy msgid "Missing Tag Message" msgstr "Версия для объединения" #: cola/widgets/createtag.py:130 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/createtag.py:132 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/createtag.py:135 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/createtag.py:142 #, fuzzy msgid "Tag Created" msgstr "Создать" #: cola/widgets/createtag.py:143 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/diff.py:22 msgid "Process Section" msgstr "" #: cola/widgets/diff.py:25 msgid "Process Selection" msgstr "" #: cola/widgets/diff.py:40 msgid "Stage &Selected Lines" msgstr "" #: cola/widgets/diff.py:46 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:51 #, fuzzy msgid "Unstage &Selected Lines" msgstr "Изменено (не будет сохранено)" #: cola/widgets/diff.py:57 msgid "Apply Diff Selection to Work Tree" msgstr "" #: cola/widgets/diff.py:86 cola/widgets/diff.py:108 cola/widgets/status.py:486 #: cola/widgets/status.py:584 msgid "Launch git-cola" msgstr "" #: cola/widgets/diff.py:91 #, fuzzy msgid "Stage Section" msgstr "Начальная версия" #: cola/widgets/diff.py:97 msgid "Revert Section..." msgstr "" #: cola/widgets/diff.py:113 msgid "Unstage Section" msgstr "" #: cola/widgets/diff.py:125 msgid "Copy" msgstr "Копировать" #: cola/widgets/diff.py:129 msgid "Select All" msgstr "Выделить все" #: cola/widgets/diff.py:245 msgid "Revert Section?" msgstr "" #: cola/widgets/diff.py:249 msgid "Revert Section" msgstr "" #: cola/widgets/diff.py:258 #, fuzzy msgid "Revert Selected Lines?" msgstr "Отменить изменения в файле %s?" #: cola/widgets/diff.py:262 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/editremotes.py:19 #, fuzzy msgid "Edit Remotes" msgstr "Внешние репозитории" #: cola/widgets/editremotes.py:22 msgid "" "Add and remove remote repositories using the \n" "Add(+) and Delete(-) buttons on the left-hand side.\n" "\n" "Remotes can be renamed by selecting one from the list\n" "and pressing \"enter\", or by double-clicking." msgstr "" #: cola/widgets/editremotes.py:32 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/widgets/editremotes.py:45 #, fuzzy msgid "Add new remote git repository" msgstr "Каталог не является репозиторием: %s" #: cola/widgets/editremotes.py:53 #, fuzzy msgid "Delete remote" msgstr "Удалить внешнюю ветвь" #: cola/widgets/editremotes.py:116 #, python-format msgid "Error creating remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:124 #, fuzzy msgid "Delete Remote" msgstr "Удалить внешнюю ветвь" #: cola/widgets/editremotes.py:125 #, fuzzy msgid "Delete remote?" msgstr "Удалить внешнюю ветвь" #: cola/widgets/editremotes.py:126 #, fuzzy, python-format msgid "Delete remote \"%s\"" msgstr "Удалить внешнюю ветвь" #: cola/widgets/editremotes.py:134 #, python-format msgid "Error deleting remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:153 #, fuzzy msgid "Rename Remote" msgstr "Внешние репозитории" #: cola/widgets/editremotes.py:154 #, fuzzy msgid "Rename remote?" msgstr "Внешние репозитории" #: cola/widgets/editremotes.py:155 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/editremotes.py:157 msgid "Rename" msgstr "Переименовать" #: cola/widgets/editremotes.py:169 #, fuzzy, python-format msgid "Gathering info for \"%s\"..." msgstr "Загрузка изменений в %s..." #: cola/widgets/editremotes.py:201 #, fuzzy msgid "Add Remote" msgstr "Внешние репозитории" #: cola/widgets/editremotes.py:213 #, fuzzy msgid "Add remote" msgstr "Внешние репозитории" #: cola/widgets/editremotes.py:214 msgid "Name for the new remote" msgstr "" #: cola/widgets/editremotes.py:221 msgid "URL" msgstr "Ссылка" #: cola/widgets/grep.py:47 cola/widgets/search.py:40 cola/widgets/search.py:58 msgid "Search" msgstr "" #: cola/widgets/grep.py:52 msgid "command-line arguments" msgstr "" #: cola/widgets/grep.py:56 msgid "grep result..." msgstr "" #: cola/widgets/grep.py:69 msgid "Shell arguments" msgstr "" #: cola/widgets/grep.py:71 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/widgets/log.py:34 #, fuzzy, python-format msgid "exit code %s" msgstr "получение %s" #: cola/widgets/recent.py:36 msgid "Recently Modified Files" msgstr "" #: cola/widgets/recent.py:46 msgid " commits ago" msgstr "" #: cola/widgets/recent.py:49 #, fuzzy msgid "Showing changes since" msgstr "Отправка изменений в %s " #: cola/widgets/recent.py:61 msgid "Expand" msgstr "" #: cola/widgets/recent.py:65 #, fuzzy msgid "Collapse" msgstr "Закрыть" #: cola/widgets/remote.py:136 #, fuzzy msgid "Remote Branch" msgstr "Переименование ветви" #: cola/widgets/remote.py:143 #, fuzzy msgid "Fast Forward Only " msgstr "Только Fast Forward" #: cola/widgets/remote.py:147 #, fuzzy msgid "Include tags " msgstr "Передать таги" #: cola/widgets/remote.py:150 #, fuzzy msgid "Rebase " msgstr "Сброс" #: cola/widgets/remote.py:314 #, fuzzy, python-format msgid "URL: %s" msgstr "Ссылка:" #: cola/widgets/remote.py:393 msgid "No repository selected." msgstr "Не указан репозиторий." #: cola/widgets/remote.py:406 msgid "Push" msgstr "Отправить" #: cola/widgets/remote.py:408 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/remote.py:410 #, fuzzy msgid "Create a new remote branch?" msgstr "Создать новую ветвь" #: cola/widgets/remote.py:411 #, fuzzy msgid "Create Remote Branch" msgstr "Удалить внешнюю ветвь" #: cola/widgets/remote.py:419 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:420 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:421 #, fuzzy, python-format msgid "Force fetching from %s?" msgstr "Получение %s из %s " #: cola/widgets/remote.py:422 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:424 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:425 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/remote.py:427 #, python-format msgid "Force push to %s?" msgstr "" #: cola/widgets/remote.py:428 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:462 msgid "Already up-to-date." msgstr "" #: cola/widgets/remote.py:485 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/widgets/search.py:44 #, fuzzy msgid "Browse..." msgstr "Показать" #: cola/widgets/search.py:50 cola/widgets/search.py:55 msgid "yyyy-MM-dd" msgstr "" #: cola/widgets/search.py:220 #, fuzzy msgid "Search by Expression" msgstr "Выражение для определения версии:" #: cola/widgets/search.py:221 msgid "Search by Path" msgstr "" #: cola/widgets/search.py:222 #, fuzzy msgid "Search Commit Messages" msgstr "Комментарий к объединению:" #: cola/widgets/search.py:223 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:224 msgid "Search Authors" msgstr "" #: cola/widgets/search.py:225 #, fuzzy msgid "Search Committers" msgstr "Сохранил:" #: cola/widgets/search.py:226 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:319 #, fuzzy msgid "Choose Path(s)" msgstr "Выберите %s" #: cola/widgets/selectcommits.py:50 msgid "Revision Expression:" msgstr "Выражение для определения версии:" #: cola/widgets/selectcommits.py:101 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/spellcheck.py:139 #, fuzzy msgid "Spelling Suggestions" msgstr "Исправлений не найдено" #: cola/widgets/startup.py:26 msgid "git-cola" msgstr "" #: cola/widgets/startup.py:33 msgid "New..." msgstr "Новый..." #: cola/widgets/startup.py:56 #, fuzzy msgid "Select Repository..." msgstr "Репозиторий" #: cola/widgets/startup.py:61 #, fuzzy msgid "Select manually..." msgstr "Выделить все" #: cola/widgets/status.py:75 #, fuzzy msgid "Untracked" msgstr "Не отслеживается, не подготовлено" #: cola/widgets/status.py:85 #, fuzzy msgid "Stage / Unstage" msgstr "Подготовить все" #: cola/widgets/status.py:114 msgid "Move Up" msgstr "" #: cola/widgets/status.py:121 msgid "Copy Path to Clipboard" msgstr "" #: cola/widgets/status.py:474 cola/widgets/status.py:550 msgid "Revert Unstaged Edits..." msgstr "" #: cola/widgets/status.py:477 cola/widgets/status.py:553 msgid "Revert Uncommited Edits..." msgstr "" #: cola/widgets/status.py:572 #, fuzzy msgid "Delete File(s)..." msgstr "Удалить..." #: cola/widgets/status.py:575 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:608 #, fuzzy msgid "Delete Files?" msgstr "Удалить" #: cola/widgets/status.py:609 msgid "The following files will be deleted:" msgstr "" #: cola/widgets/status.py:616 #, python-format msgid "Delete %d file(s)?" msgstr "" #: cola/widgets/status.py:617 #, fuzzy msgid "Delete Files" msgstr "Удалить" #: cola/widgets/status.py:633 #, fuzzy msgid "Revert Unstaged Changes?" msgstr "Изменено (не будет сохранено)" #: cola/widgets/status.py:634 msgid "" "This operation drops unstaged changes.\n" "These changes cannot be recovered." msgstr "" #: cola/widgets/status.py:636 #, fuzzy msgid "Revert the unstaged changes?" msgstr "Изменено (не будет сохранено)" #: cola/widgets/status.py:637 #, fuzzy msgid "Revert Unstaged Changes" msgstr "Изменено (не будет сохранено)" #: cola/widgets/status.py:646 cola/widgets/status.py:662 msgid "No files selected for checkout from HEAD." msgstr "" #~ msgid "Success" #~ msgstr "Процесс успешно завершен" #~ msgid "Rescan" #~ msgstr "Перечитать" #, fuzzy #~ msgid "Browse Revision..." #~ msgstr "Версия" #, fuzzy #~ msgid "Rebase Branch" #~ msgstr "Переименование ветви" #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: критическая ошибка" #~ msgid "Invalid font specified in %s:" #~ msgstr "В %s установлен неверный шрифт:" #~ msgid "Main Font" #~ msgstr "Шрифт интерфейса" #~ msgid "Diff/Console Font" #~ msgstr "Шрифт консоли и изменений (diff)" #~ msgid "Cannot find git in PATH." #~ msgstr "git не найден в PATH." #~ msgid "Cannot parse Git version string:" #~ msgstr "Невозможно распознать строку версии Git: " #~ msgid "" #~ "Git version cannot be determined.\n" #~ "\n" #~ "%s claims it is version '%s'.\n" #~ "\n" #~ "%s requires at least Git 1.5.0 or later.\n" #~ "\n" #~ "Assume '%s' is version 1.5.0?\n" #~ msgstr "" #~ "Невозможно определить версию Git\n" #~ "%s указывает на версию '%s'.\n" #~ "\n" #~ "для %s требуется версия Git, начиная с 1.5.0\n" #~ "\n" #~ "Принять '%s' как версию 1.5.0?\n" #~ msgid "Git directory not found:" #~ msgstr "Каталог Git не найден:" #~ msgid "Cannot move to top of working directory:" #~ msgstr "Невозможно перейти к корню рабочего каталога репозитория: " #~ msgid "Cannot use funny .git directory:" #~ msgstr "Каталог.git испорчен: " #~ msgid "No working directory" #~ msgstr "Отсутствует рабочий каталог" #~ msgid "Refreshing file status..." #~ msgstr "Обновление информации о состоянии файлов..." #~ msgid "Ready." #~ msgstr "Готово." #~ msgid "Modified, not staged" #~ msgstr "Изменено, не подготовлено" #~ msgid "Portions staged for commit" #~ msgstr "Части, подготовленные для сохранения" #~ msgid "Staged for commit, missing" #~ msgstr "Подготовлено для сохранения, отсутствует" #~ msgid "Staged for removal" #~ msgstr "Подготовлено для удаления" #~ msgid "Staged for removal, still present" #~ msgstr "Подготовлено для удаления, еще не удалено" #~ msgid "Requires merge resolution" #~ msgstr "Требуется разрешение конфликта при объединении" #~ msgid "Starting gitk... please wait..." #~ msgstr "Запускается gitk... пожалуйста, ждите..." #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "Не удалось запустить gitk:\n" #~ "\n" #~ "%s не существует" #~ msgid "Repository" #~ msgstr "Репозиторий" #~ msgid "Commit@@noun" #~ msgstr "Состояние" #~ msgid "Browse %s's Files" #~ msgstr "Показать файлы ветви %s" #~ msgid "Visualize %s's History" #~ msgstr "История ветви %s наглядно" #~ msgid "Database Statistics" #~ msgstr "Статистика базы данных" #~ msgid "Compress Database" #~ msgstr "Сжать базу данных" #~ msgid "Verify Database" #~ msgstr "Проверить базу данных" #~ msgid "Create Desktop Icon" #~ msgstr "Создать ярлык на рабочем столе" #~ msgid "Undo" #~ msgstr "Отменить" #~ msgid "Redo" #~ msgstr "Повторить" #~ msgid "Cut" #~ msgstr "Вырезать" #~ msgid "Paste" #~ msgstr "Вставить" #~ msgid "Rename..." #~ msgstr "Переименовать..." #~ msgid "New Commit" #~ msgstr "Новое состояние" #~ msgid "Local Merge..." #~ msgstr "Локальное объединение..." #~ msgid "Preferences..." #~ msgstr "Настройки..." #~ msgid "Current Branch:" #~ msgstr "Текущая ветвь:" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "Подготовлено (будет сохранено)" #~ msgid "Initial Commit Message:" #~ msgstr "Комментарий к первому состоянию:" #~ msgid "Amended Commit Message:" #~ msgstr "Комментарий к исправленному состоянию:" #~ msgid "Amended Initial Commit Message:" #~ msgstr "Комментарий к исправленному первоначальному состоянию:" #~ msgid "Amended Merge Commit Message:" #~ msgstr "Комментарий к исправленному объединению:" #~ msgid "Apply/Reverse Hunk" #~ msgstr "Применить/Убрать изменение" #~ msgid "Show Less Context" #~ msgstr "Меньше контекста" #~ msgid "Show More Context" #~ msgstr "Больше контекста" #~ msgid "Decrease Font Size" #~ msgstr "Уменьшить размер шрифта" #~ msgid "Increase Font Size" #~ msgstr "Увеличить размер шрифта" #~ msgid "Unstage Hunk From Commit" #~ msgstr "Не сохранять часть" #~ msgid "Stage Hunk For Commit" #~ msgstr "Подготовить часть для сохранения" #~ msgid "Initializing..." #~ msgstr "Инициализация..." #~ msgid "" #~ "Possible environment issues exist.\n" #~ "\n" #~ "The following environment variables are probably\n" #~ "going to be ignored by any Git subprocess run\n" #~ "by %s:\n" #~ "\n" #~ msgstr "" #~ "Возможны ошибки в переменных окружения.\n" #~ "\n" #~ "Переменные окружения, которые возможно\n" #~ "будут проигнорированы командами Git,\n" #~ "запущенными из %s\n" #~ "\n" #~ msgid "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "Это известная проблема с Tcl,\n" #~ "распространяемым Cygwin." #~ msgid "" #~ "\n" #~ "\n" #~ "A good replacement for %s\n" #~ "is placing values for the user.name and\n" #~ "user.email settings into your personal\n" #~ "~/.gitconfig file.\n" #~ msgstr "" #~ "\n" #~ "\n" #~ "Вместо использования %s можно\n" #~ "сохранить значения user.name и\n" #~ "user.email в Вашем персональном\n" #~ "файле ~/.gitconfig.\n" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - графический пользовательский интерфейс к Git." #~ msgid "File Viewer" #~ msgstr "Просмотр файла" #~ msgid "Reading %s..." #~ msgstr "Чтение %s..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "Загрузка аннотации копирований/переименований..." #~ msgid "lines annotated" #~ msgstr "строк прокомментировано" #~ msgid "Loading original location annotations..." #~ msgstr "Загрузка аннотаций первоначального положения объекта..." #~ msgid "Annotation complete." #~ msgstr "Аннотация завершена." #~ msgid "Loading annotation..." #~ msgstr "Загрузка аннотации..." #~ msgid "Original File:" #~ msgstr "Исходный файл:" #~ msgid "Originally By:" #~ msgstr "Источник:" #~ msgid "In File:" #~ msgstr "Файл:" #~ msgid "Copied Or Moved Here By:" #~ msgstr "Скопировано/перемещено в:" #~ msgid "Detach From Local Branch" #~ msgstr "Отсоединить от локальной ветви" #~ msgid "Match Tracking Branch Name" #~ msgstr "Взять из имен ветвей слежения" #~ msgid "Tracking branch %s is not a branch in the remote repository." #~ msgstr "Ветвь слежения %s не является ветвью во внешнем репозитории." #~ msgid "Please supply a branch name." #~ msgstr "Укажите название ветви." #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "Недопустимое название ветви '%s'." #~ msgid "Delete Local Branch" #~ msgstr "Удалить локальную ветвь" #~ msgid "Local Branches" #~ msgstr "Локальные ветви" #~ msgid "Delete Only If Merged Into" #~ msgstr "Удалить только в случае, если было объединение с" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "Всегда (не выполнять проверку на объединение)" #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "Следующие ветви объединены с %s не полностью:" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "Восстанавливать удаленные ветви сложно. \n" #~ "\n" #~ " Удалить выбранные ветви?" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "Не удалось удалить ветви:\n" #~ "%s" #~ msgid "New Name:" #~ msgstr "Новое название:" #~ msgid "Failed to rename '%s'." #~ msgstr "Не удалось переименовать '%s'. " #~ msgid "[Up To Parent]" #~ msgstr "[На уровень выше]" #~ msgid "Browse Branch Files" #~ msgstr "Показать файлы ветви" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "критическая ошибка: невозможно разрешить %s" #~ msgid "Branch '%s' does not exist." #~ msgstr "Ветвь '%s' не существует " #~ msgid "" #~ "Branch '%s' already exists.\n" #~ "\n" #~ "It cannot fast-forward to %s.\n" #~ "A merge is required." #~ msgstr "" #~ "Ветвь '%s' уже существует.\n" #~ "\n" #~ "Она не может быть прокручена(fast-forward) к %s.\n" #~ "Требуется объединение." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "Стратегия объединения '%s' не поддерживается." #~ msgid "Failed to update '%s'." #~ msgstr "Не удалось обновить '%s'." #~ msgid "Staging area (index) is already locked." #~ msgstr "Рабочая область заблокирована другим процессом." #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before the current branch can be changed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Последнее прочитанное состояние репозитория не соответствует текущему.\n" #~ "\n" #~ "С момента последней проверки репозиторий был изменен другой программой " #~ "Git. Необходимо перечитать репозиторий, прежде чем изменять текущую " #~ "ветвь.\n" #~ "\n" #~ "Это будет сделано сейчас автоматически.\n" #~ msgid "Updating working directory to '%s'..." #~ msgstr "Обновление рабочего каталога из '%s'..." #~ msgid "files checked out" #~ msgstr "файлы извлечены" #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "Прерван переход на '%s' (требуется объединение на уровне файлов)" #~ msgid "File level merge required." #~ msgstr "Требуется объединение на уровне файлов." #~ msgid "Staying on branch '%s'." #~ msgstr "Ветвь '%s' остается текущей." #~ msgid "" #~ "You are no longer on a local branch.\n" #~ "\n" #~ "If you wanted to be on a branch, create one now starting from 'This " #~ "Detached Checkout'." #~ msgstr "" #~ "Вы находитесь не в локальной ветви.\n" #~ "\n" #~ "Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, " #~ "начиная с 'Текущего отсоединенного состояния'." #~ msgid "Checked out '%s'." #~ msgstr "Ветвь '%s' сделана текущей." #~ msgid "Reset '%s'?" #~ msgstr "Сбросить '%s'?" #~ msgid "" #~ "Failed to set current branch.\n" #~ "\n" #~ "This working directory is only partially switched. We successfully " #~ "updated your files, but failed to update an internal Git file.\n" #~ "\n" #~ "This should not have occurred. %s will now close and give up." #~ msgstr "" #~ "Не удалось установить текущую ветвь.\n" #~ "\n" #~ "Ваш рабочий каталог обновлен только частично. Были обновлены все файлы " #~ "кроме служебных файлов Git. \n" #~ "\n" #~ "Этого не должно было произойти. %s завершается." #~ msgid "Font Family" #~ msgstr "Шрифт" #~ msgid "Font Example" #~ msgstr "Пример текста" #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "Это пример текста.\n" #~ "Если Вам нравится этот текст, это может быть Ваш шрифт." #~ msgid "Clone Existing Repository" #~ msgstr "Склонировать существующий репозиторий" #~ msgid "Recent Repositories" #~ msgstr "Недавние репозитории" #~ msgid "Failed to create repository %s:" #~ msgstr "Не удалось создать репозиторий %s:" #~ msgid "Directory:" #~ msgstr "Каталог:" #~ msgid "Directory %s already exists." #~ msgstr "Каталог '%s' уже существует." #~ msgid "Clone" #~ msgstr "Склонировать" #~ msgid "Clone Type:" #~ msgstr "Тип клона:" #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "Стандартный (Быстрый, полуизбыточный, \"жесткие\" ссылки)" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "Полная копия (Медленный, создает резервную копию)" #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "Общий (Самый быстрый, не рекомендуется, без резервной копии)" #~ msgid "Standard only available for local repository." #~ msgstr "Стандартный клон возможен только для локального репозитория." #~ msgid "Shared only available for local repository." #~ msgstr "Общий клон возможен только для локального репозитория." #~ msgid "Location %s already exists." #~ msgstr "Путь '%s' уже существует." #~ msgid "Failed to configure origin" #~ msgstr "Не могу сконфигурировать исходный репозиторий." #~ msgid "Counting objects" #~ msgstr "Считаю объекты" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "Не могу скопировать objects/info/alternates: %s" #~ msgid "The 'master' branch has not been initialized." #~ msgstr "Не инициализирована ветвь 'master'." #~ msgid "Hardlinks are unavailable. Falling back to copying." #~ msgstr "\"Жесткие ссылки\" не доступны. Буду использовать копирование." #~ msgid "Cloning from %s" #~ msgstr "Клонирование %s" #~ msgid "Copying objects" #~ msgstr "Копирование objects" #~ msgid "KiB" #~ msgstr "КБ" #~ msgid "Unable to copy object: %s" #~ msgstr "Не могу скопировать объект: %s" #~ msgid "Linking objects" #~ msgstr "Создание ссылок на objects" #~ msgid "objects" #~ msgstr "объекты" #~ msgid "Unable to hardlink object: %s" #~ msgstr "Не могу \"жестко связать\" объект: %s" #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "" #~ "Не могу получить ветви и объекты. Дополнительная информация на консоли." #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "Не могу получить метки. Дополнительная информация на консоли." #~ msgid "Cannot determine HEAD. See console output for details." #~ msgstr "Не могу определить HEAD. Дополнительная информация на консоли." #~ msgid "Unable to cleanup %s" #~ msgstr "Не могу очистить %s" #~ msgid "Clone failed." #~ msgstr "Клонирование не удалось." #~ msgid "No default branch obtained." #~ msgstr "Не было получено ветви по умолчанию." #~ msgid "Cannot resolve %s as a commit." #~ msgstr "Не могу распознать %s как состояние." #~ msgid "Creating working directory" #~ msgstr "Создаю рабочий каталог" #~ msgid "files" #~ msgstr "файлов" #~ msgid "Initial file checkout failed." #~ msgstr "Не удалось получить начальное состояние файлов репозитория." #~ msgid "Failed to open repository %s:" #~ msgstr "Не удалось открыть репозиторий %s:" #~ msgid "This Detached Checkout" #~ msgstr "Текущее отсоединенное состояние" #~ msgid "Updated" #~ msgstr "Обновлено" #~ msgid "" #~ "There is nothing to amend.\n" #~ "\n" #~ "You are about to create the initial commit. There is no commit before " #~ "this to amend.\n" #~ msgstr "" #~ "Отсутствует состояние для исправления.\n" #~ "\n" #~ "Вы создаете первое состояние в репозитории, здесь еще нечего исправлять.\n" #~ msgid "" #~ "Cannot amend while merging.\n" #~ "\n" #~ "You are currently in the middle of a merge that has not been fully " #~ "completed. You cannot amend the prior commit unless you first abort the " #~ "current merge activity.\n" #~ msgstr "" #~ "Невозможно исправить состояние во время объединения.\n" #~ "\n" #~ "Текущее объединение не завершено. Невозможно исправить предыдущее " #~ "сохраненное состояние не прерывая текущее объединение.\n" #~ msgid "Error loading commit data for amend:" #~ msgstr "Ошибка при загрузке данных для исправления сохраненного состояния:" #~ msgid "Unable to obtain your identity:" #~ msgstr "Невозможно получить информацию об авторстве:" #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "Неверный GIT_COMMITTER_IDENT:" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before another commit can be created.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Последнее прочитанное состояние репозитория не соответствует текущему.\n" #~ "\n" #~ "С момента последней проверки репозиторий был изменен другой программой " #~ "Git. Необходимо перечитать репозиторий, прежде чем изменять текущую " #~ "ветвь. \n" #~ "\n" #~ "Это будет сделано сейчас автоматически.\n" #~ msgid "" #~ "Unmerged files cannot be committed.\n" #~ "\n" #~ "File %s has merge conflicts. You must resolve them and stage the file " #~ "before committing.\n" #~ msgstr "" #~ "Нельзя сохранить необъединенные файлы.\n" #~ "\n" #~ "Для файла %s возник конфликт объединения. Разрешите конфликт и добавьте к " #~ "подготовленным файлам перед сохранением.\n" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "Обнаружено неизвестное состояние файла %s.\n" #~ "\n" #~ "Файл %s не может быть сохранен данной программой.\n" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "предупреждение: Tcl не поддерживает кодировку '%s'." #~ msgid "Calling pre-commit hook..." #~ msgstr "Вызов программы поддержки репозитория pre-commit..." #~ msgid "Commit declined by pre-commit hook." #~ msgstr "Сохранение прервано программой поддержки репозитория pre-commit" #~ msgid "Calling commit-msg hook..." #~ msgstr "Вызов программы поддержки репозитория commit-msg..." #~ msgid "Commit declined by commit-msg hook." #~ msgstr "Сохранение прервано программой поддержки репозитория commit-msg" #~ msgid "write-tree failed:" #~ msgstr "Программа write-tree завершилась с ошибкой:" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "Состояние %s выглядит поврежденным" #~ msgid "" #~ "No changes to commit.\n" #~ "\n" #~ "No files were modified by this commit and it was not a merge commit.\n" #~ "\n" #~ "A rescan will be automatically started now.\n" #~ msgstr "" #~ "Отсутствуют изменения для сохранения.\n" #~ "\n" #~ "Ни один файл не был изменен и не было объединения.\n" #~ "\n" #~ "Сейчас автоматически запустится перечитывание репозитория.\n" #~ msgid "commit-tree failed:" #~ msgstr "Программа commit-tree завершилась с ошибкой:" #~ msgid "update-ref failed:" #~ msgstr "Программа update-ref завершилась с ошибкой:" #~ msgid "Working... please wait..." #~ msgstr "В процессе... пожалуйста, ждите..." #~ msgid "Error: Command Failed" #~ msgstr "Ошибка: не удалось выполнить команду" #~ msgid "Number of loose objects" #~ msgstr "Количество несвязанных объектов" #~ msgid "Disk space used by loose objects" #~ msgstr "Объем дискового пространства, занятый несвязанными объектами" #~ msgid "Number of packed objects" #~ msgstr "Количество упакованных объектов" #~ msgid "Number of packs" #~ msgstr "Количество pack-файлов" #~ msgid "Disk space used by packed objects" #~ msgstr "Объем дискового пространства, занятый упакованными объектами" #~ msgid "Packed objects waiting for pruning" #~ msgstr "Несвязанные объекты, которые можно удалить" #~ msgid "Garbage files" #~ msgstr "Мусор" #~ msgid "Compressing the object database" #~ msgstr "Сжатие базы объектов" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "Проверка базы объектов при помощи fsck" #~ msgid "" #~ "This repository currently has approximately %i loose objects.\n" #~ "\n" #~ "To maintain optimal performance it is strongly recommended that you " #~ "compress the database when more than %i loose objects exist.\n" #~ "\n" #~ "Compress the database now?" #~ msgstr "" #~ "Этот репозиторий сейчас содержит примерно %i свободных объектов\n" #~ "\n" #~ "Для лучшей производительности рекомендуется сжать базу данных, когда есть " #~ "более %i несвязанных объектов.\n" #~ "\n" #~ "Сжать базу данных сейчас?" #~ msgid "Invalid date from Git: %s" #~ msgstr "Неправильная дата в репозитории: %s" #~ msgid "" #~ "No differences detected.\n" #~ "\n" #~ "%s has no changes.\n" #~ "\n" #~ "The modification date of this file was updated by another application, " #~ "but the content within the file was not changed.\n" #~ "\n" #~ "A rescan will be automatically started to find other files which may have " #~ "the same state." #~ msgstr "" #~ "Изменений не обнаружено.\n" #~ "\n" #~ "в %s отутствуют изменения.\n" #~ "\n" #~ "Дата изменения файла была обновлена другой программой, но содержимое " #~ "файла осталось прежним.\n" #~ "\n" #~ "Сейчас будет запущено перечитывание репозитория, чтобы найти подобные " #~ "файлы." #~ msgid "Unable to display %s" #~ msgstr "Не могу показать %s" #~ msgid "Git Repository (subproject)" #~ msgstr "Репозиторий Git (подпроект)" #~ msgid "* Binary file (not showing content)." #~ msgstr "* Двоичный файл (содержимое не показано)" #~ msgid "Failed to unstage selected hunk." #~ msgstr "Не удалось исключить выбранную часть." #~ msgid "Failed to stage selected hunk." #~ msgstr "Не удалось подготовить к сохранению выбранную часть." #~ msgid "warning" #~ msgstr "предупреждение" #~ msgid "You must correct the above errors before committing." #~ msgstr "Прежде чем сохранить, исправьте вышеуказанные ошибки." #~ msgid "Unable to unlock the index." #~ msgstr "Не удалось разблокировать индекс" #~ msgid "" #~ "Updating the Git index failed. A rescan will be automatically started to " #~ "resynchronize git-gui." #~ msgstr "" #~ "Не удалось обновить индекс Git. Состояние репозитория будетперечитано " #~ "автоматически." #~ msgid "Unlock Index" #~ msgstr "Разблокировать индекс" #~ msgid "Ready to commit." #~ msgstr "Подготовлено для сохранения" #~ msgid "Revert changes in these %i files?" #~ msgstr "Отменить изменения в %i файле(-ах)?" #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "" #~ "Любые изменения, не подготовленные к сохранению, будут потеряны при " #~ "данной операции." #~ msgid "Do Nothing" #~ msgstr "Ничего не делать" #~ msgid "" #~ "Cannot merge while amending.\n" #~ "\n" #~ "You must finish amending this commit before starting any type of merge.\n" #~ msgstr "" #~ "Невозможно выполнить объединение во время исправления.\n" #~ "\n" #~ "Завершите исправление данного состояния перед выполнением операции " #~ "объединения.\n" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before a merge can be performed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Последнее прочитанное состояние репозитория не соответствует текущему.\n" #~ "\n" #~ "С момента последней проверки репозиторий был изменен другой программой " #~ "Git. Необходимо перечитать репозиторий, прежде чем изменять текущую " #~ "ветвь.\n" #~ "\n" #~ "Это будет сделано сейчас автоматически.\n" #~ msgid "" #~ "You are in the middle of a conflicted merge.\n" #~ "\n" #~ "File %s has merge conflicts.\n" #~ "\n" #~ "You must resolve them, stage the file, and commit to complete the current " #~ "merge. Only then can you begin another merge.\n" #~ msgstr "" #~ "Предыдущее объединение не завершено из-за конфликта.\n" #~ "\n" #~ "Для файла %s возник конфликт объединения.\n" #~ "\n" #~ "Разрешите конфликт, подготовьте файл и сохраните. Только после этого " #~ "можно начать следующее объединение.\n" #~ msgid "" #~ "You are in the middle of a change.\n" #~ "\n" #~ "File %s is modified.\n" #~ "\n" #~ "You should complete the current commit before starting a merge. Doing so " #~ "will help you abort a failed merge, should the need arise.\n" #~ msgstr "" #~ "Изменения не сохранены.\n" #~ "\n" #~ "Файл %s изменен.\n" #~ "\n" #~ "Подготовьте и сохраните измения перед началом объединения. В случае " #~ "необходимости это позволит прервать операцию объединения.\n" #~ msgid "%s of %s" #~ msgstr "%s из %s" #~ msgid "Merging %s and %s..." #~ msgstr "Объединение %s и %s..." #~ msgid "Merge completed successfully." #~ msgstr "Объединение успешно завершено." #~ msgid "Merge failed. Conflict resolution is required." #~ msgstr "Не удалось завершить объединение. Требуется разрешение конфликта." #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\n" #~ msgstr "" #~ "Невозможно прервать исправление.\n" #~ "\n" #~ "Завершите текущее исправление сохраненного состояния.\n" #~ msgid "" #~ "Reset changes?\n" #~ "\n" #~ "Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" #~ "\n" #~ "Continue with resetting the current changes?" #~ msgstr "" #~ "Прервать объединение?\n" #~ "\n" #~ "Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n" #~ "\n" #~ "Продолжить?" #~ msgid "files reset" #~ msgstr "изменения в файлах отменены" #~ msgid "Abort failed." #~ msgstr "Прервать не удалось." #~ msgid "Abort completed. Ready." #~ msgstr "Прервано." #~ msgid "Restore Defaults" #~ msgstr "Восстановить настройки по умолчанию" #~ msgid "%s Repository" #~ msgstr "для репозитория %s" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "Чистка ветвей слежения при получении изменений" #~ msgid "Match Tracking Branches" #~ msgstr "Имя новой ветви взять из имен ветвей слежения" #~ msgid "New Branch Name Template" #~ msgstr "Шаблон для имени новой ветви" #~ msgid "Spelling Dictionary:" #~ msgstr "Словарь для проверки правописания:" #~ msgid "Change Font" #~ msgstr "Изменить шрифт" #~ msgid "Failed to completely save options:" #~ msgstr "Не удалось полностью сохранить настройки:" #~ msgid "From Repository" #~ msgstr "Из репозитория" #~ msgid "Remote:" #~ msgstr "внешний:" #~ msgid "Arbitrary URL:" #~ msgstr "по указанному URL:" #~ msgid "Delete Only If" #~ msgstr "Удалить только в случае, если" #~ msgid "Merged Into:" #~ msgstr "Объединено с:" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "Всегда (не выполнять проверку объединений)" #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "Для опции 'Объединено с' требуется указать ветвь." #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "Следующие ветви объединены с %s не полностью:\n" #~ " - %s" #~ msgid "" #~ "One or more of the merge tests failed because you have not fetched the " #~ "necessary commits. Try fetching from %s first." #~ msgstr "" #~ "Один или несколько тестов на объединение не прошли, потому что Вы не " #~ "получили необходимые состояния. Попытайтесь получить их из %s." #~ msgid "Please select one or more branches to delete." #~ msgstr "Укажите одну или несколько ветвей для удаления." #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "Восстановить удаленные ветви сложно.\n" #~ "\n" #~ "Продолжить?" #~ msgid "Prune from" #~ msgstr "Чистка" #~ msgid "Fetch from" #~ msgstr "Получение из" #~ msgid "Push to" #~ msgstr "Отправить" #~ msgid "Cannot write shortcut:" #~ msgstr "Невозможно записать ссылку:" #~ msgid "Unsupported spell checker" #~ msgstr "Неподдерживаемая программа проверки правописания" #~ msgid "Spell checking is unavailable" #~ msgstr "Проверка правописания не доступна" #~ msgid "Invalid spell checking configuration" #~ msgstr "Неправильная конфигурация программы проверки правописания" #~ msgid "Reverting dictionary to %s." #~ msgstr "Словарь вернут к %s." #~ msgid "Spell checker silently failed on startup" #~ msgstr "Программа проверки правописания не смогла запустится" #~ msgid "Unrecognized spell checker" #~ msgstr "Нераспознаная программа проверки правописания" #~ msgid "Unexpected EOF from spell checker" #~ msgstr "Программа проверки правописания прервала передачу данных" #~ msgid "Spell Checker Failed" #~ msgstr "Ошибка проверки правописания" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%s ... %*i из %*i %s (%3i%%)" #~ msgid "Fetching new changes from %s" #~ msgstr "Получение изменений из %s " # carbon copy #~ msgid "remote prune %s" #~ msgstr "чистка внешнего %s" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "Чистка ветвей слежения, удаленных из %s" #~ msgid "push %s" #~ msgstr "отправить %s" #~ msgid "Pushing %s %s to %s" #~ msgstr "Отправка %s %s в %s" #~ msgid "Push Branches" #~ msgstr "Отправить изменения в ветвях" #~ msgid "Source Branches" #~ msgstr "Исходные ветви" #~ msgid "Destination Repository" #~ msgstr "Репозиторий назначения" #~ msgid "Transfer Options" #~ msgstr "Настройки отправки" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "Намеренно переписать существующую ветвь (возможна потеря изменений)" #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Использовать thin pack (для медленных сетевых подключений)" #~ msgid "Next >" #~ msgstr "Дальше >" git-cola-1.9.3/po/sv.po000066400000000000000000002133131225156173500146430ustar00rootroot00000000000000# Swedish translation of git-gui. # Copyright (C) 2007 Shawn Pearce, et al. # This file is distributed under the same license as the git-gui package. # # Peter Karlsson , 2007-2008. msgid "" msgstr "" "Project-Id-Version: sv\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-09-24 21:42-0700\n" "PO-Revision-Date: 2008-03-14 07:23+0100\n" "Last-Translator: Peter Karlsson \n" "Language-Team: Swedish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: cola/bookmarks.py:32 msgid "Bookmarks" msgstr "" #: cola/bookmarks.py:47 msgid "Open" msgstr "Öppna" #: cola/bookmarks.py:53 msgid "Add" msgstr "" #: cola/bookmarks.py:58 cola/guicmds.py:25 cola/guicmds.py:33 #: cola/widgets/editremotes.py:127 msgid "Delete" msgstr "Ta bort" #: cola/bookmarks.py:65 cola/stash/view.py:42 cola/widgets/archive.py:65 #: cola/widgets/browse.py:117 msgid "Save" msgstr "Spara" #: cola/bookmarks.py:71 cola/difftool.py:96 cola/qt.py:57 cola/qt.py:243 #: cola/prefs/view.py:241 cola/stash/view.py:50 cola/stash/view.py:51 #: cola/widgets/about.py:66 cola/widgets/about.py:126 #: cola/widgets/browse.py:116 cola/widgets/cfgactions.py:87 #: cola/widgets/cfgactions.py:239 cola/widgets/compare.py:94 #: cola/widgets/createbranch.py:159 cola/widgets/createtag.py:104 #: cola/widgets/editremotes.py:55 cola/widgets/grep.py:75 #: cola/widgets/recent.py:75 cola/widgets/remote.py:157 #: cola/widgets/search.py:81 cola/widgets/selectcommits.py:59 #: cola/widgets/startup.py:42 msgid "Close" msgstr "Stäng" #: cola/bookmarks.py:102 msgid "Bookmarks Saved" msgstr "" #: cola/bookmarks.py:103 msgid "Successfully saved bookmarks" msgstr "" #: cola/bookmarks.py:107 #, fuzzy msgid "Path to git repository" msgstr "Inte ett Gitarkiv: %s" #: cola/bookmarks.py:108 #, fuzzy msgid "Enter Git Repository" msgstr "Gitarkiv" #: cola/cmds.py:105 msgid "Amend" msgstr "" #: cola/cmds.py:140 #, fuzzy msgid "Cannot Amend" msgstr "Kan inte skriva ikon:" #: cola/cmds.py:141 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" #: cola/cmds.py:204 #, python-format msgid "PATCH %(current)d/%(count)d" msgstr "" #: cola/cmds.py:208 msgid "Summary:" msgstr "" #: cola/cmds.py:217 msgid "Patch(es) Applied" msgstr "" #: cola/cmds.py:218 #, python-format msgid "%d patch(es) applied." msgstr "" #: cola/cmds.py:322 #, fuzzy, python-format msgid "Created commit: %s" msgstr "Skapade incheckningen %s: %s" #: cola/cmds.py:324 #, fuzzy, python-format msgid "Commit failed: %s" msgstr "Incheckningen misslyckades." #: cola/cmds.py:369 cola/cmds.py:1186 #, fuzzy msgid "Error" msgstr "fel" #: cola/cmds.py:370 #, python-format msgid "Deleting \"%s\" failed" msgstr "" #: cola/cmds.py:406 #, fuzzy msgid "Remote Branch Deleted" msgstr "Byt namn på gren" #: cola/cmds.py:407 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "" #: cola/cmds.py:411 cola/guicmds.py:108 cola/widgets/remote.py:472 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "" #: cola/cmds.py:414 #, fuzzy msgid "Error Deleting Remote Branch" msgstr "Skapa gren" #: cola/cmds.py:493 cola/widgets/grep.py:60 cola/widgets/recent.py:69 msgid "Edit" msgstr "Redigera" #: cola/cmds.py:529 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/cmds.py:531 #, fuzzy msgid "Error Editing File" msgstr "Fel vid inläsning av differens:" #: cola/cmds.py:554 msgid "Launch Diff Tool" msgstr "" #: cola/cmds.py:577 msgid "Launch Editor" msgstr "" #: cola/cmds.py:598 msgid "Error: Cannot find commit template" msgstr "" #: cola/cmds.py:599 #, fuzzy, python-format msgid "%s: No such file or directory." msgstr "" "ödesdigert: kunde inte ta status på sökvägen %s: Fil eller katalog saknas" #: cola/cmds.py:616 msgid "Error: Unconfigured commit template" msgstr "" #: cola/cmds.py:617 msgid "" "A commit template has not been configured.\n" "Use \"git config\" to define \"commit.template\"\n" "so that it points to a commit template." msgstr "" #: cola/cmds.py:669 msgid "Open Using Default Application" msgstr "" #: cola/cmds.py:692 #, fuzzy msgid "Open Parent Directory" msgstr "Öppna tidigare arkiv:" #: cola/cmds.py:732 #, python-format msgid "Error: could not clone \"%s\"" msgstr "" #: cola/cmds.py:733 #, python-format msgid "git clone returned exit code %s" msgstr "" #: cola/cmds.py:756 cola/widgets/action.py:19 cola/widgets/editremotes.py:49 #: cola/widgets/grep.py:65 cola/widgets/recent.py:52 #: cola/widgets/recent.py:121 msgid "Refresh" msgstr "Uppdatera" #: cola/cmds.py:784 #, python-format msgid "Run \"%s\"?" msgstr "" #: cola/cmds.py:791 #, fuzzy msgid "Please select a file" msgstr "Välj en gren att spåra." #: cola/cmds.py:792 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:804 #, fuzzy msgid "Invalid Revision" msgstr "Ogiltig revision: %s" #: cola/cmds.py:805 #, fuzzy msgid "The revision expression cannot be empty." msgstr "Revisionsuttrycket är tomt." #: cola/cmds.py:820 #, python-format msgid "Running command: %s" msgstr "" #: cola/cmds.py:829 cola/cmds.py:1006 cola/interaction.py:70 #, python-format msgid "Output: %s" msgstr "" #: cola/cmds.py:830 cola/guicmds.py:113 cola/interaction.py:71 #, python-format msgid "Errors: %s" msgstr "" #: cola/cmds.py:876 msgid "Sign Off" msgstr "Skriv under" #: cola/cmds.py:897 msgid "unknown" msgstr "" #: cola/cmds.py:910 cola/widgets/action.py:17 #, fuzzy msgid "Stage" msgstr "Spara" #: cola/cmds.py:917 #, fuzzy, python-format msgid "Staging: %s" msgstr "Söker %s..." #: cola/cmds.py:934 msgid "Stage Modified" msgstr "" #: cola/cmds.py:948 #, fuzzy msgid "Stage Unmerged" msgstr "Köa ändrade" #: cola/cmds.py:962 #, fuzzy msgid "Stage Untracked" msgstr "Köa ändrade" #: cola/cmds.py:980 #, python-format msgid "Tagging \"%(revision)s\" as \"%(name)s\"" msgstr "" #: cola/cmds.py:988 msgid "GPG-signed" msgstr "" #: cola/cmds.py:1020 cola/widgets/action.py:18 #, fuzzy msgid "Unstage" msgstr "Oköade ändringar" #: cola/cmds.py:1027 #, fuzzy, python-format msgid "Unstaging: %s" msgstr "Tar bort %s för incheckningskön" #: cola/cmds.py:1055 #, python-format msgid "Untracking: %s" msgstr "" #: cola/cmds.py:1137 #, fuzzy msgid "Error Launching History Browser" msgstr "Filbläddrare" #: cola/cmds.py:1138 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/difftool.py:76 msgid "git-cola diff" msgstr "" #: cola/difftool.py:92 cola/widgets/compare.py:90 msgid "Compare" msgstr "" #: cola/gitcmds.py:402 #, fuzzy msgid "Nothing to do" msgstr "Ingenting att klona från %s." #: cola/guicmds.py:25 msgid "Delete Branch" msgstr "Ta bort gren" #: cola/guicmds.py:33 #, fuzzy msgid "Delete Remote Branch" msgstr "Ta bort fjärrgren" #: cola/guicmds.py:53 #, fuzzy msgid "Browse Commits..." msgstr "Bläddra" #: cola/guicmds.py:53 #, fuzzy msgid "Browse" msgstr "Bläddra" #: cola/guicmds.py:61 msgid "Checkout Branch" msgstr "Checka ut gren" #: cola/guicmds.py:61 msgid "Checkout" msgstr "Checka ut" #: cola/guicmds.py:70 #, fuzzy msgid "Cherry-Pick Commit" msgstr "Kopiera incheckning" #: cola/guicmds.py:107 #, fuzzy msgid "Error Creating Repository" msgstr "Skapa nytt arkiv" #: cola/guicmds.py:110 #, python-format msgid "" "Output:\n" "%s" msgstr "" #: cola/guicmds.py:132 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/guicmds.py:153 #, fuzzy msgid "Error Cloning" msgstr "Fel vid läsning av fil:" #: cola/guicmds.py:154 cola/guicmds.py:155 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/guicmds.py:159 msgid "Select a parent directory for the new clone" msgstr "" #: cola/guicmds.py:169 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/guicmds.py:185 cola/widgets/search.py:75 msgid "Export Patches" msgstr "" #: cola/guicmds.py:214 cola/widgets/startup.py:124 #, fuzzy msgid "Open Git Repository..." msgstr "Öppna befintligt arkiv" #: cola/guicmds.py:223 #, fuzzy msgid "Load Commit Message" msgstr "Incheckningsmeddelande:" #: cola/guicmds.py:251 #, fuzzy msgid "Select New Base" msgstr "Välj" #: cola/guicmds.py:251 #, fuzzy msgid "Rebase" msgstr "Återställ" #: cola/guicmds.py:261 #, fuzzy msgid "Select Branch to Review" msgstr "Ta bort gren" #: cola/guicmds.py:261 msgid "Review" msgstr "" #: cola/inotify.py:47 msgid "inotify is disabled because \"cola.inotify\" is false" msgstr "" #: cola/inotify.py:53 msgid "" "file notification: disabled\n" "Note: install pywin32 to enable.\n" msgstr "" #: cola/inotify.py:56 msgid "" "inotify: disabled\n" "Note: install python-pyinotify to enable inotify.\n" msgstr "" #: cola/inotify.py:62 msgid "On Debian systems try: sudo aptitude install python-pyinotify" msgstr "" #: cola/inotify.py:71 #, fuzzy msgid "File notification enabled." msgstr "Lita på filändringstidsstämplar" #: cola/inotify.py:73 msgid "inotify enabled." msgstr "" #: cola/interaction.py:53 msgid "Continue" msgstr "Forstätt" #: cola/interaction.py:63 #, python-format msgid "Run %s?" msgstr "" #: cola/interaction.py:64 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/interaction.py:65 cola/widgets/cfgactions.py:240 msgid "Run" msgstr "" #: cola/interaction.py:72 #, python-format msgid "Exit code: %s" msgstr "" #: cola/qt.py:60 cola/qt.py:100 #, fuzzy msgid "Detach" msgstr "Ta bort gren" #: cola/qt.py:98 msgid "Attach" msgstr "" #: cola/qtutils.py:396 #, fuzzy msgid "Close..." msgstr "Klona..." #: cola/classic/controller.py:69 msgid "Select Previous Version" msgstr "" #: cola/classic/model.py:37 cola/widgets/createtag.py:51 #: cola/widgets/editremotes.py:220 #, fuzzy msgid "Name" msgstr "Namn:" #: cola/classic/model.py:39 cola/main/view.py:91 msgid "Status" msgstr "" #: cola/classic/model.py:41 msgid "Age" msgstr "" #: cola/classic/model.py:43 cola/widgets/createtag.py:74 #, fuzzy msgid "Message" msgstr "Slå ihop" #: cola/classic/model.py:45 cola/dag/view.py:371 #, fuzzy msgid "Author" msgstr "Författare:" #: cola/classic/model.py:342 #, python-format msgid "%d minutes ago" msgstr "" #: cola/classic/model.py:345 #, python-format msgid "%d hours ago" msgstr "" #: cola/classic/model.py:346 #, python-format msgid "%d days ago" msgstr "" #: cola/classic/model.py:359 cola/widgets/status.py:73 #, fuzzy msgid "Unmerged" msgstr "Slå ihop" #: cola/classic/model.py:361 msgid "Partially Staged" msgstr "" #: cola/classic/model.py:363 cola/widgets/status.py:74 #, fuzzy msgid "Modified" msgstr "Oförändrade" #: cola/classic/model.py:365 cola/widgets/status.py:72 #, fuzzy msgid "Staged" msgstr "Köa ändrade" #: cola/classic/model.py:367 msgid "Changed Upstream" msgstr "" #: cola/classic/view.py:47 cola/main/view.py:545 #, fuzzy, python-format msgid "Repository: %s" msgstr "Arkiv:" #: cola/classic/view.py:49 cola/main/view.py:547 #, fuzzy, python-format msgid "Branch: %s" msgstr "Gren:" #: cola/classic/view.py:52 #, python-format msgid "%s: %s - Browse" msgstr "" #: cola/classic/view.py:54 cola/main/view.py:552 msgid "Amending" msgstr "" #: cola/classic/view.py:79 msgid "View History..." msgstr "" #: cola/classic/view.py:80 msgid "View history for selected path(s)." msgstr "" #: cola/classic/view.py:84 cola/widgets/status.py:506 #: cola/widgets/status.py:536 cola/widgets/status.py:593 #, fuzzy msgid "Stage Selected" msgstr "Välj" #: cola/classic/view.py:85 #, fuzzy msgid "Stage selected path(s) for commit." msgstr "Köade för incheckning" #: cola/classic/view.py:90 cola/widgets/status.py:452 #: cola/widgets/status.py:494 msgid "Unstage Selected" msgstr "" #: cola/classic/view.py:91 msgid "Remove selected path(s) from the staging area." msgstr "" #: cola/classic/view.py:96 msgid "Untrack Selected" msgstr "" #: cola/classic/view.py:97 msgid "Stop tracking path(s)" msgstr "" #: cola/classic/view.py:102 msgid "Launch git-difftool on the current path." msgstr "" #: cola/classic/view.py:106 msgid "Diff Against Predecessor..." msgstr "" #: cola/classic/view.py:107 msgid "Launch git-difftool against previous versions." msgstr "" #: cola/classic/view.py:111 #, fuzzy msgid "Revert Uncommitted Changes..." msgstr "Återställ ändringar" #: cola/classic/view.py:112 #, fuzzy msgid "Revert changes to selected path(s)." msgstr "Återställ ändringarna i filen %s?" #: cola/classic/view.py:117 msgid "Edit selected path(s)." msgstr "" #: cola/classic/view.py:293 cola/widgets/status.py:652 #, fuzzy msgid "Revert Uncommitted Changes?" msgstr "Återställ ändringar" #: cola/classic/view.py:294 cola/widgets/diff.py:246 cola/widgets/diff.py:259 #: cola/widgets/status.py:653 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/classic/view.py:296 cola/widgets/diff.py:248 cola/widgets/diff.py:261 #: cola/widgets/status.py:655 msgid "Revert the uncommitted changes?" msgstr "" #: cola/classic/view.py:297 cola/widgets/status.py:656 #, fuzzy msgid "Revert Uncommitted Changes" msgstr "Återställ ändringar" #: cola/dag/view.py:166 #, fuzzy msgid "Loading..." msgstr "Läser %s..." #: cola/dag/view.py:272 msgid "Diff this -> selected" msgstr "" #: cola/dag/view.py:275 msgid "Diff selected -> this" msgstr "" #: cola/dag/view.py:278 cola/widgets/createbranch.py:89 #: cola/widgets/createbranch.py:98 cola/widgets/createbranch.py:155 #: cola/widgets/createbranch.py:330 msgid "Create Branch" msgstr "Skapa gren" #: cola/dag/view.py:281 #, fuzzy msgid "Create Patch" msgstr "Skapa gren" #: cola/dag/view.py:284 cola/widgets/createtag.py:38 #: cola/widgets/createtag.py:99 #, fuzzy msgid "Create Tag" msgstr "Skapa" #: cola/dag/view.py:287 cola/main/view.py:208 msgid "Save As Tarball/Zip..." msgstr "" #: cola/dag/view.py:290 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/dag/view.py:293 msgid "Grab File..." msgstr "" #: cola/dag/view.py:296 #, fuzzy msgid "Copy SHA-1" msgstr "Kopiera alla" #: cola/dag/view.py:371 msgid "Summary" msgstr "" #: cola/dag/view.py:371 msgid "Date, Time" msgstr "" #: cola/dag/view.py:378 msgid "Go Up" msgstr "" #: cola/dag/view.py:381 msgid "Go Down" msgstr "" #: cola/dag/view.py:511 cola/dag/view.py:1181 msgid "Zoom Out" msgstr "" #: cola/dag/view.py:514 cola/dag/view.py:1178 msgid "Zoom In" msgstr "" #: cola/dag/view.py:517 cola/dag/view.py:1184 msgid "Zoom to Fit" msgstr "" #: cola/dag/view.py:536 msgid "Log" msgstr "" #: cola/dag/view.py:541 cola/main/view.py:114 cola/main/view.py:384 msgid "Diff" msgstr "" #: cola/dag/view.py:554 msgid "Graph" msgstr "" #: cola/dag/view.py:563 msgid "View" msgstr "" #: cola/dag/view.py:636 #, python-format msgid "%s: %s - DAG" msgstr "" #: cola/dag/view.py:638 msgid " - DAG" msgstr "" #: cola/dag/view.py:1187 #, fuzzy msgid "Select Parent" msgstr "Välj" #: cola/dag/view.py:1190 msgid "Select Oldest Parent" msgstr "" #: cola/dag/view.py:1193 #, fuzzy msgid "Select Child" msgstr "Markera alla" #: cola/dag/view.py:1196 msgid "Select Newest Child" msgstr "" #: cola/main/view.py:78 #, fuzzy msgid "Browser" msgstr "Bläddra" #: cola/main/view.py:83 #, fuzzy msgid "Action" msgstr "Alternativ" #: cola/main/view.py:99 cola/merge/view.py:45 #, fuzzy msgid "Commit" msgstr "Incheckning:" #: cola/main/view.py:108 #, fuzzy msgid "Console" msgstr "Stäng" #: cola/main/view.py:120 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/main/view.py:125 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/main/view.py:130 msgid "Ignore all whitespace" msgstr "" #: cola/main/view.py:135 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/main/view.py:139 cola/widgets/createbranch.py:194 msgid "Options" msgstr "Alternativ" #: cola/main/view.py:141 cola/main/view.py:142 #, fuzzy msgid "Diff Options" msgstr "Alternativ" #: cola/main/view.py:157 cola/widgets/status.py:423 msgid "Unstage All" msgstr "" #: cola/main/view.py:161 msgid "Unstage From Commit" msgstr "Ta bort från incheckningskö" #: cola/main/view.py:165 msgid "Diffstat" msgstr "" #: cola/main/view.py:168 msgid "Stage Changed Files To Commit" msgstr "Köa ändrade filer för incheckning" #: cola/main/view.py:173 msgid "Stage All Untracked" msgstr "" #: cola/main/view.py:178 msgid "Export Patches..." msgstr "" #: cola/main/view.py:181 #, fuzzy msgid "New Repository..." msgstr "Gitarkiv" #: cola/main/view.py:185 cola/prefs/view.py:220 msgid "Preferences" msgstr "Inställningar" #: cola/main/view.py:189 msgid "Edit Remotes..." msgstr "" #: cola/main/view.py:197 #, fuzzy msgid "Recently Modified Files..." msgstr "Söker efter ändrade filer..." #: cola/main/view.py:201 #, fuzzy msgid "Cherry-Pick..." msgstr "Checka ut..." #: cola/main/view.py:205 #, fuzzy msgid "Load Commit Message..." msgstr "Incheckningsmeddelande:" #: cola/main/view.py:211 msgid "Quit" msgstr "Avsluta" #: cola/main/view.py:213 msgid "Bookmarks..." msgstr "" #: cola/main/view.py:215 msgid "Grep" msgstr "" #: cola/main/view.py:217 #, fuzzy msgid "Merge..." msgstr "Slå ihop" #: cola/main/view.py:220 cola/merge/__init__.py:20 msgid "Abort Merge..." msgstr "Avbryt sammanslagning..." #: cola/main/view.py:223 cola/widgets/action.py:20 #, fuzzy msgid "Fetch..." msgstr "Återställ..." #: cola/main/view.py:225 cola/widgets/action.py:21 msgid "Push..." msgstr "Sänd..." #: cola/main/view.py:227 cola/widgets/action.py:22 #, fuzzy msgid "Pull..." msgstr "Sänd..." #: cola/main/view.py:230 cola/widgets/startup.py:36 msgid "Open..." msgstr "Öppna..." #: cola/main/view.py:234 cola/widgets/action.py:23 #, fuzzy msgid "Stash..." msgstr "Sänd..." #: cola/main/view.py:237 cola/widgets/startup.py:39 msgid "Clone..." msgstr "Klona..." #: cola/main/view.py:241 #, fuzzy msgid "Documentation" msgstr "Webbdokumentation" #: cola/main/view.py:245 msgid "Keyboard Shortcuts" msgstr "" #: cola/main/view.py:250 #, fuzzy msgid "Visualize Current Branch..." msgstr "Visualisera grenens historik" #: cola/main/view.py:253 #, fuzzy msgid "Visualize All Branches..." msgstr "Visualisera alla grenars historik" #: cola/main/view.py:256 #, fuzzy msgid "Search..." msgstr "Startar..." #: cola/main/view.py:258 #, fuzzy msgid "Browse Current Branch..." msgstr "Bläddra i grenens filer" #: cola/main/view.py:260 #, fuzzy msgid "Browse Other Branch..." msgstr "Bläddra filer på gren..." #: cola/main/view.py:262 #, fuzzy msgid "Get Commit Message Template" msgstr "Textbredd för incheckningsmeddelande" #: cola/main/view.py:265 #, fuzzy msgid "About" msgstr "Om %s" #: cola/main/view.py:268 #, fuzzy msgid "Expression..." msgstr "Alternativ..." #: cola/main/view.py:270 #, fuzzy msgid "Branches..." msgstr "Grenar" #: cola/main/view.py:273 #, fuzzy msgid "Create Tag..." msgstr "Skapa..." #: cola/main/view.py:276 msgid "Create..." msgstr "Skapa..." #: cola/main/view.py:279 msgid "Delete..." msgstr "Ta bort..." #: cola/main/view.py:282 #, fuzzy msgid "Delete Remote Branch..." msgstr "Ta bort fjärrgren" #: cola/main/view.py:285 msgid "Checkout..." msgstr "Checka ut..." #: cola/main/view.py:287 #, fuzzy msgid "Rebase..." msgstr "Återställ..." #: cola/main/view.py:289 #, fuzzy msgid "Review..." msgstr "Återställ..." #: cola/main/view.py:292 #, fuzzy msgid "Browser..." msgstr "Bläddra" #: cola/main/view.py:296 msgid "DAG..." msgstr "" #: cola/main/view.py:313 #, fuzzy msgid "File" msgstr "Fil:" #: cola/main/view.py:316 #, fuzzy msgid "Open Recent" msgstr "Öppna tidigare arkiv:" #: cola/main/view.py:338 cola/main/view.py:339 #, fuzzy msgid "Index" msgstr "Indexfel" #: cola/main/view.py:349 msgid "Branch" msgstr "Gren" #: cola/main/view.py:367 #, fuzzy msgid "Actions" msgstr "Alternativ" #: cola/main/view.py:393 msgid "Tools" msgstr "" #: cola/main/view.py:404 msgid "Help" msgstr "Hjälp" #: cola/main/view.py:462 #, python-format msgid "git cola version %s" msgstr "" #: cola/merge/__init__.py:21 #, fuzzy msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Avbryt sammanslagning?\n" "\n" "Om du avbryter sammanslagningen kommer *ALLA* ej incheckade ändringar att gå " "förlorade.\n" "\n" "Gå vidare med att avbryta den aktuella sammanslagningen?" #: cola/merge/__init__.py:24 msgid "Aborting the current merge?" msgstr "" #: cola/merge/__init__.py:25 #, fuzzy msgid "Abort Merge" msgstr "Avbryt sammanslagning..." #: cola/merge/view.py:23 msgid "Revision To Merge" msgstr "Revisioner att slå ihop" #: cola/merge/view.py:28 cola/widgets/cfgactions.py:220 #: cola/widgets/remote.py:122 msgid "Local Branch" msgstr "Lokal gren" #: cola/merge/view.py:31 cola/widgets/cfgactions.py:221 msgid "Tracking Branch" msgstr "Spårande gren" #: cola/merge/view.py:33 cola/widgets/cfgactions.py:222 #: cola/widgets/createbranch.py:122 msgid "Tag" msgstr "Tagg" #: cola/merge/view.py:39 msgid "Visualize" msgstr "Visualisera" #: cola/merge/view.py:42 #, fuzzy msgid "Squash" msgstr "Sänd" #: cola/merge/view.py:50 cola/widgets/archive.py:62 #: cola/widgets/editremotes.py:204 msgid "Cancel" msgstr "Avbryt" #: cola/merge/view.py:53 msgid "Merge" msgstr "Slå ihop" #: cola/merge/view.py:115 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/merge/view.py:118 #, fuzzy, python-format msgid "Merge into \"%s\"" msgstr "Slå ihop i %s" #: cola/merge/view.py:162 cola/merge/view.py:171 #, fuzzy msgid "No Revision Specified" msgstr "Ingen revision vald." #: cola/merge/view.py:163 msgid "You must specify a revision to view." msgstr "" #: cola/merge/view.py:172 msgid "You must specify a revision to merge." msgstr "" #: cola/prefs/view.py:116 msgid "User Name" msgstr "Användarnamn" #: cola/prefs/view.py:117 msgid "Email Address" msgstr "E-postadress" #: cola/prefs/view.py:118 msgid "Merge Verbosity" msgstr "Pratsamhet för sammanslagningar" #: cola/prefs/view.py:119 msgid "Number of Diff Context Lines" msgstr "Antal rader sammanhang i differenser" #: cola/prefs/view.py:120 msgid "Summarize Merge Commits" msgstr "Summera sammanslagningsincheckningar" #: cola/prefs/view.py:121 msgid "Show Diffstat After Merge" msgstr "Visa diffstatistik efter sammanslagning" #: cola/prefs/view.py:122 msgid "Display Untracked Files" msgstr "" #: cola/prefs/view.py:163 msgid "Fixed-Width Font" msgstr "" #: cola/prefs/view.py:164 msgid "Font Size" msgstr "Storlek" #: cola/prefs/view.py:165 msgid "Tab Width" msgstr "" #: cola/prefs/view.py:166 msgid "Text Width" msgstr "" #: cola/prefs/view.py:167 cola/widgets/commitmsg.py:99 msgid "Auto-Wrap Lines" msgstr "" #: cola/prefs/view.py:168 #, fuzzy msgid "Editor" msgstr "Redigera" #: cola/prefs/view.py:169 #, fuzzy msgid "History Browser" msgstr "Filbläddrare" #: cola/prefs/view.py:170 msgid "Diff Tool" msgstr "" #: cola/prefs/view.py:171 #, fuzzy msgid "Merge Tool" msgstr "Slå ihop" #: cola/prefs/view.py:172 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/prefs/view.py:173 msgid "Save GUI Settings" msgstr "" #: cola/prefs/view.py:227 #, fuzzy msgid "All Repositories" msgstr "Globalt (alla arkiv)" #: cola/prefs/view.py:228 #, fuzzy msgid "Current Repository" msgstr "Skapa nytt arkiv" #: cola/prefs/view.py:229 #, fuzzy msgid "Settings" msgstr "Startar..." #: cola/stash/view.py:28 msgid "Stash" msgstr "" #: cola/stash/view.py:38 #, fuzzy msgid "Apply" msgstr "Äpple" #: cola/stash/view.py:39 msgid "Apply the selected stash" msgstr "" #: cola/stash/view.py:43 msgid "Save modified state to new stash" msgstr "" #: cola/stash/view.py:46 msgid "Drop" msgstr "" #: cola/stash/view.py:47 msgid "Drop the selected stash" msgstr "" #: cola/stash/view.py:54 msgid "Keep Index" msgstr "" #: cola/stash/view.py:175 msgid "Save Stash" msgstr "" #: cola/stash/view.py:176 msgid "Enter a name for the stash" msgstr "" #: cola/stash/view.py:182 msgid "Error: Stash exists" msgstr "" #: cola/stash/view.py:183 #, fuzzy, python-format msgid "A stash named \"%s\" already exists" msgstr "Filen %s finns redan." #: cola/stash/view.py:198 msgid "Drop Stash?" msgstr "" #: cola/stash/view.py:199 #, fuzzy msgid "Recovering a dropped stash is not possible." msgstr "Det kanske inte är så enkelt att återskapa förlorade incheckningar." #: cola/stash/view.py:200 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/stash/view.py:201 msgid "Drop Stash" msgstr "" #: cola/widgets/about.py:47 msgid "About git-cola" msgstr "" #: cola/widgets/about.py:97 msgid "" "This PyQt4 does not include QtWebKit.\n" "The keyboard shortcuts feature is unavailable." msgstr "" #: cola/widgets/about.py:104 msgid "hotkeys.html" msgstr "" #: cola/widgets/about.py:122 msgid "Shortcuts" msgstr "" #: cola/widgets/archive.py:46 msgid "Save Archive" msgstr "" #: cola/widgets/archive.py:69 msgid "Prefix" msgstr "" #: cola/widgets/archive.py:74 msgid "Advanced" msgstr "" #: cola/widgets/archive.py:141 cola/widgets/browse.py:49 msgid "File Saved" msgstr "" #: cola/widgets/archive.py:142 cola/widgets/browse.py:50 #, python-format msgid "File saved to \"%s\"" msgstr "" #: cola/widgets/archive.py:149 msgid "Overwrite File?" msgstr "" #: cola/widgets/archive.py:150 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/widgets/archive.py:151 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:152 msgid "Overwrite" msgstr "" #: cola/widgets/browse.py:42 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/browse.py:63 #, fuzzy, python-format msgid "Browsing %s" msgstr "Lägger till %s" #: cola/widgets/browse.py:81 #, fuzzy, python-format msgid "Select file from \"%s\"" msgstr "Tar bort grenar från %s" #: cola/widgets/browse.py:90 #, fuzzy msgid "Select File" msgstr "Markera alla" #: cola/widgets/browse.py:117 cola/widgets/selectcommits.py:54 msgid "Select" msgstr "Välj" #: cola/widgets/cfgactions.py:85 #, fuzzy msgid "Abort" msgstr "Avbryter" #: cola/widgets/cfgactions.py:147 cola/widgets/cfgactions.py:151 #, fuzzy msgid "Abort Action" msgstr "Avbryter" #: cola/widgets/cfgactions.py:148 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/widgets/cfgactions.py:150 msgid "Abort the action?" msgstr "" #: cola/widgets/cfgactions.py:201 msgid "Arguments" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/createtag.py:85 msgid "Revision" msgstr "Revision" #: cola/widgets/commitmsg.py:50 #, fuzzy msgid "Sign off on this commit" msgstr "Köade för incheckning" #: cola/widgets/commitmsg.py:53 cola/widgets/commitmsg.py:69 msgid "Commit@@verb" msgstr "Checka in" #: cola/widgets/commitmsg.py:56 #, fuzzy msgid "Commit staged changes" msgstr "Checkar in ändringar..." #: cola/widgets/commitmsg.py:67 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:75 #, fuzzy msgid "Actions..." msgstr "Alternativ..." #: cola/widgets/commitmsg.py:85 msgid "Amend Last Commit" msgstr "Lägg till föregående incheckning" #: cola/widgets/commitmsg.py:92 msgid "Check Spelling" msgstr "" #: cola/widgets/commitmsg.py:104 #, fuzzy msgid "Load Previous Commit Message" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/widgets/commitmsg.py:135 cola/widgets/status.py:117 msgid "Move Down" msgstr "" #: cola/widgets/commitmsg.py:342 msgid "" "Please supply a commit message.\n" "\n" "A good commit message has the following format:\n" "\n" "- First line: Describe in one sentence what you did.\n" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" "Ange ett incheckningsmeddelande.\n" "\n" "Ett bra incheckningsmeddelande har följande format:\n" "\n" "- Första raden: Beskriv i en mening vad du gjorde.\n" "- Andra raden: Tom\n" "- Följande rader: Beskriv varför det här är en bra ändring.\n" #: cola/widgets/commitmsg.py:349 #, fuzzy msgid "Missing Commit Message" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/widgets/commitmsg.py:355 #, fuzzy msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Inga ändringar att checka in.\n" "\n" "Du måste köa åtminstone en fil innan du kan checka in.\n" #: cola/widgets/commitmsg.py:359 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/commitmsg.py:361 #, fuzzy msgid "Stage and commit?" msgstr "Köade för incheckning" #: cola/widgets/commitmsg.py:364 #, fuzzy msgid "Stage and Commit" msgstr "Köa för incheckning" #: cola/widgets/commitmsg.py:369 #, fuzzy msgid "Nothing to commit" msgstr "Inga ändringar att checka in." #: cola/widgets/commitmsg.py:376 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/commitmsg.py:377 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" #: cola/widgets/commitmsg.py:380 msgid "Amend the published commit?" msgstr "" #: cola/widgets/commitmsg.py:381 #, fuzzy msgid "Amend Commit" msgstr "Lägg till föregående incheckning" #: cola/widgets/commitmsg.py:386 #, fuzzy msgid "Commit failed" msgstr "Incheckningen misslyckades." #: cola/widgets/commitmsg.py:387 #, python-format msgid "\"git commit\" returned exit code %s" msgstr "" #: cola/widgets/commitmsg.py:409 #, fuzzy msgid "More..." msgstr "Klona..." #: cola/widgets/commitmsg.py:413 #, fuzzy msgid "Select Commit Message" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/widgets/commitmsg.py:450 #, fuzzy msgid "Commit summary" msgstr "Incheckningsmeddelande:" #: cola/widgets/commitmsg.py:465 msgid "Extended description..." msgstr "" #: cola/widgets/compare.py:37 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:38 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/compare.py:39 cola/widgets/compare.py:62 #: cola/widgets/compare.py:68 msgid "Local" msgstr "" #: cola/widgets/compare.py:44 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/compare.py:63 cola/widgets/compare.py:69 #: cola/widgets/remote.py:129 msgid "Remote" msgstr "Fjärr" #: cola/widgets/compare.py:98 #, fuzzy msgid "File Differences" msgstr "Inställningar" #: cola/widgets/createbranch.py:102 msgid "Branch Name" msgstr "Namn på gren" #: cola/widgets/createbranch.py:107 cola/widgets/createbranch.py:178 msgid "Starting Revision" msgstr "Inledande revision" #: cola/widgets/createbranch.py:115 #, fuzzy msgid "Local branch" msgstr "Lokal gren" #: cola/widgets/createbranch.py:119 #, fuzzy msgid "Tracking branch" msgstr "Spårande gren" #: cola/widgets/createbranch.py:127 msgid "Update Existing Branch:" msgstr "Uppdatera befintlig gren:" #: cola/widgets/createbranch.py:130 msgid "No" msgstr "Nej" #: cola/widgets/createbranch.py:133 msgid "Fast Forward Only" msgstr "Endast snabbspolning" #: cola/widgets/createbranch.py:137 msgid "Reset" msgstr "Återställ" #: cola/widgets/createbranch.py:143 msgid "Fetch Tracking Branch" msgstr "Hämta spårande gren" #: cola/widgets/createbranch.py:148 msgid "Checkout After Creation" msgstr "Checka ut när skapad" #: cola/widgets/createbranch.py:259 #, fuzzy msgid "Missing Data" msgstr "Saknade" #: cola/widgets/createbranch.py:260 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/widgets/createbranch.py:265 #, fuzzy, python-format msgid "Branch \"%s\" already exists." msgstr "Grenen \"%s\" finns redan." #: cola/widgets/createbranch.py:266 cola/widgets/createbranch.py:277 #, fuzzy msgid "Branch Exists" msgstr "Grenar" #: cola/widgets/createbranch.py:273 #, fuzzy, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "" "Om du återställer \"%s\" till \"%s\" går följande incheckningar förlorade:" #: cola/widgets/createbranch.py:288 #, python-format msgid "%d skipped" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Recovering lost commits may not be easy." msgstr "Det kanske inte är så enkelt att återskapa förlorade incheckningar." #: cola/widgets/createbranch.py:292 #, fuzzy msgid "Reset Branch?" msgstr "Ta bort gren" #: cola/widgets/createbranch.py:294 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/widgets/createbranch.py:296 #, fuzzy msgid "Reset Branch" msgstr "Ta bort gren" #: cola/widgets/createbranch.py:305 #, fuzzy msgid "Updating..." msgstr "Startar..." #: cola/widgets/createbranch.py:321 #, fuzzy msgid "Error Creating Branch" msgstr "Skapa gren" #: cola/widgets/createbranch.py:322 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/widgets/createbranch.py:331 #, fuzzy msgid "Branch created" msgstr "Namn på gren" #: cola/widgets/createtag.py:55 msgid "vX.Y.Z" msgstr "" #: cola/widgets/createtag.py:56 msgid "Specifies the tag name" msgstr "" #: cola/widgets/createtag.py:62 #, fuzzy msgid "Sign Tag" msgstr "Skriv under" #: cola/widgets/createtag.py:67 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:91 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:121 #, fuzzy msgid "Missing Revision" msgstr "Inledande revision" #: cola/widgets/createtag.py:122 #, fuzzy msgid "Please specify a revision to tag." msgstr "Välj en gren att byta namn på." #: cola/widgets/createtag.py:125 #, fuzzy msgid "Missing Name" msgstr "Saknade" #: cola/widgets/createtag.py:126 msgid "Please specify a name for the new tag." msgstr "" #: cola/widgets/createtag.py:129 #, fuzzy msgid "Missing Tag Message" msgstr "Revisioner att slå ihop" #: cola/widgets/createtag.py:130 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/createtag.py:132 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/createtag.py:135 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/createtag.py:142 #, fuzzy msgid "Tag Created" msgstr "Skapa" #: cola/widgets/createtag.py:143 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/diff.py:22 msgid "Process Section" msgstr "" #: cola/widgets/diff.py:25 msgid "Process Selection" msgstr "" #: cola/widgets/diff.py:40 msgid "Stage &Selected Lines" msgstr "" #: cola/widgets/diff.py:46 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:51 #, fuzzy msgid "Unstage &Selected Lines" msgstr "Oköade ändringar" #: cola/widgets/diff.py:57 msgid "Apply Diff Selection to Work Tree" msgstr "" #: cola/widgets/diff.py:86 cola/widgets/diff.py:108 cola/widgets/status.py:486 #: cola/widgets/status.py:584 msgid "Launch git-cola" msgstr "" #: cola/widgets/diff.py:91 #, fuzzy msgid "Stage Section" msgstr "Inledande revision" #: cola/widgets/diff.py:97 msgid "Revert Section..." msgstr "" #: cola/widgets/diff.py:113 msgid "Unstage Section" msgstr "" #: cola/widgets/diff.py:125 msgid "Copy" msgstr "Kopiera" #: cola/widgets/diff.py:129 msgid "Select All" msgstr "Markera alla" #: cola/widgets/diff.py:245 msgid "Revert Section?" msgstr "" #: cola/widgets/diff.py:249 msgid "Revert Section" msgstr "" #: cola/widgets/diff.py:258 #, fuzzy msgid "Revert Selected Lines?" msgstr "Återställ ändringarna i filen %s?" #: cola/widgets/diff.py:262 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/editremotes.py:19 #, fuzzy msgid "Edit Remotes" msgstr "Fjärr" #: cola/widgets/editremotes.py:22 msgid "" "Add and remove remote repositories using the \n" "Add(+) and Delete(-) buttons on the left-hand side.\n" "\n" "Remotes can be renamed by selecting one from the list\n" "and pressing \"enter\", or by double-clicking." msgstr "" #: cola/widgets/editremotes.py:32 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/widgets/editremotes.py:45 #, fuzzy msgid "Add new remote git repository" msgstr "Inte ett Gitarkiv: %s" #: cola/widgets/editremotes.py:53 #, fuzzy msgid "Delete remote" msgstr "Ta bort fjärrgren" #: cola/widgets/editremotes.py:116 #, python-format msgid "Error creating remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:124 #, fuzzy msgid "Delete Remote" msgstr "Ta bort fjärrgren" #: cola/widgets/editremotes.py:125 #, fuzzy msgid "Delete remote?" msgstr "Ta bort fjärrgren" #: cola/widgets/editremotes.py:126 #, fuzzy, python-format msgid "Delete remote \"%s\"" msgstr "Ta bort fjärrgren" #: cola/widgets/editremotes.py:134 #, python-format msgid "Error deleting remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:153 #, fuzzy msgid "Rename Remote" msgstr "Fjärr" #: cola/widgets/editremotes.py:154 #, fuzzy msgid "Rename remote?" msgstr "Fjärr" #: cola/widgets/editremotes.py:155 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/editremotes.py:157 msgid "Rename" msgstr "Byt namn" #: cola/widgets/editremotes.py:169 #, fuzzy, python-format msgid "Gathering info for \"%s\"..." msgstr "Läser differens för %s..." #: cola/widgets/editremotes.py:201 #, fuzzy msgid "Add Remote" msgstr "Fjärr" #: cola/widgets/editremotes.py:213 #, fuzzy msgid "Add remote" msgstr "Fjärr" #: cola/widgets/editremotes.py:214 msgid "Name for the new remote" msgstr "" #: cola/widgets/editremotes.py:221 msgid "URL" msgstr "Webbadress" #: cola/widgets/grep.py:47 cola/widgets/search.py:40 cola/widgets/search.py:58 msgid "Search" msgstr "" #: cola/widgets/grep.py:52 msgid "command-line arguments" msgstr "" #: cola/widgets/grep.py:56 msgid "grep result..." msgstr "" #: cola/widgets/grep.py:69 msgid "Shell arguments" msgstr "" #: cola/widgets/grep.py:71 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/widgets/log.py:34 #, fuzzy, python-format msgid "exit code %s" msgstr "hämta %s" #: cola/widgets/recent.py:36 msgid "Recently Modified Files" msgstr "" #: cola/widgets/recent.py:46 msgid " commits ago" msgstr "" #: cola/widgets/recent.py:49 #, fuzzy msgid "Showing changes since" msgstr "Sänder ändringar till %s" #: cola/widgets/recent.py:61 msgid "Expand" msgstr "" #: cola/widgets/recent.py:65 #, fuzzy msgid "Collapse" msgstr "Stäng" #: cola/widgets/remote.py:136 #, fuzzy msgid "Remote Branch" msgstr "Byt namn på gren" #: cola/widgets/remote.py:143 #, fuzzy msgid "Fast Forward Only " msgstr "Endast snabbspolning" #: cola/widgets/remote.py:147 #, fuzzy msgid "Include tags " msgstr "Ta med taggar" #: cola/widgets/remote.py:150 #, fuzzy msgid "Rebase " msgstr "Återställ" #: cola/widgets/remote.py:314 #, fuzzy, python-format msgid "URL: %s" msgstr "Webbadress:" #: cola/widgets/remote.py:393 msgid "No repository selected." msgstr "Inget arkiv markerat." #: cola/widgets/remote.py:406 msgid "Push" msgstr "Sänd" #: cola/widgets/remote.py:408 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/remote.py:410 #, fuzzy msgid "Create a new remote branch?" msgstr "Skapa ny gren" #: cola/widgets/remote.py:411 #, fuzzy msgid "Create Remote Branch" msgstr "Ta bort fjärrgren" #: cola/widgets/remote.py:419 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:420 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:421 #, fuzzy, python-format msgid "Force fetching from %s?" msgstr "Hämtar %s från %s" #: cola/widgets/remote.py:422 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:424 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:425 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/remote.py:427 #, python-format msgid "Force push to %s?" msgstr "" #: cola/widgets/remote.py:428 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:462 msgid "Already up-to-date." msgstr "" #: cola/widgets/remote.py:485 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/widgets/search.py:44 #, fuzzy msgid "Browse..." msgstr "Bläddra" #: cola/widgets/search.py:50 cola/widgets/search.py:55 msgid "yyyy-MM-dd" msgstr "" #: cola/widgets/search.py:220 #, fuzzy msgid "Search by Expression" msgstr "Revisionsuttryck:" #: cola/widgets/search.py:221 msgid "Search by Path" msgstr "" #: cola/widgets/search.py:222 #, fuzzy msgid "Search Commit Messages" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/widgets/search.py:223 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:224 msgid "Search Authors" msgstr "" #: cola/widgets/search.py:225 #, fuzzy msgid "Search Committers" msgstr "Incheckare:" #: cola/widgets/search.py:226 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:319 #, fuzzy msgid "Choose Path(s)" msgstr "Välj %s" #: cola/widgets/selectcommits.py:50 msgid "Revision Expression:" msgstr "Revisionsuttryck:" #: cola/widgets/selectcommits.py:101 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/spellcheck.py:139 #, fuzzy msgid "Spelling Suggestions" msgstr "Inga förslag" #: cola/widgets/startup.py:26 msgid "git-cola" msgstr "" #: cola/widgets/startup.py:33 msgid "New..." msgstr "Nytt..." #: cola/widgets/startup.py:56 #, fuzzy msgid "Select Repository..." msgstr "Gitarkiv" #: cola/widgets/startup.py:61 #, fuzzy msgid "Select manually..." msgstr "Markera alla" #: cola/widgets/status.py:75 #, fuzzy msgid "Untracked" msgstr "Ej spårade, ej köade" #: cola/widgets/status.py:85 #, fuzzy msgid "Stage / Unstage" msgstr "Köa ändrade" #: cola/widgets/status.py:114 msgid "Move Up" msgstr "" #: cola/widgets/status.py:121 msgid "Copy Path to Clipboard" msgstr "" #: cola/widgets/status.py:474 cola/widgets/status.py:550 msgid "Revert Unstaged Edits..." msgstr "" #: cola/widgets/status.py:477 cola/widgets/status.py:553 msgid "Revert Uncommited Edits..." msgstr "" #: cola/widgets/status.py:572 #, fuzzy msgid "Delete File(s)..." msgstr "Ta bort..." #: cola/widgets/status.py:575 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:608 #, fuzzy msgid "Delete Files?" msgstr "Ta bort" #: cola/widgets/status.py:609 msgid "The following files will be deleted:" msgstr "" #: cola/widgets/status.py:616 #, python-format msgid "Delete %d file(s)?" msgstr "" #: cola/widgets/status.py:617 #, fuzzy msgid "Delete Files" msgstr "Ta bort" #: cola/widgets/status.py:633 #, fuzzy msgid "Revert Unstaged Changes?" msgstr "Oköade ändringar" #: cola/widgets/status.py:634 msgid "" "This operation drops unstaged changes.\n" "These changes cannot be recovered." msgstr "" #: cola/widgets/status.py:636 #, fuzzy msgid "Revert the unstaged changes?" msgstr "Oköade ändringar" #: cola/widgets/status.py:637 #, fuzzy msgid "Revert Unstaged Changes" msgstr "Oköade ändringar" #: cola/widgets/status.py:646 cola/widgets/status.py:662 msgid "No files selected for checkout from HEAD." msgstr "" #~ msgid "Success" #~ msgstr "Lyckades" #~ msgid "Rescan" #~ msgstr "Sök på nytt" #, fuzzy #~ msgid "Browse Revision..." #~ msgstr "Revision" #, fuzzy #~ msgid "Rebase Branch" #~ msgstr "Byt namn på gren" #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: ödesdigert fel" #~ msgid "Invalid font specified in %s:" #~ msgstr "Ogiltigt teckensnitt angivet i %s:" #~ msgid "Main Font" #~ msgstr "Huvudteckensnitt" #~ msgid "Diff/Console Font" #~ msgstr "Diff/konsolteckensnitt" #~ msgid "Cannot find git in PATH." #~ msgstr "Hittar inte git i PATH." #~ msgid "Cannot parse Git version string:" #~ msgstr "Kan inte tolka versionssträng från Git:" #~ msgid "" #~ "Git version cannot be determined.\n" #~ "\n" #~ "%s claims it is version '%s'.\n" #~ "\n" #~ "%s requires at least Git 1.5.0 or later.\n" #~ "\n" #~ "Assume '%s' is version 1.5.0?\n" #~ msgstr "" #~ "Kan inte avgöra Gits version.\n" #~ "\n" #~ "%s säger att dess version är \"%s\".\n" #~ "\n" #~ "%s kräver minst Git 1.5.0 eller senare.\n" #~ "\n" #~ "Anta att \"%s\" är version 1.5.0?\n" #~ msgid "Git directory not found:" #~ msgstr "Git-katalogen hittades inte:" #~ msgid "Cannot move to top of working directory:" #~ msgstr "Kan inte gå till början på arbetskatalogen:" #~ msgid "Cannot use funny .git directory:" #~ msgstr "Kan inte använda underlig .git-katalog:" #~ msgid "No working directory" #~ msgstr "Ingen arbetskatalog" #~ msgid "Refreshing file status..." #~ msgstr "Uppdaterar filstatus..." #~ msgid "Ready." #~ msgstr "Klar." #~ msgid "Modified, not staged" #~ msgstr "Förändrade, ej köade" #~ msgid "Portions staged for commit" #~ msgstr "Delar köade för incheckning" #~ msgid "Staged for commit, missing" #~ msgstr "Köade för incheckning, saknade" #~ msgid "Staged for removal" #~ msgstr "Köade för borttagning" #~ msgid "Staged for removal, still present" #~ msgstr "Köade för borttagning, fortfarande närvarande" #~ msgid "Requires merge resolution" #~ msgstr "Kräver konflikthantering efter sammanslagning" #~ msgid "Starting gitk... please wait..." #~ msgstr "Startar gitk... vänta..." #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "Kan inte starta gitk:\n" #~ "\n" #~ "%s finns inte" #~ msgid "Repository" #~ msgstr "Arkiv" #~ msgid "Commit@@noun" #~ msgstr "Incheckning" #~ msgid "Browse %s's Files" #~ msgstr "Bläddra i filer för %s" #~ msgid "Visualize %s's History" #~ msgstr "Visualisera historik för %s" #~ msgid "Database Statistics" #~ msgstr "Databasstatistik" #~ msgid "Compress Database" #~ msgstr "Komprimera databas" #~ msgid "Verify Database" #~ msgstr "Verifiera databas" #~ msgid "Create Desktop Icon" #~ msgstr "Skapa skrivbordsikon" #~ msgid "Undo" #~ msgstr "Ångra" #~ msgid "Redo" #~ msgstr "Gör om" #~ msgid "Cut" #~ msgstr "Klipp ut" #~ msgid "Paste" #~ msgstr "Klistra in" #~ msgid "Rename..." #~ msgstr "Byt namn..." #~ msgid "New Commit" #~ msgstr "Ny incheckning" #~ msgid "Local Merge..." #~ msgstr "Lokal sammanslagning..." #~ msgid "Preferences..." #~ msgstr "Inställningar..." #~ msgid "Current Branch:" #~ msgstr "Aktuell gren:" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "Köade ändringar (kommer att checkas in)" #~ msgid "Initial Commit Message:" #~ msgstr "Inledande incheckningsmeddelande:" #~ msgid "Amended Commit Message:" #~ msgstr "Utökat incheckningsmeddelande:" #~ msgid "Amended Initial Commit Message:" #~ msgstr "Utökat inledande incheckningsmeddelande:" #~ msgid "Amended Merge Commit Message:" #~ msgstr "Utökat incheckningsmeddelande för sammanslagning:" #~ msgid "Apply/Reverse Hunk" #~ msgstr "Använd/återställ del" #~ msgid "Show Less Context" #~ msgstr "Visa mindre sammanhang" #~ msgid "Show More Context" #~ msgstr "Visa mer sammanhang" #~ msgid "Decrease Font Size" #~ msgstr "Minska teckensnittsstorlek" #~ msgid "Increase Font Size" #~ msgstr "Öka teckensnittsstorlek" #~ msgid "Unstage Hunk From Commit" #~ msgstr "Ta bort del ur incheckningskö" #~ msgid "Stage Hunk For Commit" #~ msgstr "Ställ del i incheckningskö" #~ msgid "Initializing..." #~ msgstr "Initierar..." #~ msgid "" #~ "Possible environment issues exist.\n" #~ "\n" #~ "The following environment variables are probably\n" #~ "going to be ignored by any Git subprocess run\n" #~ "by %s:\n" #~ "\n" #~ msgstr "" #~ "Det finns möjliga problem med miljövariabler.\n" #~ "\n" #~ "Följande miljövariabler kommer troligen att\n" #~ "ignoreras av alla Git-underprocesser som körs\n" #~ "av %s:\n" #~ "\n" #~ msgid "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "Detta beror på ett känt problem med\n" #~ "Tcl-binären som följer med Cygwin." #~ msgid "" #~ "\n" #~ "\n" #~ "A good replacement for %s\n" #~ "is placing values for the user.name and\n" #~ "user.email settings into your personal\n" #~ "~/.gitconfig file.\n" #~ msgstr "" #~ "\n" #~ "\n" #~ "Du kan ersätta %s\n" #~ "med att lägga in värden för inställningarna\n" #~ "user.name och user.email i din personliga\n" #~ "~/.gitconfig-fil.\n" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - ett grafiskt användargränssnitt för Git." #~ msgid "File Viewer" #~ msgstr "Filvisare" #~ msgid "Reading %s..." #~ msgstr "Läser %s..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "Läser annoteringar för kopiering/flyttning..." #~ msgid "lines annotated" #~ msgstr "rader annoterade" #~ msgid "Loading original location annotations..." #~ msgstr "Läser in annotering av originalplacering..." #~ msgid "Annotation complete." #~ msgstr "Annotering fullbordad." #~ msgid "Loading annotation..." #~ msgstr "Läser in annotering..." #~ msgid "Original File:" #~ msgstr "Ursprunglig fil:" #~ msgid "Originally By:" #~ msgstr "Ursprungligen av:" #~ msgid "In File:" #~ msgstr "I filen:" #~ msgid "Copied Or Moved Here By:" #~ msgstr "Kopierad eller flyttad hit av:" #~ msgid "Detach From Local Branch" #~ msgstr "Koppla bort från lokal gren" #~ msgid "Match Tracking Branch Name" #~ msgstr "Använd namn på spårad gren" #~ msgid "Tracking branch %s is not a branch in the remote repository." #~ msgstr "Den spårade grenen %s är inte en gren i fjärrarkivet." #~ msgid "Please supply a branch name." #~ msgstr "Ange ett namn för grenen." #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "\"%s\" kan inte användas som namn på grenen." #~ msgid "Delete Local Branch" #~ msgstr "Ta bort lokal gren" #~ msgid "Local Branches" #~ msgstr "Lokala grenar" #~ msgid "Delete Only If Merged Into" #~ msgstr "Ta bara bort om sammanslagen med" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "Alltid (utför inte sammanslagningstest)." #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "Följande grenar är inte till fullo sammanslagna med %s:" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "Det är svårt att återställa borttagna grenar.\n" #~ "\n" #~ " Ta bort valda grenar?" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "Kunde inte ta bort grenar:\n" #~ "%s" #~ msgid "New Name:" #~ msgstr "Nytt namn:" #~ msgid "Failed to rename '%s'." #~ msgstr "Kunde inte byta namn på \"%s\"." #~ msgid "[Up To Parent]" #~ msgstr "[Upp till förälder]" #~ msgid "Browse Branch Files" #~ msgstr "Bläddra filer på grenen" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "ödesdigert: Kunde inte slå upp %s" #~ msgid "Branch '%s' does not exist." #~ msgstr "Grenen \"%s\" finns inte." #~ msgid "" #~ "Branch '%s' already exists.\n" #~ "\n" #~ "It cannot fast-forward to %s.\n" #~ "A merge is required." #~ msgstr "" #~ "Grenen \"%s\" finns redan.\n" #~ "\n" #~ "Den kan inte snabbspolas till %s.\n" #~ "En sammanslagning krävs." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "Sammanslagningsstrategin \"%s\" stöds inte." #~ msgid "Failed to update '%s'." #~ msgstr "Misslyckades med att uppdatera \"%s\"." #~ msgid "Staging area (index) is already locked." #~ msgstr "Köområdet (index) är redan låst." #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before the current branch can be changed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Det senaste inlästa tillståndet motsvarar inte tillståndet i arkivet.\n" #~ "\n" #~ "Ett annat Git-program har ändrat arkivet sedan senaste avsökningen. Du " #~ "måste utföra en ny sökning innan den aktuella grenen kan ändras.\n" #~ "\n" #~ "Sökningen kommer att startas automatiskt nu.\n" #~ msgid "Updating working directory to '%s'..." #~ msgstr "Uppdaterar arbetskatalogen till \"%s\"..." #~ msgid "files checked out" #~ msgstr "filer utcheckade" #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "Avbryter utcheckning av \"%s\" (sammanslagning på filnivå krävs)." #~ msgid "File level merge required." #~ msgstr "Sammanslagning på filnivå krävs." #~ msgid "Staying on branch '%s'." #~ msgstr "Stannar på grenen \"%s\"." #~ msgid "" #~ "You are no longer on a local branch.\n" #~ "\n" #~ "If you wanted to be on a branch, create one now starting from 'This " #~ "Detached Checkout'." #~ msgstr "" #~ "Du är inte längre på en lokal gren.\n" #~ "\n" #~ "Om du ville vara på en gren skapar du en nu, baserad på \"Denna " #~ "frånkopplade utcheckning\"." #~ msgid "Checked out '%s'." #~ msgstr "Checkade ut \"%s\"." #~ msgid "Reset '%s'?" #~ msgstr "Återställa \"%s\"?" #~ msgid "" #~ "Failed to set current branch.\n" #~ "\n" #~ "This working directory is only partially switched. We successfully " #~ "updated your files, but failed to update an internal Git file.\n" #~ "\n" #~ "This should not have occurred. %s will now close and give up." #~ msgstr "" #~ "Kunde inte ställa in aktuell gren.\n" #~ "\n" #~ "Arbetskatalogen har bara växlats delvis. Vi uppdaterade filerna utan " #~ "problem, men kunde inte uppdatera en intern fil i Git.\n" #~ "\n" #~ "Detta skulle inte ha hänt. %s kommer nu stängas och ge upp." #~ msgid "Font Family" #~ msgstr "Teckensnittsfamilj" #~ msgid "Font Example" #~ msgstr "Exempel" #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "Detta är en exempeltext.\n" #~ "Om du tycker om den här texten kan den vara ditt teckensnitt." #~ msgid "Git Gui" #~ msgstr "Git Gui" #~ msgid "Clone Existing Repository" #~ msgstr "Klona befintligt arkiv" #~ msgid "Recent Repositories" #~ msgstr "Senaste arkiven" #~ msgid "Failed to create repository %s:" #~ msgstr "Kunde inte skapa arkivet %s:" #~ msgid "Directory:" #~ msgstr "Katalog:" #~ msgid "Directory %s already exists." #~ msgstr "Katalogen %s finns redan." #~ msgid "Clone" #~ msgstr "Klona" #~ msgid "Clone Type:" #~ msgstr "Typ av klon:" #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "Standard (snabb, semiredundant, hårda länkar)" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "Full kopia (långsammare, redundant säkerhetskopia)" #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "Delad (snabbast, rekommenderas ej, ingen säkerhetskopia)" #~ msgid "Standard only available for local repository." #~ msgstr "Standard är endast tillgängligt för lokala arkiv." #~ msgid "Shared only available for local repository." #~ msgstr "Delat är endast tillgängligt för lokala arkiv." #~ msgid "Location %s already exists." #~ msgstr "Platsen %s finns redan." #~ msgid "Failed to configure origin" #~ msgstr "Kunde inte konfigurera ursprung" #~ msgid "Counting objects" #~ msgstr "Räknar objekt" #~ msgid "buckets" #~ msgstr "hinkar" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "Kunde inte kopiera objekt/info/alternativ: %s" #~ msgid "The 'master' branch has not been initialized." #~ msgstr "Grenen \"master\" har inte initierats." #~ msgid "Hardlinks are unavailable. Falling back to copying." #~ msgstr "Hårda länkar är inte tillgängliga. Faller tillbaka på kopiering." #~ msgid "Cloning from %s" #~ msgstr "Klonar från %s" #~ msgid "Copying objects" #~ msgstr "Kopierar objekt" #~ msgid "KiB" #~ msgstr "KiB" #~ msgid "Unable to copy object: %s" #~ msgstr "Kunde inte kopiera objekt: %s" #~ msgid "Linking objects" #~ msgstr "Länkar objekt" #~ msgid "objects" #~ msgstr "objekt" #~ msgid "Unable to hardlink object: %s" #~ msgstr "Kunde inte hårdlänka objekt: %s" #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "Kunde inte hämta grenar och objekt. Se konsolutdata för detaljer." #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "Kunde inte hämta taggar. Se konsolutdata för detaljer." #~ msgid "Cannot determine HEAD. See console output for details." #~ msgstr "Kunde inte avgöra HEAD. Se konsolutdata för detaljer." #~ msgid "Unable to cleanup %s" #~ msgstr "Kunde inte städa upp %s" #~ msgid "Clone failed." #~ msgstr "Kloning misslyckades." #~ msgid "No default branch obtained." #~ msgstr "Hämtade ingen standardgren." #~ msgid "Cannot resolve %s as a commit." #~ msgstr "Kunde inte slå upp %s till någon incheckning." #~ msgid "Creating working directory" #~ msgstr "Skapar arbetskatalog" #~ msgid "files" #~ msgstr "filer" #~ msgid "Initial file checkout failed." #~ msgstr "Inledande filutcheckning misslyckades." #~ msgid "Failed to open repository %s:" #~ msgstr "Kunde inte öppna arkivet %s:" #~ msgid "This Detached Checkout" #~ msgstr "Denna frånkopplade utcheckning" #~ msgid "Updated" #~ msgstr "Uppdaterad" #~ msgid "" #~ "There is nothing to amend.\n" #~ "\n" #~ "You are about to create the initial commit. There is no commit before " #~ "this to amend.\n" #~ msgstr "" #~ "Det finns ingenting att utöka.\n" #~ "\n" #~ "Du håller på att skapa den inledande incheckningen. Det finns ingen " #~ "tidigare incheckning att utöka.\n" #~ msgid "" #~ "Cannot amend while merging.\n" #~ "\n" #~ "You are currently in the middle of a merge that has not been fully " #~ "completed. You cannot amend the prior commit unless you first abort the " #~ "current merge activity.\n" #~ msgstr "" #~ "Kan inte utöka vid sammanslagning.\n" #~ "\n" #~ "Du är i mitten av en sammanslagning som inte är fullbordad. Du kan inte " #~ "utöka tidigare incheckningar om du inte först avbryter den pågående " #~ "sammanslagningen.\n" #~ msgid "Error loading commit data for amend:" #~ msgstr "Fel vid inläsning av incheckningsdata för utökning:" #~ msgid "Unable to obtain your identity:" #~ msgstr "Kunde inte hämta din identitet:" #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "Felaktig GIT_COMMITTER_IDENT:" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before another commit can be created.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Det senaste inlästa tillståndet motsvarar inte tillståndet i arkivet.\n" #~ "\n" #~ "Ett annat Git-program har ändrat arkivet sedan senaste avsökningen. Du " #~ "måste utföra en ny sökning innan du kan göra en ny incheckning.\n" #~ "\n" #~ "Sökningen kommer att startas automatiskt nu.\n" #~ msgid "" #~ "Unmerged files cannot be committed.\n" #~ "\n" #~ "File %s has merge conflicts. You must resolve them and stage the file " #~ "before committing.\n" #~ msgstr "" #~ "Osammanslagna filer kan inte checkas in.\n" #~ "\n" #~ "Filen %s har sammanslagningskonflikter. Du måste lösa dem och köa filen " #~ "innan du checkar in den.\n" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "Okänd filstatus %s upptäckt.\n" #~ "\n" #~ "Filen %s kan inte checkas in av programmet.\n" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "varning: Tcl stöder inte teckenkodningen \"%s\"." #~ msgid "Calling pre-commit hook..." #~ msgstr "Anropar krok före incheckning..." #~ msgid "Commit declined by pre-commit hook." #~ msgstr "Incheckningen avvisades av krok före incheckning." #~ msgid "Calling commit-msg hook..." #~ msgstr "Anropar krok för incheckningsmeddelande..." #~ msgid "Commit declined by commit-msg hook." #~ msgstr "Incheckning avvisad av krok för incheckningsmeddelande." #~ msgid "write-tree failed:" #~ msgstr "write-tree misslyckades:" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "Incheckningen %s verkar vara trasig" #~ msgid "" #~ "No changes to commit.\n" #~ "\n" #~ "No files were modified by this commit and it was not a merge commit.\n" #~ "\n" #~ "A rescan will be automatically started now.\n" #~ msgstr "" #~ "Inga ändringar att checka in.\n" #~ "\n" #~ "Inga filer ändrades av incheckningen och det var inte en sammanslagning.\n" #~ "\n" #~ "En sökning kommer att startas automatiskt nu.\n" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree misslyckades:" #~ msgid "update-ref failed:" #~ msgstr "update-ref misslyckades:" #~ msgid "Working... please wait..." #~ msgstr "Arbetar... vänta..." #~ msgid "Error: Command Failed" #~ msgstr "Fel: Kommando misslyckades" #~ msgid "Number of loose objects" #~ msgstr "Antal lösa objekt" #~ msgid "Disk space used by loose objects" #~ msgstr "Diskutrymme använt av lösa objekt" #~ msgid "Number of packed objects" #~ msgstr "Antal packade objekt" #~ msgid "Number of packs" #~ msgstr "Antal paket" #~ msgid "Disk space used by packed objects" #~ msgstr "Diskutrymme använt av packade objekt" #~ msgid "Packed objects waiting for pruning" #~ msgstr "Packade objekt som väntar på städning" #~ msgid "Garbage files" #~ msgstr "Skräpfiler" #~ msgid "Compressing the object database" #~ msgstr "Komprimerar objektdatabasen" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "Verifierar objektdatabasen med fsck-objects" #~ msgid "" #~ "This repository currently has approximately %i loose objects.\n" #~ "\n" #~ "To maintain optimal performance it is strongly recommended that you " #~ "compress the database when more than %i loose objects exist.\n" #~ "\n" #~ "Compress the database now?" #~ msgstr "" #~ "Arkivet har för närvarande omkring %i lösa objekt.\n" #~ "\n" #~ "För att bibehålla optimal prestanda rekommenderas det å det bestämdaste " #~ "att du komprimerar databasen när den innehåller mer än %i lösa objekt.\n" #~ "\n" #~ "Komprimera databasen nu?" #~ msgid "Invalid date from Git: %s" #~ msgstr "Ogiltigt datum från Git: %s" #~ msgid "" #~ "No differences detected.\n" #~ "\n" #~ "%s has no changes.\n" #~ "\n" #~ "The modification date of this file was updated by another application, " #~ "but the content within the file was not changed.\n" #~ "\n" #~ "A rescan will be automatically started to find other files which may have " #~ "the same state." #~ msgstr "" #~ "Hittade inga skillnader.\n" #~ "\n" #~ "%s innehåller inga ändringar.\n" #~ "\n" #~ "Modifieringsdatum för filen uppdaterades av ett annat program, men " #~ "innehållet i filen har inte ändrats.\n" #~ "\n" #~ "En sökning kommer automatiskt att startas för att hitta andra filer som " #~ "kan vara i samma tillstånd." #~ msgid "Unable to display %s" #~ msgstr "Kan inte visa %s" #~ msgid "Git Repository (subproject)" #~ msgstr "Gitarkiv (underprojekt)" #~ msgid "* Binary file (not showing content)." #~ msgstr "* Binärfil (visar inte innehållet)." #~ msgid "Failed to unstage selected hunk." #~ msgstr "Kunde inte ta bort den valda delen från kön." #~ msgid "Failed to stage selected hunk." #~ msgstr "Kunde inte lägga till den valda delen till kön." #~ msgid "warning" #~ msgstr "varning" #~ msgid "You must correct the above errors before committing." #~ msgstr "Du måste rätta till felen ovan innan du checkar in." #~ msgid "Unable to unlock the index." #~ msgstr "Kunde inte låsa upp indexet." #~ msgid "" #~ "Updating the Git index failed. A rescan will be automatically started to " #~ "resynchronize git-gui." #~ msgstr "" #~ "Misslyckades med att uppdatera Gitindexet. En omsökning kommer att " #~ "startas automatiskt för att synkronisera om git-gui." #~ msgid "Unlock Index" #~ msgstr "Lås upp index" #~ msgid "Ready to commit." #~ msgstr "Redo att checka in." #~ msgid "Revert changes in these %i files?" #~ msgstr "Återställ ändringarna i dessa %i filer?" #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "" #~ "Alla oköade ändringar kommer permanent gå förlorade vid återställningen." #~ msgid "Do Nothing" #~ msgstr "Gör ingenting" #~ msgid "" #~ "Cannot merge while amending.\n" #~ "\n" #~ "You must finish amending this commit before starting any type of merge.\n" #~ msgstr "" #~ "Kan inte slå ihop vid utökning.\n" #~ "\n" #~ "Du måste göra färdig utökningen av incheckningen innan du påbörjar någon " #~ "slags sammanslagning.\n" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before a merge can be performed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Det senaste inlästa tillståndet motsvarar inte tillståndet i arkivet.\n" #~ "\n" #~ "Ett annat Git-program har ändrat arkivet sedan senaste avsökningen. Du " #~ "måste utföra en ny sökning innan du kan utföra en sammanslagning.\n" #~ "\n" #~ "Sökningen kommer att startas automatiskt nu.\n" #~ msgid "" #~ "You are in the middle of a conflicted merge.\n" #~ "\n" #~ "File %s has merge conflicts.\n" #~ "\n" #~ "You must resolve them, stage the file, and commit to complete the current " #~ "merge. Only then can you begin another merge.\n" #~ msgstr "" #~ "Du är mitt i en sammanslagning med konflikter.\n" #~ "\n" #~ "Filen %s har sammanslagningskonflikter.\n" #~ "\n" #~ "Du måste lösa dem, köa filen och checka in för att fullborda den aktuella " #~ "sammanslagningen. När du gjort det kan du påbörja en ny sammanslagning.\n" #~ msgid "" #~ "You are in the middle of a change.\n" #~ "\n" #~ "File %s is modified.\n" #~ "\n" #~ "You should complete the current commit before starting a merge. Doing so " #~ "will help you abort a failed merge, should the need arise.\n" #~ msgstr "" #~ "Du är mitt i en ändring.\n" #~ "\n" #~ "Filen %s har ändringar.\n" #~ "\n" #~ "Du bör fullborda den aktuella incheckningen innan du påbörjar en " #~ "sammanslagning. Om du gör det blir det enklare att avbryta en misslyckad " #~ "sammanslagning, om det skulle vara nödvändigt.\n" #~ msgid "%s of %s" #~ msgstr "%s av %s" #~ msgid "Merging %s and %s..." #~ msgstr "Slår ihop %s och %s..." #~ msgid "Merge completed successfully." #~ msgstr "Sammanslagningen avslutades framgångsrikt." #~ msgid "Merge failed. Conflict resolution is required." #~ msgstr "Sammanslagningen misslyckades. Du måste lösa konflikterna." #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\n" #~ msgstr "" #~ "Kan inte avbryta vid utökning.\n" #~ "\n" #~ "Du måste göra dig färdig med att utöka incheckningen.\n" #~ msgid "" #~ "Reset changes?\n" #~ "\n" #~ "Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" #~ "\n" #~ "Continue with resetting the current changes?" #~ msgstr "" #~ "Återställ ändringar?\n" #~ "\n" #~ "Om du återställer ändringarna kommer *ALLA* ej incheckade ändringar att " #~ "gå förlorade.\n" #~ "\n" #~ "Gå vidare med att återställa de aktuella ändringarna?" #~ msgid "files reset" #~ msgstr "filer återställda" #~ msgid "Abort failed." #~ msgstr "Misslyckades avbryta." #~ msgid "Abort completed. Ready." #~ msgstr "Avbrytning fullbordad. Redo." #~ msgid "Restore Defaults" #~ msgstr "Återställ standardvärden" #~ msgid "%s Repository" #~ msgstr "Arkivet %s" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "Städa spårade grenar vid hämtning" #~ msgid "Match Tracking Branches" #~ msgstr "Matcha spårade grenar" #~ msgid "New Branch Name Template" #~ msgstr "Mall för namn på nya grenar" #~ msgid "Spelling Dictionary:" #~ msgstr "Stavningsordlista:" #~ msgid "Change Font" #~ msgstr "Byt teckensnitt" #~ msgid "pt." #~ msgstr "p." #~ msgid "Failed to completely save options:" #~ msgstr "Misslyckades med att helt spara alternativ:" #~ msgid "From Repository" #~ msgstr "Från arkiv" #~ msgid "Remote:" #~ msgstr "Fjärr:" #~ msgid "Arbitrary URL:" #~ msgstr "Godtycklig webbadress:" #~ msgid "Delete Only If" #~ msgstr "Ta endast bort om" #~ msgid "Merged Into:" #~ msgstr "Sammanslagen i:" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "Alltid (utför inte sammanslagningstest)" #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "En gren krävs för \"Sammanslagen i\"." #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "Följande grenar har inte helt slagits samman i %s:\n" #~ "\n" #~ " - %s" #~ msgid "" #~ "One or more of the merge tests failed because you have not fetched the " #~ "necessary commits. Try fetching from %s first." #~ msgstr "" #~ "En eller flera av sammanslagningstesterna misslyckades eftersom du inte " #~ "har hämtat de nödvändiga incheckningarna. Försök hämta från %s först." #~ msgid "Please select one or more branches to delete." #~ msgstr "Välj en eller flera grenar att ta bort." #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "Det kan vara svårt att återställa borttagna grenar.\n" #~ "\n" #~ "Ta bort de valda grenarna?" #~ msgid "Prune from" #~ msgstr "Ta bort från" #~ msgid "Fetch from" #~ msgstr "Hämta från" #~ msgid "Push to" #~ msgstr "Sänd till" #~ msgid "Cannot write shortcut:" #~ msgstr "Kan inte skriva genväg:" #~ msgid "Unsupported spell checker" #~ msgstr "Stavningskontrollprogrammet stöds inte" #~ msgid "Spell checking is unavailable" #~ msgstr "Stavningskontroll är ej tillgänglig" #~ msgid "Invalid spell checking configuration" #~ msgstr "Ogiltig inställning för stavningskontroll" #~ msgid "Reverting dictionary to %s." #~ msgstr "Återställer ordlistan till %s." #~ msgid "Spell checker silently failed on startup" #~ msgstr "Stavningskontroll misslyckades tyst vid start" #~ msgid "Unrecognized spell checker" #~ msgstr "Stavningskontrollprogrammet känns inte igen" #~ msgid "Unexpected EOF from spell checker" #~ msgstr "Oväntat filslut från stavningskontroll" #~ msgid "Spell Checker Failed" #~ msgstr "Stavningskontroll misslyckades" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%s... %*i av %*i %s (%3i%%)" #~ msgid "Fetching new changes from %s" #~ msgstr "Hämtar nya ändringar från %s" #~ msgid "remote prune %s" #~ msgstr "fjärrborttagning %s" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "Tar bort spårande grenar som tagits bort från %s" #~ msgid "push %s" #~ msgstr "sänd %s" #~ msgid "Pushing %s %s to %s" #~ msgstr "Sänder %s %s till %s" #~ msgid "Push Branches" #~ msgstr "Sänder grenar" #~ msgid "Source Branches" #~ msgstr "Källgrenar" #~ msgid "Destination Repository" #~ msgstr "Destinationsarkiv" #~ msgid "Transfer Options" #~ msgstr "Överföringsalternativ" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "Tvinga överskrivning av befintlig gren (kan kasta bort ändringar)" #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Använd tunt paket (för långsamma nätverksanslutningar)" #~ msgid "Not connected to aspell" #~ msgstr "Inte ansluten till aspell" git-cola-1.9.3/po/zh_CN.po000066400000000000000000002036461225156173500152240ustar00rootroot00000000000000# Translation of git-gui to Chinese # Copyright (C) 2007 Shawn Pearce # This file is distributed under the same license as the git-gui package. # Xudong Guan , 2007. # # Please use the following translation throughout the file for consistence: # # repository 版本库 # commit 提交 # revision 版本 # branch 分支 # tag 标签 # annotation 标注 # merge 合并 # fast forward 快速合并(??) # stage 缓存 (译自 index/cache) # amend 修正 # reset 复位 # # 2008-01-06 Eric Miao # FIXME: checkout 的标准翻译 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-09-24 21:42-0700\n" "PO-Revision-Date: 2007-07-21 01:23-0700\n" "Last-Translator: Eric Miao \n" "Language-Team: Chinese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: cola/bookmarks.py:32 msgid "Bookmarks" msgstr "" #: cola/bookmarks.py:47 msgid "Open" msgstr "打开" #: cola/bookmarks.py:53 msgid "Add" msgstr "" #: cola/bookmarks.py:58 cola/guicmds.py:25 cola/guicmds.py:33 #: cola/widgets/editremotes.py:127 msgid "Delete" msgstr "删除" #: cola/bookmarks.py:65 cola/stash/view.py:42 cola/widgets/archive.py:65 #: cola/widgets/browse.py:117 msgid "Save" msgstr "保存" #: cola/bookmarks.py:71 cola/difftool.py:96 cola/qt.py:57 cola/qt.py:243 #: cola/prefs/view.py:241 cola/stash/view.py:50 cola/stash/view.py:51 #: cola/widgets/about.py:66 cola/widgets/about.py:126 #: cola/widgets/browse.py:116 cola/widgets/cfgactions.py:87 #: cola/widgets/cfgactions.py:239 cola/widgets/compare.py:94 #: cola/widgets/createbranch.py:159 cola/widgets/createtag.py:104 #: cola/widgets/editremotes.py:55 cola/widgets/grep.py:75 #: cola/widgets/recent.py:75 cola/widgets/remote.py:157 #: cola/widgets/search.py:81 cola/widgets/selectcommits.py:59 #: cola/widgets/startup.py:42 msgid "Close" msgstr "关闭" #: cola/bookmarks.py:102 msgid "Bookmarks Saved" msgstr "" #: cola/bookmarks.py:103 msgid "Successfully saved bookmarks" msgstr "" #: cola/bookmarks.py:107 #, fuzzy msgid "Path to git repository" msgstr "不是一个 Git 版本库: %s" #: cola/bookmarks.py:108 #, fuzzy msgid "Enter Git Repository" msgstr "Git 版本库" #: cola/cmds.py:105 msgid "Amend" msgstr "" #: cola/cmds.py:140 #, fuzzy msgid "Cannot Amend" msgstr "无法修改图标:" #: cola/cmds.py:141 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" #: cola/cmds.py:204 #, python-format msgid "PATCH %(current)d/%(count)d" msgstr "" #: cola/cmds.py:208 msgid "Summary:" msgstr "" #: cola/cmds.py:217 msgid "Patch(es) Applied" msgstr "" #: cola/cmds.py:218 #, python-format msgid "%d patch(es) applied." msgstr "" #: cola/cmds.py:322 #, fuzzy, python-format msgid "Created commit: %s" msgstr "创建了 commit %s: %s" #: cola/cmds.py:324 #, fuzzy, python-format msgid "Commit failed: %s" msgstr "克隆失败." #: cola/cmds.py:369 cola/cmds.py:1186 #, fuzzy msgid "Error" msgstr "错误" #: cola/cmds.py:370 #, python-format msgid "Deleting \"%s\" failed" msgstr "" #: cola/cmds.py:406 #, fuzzy msgid "Remote Branch Deleted" msgstr "更改分支名:" #: cola/cmds.py:407 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "" #: cola/cmds.py:411 cola/guicmds.py:108 cola/widgets/remote.py:472 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "" #: cola/cmds.py:414 #, fuzzy msgid "Error Deleting Remote Branch" msgstr "创建分支" #: cola/cmds.py:493 cola/widgets/grep.py:60 cola/widgets/recent.py:69 msgid "Edit" msgstr "编辑" #: cola/cmds.py:529 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/cmds.py:531 #, fuzzy msgid "Error Editing File" msgstr "装载 diff 错误:" #: cola/cmds.py:554 msgid "Launch Diff Tool" msgstr "" #: cola/cmds.py:577 msgid "Launch Editor" msgstr "" #: cola/cmds.py:598 msgid "Error: Cannot find commit template" msgstr "" #: cola/cmds.py:599 #, fuzzy, python-format msgid "%s: No such file or directory." msgstr "致命错误: 无法获取路径 %s 的信息: 该文件或目录不存在" #: cola/cmds.py:616 msgid "Error: Unconfigured commit template" msgstr "" #: cola/cmds.py:617 msgid "" "A commit template has not been configured.\n" "Use \"git config\" to define \"commit.template\"\n" "so that it points to a commit template." msgstr "" #: cola/cmds.py:669 msgid "Open Using Default Application" msgstr "" #: cola/cmds.py:692 #, fuzzy msgid "Open Parent Directory" msgstr "打开最近版本库" #: cola/cmds.py:732 #, python-format msgid "Error: could not clone \"%s\"" msgstr "" #: cola/cmds.py:733 #, python-format msgid "git clone returned exit code %s" msgstr "" #: cola/cmds.py:756 cola/widgets/action.py:19 cola/widgets/editremotes.py:49 #: cola/widgets/grep.py:65 cola/widgets/recent.py:52 #: cola/widgets/recent.py:121 msgid "Refresh" msgstr "刷新" #: cola/cmds.py:784 #, python-format msgid "Run \"%s\"?" msgstr "" #: cola/cmds.py:791 #, fuzzy msgid "Please select a file" msgstr "请选择某个跟踪分支." #: cola/cmds.py:792 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:804 #, fuzzy msgid "Invalid Revision" msgstr "无效版本: %s" #: cola/cmds.py:805 #, fuzzy msgid "The revision expression cannot be empty." msgstr "版本表达式为空." #: cola/cmds.py:820 #, python-format msgid "Running command: %s" msgstr "" #: cola/cmds.py:829 cola/cmds.py:1006 cola/interaction.py:70 #, python-format msgid "Output: %s" msgstr "" #: cola/cmds.py:830 cola/guicmds.py:113 cola/interaction.py:71 #, python-format msgid "Errors: %s" msgstr "" #: cola/cmds.py:876 msgid "Sign Off" msgstr "签名(Sign Off)" #: cola/cmds.py:897 msgid "unknown" msgstr "" #: cola/cmds.py:910 cola/widgets/action.py:17 #, fuzzy msgid "Stage" msgstr "保存" #: cola/cmds.py:917 #, fuzzy, python-format msgid "Staging: %s" msgstr "正在扫描 %s..." #: cola/cmds.py:934 msgid "Stage Modified" msgstr "" #: cola/cmds.py:948 #, fuzzy msgid "Stage Unmerged" msgstr "缓存改动" #: cola/cmds.py:962 #, fuzzy msgid "Stage Untracked" msgstr "缓存改动" #: cola/cmds.py:980 #, python-format msgid "Tagging \"%(revision)s\" as \"%(name)s\"" msgstr "" #: cola/cmds.py:988 msgid "GPG-signed" msgstr "" #: cola/cmds.py:1020 cola/widgets/action.py:18 #, fuzzy msgid "Unstage" msgstr "未缓存的改动" #: cola/cmds.py:1027 #, fuzzy, python-format msgid "Unstaging: %s" msgstr "从提交缓存中删除 %s" #: cola/cmds.py:1055 #, python-format msgid "Untracking: %s" msgstr "" #: cola/cmds.py:1137 #, fuzzy msgid "Error Launching History Browser" msgstr "文件浏览器" #: cola/cmds.py:1138 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/difftool.py:76 msgid "git-cola diff" msgstr "" #: cola/difftool.py:92 cola/widgets/compare.py:90 msgid "Compare" msgstr "" #: cola/gitcmds.py:402 #, fuzzy msgid "Nothing to do" msgstr "没有东西可从 %s 克隆." #: cola/guicmds.py:25 msgid "Delete Branch" msgstr "删除分支" #: cola/guicmds.py:33 #, fuzzy msgid "Delete Remote Branch" msgstr "删除远端分支" #: cola/guicmds.py:53 #, fuzzy msgid "Browse Commits..." msgstr "浏览" #: cola/guicmds.py:53 #, fuzzy msgid "Browse" msgstr "浏览" #: cola/guicmds.py:61 msgid "Checkout Branch" msgstr "Checkout 分支" #: cola/guicmds.py:61 msgid "Checkout" msgstr "Checkout" #: cola/guicmds.py:70 #, fuzzy msgid "Cherry-Pick Commit" msgstr "复制提交" #: cola/guicmds.py:107 #, fuzzy msgid "Error Creating Repository" msgstr "创建新的版本库" #: cola/guicmds.py:110 #, python-format msgid "" "Output:\n" "%s" msgstr "" #: cola/guicmds.py:132 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/guicmds.py:153 #, fuzzy msgid "Error Cloning" msgstr "装载文件出错:" #: cola/guicmds.py:154 cola/guicmds.py:155 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/guicmds.py:159 msgid "Select a parent directory for the new clone" msgstr "" #: cola/guicmds.py:169 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/guicmds.py:185 cola/widgets/search.py:75 msgid "Export Patches" msgstr "" #: cola/guicmds.py:214 cola/widgets/startup.py:124 #, fuzzy msgid "Open Git Repository..." msgstr "打开已有版本库" #: cola/guicmds.py:223 #, fuzzy msgid "Load Commit Message" msgstr "提交描述:" #: cola/guicmds.py:251 #, fuzzy msgid "Select New Base" msgstr "选择" #: cola/guicmds.py:251 #, fuzzy msgid "Rebase" msgstr "复位" #: cola/guicmds.py:261 #, fuzzy msgid "Select Branch to Review" msgstr "删除分支" #: cola/guicmds.py:261 msgid "Review" msgstr "" #: cola/inotify.py:47 msgid "inotify is disabled because \"cola.inotify\" is false" msgstr "" #: cola/inotify.py:53 msgid "" "file notification: disabled\n" "Note: install pywin32 to enable.\n" msgstr "" #: cola/inotify.py:56 msgid "" "inotify: disabled\n" "Note: install python-pyinotify to enable inotify.\n" msgstr "" #: cola/inotify.py:62 msgid "On Debian systems try: sudo aptitude install python-pyinotify" msgstr "" #: cola/inotify.py:71 #, fuzzy msgid "File notification enabled." msgstr "相信文件的改动时间" #: cola/inotify.py:73 msgid "inotify enabled." msgstr "" #: cola/interaction.py:53 msgid "Continue" msgstr "继续" #: cola/interaction.py:63 #, python-format msgid "Run %s?" msgstr "" #: cola/interaction.py:64 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/interaction.py:65 cola/widgets/cfgactions.py:240 msgid "Run" msgstr "" #: cola/interaction.py:72 #, python-format msgid "Exit code: %s" msgstr "" #: cola/qt.py:60 cola/qt.py:100 #, fuzzy msgid "Detach" msgstr "删除分支" #: cola/qt.py:98 msgid "Attach" msgstr "" #: cola/qtutils.py:396 #, fuzzy msgid "Close..." msgstr "克隆..." #: cola/classic/controller.py:69 msgid "Select Previous Version" msgstr "" #: cola/classic/model.py:37 cola/widgets/createtag.py:51 #: cola/widgets/editremotes.py:220 #, fuzzy msgid "Name" msgstr "名字:" #: cola/classic/model.py:39 cola/main/view.py:91 msgid "Status" msgstr "" #: cola/classic/model.py:41 msgid "Age" msgstr "" #: cola/classic/model.py:43 cola/widgets/createtag.py:74 #, fuzzy msgid "Message" msgstr "合并(merge)" #: cola/classic/model.py:45 cola/dag/view.py:371 #, fuzzy msgid "Author" msgstr "作者:" #: cola/classic/model.py:342 #, python-format msgid "%d minutes ago" msgstr "" #: cola/classic/model.py:345 #, python-format msgid "%d hours ago" msgstr "" #: cola/classic/model.py:346 #, python-format msgid "%d days ago" msgstr "" #: cola/classic/model.py:359 cola/widgets/status.py:73 #, fuzzy msgid "Unmerged" msgstr "合并(merge)" #: cola/classic/model.py:361 msgid "Partially Staged" msgstr "" #: cola/classic/model.py:363 cola/widgets/status.py:74 #, fuzzy msgid "Modified" msgstr "未修改" #: cola/classic/model.py:365 cola/widgets/status.py:72 #, fuzzy msgid "Staged" msgstr "缓存改动" #: cola/classic/model.py:367 msgid "Changed Upstream" msgstr "" #: cola/classic/view.py:47 cola/main/view.py:545 #, fuzzy, python-format msgid "Repository: %s" msgstr "版本库" #: cola/classic/view.py:49 cola/main/view.py:547 #, fuzzy, python-format msgid "Branch: %s" msgstr "分支:" #: cola/classic/view.py:52 #, python-format msgid "%s: %s - Browse" msgstr "" #: cola/classic/view.py:54 cola/main/view.py:552 msgid "Amending" msgstr "" #: cola/classic/view.py:79 msgid "View History..." msgstr "" #: cola/classic/view.py:80 msgid "View history for selected path(s)." msgstr "" #: cola/classic/view.py:84 cola/widgets/status.py:506 #: cola/widgets/status.py:536 cola/widgets/status.py:593 #, fuzzy msgid "Stage Selected" msgstr "选择" #: cola/classic/view.py:85 #, fuzzy msgid "Stage selected path(s) for commit." msgstr "缓存为提交" #: cola/classic/view.py:90 cola/widgets/status.py:452 #: cola/widgets/status.py:494 msgid "Unstage Selected" msgstr "" #: cola/classic/view.py:91 msgid "Remove selected path(s) from the staging area." msgstr "" #: cola/classic/view.py:96 msgid "Untrack Selected" msgstr "" #: cola/classic/view.py:97 msgid "Stop tracking path(s)" msgstr "" #: cola/classic/view.py:102 msgid "Launch git-difftool on the current path." msgstr "" #: cola/classic/view.py:106 msgid "Diff Against Predecessor..." msgstr "" #: cola/classic/view.py:107 msgid "Launch git-difftool against previous versions." msgstr "" #: cola/classic/view.py:111 #, fuzzy msgid "Revert Uncommitted Changes..." msgstr "撤销修改" #: cola/classic/view.py:112 #, fuzzy msgid "Revert changes to selected path(s)." msgstr "撤销文件 %s 中的改动?" #: cola/classic/view.py:117 msgid "Edit selected path(s)." msgstr "" #: cola/classic/view.py:293 cola/widgets/status.py:652 #, fuzzy msgid "Revert Uncommitted Changes?" msgstr "撤销修改" #: cola/classic/view.py:294 cola/widgets/diff.py:246 cola/widgets/diff.py:259 #: cola/widgets/status.py:653 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/classic/view.py:296 cola/widgets/diff.py:248 cola/widgets/diff.py:261 #: cola/widgets/status.py:655 msgid "Revert the uncommitted changes?" msgstr "" #: cola/classic/view.py:297 cola/widgets/status.py:656 #, fuzzy msgid "Revert Uncommitted Changes" msgstr "撤销修改" #: cola/dag/view.py:166 #, fuzzy msgid "Loading..." msgstr "装载 %s..." #: cola/dag/view.py:272 msgid "Diff this -> selected" msgstr "" #: cola/dag/view.py:275 msgid "Diff selected -> this" msgstr "" #: cola/dag/view.py:278 cola/widgets/createbranch.py:89 #: cola/widgets/createbranch.py:98 cola/widgets/createbranch.py:155 #: cola/widgets/createbranch.py:330 msgid "Create Branch" msgstr "创建分支" #: cola/dag/view.py:281 #, fuzzy msgid "Create Patch" msgstr "创建分支" #: cola/dag/view.py:284 cola/widgets/createtag.py:38 #: cola/widgets/createtag.py:99 #, fuzzy msgid "Create Tag" msgstr "新建" #: cola/dag/view.py:287 cola/main/view.py:208 msgid "Save As Tarball/Zip..." msgstr "" #: cola/dag/view.py:290 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/dag/view.py:293 msgid "Grab File..." msgstr "" #: cola/dag/view.py:296 #, fuzzy msgid "Copy SHA-1" msgstr "全部复制" #: cola/dag/view.py:371 msgid "Summary" msgstr "" #: cola/dag/view.py:371 msgid "Date, Time" msgstr "" #: cola/dag/view.py:378 msgid "Go Up" msgstr "" #: cola/dag/view.py:381 msgid "Go Down" msgstr "" #: cola/dag/view.py:511 cola/dag/view.py:1181 msgid "Zoom Out" msgstr "" #: cola/dag/view.py:514 cola/dag/view.py:1178 msgid "Zoom In" msgstr "" #: cola/dag/view.py:517 cola/dag/view.py:1184 msgid "Zoom to Fit" msgstr "" #: cola/dag/view.py:536 msgid "Log" msgstr "" #: cola/dag/view.py:541 cola/main/view.py:114 cola/main/view.py:384 msgid "Diff" msgstr "" #: cola/dag/view.py:554 msgid "Graph" msgstr "" #: cola/dag/view.py:563 msgid "View" msgstr "" #: cola/dag/view.py:636 #, python-format msgid "%s: %s - DAG" msgstr "" #: cola/dag/view.py:638 msgid " - DAG" msgstr "" #: cola/dag/view.py:1187 #, fuzzy msgid "Select Parent" msgstr "选择" #: cola/dag/view.py:1190 msgid "Select Oldest Parent" msgstr "" #: cola/dag/view.py:1193 #, fuzzy msgid "Select Child" msgstr "全选" #: cola/dag/view.py:1196 msgid "Select Newest Child" msgstr "" #: cola/main/view.py:78 #, fuzzy msgid "Browser" msgstr "浏览" #: cola/main/view.py:83 #, fuzzy msgid "Action" msgstr "选项..." #: cola/main/view.py:99 cola/merge/view.py:45 #, fuzzy msgid "Commit" msgstr "提交:" #: cola/main/view.py:108 #, fuzzy msgid "Console" msgstr "关闭" #: cola/main/view.py:120 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/main/view.py:125 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/main/view.py:130 msgid "Ignore all whitespace" msgstr "" #: cola/main/view.py:135 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/main/view.py:139 cola/widgets/createbranch.py:194 msgid "Options" msgstr "选项..." #: cola/main/view.py:141 cola/main/view.py:142 #, fuzzy msgid "Diff Options" msgstr "选项..." #: cola/main/view.py:157 cola/widgets/status.py:423 msgid "Unstage All" msgstr "" #: cola/main/view.py:161 msgid "Unstage From Commit" msgstr "从本次提交撤除" #: cola/main/view.py:165 msgid "Diffstat" msgstr "" #: cola/main/view.py:168 msgid "Stage Changed Files To Commit" msgstr "缓存修改的文件为提交" #: cola/main/view.py:173 msgid "Stage All Untracked" msgstr "" #: cola/main/view.py:178 msgid "Export Patches..." msgstr "" #: cola/main/view.py:181 #, fuzzy msgid "New Repository..." msgstr "Git 版本库" #: cola/main/view.py:185 cola/prefs/view.py:220 msgid "Preferences" msgstr "首选项" #: cola/main/view.py:189 msgid "Edit Remotes..." msgstr "" #: cola/main/view.py:197 #, fuzzy msgid "Recently Modified Files..." msgstr "扫描修改过的文件 ..." #: cola/main/view.py:201 #, fuzzy msgid "Cherry-Pick..." msgstr "Checkout..." #: cola/main/view.py:205 #, fuzzy msgid "Load Commit Message..." msgstr "提交描述:" #: cola/main/view.py:211 msgid "Quit" msgstr "退出" #: cola/main/view.py:213 msgid "Bookmarks..." msgstr "" #: cola/main/view.py:215 msgid "Grep" msgstr "" #: cola/main/view.py:217 #, fuzzy msgid "Merge..." msgstr "合并(merge)" #: cola/main/view.py:220 cola/merge/__init__.py:20 msgid "Abort Merge..." msgstr "中止合并..." #: cola/main/view.py:223 cola/widgets/action.py:20 #, fuzzy msgid "Fetch..." msgstr "复位(Reset)..." #: cola/main/view.py:225 cola/widgets/action.py:21 msgid "Push..." msgstr "上传..." #: cola/main/view.py:227 cola/widgets/action.py:22 #, fuzzy msgid "Pull..." msgstr "上传..." #: cola/main/view.py:230 cola/widgets/startup.py:36 msgid "Open..." msgstr "打开..." #: cola/main/view.py:234 cola/widgets/action.py:23 #, fuzzy msgid "Stash..." msgstr "上传..." #: cola/main/view.py:237 cola/widgets/startup.py:39 msgid "Clone..." msgstr "克隆..." #: cola/main/view.py:241 #, fuzzy msgid "Documentation" msgstr "在线文档" #: cola/main/view.py:245 msgid "Keyboard Shortcuts" msgstr "" #: cola/main/view.py:250 #, fuzzy msgid "Visualize Current Branch..." msgstr "图示当前分支的历史" #: cola/main/view.py:253 #, fuzzy msgid "Visualize All Branches..." msgstr "图示所有分支的历史" #: cola/main/view.py:256 #, fuzzy msgid "Search..." msgstr "开始..." #: cola/main/view.py:258 #, fuzzy msgid "Browse Current Branch..." msgstr "浏览当前分支上的文件" #: cola/main/view.py:260 #, fuzzy msgid "Browse Other Branch..." msgstr "浏览分支上的文件..." #: cola/main/view.py:262 #, fuzzy msgid "Get Commit Message Template" msgstr "提交描述:" #: cola/main/view.py:265 #, fuzzy msgid "About" msgstr "关于 %s" #: cola/main/view.py:268 #, fuzzy msgid "Expression..." msgstr "选项..." #: cola/main/view.py:270 #, fuzzy msgid "Branches..." msgstr "分支" #: cola/main/view.py:273 #, fuzzy msgid "Create Tag..." msgstr "新建..." #: cola/main/view.py:276 msgid "Create..." msgstr "新建..." #: cola/main/view.py:279 msgid "Delete..." msgstr "删除..." #: cola/main/view.py:282 #, fuzzy msgid "Delete Remote Branch..." msgstr "删除远端分支" #: cola/main/view.py:285 msgid "Checkout..." msgstr "Checkout..." #: cola/main/view.py:287 #, fuzzy msgid "Rebase..." msgstr "复位(Reset)..." #: cola/main/view.py:289 #, fuzzy msgid "Review..." msgstr "复位(Reset)..." #: cola/main/view.py:292 #, fuzzy msgid "Browser..." msgstr "浏览" #: cola/main/view.py:296 msgid "DAG..." msgstr "" #: cola/main/view.py:313 #, fuzzy msgid "File" msgstr "文件:" #: cola/main/view.py:316 #, fuzzy msgid "Open Recent" msgstr "打开最近版本库" #: cola/main/view.py:338 cola/main/view.py:339 #, fuzzy msgid "Index" msgstr "缓存(Index)错误" #: cola/main/view.py:349 msgid "Branch" msgstr "分支(branch)" #: cola/main/view.py:367 #, fuzzy msgid "Actions" msgstr "选项..." #: cola/main/view.py:393 msgid "Tools" msgstr "" #: cola/main/view.py:404 msgid "Help" msgstr "帮助" #: cola/main/view.py:462 #, python-format msgid "git cola version %s" msgstr "" #: cola/merge/__init__.py:21 #, fuzzy msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "中止合并?\n" "\n" "中止当前的合并操作将导致 *所有* 尚未提交的改动丢失.\n" "\n" "是否要继续中止当前的合并操作?" #: cola/merge/__init__.py:24 msgid "Aborting the current merge?" msgstr "" #: cola/merge/__init__.py:25 #, fuzzy msgid "Abort Merge" msgstr "中止合并..." #: cola/merge/view.py:23 msgid "Revision To Merge" msgstr "要合并的版本" #: cola/merge/view.py:28 cola/widgets/cfgactions.py:220 #: cola/widgets/remote.py:122 msgid "Local Branch" msgstr "本地分支" #: cola/merge/view.py:31 cola/widgets/cfgactions.py:221 msgid "Tracking Branch" msgstr "跟踪分支:" #: cola/merge/view.py:33 cola/widgets/cfgactions.py:222 #: cola/widgets/createbranch.py:122 msgid "Tag" msgstr "标签" #: cola/merge/view.py:39 msgid "Visualize" msgstr "图示" #: cola/merge/view.py:42 #, fuzzy msgid "Squash" msgstr "上传" #: cola/merge/view.py:50 cola/widgets/archive.py:62 #: cola/widgets/editremotes.py:204 msgid "Cancel" msgstr "取消" #: cola/merge/view.py:53 msgid "Merge" msgstr "合并(merge)" #: cola/merge/view.py:115 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/merge/view.py:118 #, fuzzy, python-format msgid "Merge into \"%s\"" msgstr "合并到 %s" #: cola/merge/view.py:162 cola/merge/view.py:171 #, fuzzy msgid "No Revision Specified" msgstr "没有选择版本." #: cola/merge/view.py:163 msgid "You must specify a revision to view." msgstr "" #: cola/merge/view.py:172 msgid "You must specify a revision to merge." msgstr "" #: cola/prefs/view.py:116 msgid "User Name" msgstr "用户名" #: cola/prefs/view.py:117 msgid "Email Address" msgstr "Email 地址" #: cola/prefs/view.py:118 msgid "Merge Verbosity" msgstr "合并冗余度" #: cola/prefs/view.py:119 msgid "Number of Diff Context Lines" msgstr "Diff 上下文行数" #: cola/prefs/view.py:120 msgid "Summarize Merge Commits" msgstr "概述合并提交:" #: cola/prefs/view.py:121 msgid "Show Diffstat After Merge" msgstr "在合并后显示 Diffstat" #: cola/prefs/view.py:122 msgid "Display Untracked Files" msgstr "" #: cola/prefs/view.py:163 msgid "Fixed-Width Font" msgstr "" #: cola/prefs/view.py:164 msgid "Font Size" msgstr "字体大小" #: cola/prefs/view.py:165 msgid "Tab Width" msgstr "" #: cola/prefs/view.py:166 msgid "Text Width" msgstr "" #: cola/prefs/view.py:167 cola/widgets/commitmsg.py:99 msgid "Auto-Wrap Lines" msgstr "" #: cola/prefs/view.py:168 #, fuzzy msgid "Editor" msgstr "编辑" #: cola/prefs/view.py:169 #, fuzzy msgid "History Browser" msgstr "文件浏览器" #: cola/prefs/view.py:170 msgid "Diff Tool" msgstr "" #: cola/prefs/view.py:171 #, fuzzy msgid "Merge Tool" msgstr "合并(merge)" #: cola/prefs/view.py:172 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/prefs/view.py:173 msgid "Save GUI Settings" msgstr "" #: cola/prefs/view.py:227 #, fuzzy msgid "All Repositories" msgstr "全局 (所有版本库)" #: cola/prefs/view.py:228 #, fuzzy msgid "Current Repository" msgstr "创建新的版本库" #: cola/prefs/view.py:229 #, fuzzy msgid "Settings" msgstr "开始..." #: cola/stash/view.py:28 msgid "Stash" msgstr "" #: cola/stash/view.py:38 #, fuzzy msgid "Apply" msgstr "苹果" #: cola/stash/view.py:39 msgid "Apply the selected stash" msgstr "" #: cola/stash/view.py:43 msgid "Save modified state to new stash" msgstr "" #: cola/stash/view.py:46 msgid "Drop" msgstr "" #: cola/stash/view.py:47 msgid "Drop the selected stash" msgstr "" #: cola/stash/view.py:54 msgid "Keep Index" msgstr "" #: cola/stash/view.py:175 msgid "Save Stash" msgstr "" #: cola/stash/view.py:176 msgid "Enter a name for the stash" msgstr "" #: cola/stash/view.py:182 msgid "Error: Stash exists" msgstr "" #: cola/stash/view.py:183 #, fuzzy, python-format msgid "A stash named \"%s\" already exists" msgstr "文件 %s 已经存在." #: cola/stash/view.py:198 msgid "Drop Stash?" msgstr "" #: cola/stash/view.py:199 #, fuzzy msgid "Recovering a dropped stash is not possible." msgstr "恢复丢失的提交是比较困难的." #: cola/stash/view.py:200 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/stash/view.py:201 msgid "Drop Stash" msgstr "" #: cola/widgets/about.py:47 msgid "About git-cola" msgstr "" #: cola/widgets/about.py:97 msgid "" "This PyQt4 does not include QtWebKit.\n" "The keyboard shortcuts feature is unavailable." msgstr "" #: cola/widgets/about.py:104 msgid "hotkeys.html" msgstr "" #: cola/widgets/about.py:122 msgid "Shortcuts" msgstr "" #: cola/widgets/archive.py:46 msgid "Save Archive" msgstr "" #: cola/widgets/archive.py:69 msgid "Prefix" msgstr "" #: cola/widgets/archive.py:74 msgid "Advanced" msgstr "" #: cola/widgets/archive.py:141 cola/widgets/browse.py:49 msgid "File Saved" msgstr "" #: cola/widgets/archive.py:142 cola/widgets/browse.py:50 #, python-format msgid "File saved to \"%s\"" msgstr "" #: cola/widgets/archive.py:149 msgid "Overwrite File?" msgstr "" #: cola/widgets/archive.py:150 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/widgets/archive.py:151 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:152 msgid "Overwrite" msgstr "" #: cola/widgets/browse.py:42 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/browse.py:63 #, fuzzy, python-format msgid "Browsing %s" msgstr "添加 %s" #: cola/widgets/browse.py:81 #, fuzzy, python-format msgid "Select file from \"%s\"" msgstr "从 %s 中删除分支" #: cola/widgets/browse.py:90 #, fuzzy msgid "Select File" msgstr "全选" #: cola/widgets/browse.py:117 cola/widgets/selectcommits.py:54 msgid "Select" msgstr "选择" #: cola/widgets/cfgactions.py:85 #, fuzzy msgid "Abort" msgstr "中止" #: cola/widgets/cfgactions.py:147 cola/widgets/cfgactions.py:151 #, fuzzy msgid "Abort Action" msgstr "中止" #: cola/widgets/cfgactions.py:148 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/widgets/cfgactions.py:150 msgid "Abort the action?" msgstr "" #: cola/widgets/cfgactions.py:201 msgid "Arguments" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/createtag.py:85 msgid "Revision" msgstr "版本" #: cola/widgets/commitmsg.py:50 #, fuzzy msgid "Sign off on this commit" msgstr "缓存为提交" #: cola/widgets/commitmsg.py:53 cola/widgets/commitmsg.py:69 msgid "Commit@@verb" msgstr "提交" #: cola/widgets/commitmsg.py:56 #, fuzzy msgid "Commit staged changes" msgstr "未缓存的改动" #: cola/widgets/commitmsg.py:67 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:75 #, fuzzy msgid "Actions..." msgstr "选项..." #: cola/widgets/commitmsg.py:85 msgid "Amend Last Commit" msgstr "修正上次提交" #: cola/widgets/commitmsg.py:92 msgid "Check Spelling" msgstr "" #: cola/widgets/commitmsg.py:104 #, fuzzy msgid "Load Previous Commit Message" msgstr "合并提交描述:" #: cola/widgets/commitmsg.py:135 cola/widgets/status.py:117 msgid "Move Down" msgstr "" #: cola/widgets/commitmsg.py:342 msgid "" "Please supply a commit message.\n" "\n" "A good commit message has the following format:\n" "\n" "- First line: Describe in one sentence what you did.\n" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" "请提供一条提交信息.\n" "\n" "一条好的提交信息有下列格式:\n" "\n" "- 第一行: 一句话概括你做的修改.\n" "- 第二行: 空行\n" "- 剩余行: 请描述为什么你做的这些改动是好的.\n" #: cola/widgets/commitmsg.py:349 #, fuzzy msgid "Missing Commit Message" msgstr "合并提交描述:" #: cola/widgets/commitmsg.py:355 #, fuzzy msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "没有需要提交的变动.\n" "\n" "提交前你必须首先缓存至少一个文件.\n" #: cola/widgets/commitmsg.py:359 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/commitmsg.py:361 #, fuzzy msgid "Stage and commit?" msgstr "缓存为提交" #: cola/widgets/commitmsg.py:364 #, fuzzy msgid "Stage and Commit" msgstr "缓存为提交" #: cola/widgets/commitmsg.py:369 #, fuzzy msgid "Nothing to commit" msgstr "没有改动要提交." #: cola/widgets/commitmsg.py:376 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/commitmsg.py:377 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" #: cola/widgets/commitmsg.py:380 msgid "Amend the published commit?" msgstr "" #: cola/widgets/commitmsg.py:381 #, fuzzy msgid "Amend Commit" msgstr "修正上次提交" #: cola/widgets/commitmsg.py:386 #, fuzzy msgid "Commit failed" msgstr "克隆失败." #: cola/widgets/commitmsg.py:387 #, python-format msgid "\"git commit\" returned exit code %s" msgstr "" #: cola/widgets/commitmsg.py:409 #, fuzzy msgid "More..." msgstr "克隆..." #: cola/widgets/commitmsg.py:413 #, fuzzy msgid "Select Commit Message" msgstr "合并提交描述:" #: cola/widgets/commitmsg.py:450 #, fuzzy msgid "Commit summary" msgstr "提交描述:" #: cola/widgets/commitmsg.py:465 msgid "Extended description..." msgstr "" #: cola/widgets/compare.py:37 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:38 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/compare.py:39 cola/widgets/compare.py:62 #: cola/widgets/compare.py:68 msgid "Local" msgstr "" #: cola/widgets/compare.py:44 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/compare.py:63 cola/widgets/compare.py:69 #: cola/widgets/remote.py:129 msgid "Remote" msgstr "远端(remote)" #: cola/widgets/compare.py:98 #, fuzzy msgid "File Differences" msgstr "首选项" #: cola/widgets/createbranch.py:102 msgid "Branch Name" msgstr "分支名" #: cola/widgets/createbranch.py:107 cola/widgets/createbranch.py:178 msgid "Starting Revision" msgstr "起始版本" #: cola/widgets/createbranch.py:115 #, fuzzy msgid "Local branch" msgstr "本地分支" #: cola/widgets/createbranch.py:119 #, fuzzy msgid "Tracking branch" msgstr "跟踪分支:" #: cola/widgets/createbranch.py:127 msgid "Update Existing Branch:" msgstr "更新已有分支:" #: cola/widgets/createbranch.py:130 msgid "No" msgstr "号码" #: cola/widgets/createbranch.py:133 msgid "Fast Forward Only" msgstr "仅快速合并" #: cola/widgets/createbranch.py:137 msgid "Reset" msgstr "复位" #: cola/widgets/createbranch.py:143 msgid "Fetch Tracking Branch" msgstr "获取跟踪分支" #: cola/widgets/createbranch.py:148 msgid "Checkout After Creation" msgstr "在创建后Checkout" #: cola/widgets/createbranch.py:259 #, fuzzy msgid "Missing Data" msgstr "不存在" #: cola/widgets/createbranch.py:260 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/widgets/createbranch.py:265 #, fuzzy, python-format msgid "Branch \"%s\" already exists." msgstr "分支 '%s' 已经存在." #: cola/widgets/createbranch.py:266 cola/widgets/createbranch.py:277 #, fuzzy msgid "Branch Exists" msgstr "分支" #: cola/widgets/createbranch.py:273 #, fuzzy, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "复位 '%s' 到 '%s' 将导致下列提交的丢失:" #: cola/widgets/createbranch.py:288 #, python-format msgid "%d skipped" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Recovering lost commits may not be easy." msgstr "恢复丢失的提交是比较困难的." #: cola/widgets/createbranch.py:292 #, fuzzy msgid "Reset Branch?" msgstr "删除分支" #: cola/widgets/createbranch.py:294 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/widgets/createbranch.py:296 #, fuzzy msgid "Reset Branch" msgstr "删除分支" #: cola/widgets/createbranch.py:305 #, fuzzy msgid "Updating..." msgstr "开始..." #: cola/widgets/createbranch.py:321 #, fuzzy msgid "Error Creating Branch" msgstr "创建分支" #: cola/widgets/createbranch.py:322 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/widgets/createbranch.py:331 #, fuzzy msgid "Branch created" msgstr "分支名" #: cola/widgets/createtag.py:55 msgid "vX.Y.Z" msgstr "" #: cola/widgets/createtag.py:56 msgid "Specifies the tag name" msgstr "" #: cola/widgets/createtag.py:62 #, fuzzy msgid "Sign Tag" msgstr "签名(Sign Off)" #: cola/widgets/createtag.py:67 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:91 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:121 #, fuzzy msgid "Missing Revision" msgstr "起始版本" #: cola/widgets/createtag.py:122 #, fuzzy msgid "Please specify a revision to tag." msgstr "请选择分支更名." #: cola/widgets/createtag.py:125 #, fuzzy msgid "Missing Name" msgstr "不存在" #: cola/widgets/createtag.py:126 msgid "Please specify a name for the new tag." msgstr "" #: cola/widgets/createtag.py:129 #, fuzzy msgid "Missing Tag Message" msgstr "要合并的版本" #: cola/widgets/createtag.py:130 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/createtag.py:132 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/createtag.py:135 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/createtag.py:142 #, fuzzy msgid "Tag Created" msgstr "新建" #: cola/widgets/createtag.py:143 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/diff.py:22 msgid "Process Section" msgstr "" #: cola/widgets/diff.py:25 msgid "Process Selection" msgstr "" #: cola/widgets/diff.py:40 msgid "Stage &Selected Lines" msgstr "" #: cola/widgets/diff.py:46 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:51 #, fuzzy msgid "Unstage &Selected Lines" msgstr "未缓存的改动" #: cola/widgets/diff.py:57 msgid "Apply Diff Selection to Work Tree" msgstr "" #: cola/widgets/diff.py:86 cola/widgets/diff.py:108 cola/widgets/status.py:486 #: cola/widgets/status.py:584 msgid "Launch git-cola" msgstr "" #: cola/widgets/diff.py:91 #, fuzzy msgid "Stage Section" msgstr "起始版本" #: cola/widgets/diff.py:97 msgid "Revert Section..." msgstr "" #: cola/widgets/diff.py:113 msgid "Unstage Section" msgstr "" #: cola/widgets/diff.py:125 msgid "Copy" msgstr "复制" #: cola/widgets/diff.py:129 msgid "Select All" msgstr "全选" #: cola/widgets/diff.py:245 msgid "Revert Section?" msgstr "" #: cola/widgets/diff.py:249 msgid "Revert Section" msgstr "" #: cola/widgets/diff.py:258 #, fuzzy msgid "Revert Selected Lines?" msgstr "撤销文件 %s 中的改动?" #: cola/widgets/diff.py:262 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/editremotes.py:19 #, fuzzy msgid "Edit Remotes" msgstr "远端(remote)" #: cola/widgets/editremotes.py:22 msgid "" "Add and remove remote repositories using the \n" "Add(+) and Delete(-) buttons on the left-hand side.\n" "\n" "Remotes can be renamed by selecting one from the list\n" "and pressing \"enter\", or by double-clicking." msgstr "" #: cola/widgets/editremotes.py:32 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/widgets/editremotes.py:45 #, fuzzy msgid "Add new remote git repository" msgstr "不是一个 Git 版本库: %s" #: cola/widgets/editremotes.py:53 #, fuzzy msgid "Delete remote" msgstr "删除远端分支" #: cola/widgets/editremotes.py:116 #, python-format msgid "Error creating remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:124 #, fuzzy msgid "Delete Remote" msgstr "删除远端分支" #: cola/widgets/editremotes.py:125 #, fuzzy msgid "Delete remote?" msgstr "删除远端分支" #: cola/widgets/editremotes.py:126 #, fuzzy, python-format msgid "Delete remote \"%s\"" msgstr "删除远端分支" #: cola/widgets/editremotes.py:134 #, python-format msgid "Error deleting remote \"%s\"" msgstr "" #: cola/widgets/editremotes.py:153 #, fuzzy msgid "Rename Remote" msgstr "远端(remote)" #: cola/widgets/editremotes.py:154 #, fuzzy msgid "Rename remote?" msgstr "远端(remote)" #: cola/widgets/editremotes.py:155 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/editremotes.py:157 msgid "Rename" msgstr "更名..." #: cola/widgets/editremotes.py:169 #, fuzzy, python-format msgid "Gathering info for \"%s\"..." msgstr "装载 %s 的 diff ..." #: cola/widgets/editremotes.py:201 #, fuzzy msgid "Add Remote" msgstr "远端(remote)" #: cola/widgets/editremotes.py:213 #, fuzzy msgid "Add remote" msgstr "远端(remote)" #: cola/widgets/editremotes.py:214 msgid "Name for the new remote" msgstr "" #: cola/widgets/editremotes.py:221 msgid "URL" msgstr "URL" #: cola/widgets/grep.py:47 cola/widgets/search.py:40 cola/widgets/search.py:58 msgid "Search" msgstr "" #: cola/widgets/grep.py:52 msgid "command-line arguments" msgstr "" #: cola/widgets/grep.py:56 msgid "grep result..." msgstr "" #: cola/widgets/grep.py:69 msgid "Shell arguments" msgstr "" #: cola/widgets/grep.py:71 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/widgets/log.py:34 #, fuzzy, python-format msgid "exit code %s" msgstr "获取(fetch)" #: cola/widgets/recent.py:36 msgid "Recently Modified Files" msgstr "" #: cola/widgets/recent.py:46 msgid " commits ago" msgstr "" #: cola/widgets/recent.py:49 #, fuzzy msgid "Showing changes since" msgstr "上传改动到 %s" #: cola/widgets/recent.py:61 msgid "Expand" msgstr "" #: cola/widgets/recent.py:65 #, fuzzy msgid "Collapse" msgstr "关闭" #: cola/widgets/remote.py:136 #, fuzzy msgid "Remote Branch" msgstr "更改分支名:" #: cola/widgets/remote.py:143 #, fuzzy msgid "Fast Forward Only " msgstr "仅快速合并" #: cola/widgets/remote.py:147 #, fuzzy msgid "Include tags " msgstr "包含标签" #: cola/widgets/remote.py:150 #, fuzzy msgid "Rebase " msgstr "复位" #: cola/widgets/remote.py:314 #, fuzzy, python-format msgid "URL: %s" msgstr "URL:" #: cola/widgets/remote.py:393 msgid "No repository selected." msgstr "没有选择版本库" #: cola/widgets/remote.py:406 msgid "Push" msgstr "上传" #: cola/widgets/remote.py:408 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/remote.py:410 #, fuzzy msgid "Create a new remote branch?" msgstr "新建分支" #: cola/widgets/remote.py:411 #, fuzzy msgid "Create Remote Branch" msgstr "删除远端分支" #: cola/widgets/remote.py:419 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:420 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:421 #, fuzzy, python-format msgid "Force fetching from %s?" msgstr "获取 %s 自 %s" #: cola/widgets/remote.py:422 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:424 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:425 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/remote.py:427 #, python-format msgid "Force push to %s?" msgstr "" #: cola/widgets/remote.py:428 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:462 msgid "Already up-to-date." msgstr "" #: cola/widgets/remote.py:485 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/widgets/search.py:44 #, fuzzy msgid "Browse..." msgstr "浏览" #: cola/widgets/search.py:50 cola/widgets/search.py:55 msgid "yyyy-MM-dd" msgstr "" #: cola/widgets/search.py:220 #, fuzzy msgid "Search by Expression" msgstr "版本表达式:" #: cola/widgets/search.py:221 msgid "Search by Path" msgstr "" #: cola/widgets/search.py:222 #, fuzzy msgid "Search Commit Messages" msgstr "合并提交描述:" #: cola/widgets/search.py:223 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:224 msgid "Search Authors" msgstr "" #: cola/widgets/search.py:225 #, fuzzy msgid "Search Committers" msgstr "提交者:" #: cola/widgets/search.py:226 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:319 #, fuzzy msgid "Choose Path(s)" msgstr "选择 %s" #: cola/widgets/selectcommits.py:50 msgid "Revision Expression:" msgstr "版本表达式:" #: cola/widgets/selectcommits.py:101 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/spellcheck.py:139 msgid "Spelling Suggestions" msgstr "" #: cola/widgets/startup.py:26 msgid "git-cola" msgstr "" #: cola/widgets/startup.py:33 msgid "New..." msgstr "新建..." #: cola/widgets/startup.py:56 #, fuzzy msgid "Select Repository..." msgstr "Git 版本库" #: cola/widgets/startup.py:61 #, fuzzy msgid "Select manually..." msgstr "全选" #: cola/widgets/status.py:75 #, fuzzy msgid "Untracked" msgstr "未跟踪, 未缓存" #: cola/widgets/status.py:85 #, fuzzy msgid "Stage / Unstage" msgstr "缓存改动" #: cola/widgets/status.py:114 msgid "Move Up" msgstr "" #: cola/widgets/status.py:121 msgid "Copy Path to Clipboard" msgstr "" #: cola/widgets/status.py:474 cola/widgets/status.py:550 msgid "Revert Unstaged Edits..." msgstr "" #: cola/widgets/status.py:477 cola/widgets/status.py:553 msgid "Revert Uncommited Edits..." msgstr "" #: cola/widgets/status.py:572 #, fuzzy msgid "Delete File(s)..." msgstr "删除..." #: cola/widgets/status.py:575 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:608 #, fuzzy msgid "Delete Files?" msgstr "删除" #: cola/widgets/status.py:609 msgid "The following files will be deleted:" msgstr "" #: cola/widgets/status.py:616 #, python-format msgid "Delete %d file(s)?" msgstr "" #: cola/widgets/status.py:617 #, fuzzy msgid "Delete Files" msgstr "删除" #: cola/widgets/status.py:633 #, fuzzy msgid "Revert Unstaged Changes?" msgstr "未缓存的改动" #: cola/widgets/status.py:634 msgid "" "This operation drops unstaged changes.\n" "These changes cannot be recovered." msgstr "" #: cola/widgets/status.py:636 #, fuzzy msgid "Revert the unstaged changes?" msgstr "未缓存的改动" #: cola/widgets/status.py:637 #, fuzzy msgid "Revert Unstaged Changes" msgstr "未缓存的改动" #: cola/widgets/status.py:646 cola/widgets/status.py:662 msgid "No files selected for checkout from HEAD." msgstr "" #~ msgid "Success" #~ msgstr "成功" #~ msgid "Rescan" #~ msgstr "重新扫描" #, fuzzy #~ msgid "Browse Revision..." #~ msgstr "版本" #, fuzzy #~ msgid "Rebase Branch" #~ msgstr "更改分支名:" #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: 致命错误" #~ msgid "Invalid font specified in %s:" #~ msgstr "%s 中指定的字体无效:" #~ msgid "Main Font" #~ msgstr "主要字体" #~ msgid "Diff/Console Font" #~ msgstr "Diff/控制终端字体" #~ msgid "Cannot find git in PATH." #~ msgstr "PATH 中没有找到 git" #~ msgid "Cannot parse Git version string:" #~ msgstr "无法解析 Git 的版本信息:" #~ msgid "" #~ "Git version cannot be determined.\n" #~ "\n" #~ "%s claims it is version '%s'.\n" #~ "\n" #~ "%s requires at least Git 1.5.0 or later.\n" #~ "\n" #~ "Assume '%s' is version 1.5.0?\n" #~ msgstr "" #~ "无法确定 Git 的版本.\n" #~ "\n" #~ "%s 声明其版本为 '%s'.\n" #~ "\n" #~ "而 %s 需要 1.5.0 或这以后的 Git 版本.\n" #~ "\n" #~ "是否假定 '%s' 为版本 1.5.0?\n" #~ msgid "Git directory not found:" #~ msgstr "Git 目录无法找到:" #~ msgid "Cannot move to top of working directory:" #~ msgstr "无法移动到工作根目录:" #~ msgid "Cannot use funny .git directory:" #~ msgstr "无法使用 .git 目录:" #~ msgid "No working directory" #~ msgstr "没有工作目录" #~ msgid "Refreshing file status..." #~ msgstr "更新文件状态..." #~ msgid "Ready." #~ msgstr "就绪" #~ msgid "Modified, not staged" #~ msgstr "修改但未缓存" #~ msgid "Portions staged for commit" #~ msgstr "部分缓存为提交" #~ msgid "Staged for commit, missing" #~ msgstr "缓存为提交, 不存在" #~ msgid "Staged for removal" #~ msgstr "缓存为删除" #~ msgid "Staged for removal, still present" #~ msgstr "缓存为删除, 但仍存在" #~ msgid "Requires merge resolution" #~ msgstr "需要解决合并冲突" #~ msgid "Starting gitk... please wait..." #~ msgstr "启动 gitk... 请等待..." #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "无法启动 gitk:\n" #~ "\n" #~ "%s 不存在" #~ msgid "Repository" #~ msgstr "版本库(repository)" #~ msgid "Commit@@noun" #~ msgstr "提交(commit)" #~ msgid "Browse %s's Files" #~ msgstr "浏览 %s 上的文件" #~ msgid "Visualize %s's History" #~ msgstr "图示 %s 分支的历史" #~ msgid "Database Statistics" #~ msgstr "数据库统计信息" #~ msgid "Compress Database" #~ msgstr "压缩数据库" #~ msgid "Verify Database" #~ msgstr "验证数据库" #~ msgid "Create Desktop Icon" #~ msgstr "创建桌面图标" #~ msgid "Undo" #~ msgstr "撤销" #~ msgid "Redo" #~ msgstr "重做" #~ msgid "Cut" #~ msgstr "剪切" #~ msgid "Paste" #~ msgstr "粘贴" #~ msgid "Rename..." #~ msgstr "更名..." #~ msgid "New Commit" #~ msgstr "新建提交" #~ msgid "Local Merge..." #~ msgstr "本地合并..." #~ msgid "Preferences..." #~ msgstr "首选项..." #~ msgid "Current Branch:" #~ msgstr "当前分支:" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "已缓存的改动 (将被提交)" #~ msgid "Initial Commit Message:" #~ msgstr "初始的提交描述:" #~ msgid "Amended Commit Message:" #~ msgstr "修正的提交描述:" #~ msgid "Amended Initial Commit Message:" #~ msgstr "修正的初始提交描述:" #~ msgid "Amended Merge Commit Message:" #~ msgstr "修正的合并提交描述:" #~ msgid "Apply/Reverse Hunk" #~ msgstr "应用/撤消此修改块" #~ msgid "Show Less Context" #~ msgstr "显示更少上下文" #~ msgid "Show More Context" #~ msgstr "显示更多上下文" #~ msgid "Decrease Font Size" #~ msgstr "缩小字体" #~ msgid "Increase Font Size" #~ msgstr "放大字体" #~ msgid "Unstage Hunk From Commit" #~ msgstr "从提交中撤除修改块" #~ msgid "Stage Hunk For Commit" #~ msgstr "缓存修改块为提交" #~ msgid "Initializing..." #~ msgstr "初始化..." #~ msgid "" #~ "Possible environment issues exist.\n" #~ "\n" #~ "The following environment variables are probably\n" #~ "going to be ignored by any Git subprocess run\n" #~ "by %s:\n" #~ "\n" #~ msgstr "" #~ "可能存在环境变量的问题.\n" #~ "\n" #~ "由 %s 执行的 Git 子进程可能忽略下列环境变量:\n" #~ "\n" #~ msgid "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "这是由 Cygwin 发布的 Tcl 代码中一个\n" #~ "已知问题所引起." #~ msgid "" #~ "\n" #~ "\n" #~ "A good replacement for %s\n" #~ "is placing values for the user.name and\n" #~ "user.email settings into your personal\n" #~ "~/.gitconfig file.\n" #~ msgstr "" #~ "\n" #~ "\n" #~ "%s 的一个很好的替代方案是将 user.name 以及\n" #~ "user.email 设置放在你的个人 ~/.gitconfig 文件中.\n" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - Git 的图形化用户界面" #~ msgid "File Viewer" #~ msgstr "文件查看器" #~ msgid "Reading %s..." #~ msgstr "读取 %s..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "装载复制/移动跟踪标注..." #~ msgid "lines annotated" #~ msgstr "标注行" #~ msgid "Loading original location annotations..." #~ msgstr "装载原始位置标注..." #~ msgid "Annotation complete." #~ msgstr "标注完成." #~ msgid "Loading annotation..." #~ msgstr "裝載标注..." #~ msgid "Original File:" #~ msgstr "原始文件:" #~ msgid "Originally By:" #~ msgstr "最初由:" #~ msgid "In File:" #~ msgstr "在文件:" #~ msgid "Copied Or Moved Here By:" #~ msgstr "由复制或移动至此:" #~ msgid "Detach From Local Branch" #~ msgstr "从本地分支脱离" #~ msgid "Match Tracking Branch Name" #~ msgstr "匹配跟踪分支名字" #~ msgid "Tracking branch %s is not a branch in the remote repository." #~ msgstr "跟踪分支 %s 并不是远端版本库中的一个分支" #~ msgid "Please supply a branch name." #~ msgstr "请提供分支名字." #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "'%s'不是一个可接受的分支名." #~ msgid "Delete Local Branch" #~ msgstr "删除本地分支" #~ msgid "Local Branches" #~ msgstr "本地分支" #~ msgid "Delete Only If Merged Into" #~ msgstr "仅在合并后删除" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "总是合并 (不作合并测试.)" #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "下列分支没有完全被合并到 %s:" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "恢复被删除的分支非常困难.\n" #~ "\n" #~ "是否要删除所选分支?" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "无法删除分支:\n" #~ "%s" #~ msgid "New Name:" #~ msgstr "新名字:" #~ msgid "Failed to rename '%s'." #~ msgstr "无法更名 '%s'." #~ msgid "[Up To Parent]" #~ msgstr "[上层目录]" #~ msgid "Browse Branch Files" #~ msgstr "浏览分支文件" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "致命错误: 无法解决 %s" #~ msgid "Branch '%s' does not exist." #~ msgstr "分支 '%s' 并不存在." #~ msgid "" #~ "Branch '%s' already exists.\n" #~ "\n" #~ "It cannot fast-forward to %s.\n" #~ "A merge is required." #~ msgstr "" #~ "分支 '%s' 已经存在.\n" #~ "\n" #~ "无法快速合并到 %s.\n" #~ "需要普通合并." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "合并策略 '%s' 不支持." #~ msgid "Failed to update '%s'." #~ msgstr "无法更新 '%s'." #~ msgid "Staging area (index) is already locked." #~ msgstr "缓存区域 (index) 已被锁定." #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before the current branch can be changed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "最后一次扫描的状态和当前版本库状态不符.\n" #~ "\n" #~ "另一 Git 程序自上次扫描后修改了本版本库. 在修改当前分支之前需要重新做一次" #~ "扫描.\n" #~ "\n" #~ "重新扫描将自动开始.\n" #~ msgid "Updating working directory to '%s'..." #~ msgstr "更新工作目录到 '%s'..." #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "中止 '%s' 的 checkout 操作 (需要做文件级合并)." #~ msgid "File level merge required." #~ msgstr "需要文件级合并." #~ msgid "Staying on branch '%s'." #~ msgstr "停留在分支 '%s'." #~ msgid "" #~ "You are no longer on a local branch.\n" #~ "\n" #~ "If you wanted to be on a branch, create one now starting from 'This " #~ "Detached Checkout'." #~ msgstr "" #~ "你不在某个本地分支上.\n" #~ "\n" #~ "如果你想位于某分支上, 从当前脱节的Checkout中创建一个新分支." #~ msgid "Checked out '%s'." #~ msgstr "'%s' 已被 checkout" #~ msgid "Reset '%s'?" #~ msgstr "复位 '%s'?" #~ msgid "" #~ "Failed to set current branch.\n" #~ "\n" #~ "This working directory is only partially switched. We successfully " #~ "updated your files, but failed to update an internal Git file.\n" #~ "\n" #~ "This should not have occurred. %s will now close and give up." #~ msgstr "" #~ "无法设定当前分支.\n" #~ "\n" #~ "当前工作目录仅有部分被切换出, 我们已成功的更新了您的文件但是无法更新某个内" #~ "部的Git文件.\n" #~ "\n" #~ "这本不该发生, %s 将关闭并放弃." #~ msgid "Font Family" #~ msgstr "字体族" #~ msgid "Font Example" #~ msgstr "字体样例" #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "这是样例文本.\n" #~ "如果你喜欢, 你可以设置该字体." #~ msgid "Git Gui" #~ msgstr "Git Gui" #~ msgid "Clone Existing Repository" #~ msgstr "克隆已有版本库" #~ msgid "Recent Repositories" #~ msgstr "最近版本库" #~ msgid "Failed to create repository %s:" #~ msgstr "无法创建版本库 %s:" #~ msgid "Directory:" #~ msgstr "目录:" #~ msgid "Directory %s already exists." #~ msgstr "目录 %s 已经存在." #~ msgid "Clone" #~ msgstr "克隆" #~ msgid "Clone Type:" #~ msgstr "克隆类型:" #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "标准方式 (快速, 部分备份, 作硬连接)" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "全部复制 (较慢, 做备份)" #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "共享方式 (最快, 不推荐, 不做备份)" #~ msgid "Standard only available for local repository." #~ msgstr "标准方式仅当是本地版本库时有效." #~ msgid "Shared only available for local repository." #~ msgstr "共享方式仅当是本地版本库时有效." #~ msgid "Location %s already exists." #~ msgstr "位置 %s 已经存在." #~ msgid "Failed to configure origin" #~ msgstr "无法配置 origin" #~ msgid "Counting objects" #~ msgstr "清点对象" #, fuzzy #~ msgid "buckets" #~ msgstr "水桶??" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "无法复制 objects/info/alternates: %s" #~ msgid "The 'master' branch has not been initialized." #~ msgstr "'master'分支尚未初始化." #~ msgid "Hardlinks are unavailable. Falling back to copying." #~ msgstr "硬连接不可用. 使用复制." #~ msgid "Cloning from %s" #~ msgstr "从 %s 克隆" #~ msgid "Copying objects" #~ msgstr "复制 objects" #~ msgid "KiB" #~ msgstr "KiB" #~ msgid "Unable to copy object: %s" #~ msgstr "无法复制 object: %s" #~ msgid "Linking objects" #~ msgstr "链接 objects" #~ msgid "objects" #~ msgstr "objects" #~ msgid "Unable to hardlink object: %s" #~ msgstr "无法硬链接 object: %s" #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "无法获取分支和对象. 请查看控制终端的输出." #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "无法获取标签. 请查看控制终端的输出." #~ msgid "Cannot determine HEAD. See console output for details." #~ msgstr "无法确定 HEAD. 请查看控制终端的输出." #~ msgid "Unable to cleanup %s" #~ msgstr "无法清理 %s" #~ msgid "Clone failed." #~ msgstr "克隆失败." #~ msgid "No default branch obtained." #~ msgstr "没有获取缺省分支" #~ msgid "Cannot resolve %s as a commit." #~ msgstr "无法解析 %s 为提交." #~ msgid "Creating working directory" #~ msgstr "创建工作目录" #~ msgid "files" #~ msgstr "文件" #~ msgid "Initial file checkout failed." #~ msgstr "初始的文件checkout失败" #~ msgid "Failed to open repository %s:" #~ msgstr "无法打开版本库 %s:" #~ msgid "This Detached Checkout" #~ msgstr "该脱节的Checkout" #~ msgid "Updated" #~ msgstr "已更新" #~ msgid "" #~ "There is nothing to amend.\n" #~ "\n" #~ "You are about to create the initial commit. There is no commit before " #~ "this to amend.\n" #~ msgstr "" #~ "没有改动需要修正.\n" #~ "\n" #~ "你正在创建最初的提交. 在此之前没有提交可以修正.\n" #~ msgid "" #~ "Cannot amend while merging.\n" #~ "\n" #~ "You are currently in the middle of a merge that has not been fully " #~ "completed. You cannot amend the prior commit unless you first abort the " #~ "current merge activity.\n" #~ msgstr "" #~ "在合并时无法修正.\n" #~ "\n" #~ "你当前正在一次尚未完成的合并操作过程中. 除非中止当前合并活动,\n" #~ "否则无法修正之前的提交.\n" #~ msgid "Error loading commit data for amend:" #~ msgstr "为修正装载提交数据出错:" #~ msgid "Unable to obtain your identity:" #~ msgstr "无法获知你的身份:" #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "无效的 GIT_COMMITTER_IDENT" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before another commit can be created.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "最后一次扫描的状态和当前版本库状态不符.\n" #~ "\n" #~ "另一 Git 程序自上次扫描后修改了本版本库. 在修改当前分支之前需要重新做一次" #~ "扫描.\n" #~ "\n" #~ "重新扫描将自动开始.\n" #~ msgid "" #~ "Unmerged files cannot be committed.\n" #~ "\n" #~ "File %s has merge conflicts. You must resolve them and stage the file " #~ "before committing.\n" #~ msgstr "" #~ "尚未合并的文件没有办法提交.\n" #~ "\n" #~ "文件 %s 有合并冲突, 你必须解决这些冲突并缓存该文件作提交.\n" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "检测到未知文件状态 %s.\n" #~ "\n" #~ "文件 %s 无法由该程序提交.\n" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "警告: Tcl 不支持编码方式 '%s'." #~ msgid "write-tree failed:" #~ msgstr "write-tree 失败:" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "提交 %s 似乎已损坏" #~ msgid "" #~ "No changes to commit.\n" #~ "\n" #~ "No files were modified by this commit and it was not a merge commit.\n" #~ "\n" #~ "A rescan will be automatically started now.\n" #~ msgstr "" #~ "没有改动提交.\n" #~ "\n" #~ "该提交没有改动任何文件也不是一个合并提交.\n" #~ "\n" #~ "重新扫描将自动开始.\n" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree 失败:" #~ msgid "update-ref failed:" #~ msgstr "update-ref 失败:" #~ msgid "Working... please wait..." #~ msgstr "工作中... 请等待..." #~ msgid "Error: Command Failed" #~ msgstr "错误: 命令失败" #~ msgid "Number of loose objects" #~ msgstr "松散对象的数量" #~ msgid "Disk space used by loose objects" #~ msgstr "松散对象所使用的磁盘空间" #~ msgid "Number of packed objects" #~ msgstr "压缩对象数量" #~ msgid "Number of packs" #~ msgstr "压缩包数量" #~ msgid "Disk space used by packed objects" #~ msgstr "压缩对象所使用的磁盘空间" #~ msgid "Packed objects waiting for pruning" #~ msgstr "压缩对象等待清理" #~ msgid "Garbage files" #~ msgstr "垃圾文件" #~ msgid "Compressing the object database" #~ msgstr "压缩对象数据库" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "使用 fsck-objects 验证对象数据库" #~ msgid "" #~ "This repository currently has approximately %i loose objects.\n" #~ "\n" #~ "To maintain optimal performance it is strongly recommended that you " #~ "compress the database when more than %i loose objects exist.\n" #~ "\n" #~ "Compress the database now?" #~ msgstr "" #~ "该版本库当前约有 %i 个松散对象.\n" #~ "\n" #~ "为达到较优的性能,强烈建议你在松散对象多于 %i 时压缩数据库.\n" #~ "\n" #~ "现在就压缩数据库么?" #~ msgid "Invalid date from Git: %s" #~ msgstr "无效的日期: %s" #~ msgid "" #~ "No differences detected.\n" #~ "\n" #~ "%s has no changes.\n" #~ "\n" #~ "The modification date of this file was updated by another application, " #~ "but the content within the file was not changed.\n" #~ "\n" #~ "A rescan will be automatically started to find other files which may have " #~ "the same state." #~ msgstr "" #~ "未检测到改动.\n" #~ "\n" #~ "该文件的修改日期被另一个程序所更新, 但其内容并没有变化.\n" #~ "\n" #~ "对于类似情况的其他文件的重新扫描将自动开始." #~ msgid "Unable to display %s" #~ msgstr "无法显示 %s" #~ msgid "Git Repository (subproject)" #~ msgstr "Git 版本库 (子项目)" #~ msgid "* Binary file (not showing content)." #~ msgstr "* 二进制文件 (不显示内容)." #~ msgid "Failed to unstage selected hunk." #~ msgstr "无法将选择的代码段从缓存中删除." #~ msgid "Failed to stage selected hunk." #~ msgstr "无法缓存所选代码段." #~ msgid "warning" #~ msgstr "警告" #~ msgid "You must correct the above errors before committing." #~ msgstr "你必须在提交前修正上述错误." #~ msgid "Unable to unlock the index." #~ msgstr "无法解锁缓存 (index)" #~ msgid "" #~ "Updating the Git index failed. A rescan will be automatically started to " #~ "resynchronize git-gui." #~ msgstr "更新 Git 缓存(Index)失败, 重新扫描将自动开始以重新同步 git-gui." #~ msgid "Unlock Index" #~ msgstr "解锁 Index" #, fuzzy #~ msgid "Ready to commit." #~ msgstr "缓存为提交" #~ msgid "Revert changes in these %i files?" #~ msgstr "撤销这些 (%i个) 文件的改动?" #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "任何未缓存的改动将在这次撤销中永久丢失." #~ msgid "Do Nothing" #~ msgstr "不做操作" #~ msgid "" #~ "Cannot merge while amending.\n" #~ "\n" #~ "You must finish amending this commit before starting any type of merge.\n" #~ msgstr "" #~ "修正时无法做合并.\n" #~ "\n" #~ "你必须完成对该提交的修正才能继续任何类型的合并操作.\n" #~ msgid "" #~ "Last scanned state does not match repository state.\n" #~ "\n" #~ "Another Git program has modified this repository since the last scan. A " #~ "rescan must be performed before a merge can be performed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "最后一次扫描的状态和当前版本库状态不符.\n" #~ "\n" #~ "另一 Git 程序自上次扫描后修改了本版本库. 在修改当前分支之前需要重新做一次" #~ "扫描.\n" #~ "\n" #~ "重新扫描将自动开始.\n" #~ msgid "" #~ "You are in the middle of a conflicted merge.\n" #~ "\n" #~ "File %s has merge conflicts.\n" #~ "\n" #~ "You must resolve them, stage the file, and commit to complete the current " #~ "merge. Only then can you begin another merge.\n" #~ msgstr "" #~ "你正处在一个有冲突的合并操作中.\n" #~ "\n" #~ "文件 %s 有合并冲突.\n" #~ "\n" #~ "你必须解决这些冲突, 缓存该文件, 并提交来完成当前的合并.仅当这样后才能开始" #~ "下一个合并操作.\n" #~ msgid "" #~ "You are in the middle of a change.\n" #~ "\n" #~ "File %s is modified.\n" #~ "\n" #~ "You should complete the current commit before starting a merge. Doing so " #~ "will help you abort a failed merge, should the need arise.\n" #~ msgstr "" #~ "你正处在一个改动当中.\n" #~ "\n" #~ "文件 %s 已被修改.\n" #~ "\n" #~ "你必须完成当前的提交后才能开始合并. 如果需要, 这么做将有助于中止一次失败的" #~ "合并.\n" #, fuzzy #~ msgid "Merging %s and %s..." #~ msgstr "合并 %s 和 %s" #~ msgid "Merge completed successfully." #~ msgstr "合并成功完成." #~ msgid "Merge failed. Conflict resolution is required." #~ msgstr "合并失败. 需要解决冲突." #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\n" #~ msgstr "" #~ "修正操作中无法中止.\n" #~ "\n" #~ "你必须先完成本次修正操作.\n" #~ msgid "" #~ "Reset changes?\n" #~ "\n" #~ "Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" #~ "\n" #~ "Continue with resetting the current changes?" #~ msgstr "" #~ "是否复位当前改动?\n" #~ "\n" #~ "复位当前的改动将导致 *所有* 未提交的改动丢失.\n" #~ "\n" #~ "是否要继续复位当前的改动?" #, fuzzy #~ msgid "files reset" #~ msgstr "文件" #~ msgid "Abort failed." #~ msgstr "中止失败" #~ msgid "Abort completed. Ready." #~ msgstr "中止完成. 就绪." #~ msgid "Restore Defaults" #~ msgstr "恢复默认值" #~ msgid "%s Repository" #~ msgstr "%s 版本库" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "获取时清除跟踪分支" #~ msgid "Match Tracking Branches" #~ msgstr "匹配跟踪分支" #~ msgid "New Branch Name Template" #~ msgstr "新建分支命名模板" #~ msgid "Change Font" #~ msgstr "更改字体" #~ msgid "pt." #~ msgstr "磅" #~ msgid "Failed to completely save options:" #~ msgstr "无法完全保存选项:" #~ msgid "From Repository" #~ msgstr "从版本库" #~ msgid "Remote:" #~ msgstr "Remote:" #~ msgid "Arbitrary URL:" #~ msgstr "任意 URL:" #~ msgid "Delete Only If" #~ msgstr "删除仅当" #~ msgid "Merged Into:" #~ msgstr "合并到" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "总是合并 (不作合并检查)" #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "'合并到' 需要指定某个分支" #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "下列分支没有被全部合并到 %s 中:\n" #~ "\n" #~ " - %s" #~ msgid "" #~ "One or more of the merge tests failed because you have not fetched the " #~ "necessary commits. Try fetching from %s first." #~ msgstr "" #~ "由于没有获取到必要的提交,一个或多个合并测试失败。请尝试从 %s 处先获取。" #~ msgid "Please select one or more branches to delete." #~ msgstr "请选择某个或多个分支来删除" #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "恢复被删除的分支非常困难.\n" #~ "\n" #~ "是否要删除所选分支?" #~ msgid "Prune from" #~ msgstr "从..清除(prune)" #~ msgid "Fetch from" #~ msgstr "从..获取(fetch)" #~ msgid "Push to" #~ msgstr "上传到(push)" #~ msgid "Cannot write shortcut:" #~ msgstr "无法修改快捷方式:" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%s ... %*i of %*i %s (%3i%%)" #~ msgid "Fetching new changes from %s" #~ msgstr "从 %s 处获取新的改动" #~ msgid "remote prune %s" #~ msgstr "清除远端 %s" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "清除" #~ msgid "push %s" #~ msgstr "上传 %s" #~ msgid "Pushing %s %s to %s" #~ msgstr "上传 %s %s 到 %s" #~ msgid "Push Branches" #~ msgstr "上传分支" #~ msgid "Source Branches" #~ msgstr "源端分支:" #~ msgid "Destination Repository" #~ msgstr "目标版本库" #~ msgid "Transfer Options" #~ msgstr "传输选项" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "强制覆盖已有的分支 (可能会丢失改动)" #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "使用 thin pack (适用于低速网络连接)" git-cola-1.9.3/setup.cfg000066400000000000000000000004621225156173500150550ustar00rootroot00000000000000[bdist_rpm] release = 1 requires = python PyQt4 build_requires = python PyQt4 doc_files = COPYING COPYRIGHT README.md share/doc/git-cola/ [upload_sphinx] upload-dir = share/doc/git-cola/_build/html [build_sphinx] all_files = 1 build-dir = share/doc/git-cola/_build source-dir = share/doc/git-cola/ git-cola-1.9.3/setup.py000077500000000000000000000037201225156173500147510ustar00rootroot00000000000000#!/usr/bin/env python import os import sys from glob import glob from distutils.core import setup # Look for modules in the root srcdir = os.path.dirname(os.path.abspath(__file__)) from extras import cmdclass here = os.path.dirname(__file__) version = os.path.join(here, 'cola', '_version.py') scope = {} exec(open(version).read(), scope) version = scope['VERSION'] def main(): """Runs distutils.setup()""" scripts = [ 'bin/git-cola', 'bin/git-dag', ] if sys.platform == 'win32': scripts.append('contrib/win32/cola') setup(name='git-cola', version=version, description='The highly caffeinated git GUI', long_description='A sleek and powerful git GUI', license='GPLv2', author='David Aguilar', author_email='davvid@gmail.com', url='http://git-cola.github.io/', scripts=scripts, cmdclass=cmdclass, platforms='any', data_files = cola_data_files()) def cola_data_files(): data = [ _app_path('share/git-cola/bin', '*'), _app_path('share/git-cola/icons', '*.png'), _app_path('share/git-cola/icons', '*.svg'), _app_path('share/applications', '*.desktop'), _app_path('share/doc/git-cola', '*.txt'), _app_path('share/doc/git-cola', '*.html'), _package('cola'), _package('cola.models'), _package('cola.widgets'), ] data.extend([_app_path(localedir, 'git-cola.mo') for localedir in glob('share/locale/*/LC_MESSAGES')]) return data def _package(package, subdir=None): subdirs = package.split('.') app_dir = os.path.join('share', 'git-cola', 'lib', *subdirs) if subdir: subdirs.insert(0, subdir) src_dir = os.path.join(*subdirs) return (app_dir, glob(os.path.join(src_dir, '*.py'))) def _app_path(dirname, entry): return (dirname, glob(os.path.join(dirname, entry))) if __name__ == '__main__': main() git-cola-1.9.3/share/000077500000000000000000000000001225156173500143345ustar00rootroot00000000000000git-cola-1.9.3/share/applications/000077500000000000000000000000001225156173500170225ustar00rootroot00000000000000git-cola-1.9.3/share/applications/git-cola-folder-handler.desktop000066400000000000000000000003721225156173500250020ustar00rootroot00000000000000[Desktop Entry] Name=Git Cola TryExec=git-cola Exec=git-cola --repo %u Path=%u Icon=/usr/share/git-cola/icons/git.svg NoDisplay=true Terminal=false StartupNotify=true Type=Application Categories=Development;RevisionControl; MimeType=inode/directory; git-cola-1.9.3/share/applications/git-cola.desktop000066400000000000000000000004111225156173500221100ustar00rootroot00000000000000[Desktop Entry] Name=Git Cola Comment=The highly caffeinated Git GUI TryExec=git-cola Exec=git-cola --prompt Icon=/usr/share/git-cola/icons/git.svg StartupNotify=true Terminal=false Type=Application Categories=Development;RevisionControl; X-KDE-SubstituteUID=false git-cola-1.9.3/share/applications/git-dag.desktop000066400000000000000000000003521225156173500217310ustar00rootroot00000000000000[Desktop Entry] Name=Git DAG Comment=Git DAG visualizer Exec=git-dag --prompt Icon=/usr/share/git-cola/icons/git.svg StartupNotify=true Terminal=false Type=Application Categories=Development;RevisionControl; X-KDE-SubstituteUID=false git-cola-1.9.3/share/doc/000077500000000000000000000000001225156173500151015ustar00rootroot00000000000000git-cola-1.9.3/share/doc/git-cola/000077500000000000000000000000001225156173500166005ustar00rootroot00000000000000git-cola-1.9.3/share/doc/git-cola/.gitignore000066400000000000000000000000741225156173500205710ustar00rootroot00000000000000*.pdf *.7 *.1 /_build /git-cola.html /git-dag.html /doc.dep git-cola-1.9.3/share/doc/git-cola/Makefile000066400000000000000000000070541225156173500202460ustar00rootroot00000000000000prefix ?= $(CURDIR) docdir ?= $(prefix)/share/doc/git-cola htmldir ?= $(docdir)/html SED ?= sed RSYNC ?= rsync # DESTDIR = # Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf _build $(MAKE) -f Makefile.asciidoc clean html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html @echo @echo "Build finished. The HTML pages are in _build/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml @echo @echo "Build finished. The HTML pages are in _build/dirhtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in _build/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in _build/qthelp, like this:" @echo "# qcollectiongenerator _build/qthelp/git-cola.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile _build/qthelp/git-cola.qhc" latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex @echo @echo "Build finished; the LaTeX files are in _build/latex." @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ "run these through (pdf)latex." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes @echo @echo "The overview file is in _build/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in _build/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in _build/doctest/output.txt." all: html $(MAKE) -f Makefile.asciidoc all install: install-html install-man test -d $(DESTDIR)$(docdir) || mkdir -p $(DESTDIR)$(docdir) cp *.txt $(DESTDIR)$(docdir) cp *.html $(DESTDIR)$(docdir) install-html: html test -d $(DESTDIR)$(htmldir) || mkdir -p $(DESTDIR)$(htmldir) $(RSYNC) -ar --delete _build/html/ $(DESTDIR)$(htmldir)/ $(MAKE) -f Makefile.asciidoc prefix=$(prefix) install-html install-man: $(MAKE) -f Makefile.asciidoc prefix=$(prefix) install git-cola-1.9.3/share/doc/git-cola/Makefile.asciidoc000066400000000000000000000034371225156173500220240ustar00rootroot00000000000000MAN1_TXT=$(wildcard *.txt) DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT)) ARTICLES = # with their own formatting rules. SP_ARTICLES = DOC_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES)) DOC_PDF += $(patsubst %,%.pdf,$(ARTICLES) $(SP_ARTICLES)) DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT)) prefix?=$(CURDIR) htmldir?=$(prefix)/share/doc/git-cola/html mandir?=$(prefix)/share/man man1dir=$(mandir)/man1 # DESTDIR= ASCIIDOC=asciidoc --unsafe ASCIIDOC_EXTRA = INSTALL?=install # # Please note that there is a minor bug in asciidoc. # The version after 6.0.3 _will_ include the patch found here: # http://marc.theaimsgroup.com/?l=git&m=111558757202243&w=2 # # Until that version is released you may have to apply the patch # yourself - yes, all 6 characters of it! # all: html man html: $(DOC_HTML) pdf: $(DOC_PDF) $(DOC_HTML) $(DOC_MAN1): asciidoc.conf man: man1 man1: $(DOC_MAN1) install: man $(INSTALL) -d -m755 $(DESTDIR)$(man1dir) $(INSTALL) -m644 $(DOC_MAN1) $(DESTDIR)$(man1dir) install-html: html $(INSTALL) -d -m755 $(DESTDIR)$(htmldir) $(INSTALL) -m644 $(DOC_HTML) $(DESTDIR)$(htmldir) # # Determine "include::" file references in asciidoc files. # doc.dep : $(wildcard *.txt) build-docdep.perl rm -f $@+ $@ perl ./build-docdep.perl >$@+ mv $@+ $@ -include doc.dep clean: rm -f *.xml git-cola.html git-dag.html *.pdf *.1 doc.dep %.html : %.txt $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf $(ASCIIDOC_EXTRA) $< %.1 : %.xml xmlto -m callouts.xsl man $< %.xml : %.txt $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf $< %.pdf: %.xml xmlto pdf $< # special formatting rules ## tutorial.html : %.html : %.txt ## $(ASCIIDOC) -b xhtml11 -d article -f tutorial.conf $(ASCIIDOC_EXTRA) $< ## tutorial.xml : %.xml : %.txt ## $(ASCIIDOC) -b docbook -d article -f tutorial.conf $< git-cola-1.9.3/share/doc/git-cola/_static/000077500000000000000000000000001225156173500202265ustar00rootroot00000000000000git-cola-1.9.3/share/doc/git-cola/_static/.gitignore000066400000000000000000000000001225156173500222040ustar00rootroot00000000000000git-cola-1.9.3/share/doc/git-cola/_templates/000077500000000000000000000000001225156173500207355ustar00rootroot00000000000000git-cola-1.9.3/share/doc/git-cola/_templates/.gitignore000066400000000000000000000000011225156173500227140ustar00rootroot00000000000000 git-cola-1.9.3/share/doc/git-cola/asciidoc.conf000066400000000000000000000061631225156173500212330ustar00rootroot00000000000000## linkgit: macro # # Usage: linkgit:command[manpage-section] # # Note, {0} is the manpage section, while {target} is the command. # # Show GIT link as: (
); if section is defined, else just show # the command. [attributes] caret=^ startsb=[ endsb=] tilde=~ asterisk=* plus=+ ifdef::backend-docbook[] [linkgit-inlinemacro] {0%{target}} {0#} {0#{target}{0}} {0#} endif::backend-docbook[] ifdef::backend-docbook[] ifndef::docbook-xsl-172[] # "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. # v1.72 breaks with this because it replaces dots not in roff requests. [listingblock] {title} ifdef::doctype-manpage[] .ft C endif::doctype-manpage[] | ifdef::doctype-manpage[] .ft endif::doctype-manpage[] {title#} endif::docbook-xsl-172[] endif::backend-docbook[] ifdef::doctype-manpage[] ifdef::backend-docbook[] [header] template::[header-declarations] {mantitle} {manvolnum} Git {git_version} Git Manual {manname} {manpurpose} endif::backend-docbook[] endif::doctype-manpage[] ifdef::backend-xhtml11[] [linkgit-inlinemacro] {target}{0?({0})} endif::backend-xhtml11[] ## linkcola: macro # # Usage: linkcola:command[manpage-section] # # Note, {0} is the manpage section, while {target} is the command. # # Show GIT link as: (
); if section is defined, else just show # the command. ifdef::backend-docbook[] [linkcola-inlinemacro] {0%{target}} {0#} {0#{target}{0}} {0#} endif::backend-docbook[] ifdef::backend-docbook[] ifndef::docbook-xsl-172[] # "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. # v1.72 breaks with this because it replaces dots not in roff requests. [listingblock] {title} ifdef::doctype-manpage[] .ft C endif::doctype-manpage[] | ifdef::doctype-manpage[] .ft endif::doctype-manpage[] {title#} endif::docbook-xsl-172[] endif::backend-docbook[] ifdef::doctype-manpage[] ifdef::backend-docbook[] [header] template::[header-declarations] {mantitle} {manvolnum} Git {git_version} Git Manual {manname} {manpurpose} endif::backend-docbook[] endif::doctype-manpage[] ifdef::backend-xhtml11[] [linkcola-inlinemacro] {target}{0?({0})} endif::backend-xhtml11[] git-cola-1.9.3/share/doc/git-cola/build-docdep.perl000077500000000000000000000020311225156173500220160ustar00rootroot00000000000000#!/usr/bin/perl my %include = (); my %included = (); for my $text (<*.txt>) { open I, '<', $text || die "cannot read: $text"; while () { if (/^include::/) { chomp; s/^include::\s*//; s/\[\]//; $include{$text}{$_} = 1; $included{$_} = 1; } } close I; } # Do we care about chained includes??? my $changed = 1; while ($changed) { $changed = 0; while (my ($text, $included) = each %include) { for my $i (keys %$included) { # $text has include::$i; if $i includes $j # $text indirectly includes $j. if (exists $include{$i}) { for my $j (keys %{$include{$i}}) { if (!exists $include{$text}{$j}) { $include{$text}{$j} = 1; $included{$j} = 1; $changed = 1; } } } } } } while (my ($text, $included) = each %include) { if (! exists $included{$text} && (my $base = $text) =~ s/\.txt$//) { my ($suffix) = '1'; if ($base eq 'git') { $suffix = '7'; # yuck... } print "$base.html $base.$suffix : ", join(" ", keys %$included), "\n"; } } git-cola-1.9.3/share/doc/git-cola/callouts.xsl000066400000000000000000000020411225156173500211530ustar00rootroot00000000000000 .sp .br git-cola-1.9.3/share/doc/git-cola/conf.py000066400000000000000000000155161225156173500201070ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # git-cola documentation build configuration file, created by # sphinx-quickstart on Sat Apr 18 22:49:53 2009. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # Add the cola source directory to sys.path docdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) srcdir = os.path.dirname(os.path.dirname(docdir)) extrasdir = os.path.join(srcdir, 'extras') sys.path.insert(1, extrasdir) sys.path.insert(1, srcdir) import cola.version # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.append(os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinxtogithub'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = u'git-cola' copyright = u'2007-2012, David Aguilar and contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = cola.version.version() # The full version, including alpha/beta/rc tags. release = cola.version.version() # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. #unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. html_theme = 'haiku' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_use_modindex = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'git-coladoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'git-cola.tex', u'git-cola Documentation', u'David Aguilar and contributors', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_use_modindex = True # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'http://docs.python.org/': None} git-cola-1.9.3/share/doc/git-cola/custom.rst000066400000000000000000000044261225156173500206520ustar00rootroot00000000000000Custom GUI Actions ================== `git cola` allows you to define custom GUI actions by setting `git config` variables. The "name" of the command appears in the "Tools" menu. guitool..cmd ------------------ Specifies the shell command line to execute when the corresponding item of the Tools menu is invoked. This option is mandatory for every tool. The command is executed from the root of the working directory, and in the environment it receives the name of the tool as GIT_GUITOOL, the name of the currently selected file as FILENAME, and the name of the current branch as CUR_BRANCH (if the head is detached, CUR_BRANCH is empty). guitool..needsfile ------------------------ Run the tool only if a diff is selected in the GUI. It guarantees that FILENAME is not empty. guitool..noconsole ------------------------ Run the command silently, without creating a window to display its output. guitool..norescan ----------------------- Don’t rescan the working directory for changes after the tool finishes execution. guitool..confirm ---------------------- Show a confirmation dialog before actually running the tool. guitool..argprompt ------------------------ Request a string argument from the user, and pass it to the tool through the ARGS environment variable. Since requesting an argument implies confirmation, the confirm option has no effect if this is enabled. If the option is set to true, yes, or 1, the dialog uses a built-in generic prompt; otherwise the exact value of the variable is used. guitool..revprompt ------------------------ Request a single valid revision from the user, and set the REVISION environment variable. In other aspects this option is similar to argprompt, and can be used together with it. guitool..revunmerged -------------------------- Show only unmerged branches in the revprompt subdialog. This is useful for tools similar to merge or rebase, but not for things like checkout or reset. guitool..title -------------------- Specifies the title to use for the prompt dialog. The default is the tool name. guitool..prompt --------------------- Specifies the general prompt string to display at the top of the dialog, before subsections for argprompt and revprompt. The default value includes the actual command. git-cola-1.9.3/share/doc/git-cola/git-cola.txt000066400000000000000000000114241225156173500210420ustar00rootroot00000000000000git-cola(1) =========== NAME ---- git-cola - The highly caffeinated git GUI SYNOPSIS -------- 'git cola' [options] [sub-command] DESCRIPTION ----------- 'git-cola' is a sleek and powerful git GUI. OPTIONS ------- --amend:: Start 'git-cola' in amend mode. -g:: --git-path:: Specifies the path to the 'git' binary. --prompt:: Prompt for a git repository instead of using the current directory. -r:: --repo=:: Run 'git-cola' on the git repository in . Defaults to the current directory. --version:: Print the 'git-cola' version and exit. SUB-COMMANDS ------------ branch:: Create branches. browse:: Browse tracked files. config:: Configure 'git-cola' settings. diff:: Diff changed files. fetch:: Fetch remote branches. grep:: Use `git grep` to search for content. merge:: Merge branches. pull:: Fetch and merge remote branches. push:: Push branches to remotes. rebase:: Start an interactive rebase. search:: Search for commits. stash:: Stash modifications. tag:: Create tags. version:: Print the 'git-cola' version. CONFIG VARIABLES ---------------- cola.savewindowsettings:: 'git-cola' will remember its window settings when set to `true`. These settings are saved in `$HOME/.config/git-cola`. cola.fileattributes:: Enables per-file linkgit:gitattributes[5] encoding support when set to `true`. This tells 'git-cola' to honor the configured encoding when displaying and applying diffs. cola.fontdiff:: Specifies the font to use for 'git-cola''s diff display. cola.browserdockable:: Whether to create a dock widget with the 'Browser' tool. Defaults to 'false' to speedup startup time. cola.inotify:: Set to 'false' to disable inotify support. Defaults to 'true' when the 'pyinotify' module is available. cola.linebreak:: Whether to automatically break long lines while editing commit messages. Defaults to 'true'. This setting is configured using the 'Preferences' dialog, but it can be toggled for one-off usage using the commit message editor's settings sub-menu. cola.tabwidth:: The number of columns occupied by a tab character. cola.textwidth:: The number of columns used for line wrapping. Tabs are counted according to `cola.tabwidth`. cola.readsize:: 'git-cola' avoids reading large binary untracked files. The maximum size to read is controlled by `cola.readsize` and defaults to `2048`. gui.diffcontext:: The number of diff context lines used and displayed by 'git-cola'. gui.displayuntracked:: 'git-cola' avoids showing untracked files when set to `false`. gui.editor:: The default text editor is controlled by `gui.editor`. The config variable overrides the EDITOR environment variable. gui.historybrowser:: Specifies the history browser to use when visualizing history. diff.tool:: The default diff tool to use. merge.tool:: The default merge tool to use. user.email:: Your email address to be recorded in any newly created commits. Can be overridden by the 'GIT_AUTHOR_EMAIL', 'GIT_COMMITTER_EMAIL', and 'EMAIL' environment variables. See linkgit:git-commit-tree[1]. user.name:: Your full name to be recorded in any newly created commits. Can be overridden by the 'GIT_AUTHOR_NAME' and 'GIT_COMMITTER_NAME' environment variables. See linkgit:git-commit-tree[1]. See linkgit:git-config[1] for more details. ENVIRONMENT VARIABLES --------------------- EDITOR:: Specifies the default editor to use. This is ignored when the git config variable `gui.editor` is defined. GIT_COLA_TRACE:: When defined, 'git-cola' logs 'git' commands to stdout. When set to 'full', 'git-cola' also logs the exit status and output. When set to 'trace', 'git-cola' logs to the 'Console' widget. LANGUAGE SETTINGS ----------------- 'git-cola' automatically detects your language and presents some translations when available. This may not be desired, or you may want 'git-cola' to use a specific language. You can make 'git-cola' use an alternative language by creating a `~/.config/git-cola/language` file containing the standard two-letter gettext language code, e.g. "en", "de", "ja", "zh", etc.:: echo en >~/.config/git-cola/language SOURCE ------ A 'git-cola' development repository can be obtained via git: git clone git://github.com/git-cola/git-cola.git LINKS ----- 'git-cola' homepage:: http://git-cola.github.io/ 'git-cola' sources on github:: https://github.com/git-cola/git-cola/ SEE ALSO -------- linkgit:git-difftool[1]:: Compare changes using common merge tools. linkgit:gitk[1]:: The git repository browser. Shows branches, commit history and file differences. gitk is the utility started by 'git-cola''s Repository Visualize actions. GIT --- 'git-cola' is independently developed from the linkgit:git[7] suite, but you can use it just like any other git command, e.g. `git cola`. AUTHOR ------ Written by David Aguilar . git-cola-1.9.3/share/doc/git-cola/git-dag.txt000066400000000000000000000030331225156173500206540ustar00rootroot00000000000000git-dag(1) ========== NAME ---- git-dag - An advanced git DAG visualizer SYNOPSIS -------- 'git dag' [options] [..] [[--] [...]] DESCRIPTION ----------- 'git-dag' is a powerful git DAG visualizer written in Python. 'git-dag' supports many of the 'git-log' options through its graphical interface. See below for a full list of command-line options and usage information. OPTIONS ------- -g:: --git-path:: Specifies the path to the 'git' binary. --prompt:: Prompt for a git repository instead of auto-detecting it in the current directory. -r:: --repo=:: Run 'git-cola' on the git repository in . Defaults to the current directory. -v:: --version:: Print the 'git-cola' version and exit. CONFIG VARIABLES ---------------- log.date:: Set the default date-time format for the 'Date' field. Setting a value for log.date is similar to using 'git log''s `--date` option. Possible values are `relative`, `local`, `default`, `iso`, `rfc`, and `short`; see linkgit:git-log[1] for details. LINKS ----- 'git-cola' homepage:: http://git-cola.github.io/ 'git-cola' sources on github:: https://github.com/git-cola/git-cola/ SEE ALSO -------- linkgit:git-difftool[1]:: Compare changes using common merge tools. linkgit:gitk[1]:: The git repository browser. Shows branches, commit history and file differences. GIT --- 'git-dag' is independently developed from the linkgit:git[7] suite, but you can use it just like any other git command, e.g. `git dag`. AUTHOR ------ Written by David Aguilar . git-cola-1.9.3/share/doc/git-cola/hotkeys.html000066400000000000000000000116251225156173500211610ustar00rootroot00000000000000 Keyboard shortcuts
    Commit
Ctrl + m : Amend last commit
Ctrl + Return : Commit staged changes
Ctrl + s : Stage selected files
Alt + a : Stage modified files
Alt + u : Stage untracked files
Ctrl + r : Refresh
    Actions
Ctrl + b : Create branch
Alt + b : Checkout branch
Ctrl + g : Grep
Alt + d : Show diffstat
Alt + e : Export patches
Ctrl + p : Cherry pick
Shift + Alt + s : Stash
? : Keyboard shortcuts
    Editing
Ctrl + e, Enter : Launch editor
Space : Open using default application
Shift + Space : Open parent directory
Shift + Ctrl + e : View / edit recently modified files
Ctrl + d : View diff using `git difftool`
Ctrl + # : Focus tools
Shift + Ctrl + # : Show and hide tools
    Browser actions
Ctrl + e : Launch editor
Ctrl + s : Stage selected
Ctrl + u : Unstage selected
Shift + Ctrl + h : View history
Ctrl + d : View diff using `git difftool`
Shift + Ctrl + d : View diff against predecessor
Ctrl + z : Revert uncommitted changes
    Diff viewer
s : Stage selection or same as h when nothing is selected
h : Stage diff section beneath text cursor
    Navigation
h : Move left/collapse
j : Move down
k : Move up
l : Move right/expand
Ctrl + l : Focus the DAG input field
git-cola-1.9.3/share/doc/git-cola/hotkeys_de.html000066400000000000000000000120421225156173500216230ustar00rootroot00000000000000 Tastenkürzel
    Version
Ctrl + m : Letzte Version nachbessern
Ctrl + Return : Vorgemerkte Änderungen versionieren
Ctrl + s : Ausgewählte Dateien vormerken
Alt + a : Geänderte Dateien vormerken
Alt + u : Alle neuen Dateien vormerken
Ctrl + r : Ansicht aktualisieren
    Befehle
Ctrl + b : Neuen Zweig erstellen
Alt + b : Zweig wechseln
Ctrl + g : Suchen
Alt + d : Vergleichsstatistik anzeigen
Alt + e : Patches exportieren
Ctrl + p : Einzelne Version übernehmen
Shift + Alt + s : Weglegen und zurückholen
? : Tastenkürzel
    Bearbeiten
Ctrl + e, Enter : Im Editor bearbeiten
Space : Mit der Standardanwendung öffnen
Shift + Space : Übergeordnetes Verzeichnis öffnen
Shift + Ctrl + e : Kürzlich geänderte Dateien anzeigen/bearbeiten
Ctrl + d : Mithilfe von `git difftool` ansehen
Ctrl + # : Werkzeuge fokussieren
Shift + Ctrl + # : Werkzeuge anzeigen und verstecken
    Browser-Befehle
Ctrl + e : Im Editor bearbeiten
Ctrl + s : Auswahl vormerken
Ctrl + u : Vormerkung für Auswahl aufheben
Shift + Ctrl + h : Verlauf anzeigen
Ctrl + d : Mithilfe von `git difftool` ansehen
Shift + Ctrl + d : Mit Vorgänger vergleichen
Ctrl + z : Nicht versionierte Änderungen verwerfen
    Vergleichsansicht
s : Auswahl vormerken; falls nichts ausgewählt ist, siehe h
h : Änderung am Cursor vormerken
    Navigation
h : Nach links/einklappen
j : Nach unten
k : Nach oben
l : Nach rechts/ausklappen
git-cola-1.9.3/share/doc/git-cola/index.rst000066400000000000000000000005301225156173500204370ustar00rootroot00000000000000=================================== Welcome to git-cola's Documentation =================================== .. toctree:: intro tools mainwindow custom thanks Release Notes ============= .. toctree:: :maxdepth: 1 relnotes Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` git-cola-1.9.3/share/doc/git-cola/intro.rst000066400000000000000000000020151225156173500204630ustar00rootroot00000000000000============ Introduction ============ `git cola` is a simple, powerful, and feature-rich GUI for `git` that provides an easy way to interact with Git repositories. Git Cola? ========= Out of cola? Don't panic. Download Visit the `git cola home page `_ Discuss `git cola mailing list `_. Improve Submit issues and enhancement requests to the `git cola issue tracker `_. Contribute `git cola on github `_ .. sourcecode:: sh git clone git://github.com/git-cola/git-cola.git Installation ============ The `git cola` installation instructions are included in the source tarball. See the ``README.md`` file for more details, or `read it on github `_. Running `git cola` ================== If you've already installed cola:: git cola If you have the `git cola` source:: make && bin/git-cola git-cola-1.9.3/share/doc/git-cola/mainwindow.rst000066400000000000000000000024471225156173500215150ustar00rootroot00000000000000Keyboard Shortcuts ================== `git cola` has many useful keyboard shortcuts. Learn about them by either pressing the ``?`` key, choosing ``Help -> Keyboard shortcuts`` from the main menu, or by consulting the `git cola keyboard shortcuts reference <../hotkeys.html>`_. Drag and Drop `git am` ====================== Dragging and dropping patches onto the `git cola` interface applies patches using `git am `_. You can drag either a set of patches or a directory containing patches. All files are sorted alphanumerically before being applied. This means that patches named ``0001-foo.patch`` are applied before ``0002-bar.patch``. When a directory is dropped `git cola` walks the directory tree in search of patches. `git cola` sorts the list of patches after they have all been found. This allows you to control the order in which patchs are applied by placing patchsets into alphanumerically-sorted directories. Custom GUI Layouts ================== `git cola` remembers modifications to the layout and arrangement of tools within the `git cola` interface. Changes are saved and restored at application shutdown/startup. `git cola` can be configured to not save custom layouts-- simply uncheck the `Save Window Settings` option in the `git cola` preferences. git-cola-1.9.3/share/doc/git-cola/make.bat000066400000000000000000000056231225156173500202130ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation set SPHINXBUILD=sphinx-build set ALLSPHINXOPTS=-d _build/doctrees %SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (_build\*) do rmdir /q /s %%i del /q /s _build\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% _build/html echo. echo.Build finished. The HTML pages are in _build/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% _build/dirhtml echo. echo.Build finished. The HTML pages are in _build/dirhtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% _build/pickle echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% _build/json echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% _build/htmlhelp echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in _build/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% _build/qthelp echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in _build/qthelp, like this: echo.^> qcollectiongenerator _build\qthelp\git-cola.qhcp echo.To view the help file: echo.^> assistant -collectionFile _build\qthelp\git-cola.ghc goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% _build/latex echo. echo.Build finished; the LaTeX files are in _build/latex. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% _build/changes echo. echo.The overview file is in _build/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% _build/linkcheck echo. echo.Link check complete; look for any errors in the above output ^ or in _build/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% _build/doctest echo. echo.Testing of doctests in the sources finished, look at the ^ results in _build/doctest/output.txt. goto end ) :end git-cola-1.9.3/share/doc/git-cola/relnotes.rst000066400000000000000000001146461225156173500212010ustar00rootroot00000000000000git-cola v1.9.3 --------------- Usability, bells and whistles ----------------------------- * `git cola --amend` now starts the editor in `amend` mode. https://github.com/git-cola/git-cola/issues/187 * Multiple lines of text can now be pasted into the `summary` field. All text beyond the first newline will be automatically moved to the `extended description` field. https://github.com/git-cola/git-cola/issues/212 Fixes ----- * Stray whitespace in `.git` files is now ignored. https://github.com/git-cola/git-cola/issues/213 * Fix "known incorrect sRGB profile" in `staged-item.png`. http://comments.gmane.org/gmane.linux.gentoo.devel/85066 git-cola v1.9.2 --------------- Fixes ----- * Fix a traceback when `git push` fails. https://bugzilla.redhat.com/show_bug.cgi?id=1034778 Packaging --------- * Most of the git-cola sub-packages have been removed. The only remaining packages are `cola`, `cola.models`, and `cola.widgets`. * The translation file for Simplified Chinese was renamed to `zh_CN.po`. https://github.com/git-cola/git-cola/issues/209 git-cola v1.9.1 --------------- Packaging --------- * `git cola version --brief` now prints the brief version number. Fixes ----- * Resurrected the "make dist" target, for those that prefer to create their own tarballs. * Fixed the typo that broke the preferences dialog. git-cola v1.9.0 --------------- Usability, bells and whistles ----------------------------- * We now ship a full-featured interactive `git rebase` editor. The rebase todo file is edited using the `git xbase` script which is provided at `$prefix/share/git-cola/bin/git-xbase`. This script can be used standalone by setting the `$GIT_SEQUENCE_EDITOR` before running `git rebase --interactive`. https://github.com/git-cola/git-cola/issues/1 * Fixup commit messages can now be loaded from the commit message editor. * Tool widgets can be locked in place by using the "Tools/Lock Layout" menu action. https://github.com/git-cola/git-cola/issues/202 * You can now push to several remotes simultaneously by selecting multiple remotes in the "Push" dialog. https://github.com/git-cola/git-cola/issues/148 * The `grep` tool learned to search using three different modes: basic regular expressions (default), extended regular expressions, and fixed strings. Packaging --------- * `git cola` now depends on the `argparse` Python module. This module is part of the stdlib in Python 2.7 and must be installed separately when using Python 2.6 and below. Fixes ----- * Support unicode in the output from `fetch`, `push`, and `pull`. git-cola v1.8.5 --------------- Usability, bells and whistles ----------------------------- * We now detect when the editor or history browser are misconfigured. https://github.com/git-cola/git-cola/issues/197 https://bugzilla.redhat.com/show_bug.cgi?id=886826 * Display of untracked files can be disabled from the Preferences dialog or by setting the `gui.displayuntracked` configuration variable to `false`. http://thread.gmane.org/gmane.comp.version-control.git/232683 Fixes ----- * Unicode stash names are now supported https://github.com/git-cola/git-cola/issues/198 * The diffs produced when reverting workspace changes were made more robust. git-cola v1.8.4 ======================= Usability, bells and whistles ----------------------------- * Brand new German translation thanks to Sven Claussner. * The "File" menu now provides a "New Repository..." menu action. * `git dag` now uses a dock-widget interface so that its widgets can be layed-out and arranged. Customizations are saved and restored the next time `git dag` is launched. * `git dag` now has a "Zoom Best Fit" button next alongside the "Zoom In" and "Zoom Out" buttons. * `Ctrl+L` now focuses the "Search" field in the `git dag` tool. * Right-clicking in the "diff" viewer now updates the cursor position before performing actions, which makes it much easier to click around and selectively stage sections. Previously, the current cursor position was used which meant that it required two clicks (left-click to update the position followed by right-click to get the context menu) for the desired section to be used. This is now a single right-click operation. * The `Ctrl+D` "Launch Diff Tool" action learned to automatically choose between `git difftool` and `git mergetool`. If the file is unmerged then we automatically launch `git mergetool` on the path, otherwise we use `git difftool`. We do this because `git difftool` is not intended to be used on unmerged paths. Automatically using `git mergetool` when appropriate is the most intuitive and muscle-memory-friendly thing to do. * You can now right-click on folders in your standard file browser and choose "Open With -> Git Cola" (Linux-only). Fixes ----- * Python 2.6 on Mac OS X Snow Leopard does not provide a namedtuple at `sys.version_info`. We now avoid using that variable for better portability. * We now read the user's Git configuration from `~/.config/git/config` if that file is available, otherwise we use the traditional `~/.gitconfig` path, just like Git itself. * Some edge cases were fixed when applying partial/selected diffs. * The diff viewer is now properly cleared when refreshing. https://github.com/git-cola/git-cola/issues/194 git-cola v1.8.3 =============== Usability, bells and whistles ----------------------------- * The diff viewer now has an "Options" menu which can be used to set "git diff" options. This can be used to ignore whitespace changes or to show a change with its surrounding function as context. https://github.com/git-cola/git-cola/issues/150 * `git cola` now remembers your commit message and will restore it when `git cola` is restarted. https://github.com/git-cola/git-cola/pull/175 * Ctrl+M can now be used to toggle the "Amend last commit" checkbox in the commit message editor. https://github.com/git-cola/git-cola/pull/161 * Deleting remote branches can now be done from the "Branch" menu. https://github.com/git-cola/git-cola/issues/152 * The commit message editor now has a built-in spell checker. Fixes ----- * We now avoid invoking external diffs when showing diffstats. https://github.com/git-cola/git-cola/pull/163 * The `Status` tool learned to reselect files when refreshing. https://github.com/git-cola/git-cola/issues/165 * `git cola` now remembers whether it has been maximized and will restore the maximized state when `git cola` is restarted. https://github.com/git-cola/git-cola/issues/172 * Performance is now vastly improved when staging hundreds or thousands of files. * `git cola` was not correctly saving repo-specific configuration. https://github.com/git-cola/git-cola/issues/174 * Fix a UnicodeDecode in sphinxtogithub when building from source. git-cola v1.8.2 =============== Usability, bells and whistles ----------------------------- * We now automatically remove missing repositories from the "Select Repository" dialog. https://github.com/git-cola/git-cola/issues/145 * A new `git cola diff` sub-command was added for diffing changed files. Fixes ----- * The inotify auto-refresh feature makes it difficult to select text in the "diff" editor when files are being continually modified by another process. The auto-refresh causes it to lose the currently selected text, which is not wanted. We now avoid this problem by saving and restoring the selection when refreshing the editor. https://github.com/git-cola/git-cola/issues/155 * More strings have been marked for l10n. https://github.com/git-cola/git-cola/issues/157 * Fixed the Alt+D Diffstat shortcut. https://github.com/git-cola/git-cola/issues/159 Fixes ----- * Better error handling when cloning repositories. We were not handling the case where a git URL has no basename, e.g. `https://git.example.com/`. `git cola` originally rejected these URLs instead of allowing users to clone them. It now allows these URLs when they point to valid git repositories. Additionally, `git cola` learned to echo the errors reported by `git clone` when it fails. https://github.com/git-cola/git-cola/issues/156 git-cola v1.8.1 =============== Usability, bells and whistles ----------------------------- * `git dag` got a big visual upgrade. * Ctrl+G now launches the "Grep" tool. * Ctrl+D launches difftool and Ctrl+E launches your editor when in the diff panel. * git-cola can now be told to use an alternative language. For example, if the native language is German and we want git-cola to use English then we can create a `~/.config/git-cola/language` file with "en" as its contents: $ echo en >~/.config/git-cola/language https://github.com/git-cola/git-cola/issues/140 * A new `git cola merge` sub-command was added for merging branches. * Less blocking in the main UI Fixes ----- * Autocomplete issues on KDE https://github.com/git-cola/git-cola/issues/144 * The "recently opened repositories" startup dialog did not display itself in the absence of bookmarks. https://github.com/git-cola/git-cola/issues/139 git-cola v1.8.0 =============== Usability, bells and whistles ----------------------------- * `git cola` learned to honor `.gitattributes` when showing and interactively applying diffs. This makes it possible to store files in git using a non-utf-8 encoding and `git cola` will properly accept them. This must be enabled by settings `cola.fileattributes` to true, as it incurs a small performance penalty. https://github.com/git-cola/git-cola/issues/96 * `git cola` now wraps commit messages at 72 columns automatically. This is configurable using the `cola.linebreak` variable to enable/disable the feature, and `cola.textwidth` to configure the limit. https://github.com/git-cola/git-cola/issues/133 * A new "Open Recent" sub-menu was added to the "File" menu. This makes it easy to open a recently-edited repository. https://github.com/git-cola/git-cola/issues/135 * We now show a preview for untracked files when they are clicked using the `Status` tool. * A new "Open Using Default Application" action was added to the `Status` tool. It is activated using either `Spacebar` or through the context menu. This action uses `xdg-open` on Linux and `open` on Mac OS X. * A new "Open Parent Directory" action was added to the `Status` tool. It is activated using either `Shift+Spacebar` or through the context menu. * `git dag` learned to honor the `log.date` git configuration variable. This makes the date display follow whatever format the user has configured. * A new `git cola config` sub-command was added for quickly tweaking `git cola`'s git configuration settings. * Some small usability tweaks -- some user confirmation prompts were defaulting to "Cancel" when they should have been defaulting to the affirmative option instead. Fixes ----- * Properly handle arbitrarily-named branches. * We went back to launching `git mergetool` using an xterm. The reason is that there are a couple of places where `git mergetool` requires a terminal for user interaction not covered by `--no-prompt`. * We now properly handle an edge case when applying short diffs at the start of a file. git-cola v1.7.7 =============== Usability, bells and whistles ----------------------------- * New and improved `grep` mode lets you instantly find and edit files. * New `git cola grep` standalone mode. * Support for passing arguments to the configured editors, e.g. `gvim -p` This makes it possible to select multiple files in the status window and use `Ctrl-e` to edit them all at once. * Remote operations now prompt on errors only. * The `Tab` key now jumps to the extended description when editing the summary. * More shortcut key labels and misc. UX improvements. Fixes ----- * Selecting an item no longer copies its filename to the copy/paste buffer. `Ctrl-c` or the "Copy" context-menu action can be used instead. * The repository monitoring feature on Windows learned to ignore changes within the ".git" directory. Thanks to Andreas Sommer. https://github.com/git-cola/git-cola/issues/120 git-cola v1.7.6 =============== Usability, bells and whistles ----------------------------- * `git dag` learned to color-code branchy edges. The edge colors change when a new branch is detected, which makes the history much easier to follow. A huge thanks to Uri Okrent for making it happen. * New GUI for editing remote repositories. * New `git cola archive` and `git cola remote` sub-commands. * `git cola browser` learned an 'Untrack' command. * The diff editor learned to staged/unstaged while amending. * The status tool can now scroll horizontally. * New git repositories can be created by clicking 'New' on the `git cola --prompt` startup screen. git-cola v1.7.5 =============== Usability, bells and whistles ----------------------------- * Auto-completion was added to more tools. * `git dag` is easier to use on smaller displays -- the author field elides its text which allows for a more compact display. * Selected commits in `git dag` were made more prominent and easier to see. * 'Create Branch' learned to fetch remote branches and uses a background thread to do so. * User-configured GUI tools are listed alphabetically in the 'Actions' menu. * The 'Pull' dialog remembers the value of the 'Rebase' checkbox between invocations. git-cola v1.7.4.1 ================= Fixes ----- * Detect Homebrew so that OS X users do not need to set PYTHONPATH. * `git dag` can export patches again. git-cola v1.7.4 =============== Usability, bells and whistles ----------------------------- * The 'Classic' tool was renamed to 'Browser' and learned to limit history to the current branch. * `git dag` learned about gravatar and uses it to show images for commit authors. * `git dag` learned to use OpenGL for rendering resulting in much faster rendering. * More dialogs learned vim-style keyboard shortcuts. * The commit message editor learned better arrow key navigation. git-cola v1.7.3 =============== Usability, bells and whistles ----------------------------- * `git cola` learned a few new sub commands: .. sourcecode:: sh git cola dag git cola branch git cola search * `Return` in the summary field jumps to the extended description. * `Ctrl+Return` is now a shortcut for 'Commit'. * Better French translation for 'Sign-off'. * The 'Search' widget now has a much simpler and streamlined user interface. * vim-style `h,j,k,l` navigation shortcuts were added to the DAG widget. * `git dag` no longer prompts for files when diffing commits if the text field contains paths. * General user interface and performance improvements. Fixes ----- * The diff viewer no longer changes font size when holding `Control` while scrolling with the mouse wheel. * Files with a typechange (e.g. symlinks that become files, etc.) are now correctly identified as being modified. Packaging --------- * The `cola.controllers` and `cola.views` packages were removed. git-cola v1.7.2 =============== Usability, bells and whistles ----------------------------- * `git cola` can now launch sub commands, e.g.: .. sourcecode:: sh git cola classic git cola stash git cola fetch git cola push git cola pull git cola tag * `git dag` is more responsive when gathering auto-completions. * Keyboard shortcuts are displayed when the '?' key is pressed. * Various keyboard shortcuts were added for improved usability. * The status widget now lists unmerged files before modified files. * vim-style `h,j,k,l` navigation shortcuts were added to the status widget. * A 'Recently Modified Files...' tool was added. * Tools can now be hidden with `Alt + #` (where `#` is a keyboard number) and focused with `Shift + Alt + #`. * The syntax highlighting colors for diffs was made less intrusive. * The commit message editor was redesigned to have a more compact and keyboard-convenient user interface. * Keyboard shortcuts for adding a Signed-off-by (`Ctrl + i`) and creating a commit (`Ctrl + m`) were added. * The status widget was adjusted to use less screen real-estate. Fixes ----- * Avoid updating the index when responding to inotify events. This avoids interfering with operations such as `git rebase --interactive`. https://github.com/git-cola/git-cola/issues/99 Packaging --------- * Create `git-dag.pyw` in the win32 installer. * win32 shortcuts now contain explicit calls to `pythonw.exe` instead of calling the `.pyw` file directly. Deprecated Features ------------------- * The 'Apply Changes from Branch...' feature was removed. `git dag`'s 'Grab File...' feature used alongside the index/worktree editor is a simpler alternative. git-cola v1.7.1.1 ================= Fixes ----- * Further enhanced the staging/unstaging behavior in the status widget. https://github.com/git-cola/git-cola/issues/97 * Unmerged files are no longer listed as modified. Packaging --------- The `cola-$version` tarballs on github were originally setup to have the same contents as the old tarballs hosted on tuxfamily. The `make dist` target was changed to write files to a `git-cola-$version` subdirectory and tarball. This makes the filenames consistent for the source tarball, the darwin .app tarball, and the win32 .exe installer. git-cola v1.7.1 =============== Usability, bells and whistles ----------------------------- * Refined the staging/unstaging behavior for code reviews. https://github.com/git-cola/git-cola/issues/97 * Added more styling and icons to menus and buttons. * Adjusted some terminology to more closely match the git CLI. Fixes ----- * Boolean `git config` settings with no value are now supported (these are not created by git these days but exist in legacy repositories). * Unicode branches and tags are supported in the "branch diff" tool. * Guard against low-memory conditions and more interrupted system calls. Packaging --------- * Added desktop launchers for git-cola.desktop and git-dag.desktop. This replaces the old cola.desktop, so some adjustments to RPM .spec and debian/ files will be needed. * Fixed the darwin app-tarball Makefile target to create relative paths. Cleanup ------- * The `--style` option was removed. `git cola` follows the system theme so there's no need for this option these days. git-cola v1.7.0 =============== Usability, bells and whistles ----------------------------- * Export a patch series from `git dag` into a `patches/` directory. * `git dag` learned to diff commits, slice history along paths, etc. * Added instant-preview to the `git stash` widget. * A simpler preferences editor is used to edit `git config` values. https://github.com/git-cola/git-cola/issues/90 https://github.com/git-cola/git-cola/issues/89 * Previous commit messages can be re-loaded from the message editor. https://github.com/git-cola/git-cola/issues/33 Fixes ----- * Display commits with no file changes. https://github.com/git-cola/git-cola/issues/82 * Improved the diff editor's copy/paste behavior https://github.com/git-cola/git-cola/issues/90 Packaging --------- * Bumped version number to ceil(minimum git version). `git cola` now requires `git` >= 1.6.3. * Simplified git-cola's versioning when building from tarballs outside of git. We no longer check for a 'version' file at the root of the repository. We instead keep a default version in `cola/version.py` and use it when `git cola`'s `.git` repository is not available. git-cola v1.4.3.5 ================= Usability, bells and whistles ----------------------------- * inotify is much snappier and available on Windows thanks to Karl Bielefeldt. * New right-click command to add untracked files to .gitignore thanks to Audrius Karabanovas. * Stash, fetch, push, and pull usability improvements * General usability improvements * stderr is logged when applying partial diffs. Fixes ----- * Files can be unstaged when amending. https://github.com/git-cola/git-cola/issues/82 * Show the configured remote.$remote.pushurl in the GUI https://github.com/git-cola/git-cola/issues/83 * Removed usage of the "user" module. https://github.com/git-cola/git-cola/issues/86 * Avoids an extra `git update-index` call during startup. git-cola v1.4.3.4 ================= Usability, bells and whistles ----------------------------- * We now provide better feedback when `git push` fails. https://github.com/git-cola/git-cola/issues/69 * The Fetch, Push, and Pull dialogs now give better feedback when interacting with remotes. The dialogs are modal and a progress dialog is used. Fixes ----- * More unicode fixes, again. It is now possible to have unicode branch names, repository paths, home directories, etc. This continued the work initiated by Redhat's bugzilla #694806. https://bugzilla.redhat.com/show_bug.cgi?id=694806 git-cola v1.4.3.3 ================= Usability, bells and whistles ----------------------------- * The `git cola` desktop launchers now prompt for a repo by default. This is done by using the new `--prompt` flag which tells `git cola` to ignore any git repositories in the current directory and prompt for one instead. Fixes ----- * More Unicode fixes for repositories and home directories with embedded unicode characters. Thanks to Christian Jann for patience and helpful bug reports. * Fix the 'Clone' button in the startup dialog. git-cola v1.4.3.2 ================= Usability, bells and whistles ----------------------------- * Faster startup time! `git cola` now offloads initialization to a background thread so that the GUI appears almost instantly. * Specialized diff options for p4merge, vimdiff, araxis, emerge, and ecmerge in difftool (backported from git.git). Fixes ----- * Fix launching commands in the background on Windows (e.g. when launching `git difftool`). * Fix unicode errors when home or repository directories contain unicode characters. https://github.com/git-cola/git-cola/issues/74 Redhat's bugzilla #694806 https://bugzilla.redhat.com/show_bug.cgi?id=694806 git-cola v1.4.3.1 ================= Usability, bells and whistles ----------------------------- * The `cola classic` tool can be now configured to be dockable. https://github.com/git-cola/git-cola/issues/56 * The `cola classic` tool now uses visual sigils to indicate a file's status. The idea and icons were provided by Uri Okrent. * Include the 'Rescan' button in the 'Actions' widget regardless of whether inotify is installed. Packaging --------- * Fix installation of translations per Fedora This incorporates Fedora's fix for the translations path which originally appeared in cola-1.4.3-translations.patch. * Mac OS X git-cola developers can now generate git-cola.app application bundles using 'make app-bundle'. Fixes ----- * Fixed a stacktrace when trying to use "Get Commit Message Template" with an unconfigured "commit.template" git config variable. https://github.com/git-cola/git-cola/issues/72 This bug originated in Redhat's bugzilla #675721 via a Fedora user. https://bugzilla.redhat.com/show_bug.cgi?id=675721 * Properly raise the main window on Mac OS X. * Properly handle staging a huge numbers of files at once. * Speed up 'git config' usage by fixing cola's caching proxy. * Guard against damaged ~/.cola files. git-cola v1.4.3 =============== Usability, bells and whistles ----------------------------- * `git dag` now has a separate display area for displaying commit metadata. This area will soon grow additional functionality such as cherry-picking, branching, etc. Fixes ----- * Fixed tests from a previous refactoring. * Guard against 'diff.external' configuration by always calling 'git diff' with the '--no-ext-diff' option. https://github.com/git-cola/git-cola/issues/67 * Respect 'gui.diffcontext' so that cola's diff display shows the correct number of context lines. * Raise the GUI so that it is in the foreground on OS X. Packaging --------- * We now allow distutils to rewrite cola's shebang line. This allows us to run on systems where "which python" is Python3k. This is exposed by setting the `PYTHON` Makefile variable to the location of python2.x. * git-cola.app is now a tiny download because it no longer contains Qt and PyQt. These libraries are provided as a separate download. http://code.google.com/p/git-cola/downloads/list git-cola v1.4.2.5 ================= Usability, bells and whistles ----------------------------- * Clicking on paths in the status widget copies them into the copy/paste buffer for easy middle-clicking into terminals. * `Ctrl+C` in diff viewer copies the selected diff to the clipboard. Fixes ----- * Fixed the disappearing actions buttons on PyQt 4.7.4 as reported by Arch and Ubuntu 10.10. https://github.com/git-cola/git-cola/issues/62 * Fixed mouse interaction with the status widget where some items could not be de-selected. Packaging --------- * Removed hard-coded reference to lib/ when calculating Python's site-packages directory. git-cola v1.4.2.4 ================= Usability, bells and whistles ----------------------------- * Removed "single-click to (un)stage" in the status view. This is a usability improvement since we no longer perform different actions depending on where a row is clicked. * Added ability to create unsigned, annotated tags. Fixes ----- * Updated documentation to use `cola.git` instead of `cola.gitcmd`. git-cola v1.4.2.3 ================= Usability, bells and whistles ----------------------------- * Allow un/staging by right-clicking top-level items https://github.com/git-cola/git-cola/issues/57 * Running 'commit' with no staged changes prompts to allow staging all files. https://github.com/git-cola/git-cola/issues/55 * Fetch, Push, and Pull are now available via the menus https://github.com/git-cola/git-cola/issues/58 Fixes ----- * Simplified the actions widget to work around a regression in PyQt4 4.7.4. https://github.com/git-cola/git-cola/issues/62 git-cola v1.4.2.2 ================= Usability, bells and whistles ----------------------------- * `git dag` interaction was made faster. Fixes ----- * Added '...' indicators to the buttons for 'Fetch...', 'Push...', 'Pull...', and 'Stash...'. https://github.com/git-cola/git-cola/issues/51 * Fixed a hang-on-exit bug in the cola-provided 'ssh-askpass' implementation. git-cola v1.4.2.1 ================= Usability, bells and whistles ----------------------------- * Staging and unstaging is faster. https://github.com/git-cola/git-cola/issues/48 * `git dag` reads history in a background thread. Portability ----------- * Added :data:`cola.compat.hashlib` for `Python 2.4` compatibility * Improved `PyQt 4.1.x` compatibility. Fixes ----- * Configured menu actions use ``sh -c`` for Windows portability. git-cola v1.4.2 =============== Usability, bells and whistles ----------------------------- * Added support for the configurable ``guitool..*`` actions as described in ``git-config(1)``. https://github.com/git-cola/git-cola/issues/44 http://schacon.github.com/git/git-config.html This makes it possible to add new actions to `git cola` by simply editing ``~/.gitconfig``. This implements the same guitool support as `git gui`. * Introduced a stat cache to speed up `git config` and repository status checks. * Added Alt-key shortcuts to the main `git cola` interface. * The `Actions` dock widget switches between a horizontal and vertical layout when resized. * We now use ``git diff --submodule`` for submodules (used when git >= 1.6.6). * The context menu for modified submodules includes an option to launch `git cola`. https://github.com/git-cola/git-cola/issues/17 * Prefer ``$VISUAL`` over ``$EDITOR`` when both are defined. These are used to set a default editor in lieu of `core.editor` configuration. * Force the editor to be ``gvim`` when we see ``vim``. This prevents us from launching an editor in the (typically unattached) parent terminal and creating zombie editors that cannot be easily killed. * Selections are remembered and restored across updates. This makes the `partial-staging` workflow easier since the diff view will show the updated diff after staging. * Show the path to the current repository in a tooltip over the commit message editor. https://github.com/git-cola/git-cola/issues/45 * Log internal ``git`` commands when ``GIT_COLA_TRACE`` is defined. https://github.com/git-cola/git-cola/issues/39 Fixes ----- * Improved backwards compatibility for Python 2.4. * `Review mode` can now review the current branch; it no longer requires you to checkout the branch into which the reviewed branch will be merged. * Guard against `color.ui = always` configuration when using `git log` by passing ``--no-color``. * ``yes`` and ``no`` are now supported as valid booleans by the `git config` parser. * Better defaults are used for `fetch`, `push`, and `pull`.. https://github.com/git-cola/git-cola/issues/43 Packaging --------- * Removed colon (`:`) from the applilcation name on Windows https://github.com/git-cola/git-cola/issues/41 * Fixed bugs with the Windows installer https://github.com/git-cola/git-cola/issues/40 * Added a more standard i18n infrastructure. The install tree now has the common ``share/locale/$lang/LC_MESSAGES/git-cola.mo`` layout in use by several projects. * Started trying to accomodate Mac OSX 10.6 (Snow Leopard) in the ``darwin/`` build scripts but our tester is yet to report success building a `.app` bundle. * Replaced use of ``perl`` in Sphinx/documentation Makefile with more-portable ``sed`` constructs. Thanks to Stefan Naewe for discovering the portability issues and providing msysgit-friendly patches. git-cola v1.4.1.2 ================= Usability, bells and whistles ----------------------------- * It is now possible to checkout from the index as well as from `HEAD`. This corresponds to the `Removed Unstaged Changes` action in the `Repository Status` tool. * The `remote` dialogs (fetch, push, pull) are now slightly larger by default. * Bookmarks can be selected when `git cola` is run outside of a git repository. * Added more user documentation. We now include many links to external git resources. * Added `git dag` to the available tools. `git dag` is a node-based DAG history browser. It doesn't do much yet, but it's been merged so that we can start building and improving upon it. Fixes ----- * Fixed a missing ``import`` when showing `right-click` actions for unmerged files in the `Repository Status` tool. * ``git update-index --refresh`` is no longer run everytime ``git cola version`` is run. * Don't try to watch non-existant directories when using `inotify`. * Use ``git rev-parse --symbolic-full-name`` plumbing to find the name of the current branch. Packaging --------- * The ``Makefile`` will now conditionally include a ``config.mak`` file located at the root of the project. This allows for user customizations such as changes to the `prefix` variable to be stored in a file so that custom settings do not need to be specified every time on the command-line. * The build scripts no longer require a ``.git`` directory to generate the ``builtin_version.py`` module. The release tarballs now include a ``version`` file at the root of the project which is used in lieu of having the git repository available. This allows for ``make clean && make`` to function outside of a git repository. * Added maintainer's ``make dist`` target to the ``Makefile``. * The built-in `simplejson` and `jsonpickle` libraries can be excluded from ``make install`` by specifying the ``standalone=true`` `make` variable. For example, ``make standalone=true install``. This corresponds to the ``--standalone`` option to ``setup.py``. git-cola v1.4.1.1 ================= Usability, bells and whistles ----------------------------- * We now use patience diff by default when it is available via `git diff --patience`. * Allow closing the `cola classic` tool with `Ctrl+W`. Fixes ----- * Fixed an unbound variable error in the `push` dialog. Packaging --------- * Don't include `simplejson` in MANIFEST.in. * Update desktop entry to read `Cola Git GUI`. git-cola v1.4.1 =============== This feature release adds two new features directly from `git cola`'s github issues backlog. On the developer front, further work was done towards modularizing the code base. Usability, bells and whistles ----------------------------- * Dragging and dropping patches invokes `git am` https://github.com/git-cola/git-cola/issues/3 * A dialog to allow opening or cloning a repository is presented when `git cola` is launched outside of a git repository. https://github.com/git-cola/git-cola/issues/22 * Warn when `push` is used to create a new branch https://github.com/git-cola/git-cola/issues/35 * Optimized startup time by removing several calls to `git`. Portability ----------- * `git cola` is once again compatible with PyQt 4.3.x. Developer --------- * `cola.gitcmds` was added to factor out git command-line utilities * `cola.gitcfg` was added for interacting with `git config` * `cola.models.browser` was added to factor out repobrowser data * Added more tests git-cola v1.4.0.5 ================= Fixes ----- * Fix launching external applications on Windows * Ensure that the `amend` checkbox is unchecked when switching modes * Update the status tree when amending commits git-cola v1.4.0.4 ================= Packaging --------- * Fix Lintian warnings git-cola v1.4.0.3 ================= Fixes ----- * Fix X11 warnings on application startup git-cola v1.4.0.2 ================= Fixes ----- * Added missing 'Exit Diff Mode' button for 'Diff Expression' mode https://github.com/git-cola/git-cola/issues/31 * Fix a bug when initializing fonts on Windows https://github.com/git-cola/git-cola/issues/32 git-cola v1.4.0.1 ================= Fixes ----- * Keep entries in sorted order in the `cola classic` tool * Fix staging untracked files https://github.com/git-cola/git-cola/issues/27 * Fix the `show` command in the Stash dialog https://github.com/git-cola/git-cola/issues/29 * Fix a typo when loading merge commit messages https://github.com/git-cola/git-cola/issues/30 git-cola v1.4.0 =============== This release focuses on a redesign of the git-cola user interface, a tags interface, and better integration of the `cola classic` tool. A flexible interface based on configurable docks is used to manage the various cola widgets. Usability, bells and whistles ----------------------------- * New GUI is flexible and user-configurable * Individual widgets can be detached and rearranged arbitrarily * Add an interface for creating tags * Provide a fallback `SSH_ASKPASS` implementation to prompt for SSH passwords on fetch/push/pull * The commit message editor displays the current row/column and warns when lines get too long * The `cola classic` tool displays upstream changes * `git cola --classic` launches `cola classic` in standalone mode * Provide more information in log messages Fixes ----- * Inherit the window manager's font settings * Miscellaneous PyQt4 bug fixes and workarounds Developer --------- * Removed all usage of Qt Designer `.ui` files * Simpler model/view architecture * Selection is now shared across tools * Centralized notifications are used to keep views in sync * The `cola.git` command class was made thread-safe * Less coupling between model and view actions * The status view was rewritten to use the MVC architecture * Added more documentation and tests git-cola v1.3.9 =============== Usability, bells and whistles ----------------------------- * Added a `cola classic` tool for browsing the entire repository * Handle diff expressions with spaces * Handle renamed files Portability ----------- * Handle carat `^` characters in diff expressions on Windows * Worked around a PyQt 4.5/4.6 QThreadPool bug Documentation ------------- * Added a keyboard shortcuts reference page * Added developer API documentation Fixes ----- * Fix the diff expression used when reviewing branches * Fix a bug when pushing branches * Fix X11 warnings at startup * Fix more interrupted system calls on Mac OS X git-cola v1.3.8 =============== Usability, bells and whistles ----------------------------- * Fresh and tasty SVG logos * Added `Branch Review` mode for reviewing topic branches * Added diff modes for diffing between tags, branches, or arbitrary `git diff` expressions * The push dialog selects the current branch by default. This is in preparation for `git 1.7.0` where unconfigured `git push` will refuse to push when run without specifying the remote name and branch. See the `git` release notes for more information * Support `open` and `clone` commands on Windows * Allow saving cola UI layouts * Re-enabled `double-click-to-stage` for unmerged entries. Disabling it for unmerged items was inconsistent, though safer. * Show diffs when navigating the status tree with the keyboard Packaging --------- * Worked around `pyuic4` bugs in the `setup.py` build script * Added Mac OSX application bundles to the download page git-cola v1.3.7 =============== Subsystems ---------- * `git difftool` became an official git command in `git 1.6.3`. * `git difftool` learned `--no-prompt` / `-y` and a corresponding `difftool.prompt` configuration variable Usability, bells and whistles ----------------------------- * Warn when `non-fast-forward` is used with fetch, push or pull * Allow `Ctrl+C` to exit cola when run from the command line Fixes ----- * Support Unicode font names * Handle interrupted system calls Developer --------- * `PEP-8`-ified more of the cola code base * Added more tests Packaging --------- * All resources are now installed into `$prefix/share/git-cola`. Closed Debian bug #519972 http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=519972 git-cola v1.3.6 =============== Subsystems ---------- * Added support for Kompare in `git difftool` * Added a separate configuration namespace for `git difftool` * Added the `diff.tool` configuration variable to define the default diff tool Usability, bells and whistles ----------------------------- * The stash dialog allows passing the `--keep-index` option to `git stash` * Amending a published commit warns at commit time * Simplified the file-across-revisions comparison dialog * `origin` is selected by default in fetch/push/pull * Removed the search field from the log widget * The log window moved into a drawer widget at the bottom of the UI * Log window display can be configured with `cola.showoutput` = `{never, always, errors}`. `errors` is the default. * `NOTE` -- `cola.showoutput` was removed with the GUI rewrite in 1.4.0. Developer --------- * Improved nose unittest usage Packaging --------- * Added a Windows/msysGit installer * Included private versions of `simplejson` and `jsonpickle` for ease of installation and development git-cola-1.9.3/share/doc/git-cola/thanks.rst000066400000000000000000000020101225156173500206130ustar00rootroot00000000000000Thanks ====== `git-cola` was made possible thanks to the contributions of the following people: * Aaron Cook * Andreas Sommer * Audrius Karabanovas * Barry Roberts * Boris W * Ben Boeckel * Christian Jann * Christopher Meng * Daniel King * Daniel Fahlke * David Aguilar * David Martínez Martí * Dennis Gilmore * Eric Drechsel * `GIT Hackers `_ * Glen Mailer * Guillaume de Bure * Ingo Weinhold * Ismael Juma * Iulian Udrea * Ivar Smolin * Jakub Wilk * Jérôme Carretero * Johann Schmitz * Jeff Dagenais * Justin Lecher * Karl Bielefeldt * Karthik Manamcheri * Kelvie Wong * Kerrick Staley * Kevin Kofler * Libor Jelinek * Maciej Filipiak * Mahmoud Hossam * Marco Costalba * Markus Heidelberg * Maarten Nieber * Matthew Levine * Michael Geddes * Michael Homer * Nicolas Dietrich * Omega Weapon * Paolo G. Giarrusso * Peter Júnoš * Rustam Safin * Sergey Leschina * Srinivasa Nallapati * Stanisław Halik * Stefan Naewe * Steffen Prohaska * Sven Claussner * Taylor Braun-Jones * Ugo Riboni * Uri Okrent git-cola-1.9.3/share/doc/git-cola/tools.rst000066400000000000000000000161361225156173500205010ustar00rootroot00000000000000===== Tools ===== The `git cola` interface is composed of various cooperating tools. Double-clicking a tool opens it in its own subwindow. Dragging it around moves and places it within the window. Tools can be hidden and rearranged however you like. `git cola` carefully remembers your window layout and restores it the next time it is launched. A hidden tool can be re-opened using the `Tools` menu as well as the `Alt-1,2,3,...`, shortcut keys. .. _status: Status ====== The `Status` tool provides a visual analog to the `git status `_ command. `Status` displays files that are `modified` relative to the staging area, `staged` for the next commit, `unmerged` files from an in-progress merge, and files that are `untracked` to git. These are the same categories one sees when running `git status `_ on the command line. You can navigate through the list of files using keyboard arrows as well as the ergonomical and vim-like `j` and `k` shortcut keys. There are several convenient ways to interact with files in the `Status` tool. Selecting a file displays its diff in the :ref:`Diff ` viewer. Double-clicking a file stages its contents, as does the the `Ctrl-s` shortcut key. `Ctrl-e` opens selected files in the conifgured `$EDITOR`, and `Ctrl-d` opens selected files using `git difftool `_. Additional actions can be performed using the right-click context menu. Configuring your $EDITOR ------------------------ The editor used by `Ctrl-e` is configured from the Preferences screen. The environment variables `$VISUAL` and `$EDITOR` are used when no editor has been configured. The editor preference is saved in the `gui.editor` variable using `git config `_. *ProTip* -- Setting `gvim -p` as your configured editor opens multiple files using tabs (and `gvim -o` uses splits). `git cola` is {vim, emacs, textpad, notepad++}-aware. When you select a line in the `grep` screen and press any of `Enter`, `Ctrl-e`, or the "Edit" button, you are taken to that exact line. Actions ------- Clicking the `Staged` folder shows a diffstat for the index. Clicking the `Modified` folder shows a diffstat for the worktree. Clicking individual files sends diffs to the `Diff Display`. Double-clicking individual files adds and removes their content from the index. Various actions that are available through the right-click context menu. Different actions are available depending a file's status. Staged Files ~~~~~~~~~~~~ Unstage Selected Remove from the index/staging area with `git reset `_ Launch Editor Launch the configured visual editor Launch Difftool Visualize changes with `git difftool `_ Revert Unstaged Edits Throw away unstaged edits. Modified Files ~~~~~~~~~~~~~~ Stage Selected Add to the staging area with `git add `_ Launch Editor Launches the configured visual text editor Launch Difftool Visualize changes relative to the index with `git difftool `_ Revert Unstaged Edits Reverts unstaged content by checking out selected paths from the index/staging area Revert Uncommited Edits Throws away uncommitted edits Unmerged Files ~~~~~~~~~~~~~~ Launch Merge Tool Resolve conflicts using `git mergetool `_ Stage Selected Mark as resolved using `git add `_ Launch Editor Launch the configured visual text editor Untracked Files ~~~~~~~~~~~~~~~ Stage Selected Add to the index/staging area with `git add `_ Launch Editor Launch the configured visual text editor Delete File(s) Delete files from the filesystem Add to .gitignore Adds file/files to GIT ignore list for untracked files .. _diff: Diff ==== The diff viewer/editor displays diffs for selected files. Additions are shown in green and removals are displayed in light red. Extraneous whitespace is shown with a pure-red background. Right-clicking in the diff provides access to additional actions that use either the cursor location or text selection. Staging content for commit -------------------------- The ``@@`` patterns denote a new diff region. Selecting lines of diff and using the `Stage Selected` command will stage just the selected lines. Clicking within a diff region and selecting `Stage Section` stages the entire patch region. The corresponding opposite commands can be performed on staged files as well, e.g. staged content can be selectively removed from the index when we are viewing diffs for staged content. Commit Message Editor ===================== The `git cola` commit message editor is a simple text widget for entering commit messages. You can navigate between the `Subject` and `Extended description...` fields using the keyboard arrow keys. Pressing enter when inside the `Subject` field jumps down to the extended description field. The `Options` button menu to the left of the subject field provides access to the additional actions. The `Ctrl+i` keyboard shortcut adds a standard "Signed-off-by: " line, and `Ctrl+Enter` creates a new commit using the commit message and staged content. Sign Off -------- The `Sign Off` button adds a standard:: Signed-off-by: A. U. Thor line to the bottom of the commit message. Invoking this action is equivalent to passing the ``-s`` option to `git commit `_. Commit ------ The commit button runs `git commit `_. The contents of the commit message editor is provided as the commit message. Only staged files are included in the commit -- this is the same behavior as running ``git commit`` on the command-line. Line and Column Display ----------------------- The current line and column number is displayed by the editor. E.g. a ``5,0`` display means that the cursor is located at line five, column zero. The display changes colors when lines get too long. Yellow indicates the safe boundary for sending patches to a mailing list while keeping space for inline reply markers. Orange indicates that the line is starting to run a bit long and should break soon. Red indicates that the line is running up against the standard 80-column limit for commit messages. Keeping commit messages less than 76-characters wide is encouraged. `git log `_ is a great tool but long lines mess up its formatting for everyone else, so please be mindful when writing commit messages. Amend Last Commit ----------------- Clicking on `Amend Last Commit` makes `git cola` amend the previous commit instead of creating a new one. `git cola` loads the previous commit message into the commit message editor when this option is selected. The `Status` tool will display all of the changes for the amended commit. git-cola-1.9.3/share/git-cola/000077500000000000000000000000001225156173500160335ustar00rootroot00000000000000git-cola-1.9.3/share/git-cola/bin/000077500000000000000000000000001225156173500166035ustar00rootroot00000000000000git-cola-1.9.3/share/git-cola/bin/git-xbase000077500000000000000000000457401225156173500204260ustar00rootroot00000000000000#!/usr/bin/env python import os import sys import re from argparse import ArgumentParser from os.path import abspath from os.path import dirname def setup_environment(): prefix = dirname(dirname(dirname(dirname(abspath(__file__))))) source_tree = os.path.join(prefix, 'cola', '__init__.py') if os.path.exists(source_tree): modules = prefix else: modules = os.path.join(prefix, 'share', 'git-cola', 'lib') sys.path.insert(1, modules) setup_environment() from cola import app from cola import cmds from cola import core from cola import difftool from cola import observable from cola import qtutils from cola import utils from cola.compat import json from cola.compat import set from cola.i18n import N_ from cola.models.dag import DAG from cola.models.dag import RepoReader from cola.qtutils import diff_font from cola.widgets import defs from cola.widgets.diff import DiffWidget from cola.widgets.diff import COMMITS_SELECTED from cola.widgets.standard import TreeWidget from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4.QtCore import Qt from PyQt4.QtCore import SIGNAL XBASE_MIMETYPE = 'application/git-xbase-items' PICK = 'pick' REWORD = 'reword' EDIT = 'edit' FIXUP = 'fixup' SQUASH = 'squash' COMMANDS = (PICK, REWORD, EDIT, FIXUP, SQUASH,) COMMAND_TO_IDX = dict([(cmd, idx) for idx, cmd in enumerate(COMMANDS)]) def main(): args = parse_args() app.setup_environment() new_app = app.new_application() app.new_model(new_app, os.getcwd()) desktop = new_app.desktop() window = new_window(args.filename) window.resize(desktop.width(), desktop.height()) window.show() window.raise_() new_app.exec_() return window.status def parse_args(): parser = ArgumentParser() parser.add_argument('filename', metavar='', help='git-rebase-todo file to edit') return parser.parse_args() def new_window(filename): editor = Editor(filename) window = MainWindow(editor) return window class MainWindow(QtGui.QMainWindow): def __init__(self, editor, parent=None): super(MainWindow, self).__init__(parent) self.status = 1 default_title = '%s - git xbase' % core.getcwd() title = core.getenv('GIT_XBASE_TITLE', default_title) self.setAttribute(Qt.WA_MacMetalStyle) self.setWindowTitle(title) self.setCentralWidget(editor) self.connect(editor, SIGNAL('exit(int)'), self.exit) editor.setFocus() self.show_help_action = qtutils.add_action(self, N_('Show Help'), show_help, Qt.Key_Question) self.menubar = QtGui.QMenuBar(self) self.help_menu = self.menubar.addMenu(N_('Help')) self.help_menu.addAction(self.show_help_action) self.setMenuBar(self.menubar) qtutils.add_close_action(self) def exit(self, status): self.status = status self.close() class Editor(QtGui.QWidget): def __init__(self, filename, parent=None): super(Editor, self).__init__(parent) self.widget_version = 1 self.filename = filename self.notifier = notifier = observable.Observable() self.diff = DiffWidget(notifier, self) self.tree = RebaseTreeWidget(notifier, self) self.setFocusProxy(self.tree) self.rebase_button = qtutils.create_button( text=core.getenv('GIT_XBASE_ACTION', N_('Rebase')), tooltip=N_('Accept changes and rebase\n' 'Shortcut: Ctrl+Enter'), icon=qtutils.apply_icon()) self.external_diff_button = qtutils.create_button( text=N_('External Diff'), tooltip=N_('Launch external diff\n' 'Shortcut: Ctrl+D')) self.external_diff_button.setEnabled(False) self.help_button = qtutils.create_button( text=N_('Help'), tooltip=N_('Show help\nShortcut: ?'), icon=qtutils.help_icon()) self.cancel_button = qtutils.create_button( text=N_('Cancel'), tooltip=N_('Cancel rebase\nShortcut: Ctrl+Q'), icon=qtutils.close_icon()) splitter = QtGui.QSplitter() splitter.setHandleWidth(defs.handle_width) splitter.setOrientation(Qt.Vertical) splitter.insertWidget(0, self.tree) splitter.insertWidget(1, self.diff) splitter.setStretchFactor(0, 1) splitter.setStretchFactor(1, 1) controls_layout = QtGui.QHBoxLayout() controls_layout.setMargin(defs.no_margin) controls_layout.setSpacing(defs.button_spacing) controls_layout.addWidget(self.rebase_button) controls_layout.addWidget(self.external_diff_button) controls_layout.addWidget(self.help_button) controls_layout.addStretch() controls_layout.addWidget(self.cancel_button) layout = QtGui.QVBoxLayout() layout.setMargin(defs.no_margin) layout.setSpacing(defs.spacing) layout.addWidget(splitter) layout.addLayout(controls_layout) self.setLayout(layout) self.action_rebase = qtutils.add_action(self, N_('Rebase'), self.rebase, 'Ctrl+Return') notifier.add_observer(COMMITS_SELECTED, self.commits_selected) qtutils.connect_button(self.rebase_button, self.rebase) qtutils.connect_button(self.external_diff_button, self.external_diff) qtutils.connect_button(self.help_button, show_help) qtutils.connect_button(self.cancel_button, self.cancel) self.connect(self.tree, SIGNAL('external_diff()'), self.external_diff) insns = core.read(filename) self.parse_sequencer_instructions(insns) # notifier callbacks def commits_selected(self, commits): self.external_diff_button.setEnabled(bool(commits)) # helpers def emit_exit(self, status): self.emit(SIGNAL('exit(int)'), status) def parse_sequencer_instructions(self, insns): idx = 1 rebase_command = re.compile( r'^(# )?(pick|fixup|squash) ([0-9a-f]{7,40}) (.+)$') for line in insns.splitlines(): match = rebase_command.match(line) if match is None: continue enabled = match.group(1) is None command = match.group(2) sha1hex = match.group(3) summary = match.group(4) self.tree.add_step(idx, enabled, command, sha1hex, summary) idx += 1 self.tree.decorate() self.tree.refit() self.tree.select_first() # actions def cancel(self): self.emit_exit(1) def rebase(self): lines = [item.value() for item in self.tree.items()] sequencer_instructions = '\n'.join(lines) + '\n' try: core.write(self.filename, sequencer_instructions) self.emit_exit(0) except Exception as e: msg, details = utils.format_exception(e) sys.stderr.write(msg + '\n\n' + details) self.emit_exit(128) def external_diff(self): items = self.tree.selected_items() if not items: return item = items[0] difftool.diff_expression(self, item.sha1hex + '^!', hide_expr=True) class RebaseTreeWidget(TreeWidget): def __init__(self, notifier, parent=None): super(RebaseTreeWidget, self).__init__() self.notifier = notifier # header self.setHeaderLabels([N_('#'), N_('Enabled'), N_('Command'), N_('SHA-1'), N_('Summary')]) self.header().setStretchLastSection(True) self.setColumnCount(5) # drag+drop self.clicked_item = None self.clicked_idx = -1 self.dragged_items = [] self.inner_drag = False self.setSelectionMode(self.SingleSelection) self.setDragEnabled(True) self.setAcceptDrops(True) self.setDropIndicatorShown(True) self.setDragDropMode(QtGui.QAbstractItemView.InternalMove) self.setSortingEnabled(False) # actions self.copy_sha1_action = qtutils.add_action(self, N_('Copy SHA-1'), self.copy_sha1, QtGui.QKeySequence.Copy) self.external_diff_action = qtutils.add_action(self, N_('External Diff'), self.external_diff, cmds.LaunchDifftool.SHORTCUT) self.toggle_enabled_action = qtutils.add_action(self, N_('Toggle Enabled'), self.toggle_enabled, Qt.Key_Space) self.action_pick = qtutils.add_action(self, N_('Pick'), lambda: self.set_selected_to(PICK), Qt.Key_1, Qt.Key_P) self.action_reword = qtutils.add_action(self, N_('Reword'), lambda: self.set_selected_to(REWORD), Qt.Key_2, Qt.Key_R) self.action_edit = qtutils.add_action(self, N_('Edit'), lambda: self.set_selected_to(EDIT), Qt.Key_3, Qt.Key_E) self.action_fixup = qtutils.add_action(self, N_('Fixup'), lambda: self.set_selected_to(FIXUP), Qt.Key_4, Qt.Key_F) self.action_squash = qtutils.add_action(self, N_('Squash'), lambda: self.set_selected_to(SQUASH), Qt.Key_5, Qt.Key_S) self.action_shift_down = qtutils.add_action(self, N_('Shift Down'), self.shift_down, 'Shift+j') self.action_shift_up = qtutils.add_action(self, N_('Shift Up'), self.shift_up, 'Shift+k') self.connect(self, SIGNAL('itemChanged(QTreeWidgetItem *, int)'), self.item_changed) self.connect(self, SIGNAL('itemSelectionChanged()'), self.selection_changed) self.connect(self, SIGNAL('move'), self.move) def add_step(self, idx, enabled, command, sha1hex, summary): item = RebaseTreeWidgetItem(idx, enabled, command, sha1hex, summary) self.invisibleRootItem().addChild(item) def decorate(self): for item in self.items(): self.decorate_item(item) def refit(self): self.resizeColumnToContents(0) self.resizeColumnToContents(1) self.resizeColumnToContents(2) self.resizeColumnToContents(3) self.resizeColumnToContents(4) # actions def item_changed(self, item, column): if column == item.ENABLED_COLUMN: self.validate() def validate(self): invalid_first_choice = set([FIXUP, SQUASH]) for item in self.items(): if not item.is_enabled(): continue if item.command in invalid_first_choice: item.command = PICK self.decorate_item(item) break def decorate_item(self, item): item.combo = combo = QtGui.QComboBox() combo.addItems(COMMANDS) combo.setEditable(False) combo.setCurrentIndex(COMMAND_TO_IDX[item.command]) combo.connect(combo, SIGNAL('currentIndexChanged(const QString &)'), lambda s: self.set_command(item, unicode(s))) self.setItemWidget(item, item.COMMAND_COLUMN, combo) def set_selected_to(self, command): for i in self.selected_items(): i.command = command i.combo.setCurrentIndex(COMMAND_TO_IDX[command]) self.validate() def set_command(self, item, command): item.command = command item.combo.setCurrentIndex(COMMAND_TO_IDX[command]) self.validate() def copy_sha1(self): item = self.selected_item() if item is None: return sha1hex = item.sha1hex qtutils.set_clipboard(sha1hex) def selection_changed(self): item = self.selected_item() if item is None: return sha1hex = item.sha1hex dag = DAG(sha1hex, 2) repo = RepoReader(dag) commits = [] for c in repo: commits.append(c) if commits: commits = commits[-1:] self.notifier.notify_observers(COMMITS_SELECTED, commits) def external_diff(self): self.emit(SIGNAL('external_diff()')) def toggle_enabled(self): item = self.selected_item() if item is None: return item.toggle_enabled() def select_first(self): items = self.items() if not items: return idx = self.model().index(0, 0) if idx.isValid(): self.setCurrentIndex(idx) def shift_down(self): item = self.selected_item() if item is None: return items = self.items() idx = items.index(item) if idx < len(items) - 1: self.emit(SIGNAL('move'), [idx], idx + 1) def shift_up(self): item = self.selected_item() if item is None: return items = self.items() idx = items.index(item) if idx > 0: self.emit(SIGNAL('move'), [idx], idx - 1) # Qt events def mimeTypes(self): return [XBASE_MIMETYPE] def mousePressEvent(self, event): self.clicked_item = self.itemAt(event.pos()) if self.clicked_item: self.clicked_idx = self.items().index(self.clicked_item) else: self.clicked_idx = -1 self.clearSelection() super(RebaseTreeWidget, self).mousePressEvent(event) return QtGui.QTreeWidget.mousePressEvent(self, event) def supportedDropActions(self): return Qt.CopyAction def dropMimeData(self, parent, index, data, action): return False def mimeData(self, items): mime = QtCore.QMimeData() data = [i.copy() for i in self.selected_items()] mime.setData(XBASE_MIMETYPE, json.dumps(data)) self.dragged_items = self.selected_items() return mime def dragEnterEvent(self, event): """Detect drag enter events to flag internal moves.""" self.inner_drag = event.source() == self event.accept() return super(RebaseTreeWidget, self).dragEnterEvent(event) def dragLeaveEvent(self, event): """Detect when drags leave so that we can flag it.""" self.inner_drag = False return super(RebaseTreeWidget, self).dragLeaveEvent(event) def dropEvent(self, event): # Qt's default action is losing items so we handle the internal # move ourselves. Ignore the event and reorder the tree. event.accept() if self.clicked_item is None: return drop_pos = event.pos() dst_item = self.itemAt(drop_pos) if dst_item: dst_idx = self.items().index(dst_item) else: dst_idx = len(self.items()) src_idxs = [self.items().index(i) for i in self.dragged_items] if src_idxs: self.emit(SIGNAL('move'), src_idxs, dst_idx) self.viewport().update() self.dragged_items = [] def move(self, src_idxs, dst_idx): new_items = [] items = self.items() for idx in reversed(sorted(src_idxs)): data = items[idx].copy() self.invisibleRootItem().takeChild(idx) item = RebaseTreeWidgetItem(data['idx'], data['enabled'], data['command'], data['sha1hex'], data['summary']) new_items.insert(0, item) if new_items: self.invisibleRootItem().insertChildren(dst_idx, new_items) self.setCurrentItem(new_items[0]) self.decorate() self.validate() def contextMenuEvent(self, event): menu = QtGui.QMenu(self) menu.addAction(self.action_pick) menu.addAction(self.action_reword) menu.addAction(self.action_edit) menu.addAction(self.action_fixup) menu.addAction(self.action_squash) menu.addSeparator() menu.addAction(self.toggle_enabled_action) menu.addSeparator() menu.addAction(self.copy_sha1_action) menu.addAction(self.external_diff_action) menu.exec_(self.mapToGlobal(event.pos())) class RebaseTreeWidgetItem(QtGui.QTreeWidgetItem): ENABLED_COLUMN = 1 COMMAND_COLUMN = 2 def __init__(self, idx, enabled, command, sha1hex, summary, parent=None): QtGui.QTreeWidgetItem.__init__(self, parent) self.combo = None self.command = command self.idx = idx self.sha1hex = sha1hex self.summary = summary self.setText(0, '%02d' % idx) self.set_enabled(enabled) # combo box on 2 self.setText(3, sha1hex) self.setText(4, summary) flags = self.flags() | Qt.ItemIsUserCheckable flags = flags | Qt.ItemIsDragEnabled flags = flags & ~Qt.ItemIsDropEnabled self.setFlags(flags) def copy(self): return { 'command': self.command, 'enabled': self.is_enabled(), 'idx': self.idx, 'sha1hex': self.sha1hex, 'summary': self.summary, } def value(self): return '%s %s %s %s' % ( not self.is_enabled() and '# ' or '', self.command, self.sha1hex, self.summary) def is_enabled(self): return self.checkState(self.ENABLED_COLUMN) == Qt.Checked def set_enabled(self, enabled): self.setCheckState(self.ENABLED_COLUMN, enabled and Qt.Checked or Qt.Unchecked) def toggle_enabled(self): self.set_enabled(not self.is_enabled()) def show_help(): help_text = N_(""" Commands -------- pick = use commit reword = use commit, but edit the commit message edit = use commit, but stop for amending squash = use commit, but meld into previous commit fixup = like "squash", but discard this commit's log message These lines can be re-ordered; they are executed from top to bottom. If you disable a line here THAT COMMIT WILL BE LOST. However, if you disable everything, the rebase will be aborted. Keyboard Shortcuts ------------------ ? = show help j = move down k = move up J = shift row down K = shift row up 1, p = pick 2, r = reword 3, e = edit 4, f = fixup 5, s = squash spacebar = toggle enabled ctrl+enter = accept changes and rebase ctrl+q = cancel and abort the rebase ctrl+d = launch external diff """) parent = qtutils.active_window() text = QtGui.QLabel(parent) text.setFont(diff_font()) text.setText(help_text) text.setTextInteractionFlags(Qt.NoTextInteraction) layout = QtGui.QHBoxLayout() layout.setMargin(defs.margin) layout.setSpacing(defs.spacing) layout.addWidget(text) widget = QtGui.QDialog(parent) widget.setWindowModality(Qt.WindowModal) widget.setWindowTitle(N_('Help - git-xbase')) widget.setLayout(layout) qtutils.add_action(widget, N_('Close'), widget.accept, Qt.Key_Question, Qt.Key_Enter, Qt.Key_Return) widget.show() return widget if __name__ == '__main__': sys.exit(main()) git-cola-1.9.3/share/git-cola/bin/ssh-askpass000077500000000000000000000025341225156173500207750ustar00rootroot00000000000000#!/bin/sh # Tcl ignores the next line -*- tcl -*- \ exec wish "$0" -- "$@" # This is a trivial implementation of an SSH_ASKPASS handler. # Git-gui uses this script if none are already configured. package require Tk set answer {} set yesno 0 set rc 255 if {$argc < 1} { set prompt "Enter your OpenSSH passphrase:" } else { set prompt [join $argv " "] if {[regexp -nocase {\(yes\/no\)\?\s*$} $prompt]} { set yesno 1 } } message .m -text $prompt -justify center -aspect 4000 pack .m -side top -fill x -padx 20 -pady 20 -expand 1 entry .e -textvariable answer -width 50 pack .e -side top -fill x -padx 10 -pady 10 if {!$yesno} { .e configure -show "*" } frame .b button .b.ok -text OK -command finish button .b.cancel -text Cancel -command cancel pack .b.ok -side left -expand 1 pack .b.cancel -side right -expand 1 pack .b -side bottom -fill x -padx 10 -pady 10 bind . {focus -force .e} bind . [list .b.ok invoke] bind . [list .b.cancel invoke] bind . {set rc $rc} proc cancel {} { set ::rc 255 } proc finish {} { if {$::yesno} { if {$::answer ne "yes" && $::answer ne "no"} { tk_messageBox -icon error -title "Error" -type ok \ -message "Only 'yes' or 'no' input allowed." return } } puts $::answer set ::rc 0 } wm title . "OpenSSH" tk::PlaceWindow . vwait rc exit $rc git-cola-1.9.3/share/git-cola/bin/ssh-askpass-darwin000077500000000000000000000011211225156173500222460ustar00rootroot00000000000000#! /bin/sh TITLE=${MACOS_ASKPASS_TITLE:-"SSH"} DIALOG="display dialog \"$@\" default answer \"\" with title \"$TITLE\"" DIALOG="$DIALOG with icon caution" yesno= if echo "$1" | grep "'yes'" 2>&1 >/dev/null || echo "$1" | grep "yes/no" 2>&1 >/dev/null; then yesno=true fi if test -z "$yesno"; then DIALOG="$DIALOG with hidden answer" fi result=$(osascript \ -e 'tell application "Finder"' \ -e "activate" \ -e "$DIALOG" \ -e 'end tell') if test -z "$result"; then exit 1 else echo "$result" | sed -e 's/^text returned://' -e 's/, button returned:.*$//' exit 0 fi git-cola-1.9.3/share/git-cola/icons/000077500000000000000000000000001225156173500171465ustar00rootroot00000000000000git-cola-1.9.3/share/git-cola/icons/COPYING000066400000000000000000000237351225156173500202130ustar00rootroot00000000000000The following license applies to all icons except staged.png. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. git-cola-1.9.3/share/git-cola/icons/README000066400000000000000000000010251225156173500200240ustar00rootroot00000000000000The following icons are from the Apache httpd server icon set: binary.png c.png dir.png generic.png image.png removed.png script.png untracked.png See the COPYING file for license details. The following files are from the Tango icon set: add.svg edit-clear.svg edit-copy.svg edit-select-all.svg open.svg options.svg remove.svg undo.svg view-refresh.svg zoom-in.png zoom-out.png http://creativecommons.org/licenses/publicdomain/ The rest of the icons are original works, copyright (c) 2007-2012 David Aguilar and contributors git-cola-1.9.3/share/git-cola/icons/add.svg000066400000000000000000000347301225156173500204260ustar00rootroot00000000000000 image/svg+xml Add 2006-01-04 Andreas Nilsson http://tango-project.org add plus git-cola-1.9.3/share/git-cola/icons/binary.png000066400000000000000000000004741225156173500211450ustar00rootroot00000000000000PNG  IHDR2o5PLTE̙333}tRNS0JbKGDHbIDAT}A 0 Mxw ]Wi^tNòYTUCĕ /AuM'2⡩D2bs#t-uŠ[gw.<'ޮ|!v|VtEXtcommentThis art is in the public domain. Kevin Hughes, kevinh@eit.com, September 1995vIENDB`git-cola-1.9.3/share/git-cola/icons/c.png000066400000000000000000000004641225156173500201020ustar00rootroot00000000000000PNG  IHDR2o5PLTE333tRNS0JbKGDHZIDATץ @@V@ PDgKSu3 'R\bYIQ/Inzntٞƈ]\VtEXtcommentThis art is in the public domain. Kevin Hughes, kevinh@eit.com, September 1995vIENDB`git-cola-1.9.3/share/git-cola/icons/dir.png000066400000000000000000000004551225156173500204360ustar00rootroot00000000000000PNG  IHDR2o5PLTE̙f3333.2tRNS AbKGDHRIDATcPP 0U  1ECCALC (j @pD™®TWUc0qeP q%Pp~ .$VtEXtcommentThis art is in the public domain. Kevin Hughes, kevinh@eit.com, September 1995vIENDB`git-cola-1.9.3/share/git-cola/icons/edit-clear.svg000066400000000000000000000460531225156173500217100ustar00rootroot00000000000000 image/svg+xml Edit Clear Andreas Nilsson http://www.tango-project.org clear reset blank edit Jakub Steiner (although minimally ;) git-cola-1.9.3/share/git-cola/icons/edit-copy.svg000066400000000000000000000363531225156173500215760ustar00rootroot00000000000000 image/svg+xml Edit Copy 2005-10-15 Andreas Nilsson edit copy Jakub Steiner git-cola-1.9.3/share/git-cola/icons/edit-select-all.svg000066400000000000000000000370371225156173500226510ustar00rootroot00000000000000 image/svg+xml Select All Andreas Nilsson select all git-cola-1.9.3/share/git-cola/icons/generic.png000066400000000000000000000004341225156173500212710ustar00rootroot00000000000000PNG  IHDR2o5PLTE333tRNS0JbKGDHBIDATc0CAAA `fF0 Lf( a...P& ɀd;X tAe TLVtEXtcommentThis art is in the public domain. Kevin Hughes, kevinh@eit.com, September 1995vIENDB`git-cola-1.9.3/share/git-cola/icons/git.svg000066400000000000000000000224761225156173500204650ustar00rootroot00000000000000 git-cola-1.9.3/share/git-cola/icons/image.png000066400000000000000000000005771225156173500207470ustar00rootroot00000000000000PNG  IHDR2o50PLTE33̙ffff33333fI~tRNS AbKGDHIDATE; @Wji Us.b"`la6G8ՁKǔ1+ѭ4@{?3PMsO‘cM"-EW-[y}ȯϤ#@(#@8"@S"#i̢W7u7Ƙ&/xv@ev3> &|0IN{;pYx|qoN6(7vݔvkFƃcG_-io <L40Jr0&R]'fUaq_!=2H'A fg*='%?>B=gϞݺ{.x4ߚp㘾1D?⧅.Nqn?(Bz>Z?~^QimdɢWmZ<2Tj9PyCW"Pb$V,s04i%1_2${ URd&۝(##Rd'zȀZOJxfTd:޶AQc&Ԋ8˝\>fB`fSs0Ϡ=ص71L zĄ>bXXzXnlՕ*s{Fǟxxv+f}v2WM'9}||5xpbvEcm}#")5Rsqv>Övگ]w7}ב<3C{*%l4 p"5)/5ph#&BԼP8u'@'d22%ϑs pkwOޙ81aS./P ༼:"likVXp6̄R1  LJ<3`㰅e鷾'윱%z@ ,8t*9ܩj2vpn\"L<|D2a 8j@ nƱ 57bC{: gx`hFymƜ+@ͮأ&1 5ƞ9 s/Ny{Cex`O\-wuЅLv>AՕ@'g6wV{%࠵%27,-)rZ' BwBM'^]>`6>h[f]>6" HeM Z?)=! 0w3 :E{>j^r@T1 )0NRfuRr5'ЖngDJڥx\ԛT3 @R [1Km81[Y(Msy[Gj!VgbʬuO{pjAPwڃ1>Ǿ&)8`'\(&H"^-ݨo8:2 {Z8Θ)}2VHy@pĔ37[dXuB baOD(}1l = g,!DI@p: 1-32j]Y""'b99nX:"K46RSS8Z+џʳ`l kGe&2vKZkRHPԚdGvc} pc,cSo/  ,HqQR,@mCN 1 ߾#/%4鹵I[^ 5^KOBpv$xms͙}5:)02 ўneTC0s6s؂e :S NFDN7ICh7hJZ&8@%zrH^)vŸ?Ka[OAqo3B^^0oۤLz0Oe>?lW? "/ |"io]ĴNG 2̳^o>F>[XkypN`;ml=>."%ch)#:weVw &*-`O-fCgmkg"0v2}*ֳ$7ҝ<2ރx$>(uΟ>c $`=6x;^|٫YW<3Ϙ'#ɳwsHuL_+9f=1J9ڷ QHf)Ys W >ĢDO҉Wv]{B@7UaKþegd5+){SBocrz(z?,4J- 0^܃-~ g\*WeMuhK裔޾ڨ=N}UMQ3gUMJyvm ,ouqS= e٨\m:x'z{{]+mnDh7beZ-}2ϛrف{[z8M_g%1,ǟ7 Sv*a;+´+h|Iz׶^|8skr[=0\_.=~~&3`_l]1S+Igui8mafG/E}av ^ag\פֿq]=4IC#idu%Jmr ?6j/J^(&UMD Vc֟Ŕ(QncB96bQkQ(|Y[!j-J%[o6>a%J](a#yDA FIENDB`git-cola-1.9.3/share/git-cola/icons/modified.png000066400000000000000000000010211225156173500214260ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIMELbEtEXtCommentCreated with GIMPWlIDAT8˅Kn0 D]NMr$@N &-YBT LH i~{s,f,D 1cf8Pfw6 {83/`g``0p; 9P^ g3V sv}>SJr/Q)^IENDB`git-cola-1.9.3/share/git-cola/icons/open.svg000066400000000000000000000624771225156173500206500ustar00rootroot00000000000000 image/svg+xml Folder Icon Accept 2005-01-31 Jakub Steiner http://jimmac.musichall.cz Active state - when files are being dragged to. Novell, Inc. Garrett LeSage git-cola-1.9.3/share/git-cola/icons/options.svg000066400000000000000000000175761225156173500214020ustar00rootroot00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz/ system applications group category admin root git-cola-1.9.3/share/git-cola/icons/partial.png000066400000000000000000000010701225156173500213060ustar00rootroot00000000000000PNG  IHDRasRGB pHYs  IDAT8˝OkQәfɴBb\"Fi(H7nAѥ K7v!uMhiڝhK@&i3ybi=p{9tzeZ^v)Yb_S#@2yMn/*JE-'*ᓀ2u!󶽻HKؗ' c[.awAS3A`$Q4m_yΌu ᧄr|;Ő%2 ;$KU0::LJhRUWU"kCw#XwL3y*!W%՚~d_@}m*$>S4plshYu&\3SE8ZX]cM區b''w*c{_= `  \7,/*wr 8\V{)_\B$rܷɖf?IENDB`git-cola-1.9.3/share/git-cola/icons/plus.png000066400000000000000000000003451225156173500206410ustar00rootroot00000000000000PNG  IHDR2o5sRGBPLTEorm333 a p3tRNS@f pHYs  \IDATcP PK$3MLB0A`f")((e)niiP t3illige*BБ P}:+HIENDB`git-cola-1.9.3/share/git-cola/icons/remove.svg000066400000000000000000000327361225156173500211770ustar00rootroot00000000000000 image/svg+xml Remove 2006-01-04 Andreas Nilsson http://tango-project.org remove delete git-cola-1.9.3/share/git-cola/icons/removed.png000066400000000000000000000004731225156173500213210ustar00rootroot00000000000000PNG  IHDR2o5PLTE33f333 tRNS@*bKGDH_IDATcHdccc `cC0!P663H( aØP&;ɂ`20`0L&lL0p HL$0f i\!#lVtEXtcommentThis art is in the public domain. Kevin Hughes, kevinh@eit.com, September 1995vIENDB`git-cola-1.9.3/share/git-cola/icons/script.png000066400000000000000000000004531225156173500211620ustar00rootroot00000000000000PNG  IHDR2o5PLTE333tRNS0JbKGDHQIDAT׭ 1l!\ _yQy b3c!**1dӲ'+ޯ{$[/! pPǃi$Ec;(f/UkkK{~emsPnl"0f'{{{#~Sk# image/svg+xml Jakub Steiner http://jimmac.musichall.cz View Refresh reload refresh view git-cola-1.9.3/share/git-cola/icons/zoom-fit-best.png000066400000000000000000000015631225156173500223600ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8Olu?Ovݺf ..)RɈm %HB!Ddd W(Q F:420`cέG }:9<<J) *UBo<5JBGxB jG `,1¡3 9nc#-ܹ_g)@wOW2xjCk0M2좋D}?WFg[_I ܚCMK~4\ɒwuj[Ο6Д4$Ch&f< _Ή[p}4DsP moفFϣ>dIq[C\NĢC 0* Xci/C)a+jqJ.%:?Ċgjlj|!\8%e!$VNH04wE!9&R#=y#e Yg{^en"Zg޲AזB3̄LF+14u0]`Yu~2R(ٿ{t]cu_?45x%qȕg?~*HS6o{^,SFJC:E~J”g-vn7O{<-nOy%]1*}ܳ 3וd25t\.Q1a ^!oVߴbp̢0gJNOܾ}d/4%X"fϻ,ŋurC5u|mf%Jh9:C&Eδ2{ʁ wKD!^KEAoǹõ_Mܑﻎ^&QfsY! he;S-}֌kNnvn?H;JDpa>o&فPvW29l^nIm 䬧uC)~ba[(xtwHabic*uPJ]±-ޙ=1/H>Kk{H&\4 4lkΎv[Sv­Qt|,`N2td2Ĝ4}nՎmRٖՕJN ,+|Yl˙=uH$[k:dpZ%'?>~IENDB`git-cola-1.9.3/share/git-cola/icons/zoom-out.png000066400000000000000000000014671225156173500214550ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kSI?3wn$ Zij U[f%ZW#At .EDIVi*Z]SFh47wFk}9a·sGh)-<*ti#KB<\`DіEt6PqwE'={|:x{ .kb)Ӥ??3#+`и|ޮqs&QޒQxR X2x: 4-i0kd֮ q%j應V4R1I}c: /dev/null echo change > A && git add A """) gitcmds.unstage_paths(['A']) self.model.update_status() self.assertTrue('A' not in self.model.staged) self.assertTrue('A' in self.model.modified) def test_unstage_paths_init(self): """Test unstage_paths() on the root commit.""" gitcmds.unstage_paths(['A']) self.model.update_status() self.assertTrue('A' not in self.model.staged) self.assertTrue('A' in self.model.untracked) def test_unstage_paths_subdir(self): """Test unstage_paths() in a subdirectory.""" self.shell("git commit -m'initial commit' > /dev/null") self.shell(""" mkdir -p foo/bar && touch foo/bar/baz && git add foo/bar/baz """) gitcmds.unstage_paths(['foo']) self.model.update_status() self.assertTrue('foo/bar/baz' in self.model.untracked) self.assertTrue('foo/bar/baz' not in self.model.staged) git-cola-1.9.3/test/core_test.py000066400000000000000000000014601225156173500165530ustar00rootroot00000000000000#!/usr/bin/env python # -*- encoding: utf-8 -*- import unittest import helper from cola import core class CoreColaUnicodeTestCase(unittest.TestCase): """Tests the cola.core module's unicode handling """ def test_core_decode(self): """Test the core.decode function """ filename = helper.fixture('unicode.txt') expect = core.decode(core.encode(u'unicøde')) actual = core.read(filename).strip() self.assertEqual(expect, actual) def test_core_encode(self): """Test the core.encode function """ filename = helper.fixture('unicode.txt') expect = core.encode(u'unicøde') actual = core.encode(core.read(filename).strip()) self.assertEqual(expect, actual) if __name__ == '__main__': unittest.main() git-cola-1.9.3/test/diffparse_test.py000066400000000000000000000140401225156173500175640ustar00rootroot00000000000000import os import unittest from cola import core from cola import gitcmds from cola import diffparse from cola.diffparse import DiffParser import helper class DiffParseModel(object): def __init__(self): self.last_worktree_diff = None self.last_diff = None self.head = 'HEAD' self.amend = False def amending(self): return self.amend def apply_diff_to_worktree(self, path): if os.path.exists(path): self.last_worktree_diff = core.read(path) def apply_diff(self, path): if os.path.exists(path): self.last_diff = core.read(path) class DiffSource(object): def __init__(self, fwd, reverse): self.fwd = core.read(fwd) self.reverse = core.read(reverse) def get(self, head, amending, filename, cached, reverse): if reverse: return self.parse(self.reverse) else: return self.parse(self.fwd) def parse(self, diffoutput): return gitcmds.extract_diff_header( status=0, deleted=False, with_diff_header=True, suppress_header=False, diffoutput=diffoutput) class DiffParseTestCase(unittest.TestCase): def setUp(self): self.model = DiffParseModel() def test_diff(self): fwd = helper.fixture('diff.txt') reverse = helper.fixture('diff-reverse.txt') source = DiffSource(fwd, reverse) model = DiffParseModel() parser = DiffParser(model, filename='', cached=False, reverse=False, diff_source=source) self.assertEqual(parser.offsets(), [916, 1798, 2550]) self.assertEqual(parser.spans(), [[0, 916], [916, 1798], [1798, 2550]]) diffs = parser.diffs() self.assertEqual(len(diffs), 3) self.assertEqual(len(diffs[0]), 23) self.assertEqual(diffs[0][0], '@@ -6,10 +6,21 @@ from cola import gitcmds') self.assertEqual(diffs[0][1], ' from cola import gitcfg') self.assertEqual(diffs[0][2], ' ') self.assertEqual(diffs[0][3], ' ') self.assertEqual(diffs[0][4], '+class DiffSource(object):') self.assertEqual(len(diffs[1]), 18) self.assertEqual(diffs[1][0], '@@ -29,13 +40,11 @@ class DiffParser(object):') self.assertEqual(diffs[1][1], ' self.diff_sel = []') self.assertEqual(diffs[1][2], ' self.selected = []') self.assertEqual(diffs[1][3], ' self.filename = filename') self.assertEqual(diffs[1][4], '+ self.diff_source = diff_source or DiffSource()') self.assertEqual(len(diffs[2]), 18) self.assertEqual(diffs[2][0], '@@ -43,11 +52,10 @@ class DiffParser(object):') def test_diff_at_start(self): fwd = helper.fixture('diff-start.txt') reverse = helper.fixture('diff-start-reverse.txt') source = DiffSource(fwd, reverse) model = DiffParseModel() parser = DiffParser(model, filename='', cached=False, reverse=False, diff_source=source) self.assertEqual(parser.diffs()[0][0], '@@ -1 +1,4 @@') self.assertEqual(parser.offsets(), [30]) self.assertEqual(parser.spans(), [[0, 30]]) self.assertEqual(parser.diffs_for_range(0, 10), ([u'@@ -1 +1,4 @@\n bar\n+a\n+b\n+c\n\n'], [0])) self.assertEqual(parser.ranges()[0].begin, [1, 1]) self.assertEqual(parser.ranges()[0].end, [1, 4]) self.assertEqual(parser.ranges()[0].make(), '@@ -1 +1,4 @@') def test_diff_at_end(self): fwd = helper.fixture('diff-end.txt') reverse = helper.fixture('diff-end-reverse.txt') source = DiffSource(fwd, reverse) model = DiffParseModel() parser = DiffParser(model, filename='', cached=False, reverse=False, diff_source=source) self.assertEqual(parser.diffs()[0][0], '@@ -1,39 +1 @@') self.assertEqual(parser.offsets(), [1114]) self.assertEqual(parser.spans(), [[0, 1114]]) self.assertEqual(parser.ranges()[0].begin, [1, 39]) self.assertEqual(parser.ranges()[0].end, [1, 1]) self.assertEqual(parser.ranges()[0].make(), '@@ -1,39 +1 @@') def test_diff_that_empties_file(self): fwd = helper.fixture('diff-empty.txt') reverse = helper.fixture('diff-empty-reverse.txt') source = DiffSource(fwd, reverse) model = DiffParseModel() parser = DiffParser(model, filename='', cached=False, reverse=False, diff_source=source) self.assertEqual(parser.diffs()[0][0], '@@ -1,2 +0,0 @@') self.assertEqual(parser.offsets(), [33]) self.assertEqual(parser.spans(), [[0, 33]]) self.assertEqual(parser.diffs_for_range(0, 1), ([u'@@ -1,2 +0,0 @@\n-first\n-second\n\n'], [0])) self.assertEqual(parser.ranges()[0].begin, [1, 2]) self.assertEqual(parser.ranges()[0].end, [0, 0]) self.assertEqual(parser.ranges()[0].make(), '@@ -1,2 +0,0 @@') class RangeTestCase(unittest.TestCase): def test_empty_becomes_non_empty(self): r = diffparse.Range('1,2', '0,0') self.assertEqual(r.begin, [1,2]) self.assertEqual(r.end, [0, 0]) self.assertEqual(r.make(), '@@ -1,2 +0,0 @@') r.set_end_count(1) self.assertEqual(r.end, [1, 1]) self.assertEqual(r.make(), '@@ -1,2 +1 @@') def test_single_line(self): r = diffparse.Range('1', '1,2') self.assertEqual(r.begin, [1, 1]) self.assertEqual(r.end, [1, 2]) self.assertEqual(r.make(), '@@ -1 +1,2 @@') r.set_end_count(1) self.assertEqual(r.make(), '@@ -1 +1 @@') if __name__ == '__main__': unittest.main() git-cola-1.9.3/test/fixtures/000077500000000000000000000000001225156173500160625ustar00rootroot00000000000000git-cola-1.9.3/test/fixtures/diff-empty-reverse.txt000066400000000000000000000001741225156173500223420ustar00rootroot00000000000000diff --git a/filename b/filename index c9317d7..e69de29 100644 --- a/filename +++ b/filename @@ -0,0 +1,2 @@ +first +second git-cola-1.9.3/test/fixtures/diff-empty.txt000066400000000000000000000001741225156173500206710ustar00rootroot00000000000000diff --git a/filename b/filename index c9317d7..e69de29 100644 --- a/filename +++ b/filename @@ -1,2 +0,0 @@ -first -second git-cola-1.9.3/test/fixtures/diff-end-reverse.txt000066400000000000000000000021301225156173500217440ustar00rootroot00000000000000@@ -1,39 +1 @@ +var lib = require('./build/Release/rijndael'); + +var Rijndael = function(key, encoding) { + if (!(this instanceof Rijndael)) + return new Rijndael(key); + + if (!Buffer.isBuffer(key)) + key = new Buffer(key, encoding); + + this._key = key; +}; + +Rijndael.prototype.encrypt = function(plaintext) { + if (!Buffer.isBuffer(plaintext)) + throw new TypeError('plaintext must be a buffer'); + return lib.rijndael(plaintext, this._key, true); +}; + +Rijndael.prototype.decrypt = function(ciphertext) { + if (!Buffer.isBuffer(ciphertext)) + throw new TypeError('ciphertext must be a buffer'); + return lib.rijndael(ciphertext, this._key, false); +}; + +var createRijndael = function(key, encoding) { + return new Rijndael(key, encoding); +}; + +createRijndael.encrypt = function(plaintext, key) { + return lib.rijndael(plaintext, key, true); +}; + +createRijndael.decrypt = function(ciphertext, key) { + return lib.rijndael(ciphertext, key, false); +}; + +createRijndael.version = "0.0.2"; + +module.exports = createRijndael; -module.exports = require('./build/Release/rijndael'); git-cola-1.9.3/test/fixtures/diff-end.txt000066400000000000000000000021301225156173500202730ustar00rootroot00000000000000@@ -1,39 +1 @@ -var lib = require('./build/Release/rijndael'); - -var Rijndael = function(key, encoding) { - if (!(this instanceof Rijndael)) - return new Rijndael(key); - - if (!Buffer.isBuffer(key)) - key = new Buffer(key, encoding); - - this._key = key; -}; - -Rijndael.prototype.encrypt = function(plaintext) { - if (!Buffer.isBuffer(plaintext)) - throw new TypeError('plaintext must be a buffer'); - return lib.rijndael(plaintext, this._key, true); -}; - -Rijndael.prototype.decrypt = function(ciphertext) { - if (!Buffer.isBuffer(ciphertext)) - throw new TypeError('ciphertext must be a buffer'); - return lib.rijndael(ciphertext, this._key, false); -}; - -var createRijndael = function(key, encoding) { - return new Rijndael(key, encoding); -}; - -createRijndael.encrypt = function(plaintext, key) { - return lib.rijndael(plaintext, key, true); -}; - -createRijndael.decrypt = function(ciphertext, key) { - return lib.rijndael(ciphertext, key, false); -}; - -createRijndael.version = "0.0.2"; - -module.exports = createRijndael; +module.exports = require('./build/Release/rijndael'); git-cola-1.9.3/test/fixtures/diff-reverse.txt000066400000000000000000000051651225156173500212130ustar00rootroot00000000000000diff --git b/cola/diffparse.py a/cola/diffparse.py index 33a892e..a680f4b 100644 --- b/cola/diffparse.py +++ a/cola/diffparse.py @@ -6,21 +6,10 @@ from cola import gitcmds from cola import gitcfg -class DiffSource(object): - def get(self, head, amending, filename, cached, reverse): - return gitcmds.diff_helper(head=head, - amending=amending, - filename=filename, - with_diff_header=True, - cached=cached, - reverse=reverse) - - class DiffParser(object): """Handles parsing diff for use by the interactive index editor.""" def __init__(self, model, filename='', - cached=True, reverse=False, - diff_source=None): + cached=True, reverse=False): self._header_re = re.compile('^@@ -(\d+),(\d+) \+(\d+),(\d+) @@.*') self._header_start_re = re.compile('^@@ -(\d+) \+(\d+),(\d+) @@.*') @@ -40,11 +29,13 @@ class DiffParser(object): self.diff_sel = [] self.selected = [] self.filename = filename - self.diff_source = diff_source or DiffSource() - (header, diff) = self.diff_source.get(self.head, self.amending, - filename, cached, - cached or reverse) + (header, diff) = gitcmds.diff_helper(head=self.head, + amending=self.amending, + filename=filename, + with_diff_header=True, + cached=cached, + reverse=cached or reverse) self.model = model self.diff = diff self.header = header @@ -52,10 +43,11 @@ class DiffParser(object): # Always index into the non-reversed diff self.fwd_header, self.fwd_diff = \ - self.diff_source.get(self.head, - self.amending, - filename, - cached, False) + gitcmds.diff_helper(head=self.head, + amending=self.amending, + filename=filename, + with_diff_header=True, + cached=cached) def write_diff(self,filename,which,selected=False,noop=False): """Writes a new diff corresponding to the user's selection.""" git-cola-1.9.3/test/fixtures/diff-start-reverse.txt000066400000000000000000000001771225156173500223440ustar00rootroot00000000000000diff --git b/foo bar/a a/foo bar/a index 5934e89..5716ca5 100644 --- b/foo bar/a +++ a/foo bar/a @@ -1,4 +1 @@ bar -a -b -c git-cola-1.9.3/test/fixtures/diff-start.txt000066400000000000000000000001771225156173500206730ustar00rootroot00000000000000diff --git a/foo bar/a b/foo bar/a index 5716ca5..5934e89 100644 --- a/foo bar/a +++ b/foo bar/a @@ -1 +1,4 @@ bar +a +b +c git-cola-1.9.3/test/fixtures/diff.txt000066400000000000000000000051651225156173500175420ustar00rootroot00000000000000diff --git a/cola/diffparse.py b/cola/diffparse.py index a680f4b..33a892e 100644 --- a/cola/diffparse.py +++ b/cola/diffparse.py @@ -6,10 +6,21 @@ from cola import gitcmds from cola import gitcfg +class DiffSource(object): + def get(self, head, amending, filename, cached, reverse): + return gitcmds.diff_helper(head=head, + amending=amending, + filename=filename, + with_diff_header=True, + cached=cached, + reverse=reverse) + + class DiffParser(object): """Handles parsing diff for use by the interactive index editor.""" def __init__(self, model, filename='', - cached=True, reverse=False): + cached=True, reverse=False, + diff_source=None): self._header_re = re.compile('^@@ -(\d+),(\d+) \+(\d+),(\d+) @@.*') self._header_start_re = re.compile('^@@ -(\d+) \+(\d+),(\d+) @@.*') @@ -29,13 +40,11 @@ class DiffParser(object): self.diff_sel = [] self.selected = [] self.filename = filename + self.diff_source = diff_source or DiffSource() - (header, diff) = gitcmds.diff_helper(head=self.head, - amending=self.amending, - filename=filename, - with_diff_header=True, - cached=cached, - reverse=cached or reverse) + (header, diff) = self.diff_source.get(self.head, self.amending, + filename, cached, + cached or reverse) self.model = model self.diff = diff self.header = header @@ -43,11 +52,10 @@ class DiffParser(object): # Always index into the non-reversed diff self.fwd_header, self.fwd_diff = \ - gitcmds.diff_helper(head=self.head, - amending=self.amending, - filename=filename, - with_diff_header=True, - cached=cached) + self.diff_source.get(self.head, + self.amending, + filename, + cached, False) def write_diff(self,filename,which,selected=False,noop=False): """Writes a new diff corresponding to the user's selection.""" git-cola-1.9.3/test/fixtures/unicode.txt000066400000000000000000000000111225156173500202410ustar00rootroot00000000000000unicøde git-cola-1.9.3/test/git_test.py000066400000000000000000000064141225156173500164120ustar00rootroot00000000000000#!/usr/bin/env python """Tests various operations using the cola.git module """ import time import signal import unittest from cola import git from cola.git import STDOUT class GitCommandTest(unittest.TestCase): """Runs tests using a git.Git instance""" def setUp(self): """Creates a git.Git instance for later use""" self.git = git.Git() def test_version(self): """Test running 'git version'""" version = self.git.version()[STDOUT] self.failUnless(version.startswith('git version')) def test_tag(self): """Test running 'git tag'""" tags = self.git.tag()[STDOUT].splitlines() self.failUnless( 'v1.0.0' in tags ) def test_show(self): """Test running 'git show'""" sha = '1b9742bda5d26a4f250fa64657f66ed20624a084' contents = self.git.show(sha)[STDOUT].splitlines() self.failUnless(contents[0] == '/build') def test_stdout(self): """Test overflowing the stdout buffer""" # Write to stdout only code = ('import sys;' 's = "\\0" * (1024 * 16 + 1);' 'sys.stdout.write(s);') status, out, err = git.Git.execute(['python', '-c', code], _raw=True) self.assertEqual(status, 0) self.assertEqual(len(out), 1024 * 16 + 1) self.assertEqual(len(err), 0) def test_stderr(self): """Test that stderr is seen""" # Write to stderr and capture it code = ('import sys;' 's = "\\0" * (1024 * 16 + 1);' 'sys.stderr.write(s);') status, out, err = git.Git.execute(['python', '-c', code], _raw=True) self.assertEqual(status, 0) self.assertEqual(len(out), 0) self.assertEqual(len(err), 1024 * 16 + 1) def test_stdout_and_stderr(self): """Test ignoring stderr when stdout+stderr are provided (v2)""" # Write to stdout and stderr but only capture stdout code = ('import sys;' 's = "\\0" * (1024 * 16 + 1);' 'sys.stdout.write(s);' 'sys.stderr.write(s);') status, out, err = git.Git.execute(['python', '-c', code], _raw=True) self.assertEqual(status, 0) self.assertEqual(len(out), 1024 * 16 + 1) self.assertEqual(len(err), 1024 * 16 + 1) def test_it_doesnt_deadlock(self): """Test that we don't deadlock with both stderr and stdout""" # 16k+1 bytes to exhaust any output buffers code = ('import sys;' 's = "\\0" * (1024 * 16 + 1);' 'sys.stderr.write(s);' 'sys.stdout.write(s);') status, out, err = git.Git.execute(['python', '-c', code], _raw=True) self.assertEqual(status, 0) self.assertEqual(out, '\0' * (1024 * 16 + 1)) self.assertEqual(err, '\0' * (1024 * 16 + 1)) def test_it_handles_interrupted_syscalls(self): """Test that we handle interrupted system calls""" # send ourselves a signal that causes EINTR prev_handler = signal.signal(signal.SIGALRM, lambda x,y: 1) signal.alarm(1) time.sleep(0.5) status, out, err = git.Git.execute(['sleep', '1']) self.assertEqual(status, 0) signal.signal(signal.SIGALRM, prev_handler) if __name__ == '__main__': unittest.main() git-cola-1.9.3/test/gitcfg_test.py000066400000000000000000000035221225156173500170670ustar00rootroot00000000000000import unittest import helper from cola import gitcfg class GitConfigTestCase(helper.GitRepositoryTestCase): """Tests the cola.gitcmds module.""" def setUp(self): helper.GitRepositoryTestCase.setUp(self) self.config = gitcfg.instance() def test_string(self): """Test string values in get().""" self.shell('git config test.value test') self.assertEqual(self.config.get('test.value'), 'test') def test_int(self): """Test int values in get().""" self.shell('git config test.int 42') self.assertEqual(self.config.get('test.int'), 42) def test_true(self): """Test bool values in get().""" self.shell('git config test.bool true') self.assertEqual(self.config.get('test.bool'), True) def test_false(self): self.shell('git config test.bool false') self.assertEqual(self.config.get('test.bool'), False) def test_yes(self): self.shell('git config test.bool yes') self.assertEqual(self.config.get('test.bool'), True) def test_no(self): self.shell('git config test.bool false') self.assertEqual(self.config.get('test.bool'), False) def test_bool_no_value(self): self.shell('printf "[test]\n" >> .git/config') self.shell('printf "\tbool\n" >> .git/config') self.assertEqual(self.config.get('test.bool'), True) def test_empty_value(self): self.shell('printf "[test]\n" >> .git/config') self.shell('printf "\tvalue = \n" >> .git/config') self.assertEqual(self.config.get('test.value'), '') def test_default(self): """Test default values in get().""" self.assertEqual(self.config.get('does.not.exist'), None) self.assertEqual(self.config.get('does.not.exist', default=42), 42) if __name__ == '__main__': unittest.main() git-cola-1.9.3/test/gitcmds_test.py000066400000000000000000000106201225156173500172530ustar00rootroot00000000000000import os import time import unittest import helper from cola import gitcmds from cola import gitcfg class GitCmdsTestCase(helper.GitRepositoryTestCase): """Tests the cola.gitcmds module.""" def setUp(self): helper.GitRepositoryTestCase.setUp(self) self.config = gitcfg.GitConfig() def test_currentbranch(self): """Test current_branch().""" self.assertEqual(gitcmds.current_branch(), 'master') def test_branch_list_local(self): """Test branch_list(remote=False).""" self.assertEqual(gitcmds.branch_list(remote=False), ['master']) def test_branch_list_remote(self): """Test branch_list(remote=False).""" self.assertEqual(gitcmds.branch_list(remote=True), []) self.shell(""" git remote add origin . && git fetch origin > /dev/null 2>&1 """) self.assertEqual(gitcmds.branch_list(remote=True), ['origin/master']) self.shell('git remote rm origin') self.assertEqual(gitcmds.branch_list(remote=True), []) def test_default_remote(self): """Test default_remote().""" self.assertEqual(gitcmds.default_remote(config=self.config), None) self.shell('git config branch.master.remote test') self.config.reset() self.assertEqual(gitcmds.default_remote(config=self.config), 'test') def test_tracked_branch(self): """Test tracked_branch().""" self.assertEqual(gitcmds.tracked_branch(config=self.config), None) self.shell(""" git config branch.master.remote test && git config branch.master.merge refs/heads/master """) self.config.reset() self.assertEqual(gitcmds.tracked_branch(config=self.config), 'test/master') def test_tracked_branch_other(self): """Test tracked_branch('other').""" self.assertEqual(gitcmds.tracked_branch('other', config=self.config), None) self.shell(""" git config branch.other.remote test && git config branch.other.merge refs/heads/other/branch """) self.config.reset() self.assertEqual(gitcmds.tracked_branch('other', config=self.config), 'test/other/branch') def test_untracked_files(self): """Test untracked_files().""" self.shell('touch C D E') self.assertEqual(gitcmds.untracked_files(), ['C', 'D', 'E']) def test_tag_list(self): """Test tag_list().""" self.shell('git tag a && git tag b && git tag c') self.assertEqual(gitcmds.tag_list(), ['c', 'b', 'a']) def test_merge_message_path(self): """Test merge_message_path().""" self.shell('touch .git/SQUASH_MSG') self.assertEqual(gitcmds.merge_message_path(), os.path.abspath('.git/SQUASH_MSG')) self.shell('touch .git/MERGE_MSG') self.assertEqual(gitcmds.merge_message_path(), os.path.abspath('.git/MERGE_MSG')) os.unlink(gitcmds.merge_message_path()) self.assertEqual(gitcmds.merge_message_path(), os.path.abspath('.git/SQUASH_MSG')) os.unlink(gitcmds.merge_message_path()) self.assertEqual(gitcmds.merge_message_path(), None) def test_all_refs(self): self.shell(""" git branch a && git branch b && git branch c && git tag d && git tag e && git tag f && git remote add origin . && git fetch origin > /dev/null 2>&1 """) refs = gitcmds.all_refs() self.assertEqual(refs, ['a', 'b', 'c', 'master', 'origin/a', 'origin/b', 'origin/c', 'origin/master', 'd', 'e', 'f']) def test_all_refs_split(self): self.shell(""" git branch a && git branch b && git branch c && git tag d && git tag e && git tag f && git remote add origin . && git fetch origin > /dev/null 2>&1 """) local, remote, tags = gitcmds.all_refs(split=True) self.assertEqual(local, ['a', 'b', 'c', 'master']) self.assertEqual(remote, ['origin/a', 'origin/b', 'origin/c', 'origin/master']) self.assertEqual(tags, ['d', 'e', 'f']) if __name__ == '__main__': unittest.main() git-cola-1.9.3/test/gitops_test.py000066400000000000000000000030611225156173500171270ustar00rootroot00000000000000#!/usr/bin/env python """Tests basic git operations: commit, log, config""" import os import unittest import helper from cola.models.main import MainModel class ColaBasicGitTestCase(helper.GitRepositoryTestCase): def setUp(self): helper.GitRepositoryTestCase.setUp(self, commit=False) def test_git_commit(self): """Test running 'git commit' via cola.git""" self.shell(""" echo A > A echo B > B git add A B """) model = MainModel(cwd=os.getcwd()) model.git.commit(m='commit test') log = helper.pipe('git log --pretty=oneline | wc -l') self.assertEqual(log.strip(), '1') def test_git_config(self): """Test cola.git.config()""" self.shell('git config section.key value') model = MainModel(cwd=os.getcwd()) value = model.git.config('section.key', get=True) self.assertEqual(value, (0, 'value', '')) # Test config_set model.config_set('section.bool', True) value = model.git.config('section.bool', get=True) self.assertEqual(value, (0, 'true', '')) model.config_set('section.bool', False) # Test config_dict config_dict = model.config_dict(local=True) self.assertEqual(config_dict['section_key'], 'value') self.assertEqual(config_dict['section_bool'], False) # Test config_dict --global global_dict = model.config_dict(local=False) self.assertEqual(type(global_dict), dict) if __name__ == '__main__': unittest.main() git-cola-1.9.3/test/helper.py000066400000000000000000000031761225156173500160510ustar00rootroot00000000000000import os import shutil import unittest import tempfile from cola import core from cola import git from cola import gitcfg from cola import gitcmds def tmp_path(*paths): """Returns a path relative to the test/tmp directory""" return os.path.join(os.path.dirname(__file__), 'tmp', *paths) def fixture(*paths): return os.path.join(os.path.dirname(__file__), 'fixtures', *paths) def shell(cmd): return os.system(cmd) def pipe(cmd): p = os.popen(cmd) out = core.fread(p).strip() p.close() return out class TmpPathTestCase(unittest.TestCase): def setUp(self): self._testdir = tempfile.mkdtemp('_cola_test') os.chdir(self._testdir) def tearDown(self): """Remove the test directory and return to the tmp root.""" path = self._testdir os.chdir(tmp_path()) shutil.rmtree(path) def shell(self, cmd): result = shell(cmd) self.failIf(result != 0) def test_path(self, *paths): return os.path.join(self._testdir, *paths) class GitRepositoryTestCase(TmpPathTestCase): """Tests that operate on temporary git repositories.""" def setUp(self, commit=True): TmpPathTestCase.setUp(self) self.initialize_repo() if commit: self.commit_files() git.instance().set_worktree(core.getcwd()) gitcfg.instance().reset() gitcmds.clear_cache() def initialize_repo(self): self.shell(""" git init > /dev/null && touch A B && git add A B """) def commit_files(self): self.shell('git commit -m"Initial commit" > /dev/null') git-cola-1.9.3/test/i18n_test.py000066400000000000000000000036271225156173500164110ustar00rootroot00000000000000# -*- encoding: utf-8 -*- import unittest from PyQt4 import QtCore from cola import i18n from cola.i18n import N_ class ColaI18nTestCase(unittest.TestCase): """Test cases for the ColaApplication class""" def tearDown(self): i18n.uninstall() def test_translates_noun(self): """Test that strings with @@noun are translated """ i18n.install('ja_JP') expect = (unichr(0x30b3) + unichr(0x30df) + unichr(0x30c3) + unichr(0x30c8)) actual = N_('Commit@@verb') self.assertEqual(expect, actual) def test_translates_verb(self): """Test that strings with @@verb are translated """ i18n.install('de_DE') expect = 'Version aufnehmen' actual = N_('Commit@@verb') self.assertEqual(expect, actual) def test_translates_english_noun(self): """Test that English strings with @@noun are properly handled """ i18n.install('en_US.UTF-8') expect = 'Commit' actual = N_('Commit@@noun') self.assertEqual(expect, actual) def test_translates_english_verb(self): """Test that English strings with @@verb are properly handled """ i18n.install('en_US.UTF-8') expect = 'Commit' actual = N_('Commit@@verb') self.assertEqual(expect, actual) def test_translates_random_english(self): """Test that random English strings are passed through as-is """ i18n.install('en_US.UTF-8') expect = 'Random' actual = N_('Random') self.assertEqual(expect, actual) def test_guards_against_qstring(self): """Test that random QString is passed through as-is """ i18n.install('en_US.UTF-8') expect = 'Random' actual = i18n.gettext(QtCore.QString('Random')) self.assertEqual(expect, actual) if __name__ == '__main__': unittest.main() git-cola-1.9.3/test/main_model_test.py000066400000000000000000000045401225156173500177310ustar00rootroot00000000000000import os import unittest import helper from cola.models.main import MainModel class MainModelTestCase(helper.GitRepositoryTestCase): """Tests the MainModel class.""" def setUp(self): helper.GitRepositoryTestCase.setUp(self) self.model = MainModel(cwd=os.getcwd()) def test_project(self): """Test the 'project' attribute.""" project = os.path.basename(self.test_path()) self.assertEqual(self.model.project, project) def test_local_branches(self): """Test the 'local_branches' attribute.""" self.model.update_status() self.assertEqual(self.model.local_branches, ['master']) def test_remote_branches(self): """Test the 'remote_branches' attribute.""" self.model.update_status() self.assertEqual(self.model.remote_branches, []) self.shell(""" git remote add origin . git fetch origin > /dev/null 2>&1 """) self.model.update_status() self.assertEqual(self.model.remote_branches, ['origin/master']) def test_modified(self): """Test the 'modified' attribute.""" self.shell('echo change > A') self.model.update_status() self.assertEqual(self.model.modified, ['A']) def test_unstaged(self): """Test the 'unstaged' attribute.""" self.shell('echo change > A') self.shell('echo C > C') self.model.update_status() self.assertEqual(self.model.unstaged, ['A', 'C']) def test_untracked(self): """Test the 'untracked' attribute.""" self.shell('echo C > C') self.model.update_status() self.assertEqual(self.model.untracked, ['C']) def test_remotes(self): """Test the 'remote' attribute.""" self.shell('git remote add origin .') self.model.update_status() self.assertEqual(self.model.remotes, ['origin']) def test_currentbranch(self): """Test the 'currentbranch' attribute.""" self.shell('git checkout -b test > /dev/null 2>&1') self.model.update_status() self.assertEqual(self.model.currentbranch, 'test') def test_tags(self): """Test the 'tags' attribute.""" self.shell('git tag test') self.model.update_status() self.assertEqual(self.model.tags, ['test']) if __name__ == '__main__': unittest.main() git-cola-1.9.3/test/settings_test.py000066400000000000000000000041001225156173500174550ustar00rootroot00000000000000import unittest import os from cola import git from cola import settings import helper class SettingsTestCase(unittest.TestCase): """Tests the cola.settings module""" def setUp(self): settings.Settings._file = self._file = helper.tmp_path('settings') settings.Settings.load_dot_cola = lambda x, y: {} def tearDown(self): if os.path.exists(self._file): os.remove(self._file) def model(self, **kwargs): return settings.Settings(**kwargs) def test_gui_save_restore(self): """Test saving and restoring gui state""" model = self.model() model.gui_state['test-gui'] = {'foo':'bar'} model.save() model = self.model() state = model.gui_state.get('test-gui', {}) self.assertTrue('foo' in state) self.assertEqual(state['foo'], 'bar') def test_bookmarks_save_restore(self): """Test the bookmark save/restore feature""" # We automatically purge missing entries so we mock-out # git.is_git_worktree() so that this bookmark is kept. bookmark = '/tmp/python/thinks/this/exists' def mock_verify(path): return path == bookmark model = self.model() model.add_bookmark(bookmark) model.save() model = self.model(verify=mock_verify) bookmarks = model.bookmarks self.assertEqual(len(model.bookmarks), 1) self.assertTrue(bookmark in bookmarks) model.remove_bookmark(bookmark) bookmarks = model.bookmarks self.assertEqual(len(bookmarks), 0) self.assertFalse(bookmark in bookmarks) def test_bookmarks_removes_missing_entries(self): """Test that missing entries are removed after a reload""" bookmark = '/tmp/this/does/not/exist' model = self.model() model.add_bookmark(bookmark) model.save() model = self.model() bookmarks = model.bookmarks self.assertEqual(len(model.bookmarks), 0) self.assertFalse(bookmark in bookmarks) if __name__ == '__main__': unittest.main() git-cola-1.9.3/test/textwrap_test.py000066400000000000000000000037121225156173500175030ustar00rootroot00000000000000#!/usr/bin/env python import unittest from cola import textwrap class WordWrapTestCase(unittest.TestCase): def setUp(self): self.tabwidth = 8 self.limit = None def wrap(self, text): return textwrap.word_wrap(text, self.tabwidth, self.limit) def test_word_wrap(self): self.limit = 16 text = """ 12345678901 3 56 8 01 3 5 7 1 3 5""" expect = """ 12345678901 3 56 8 01 3 5 7 1 3 5""" self.assertEqual(expect, self.wrap(text)) def test_word_wrap_dashes(self): self.limit = 4 text = '123-5' expect = '123-5' self.assertEqual(expect, self.wrap(text)) def test_word_wrap_double_dashes(self): self.limit = 4 text = '12--5' expect = '12--\n5' self.assertEqual(expect, self.wrap(text)) def test_word_wrap_many_lines(self): self.limit = 2 text = """ aa bb cc dd""" expect = """ aa bb cc dd""" self.assertEqual(expect, self.wrap(text)) def test_word_python_code(self): self.limit = 78 text = """ if True: print "hello world" else: print "hello world" """ self.assertEqual(text, self.wrap(text)) def test_word_wrap_spaces(self): self.limit = 2 text = ' ' * 6 self.assertEqual(' ' * 6, self.wrap(text)) def test_word_wrap_special_tag(self): self.limit = 2 text = """ This test is so meta, even this sentence With-special-tag: Avoids word-wrap """ expect = """ This test is so meta, even this sentence With-special-tag: Avoids word-wrap """ self.assertEqual(self.wrap(text), expect) def test_word_wrap_space_at_start_of_wrap(self): inputs = """0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 """ expect = """0 1 2 3 4 5 6 7 8 9\n0 1 2 3 4 5 6 7 8""" self.limit = 20 actual = self.wrap(inputs) self.assertEqual(expect, actual) if __name__ == '__main__': unittest.main() git-cola-1.9.3/test/tmp/000077500000000000000000000000001225156173500150115ustar00rootroot00000000000000git-cola-1.9.3/test/tmp/.gitignore000066400000000000000000000000001225156173500167670ustar00rootroot00000000000000git-cola-1.9.3/test/utils_test.py000066400000000000000000000034641225156173500167710ustar00rootroot00000000000000#!/usr/bin/env python import unittest from cola import utils class ColaUtilsTestCase(unittest.TestCase): """Tests the cola.utils module.""" def test_basename(self): """Test the utils.basename function.""" self.assertEqual(utils.basename('bar'), 'bar') self.assertEqual(utils.basename('/bar'), 'bar') self.assertEqual(utils.basename('/bar '), 'bar ') self.assertEqual(utils.basename('foo/bar'), 'bar') self.assertEqual(utils.basename('/foo/bar'), 'bar') self.assertEqual(utils.basename('foo/foo/bar'), 'bar') self.assertEqual(utils.basename('/foo/foo/bar'), 'bar') self.assertEqual(utils.basename('/foo/foo//bar'), 'bar') self.assertEqual(utils.basename('////foo //foo//bar'), 'bar') def test_dirname(self): """Test the utils.dirname function.""" self.assertEqual(utils.dirname('bar'), '') self.assertEqual(utils.dirname('/bar'), '') self.assertEqual(utils.dirname('//bar'), '') self.assertEqual(utils.dirname('///bar'), '') self.assertEqual(utils.dirname('foo/bar'), 'foo') self.assertEqual(utils.dirname('foo//bar'), 'foo') self.assertEqual(utils.dirname('foo /bar'), 'foo ') self.assertEqual(utils.dirname('/foo//bar'), '/foo') self.assertEqual(utils.dirname('/foo /bar'), '/foo ') self.assertEqual(utils.dirname('//foo//bar'), '/foo') self.assertEqual(utils.dirname('///foo///bar'), '/foo') def test_add_parents(self): """Test the utils.add_parents() function.""" path_set = set(['foo///bar///baz']) utils.add_parents(path_set) self.assertTrue('foo/bar/baz' in path_set) self.assertTrue('foo/bar' in path_set) self.assertTrue('foo' in path_set) if __name__ == '__main__': unittest.main()