pax_global_header00006660000000000000000000000064145712647370014532gustar00rootroot0000000000000052 comment=38604f46f170fba07f0d8545bf2d50d6319bc06f git-cola-4.6.1/000077500000000000000000000000001457126473700132415ustar00rootroot00000000000000git-cola-4.6.1/.github/000077500000000000000000000000001457126473700146015ustar00rootroot00000000000000git-cola-4.6.1/.github/FUNDING.yml000066400000000000000000000000471457126473700164170ustar00rootroot00000000000000github: [davvid] patreon: daveinthesky git-cola-4.6.1/.github/dependabot.yml000066400000000000000000000001671457126473700174350ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "monthly" git-cola-4.6.1/.github/workflows/000077500000000000000000000000001457126473700166365ustar00rootroot00000000000000git-cola-4.6.1/.github/workflows/ci.yml000066400000000000000000000076771457126473700177750ustar00rootroot00000000000000name: CI on: [push, pull_request] jobs: build: name: Build runs-on: ubuntu-latest steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@0.12.1 - name: Checkout uses: actions/checkout@v4 - name: Install Rust run: rustup toolchain install stable --profile minimal --no-self-update - name: Install Garden run: cargo install garden-tools - uses: Swatinem/rust-cache@v2 - name: Install build dependencies run: | set -x sudo apt-get update sudo apt-get install python3-sphinx python3-qtpy python3-pyqt5 - name: Install Git Cola run: garden -vv -D prefix=dist install test: name: Test runs-on: ubuntu-latest steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@0.12.1 - name: Checkout uses: actions/checkout@v4 - name: Install Rust run: rustup toolchain install stable --profile minimal --no-self-update - name: Install Garden run: cargo install garden-tools - uses: Swatinem/rust-cache@v2 - name: Install Dependencies run: | set -x sudo apt-get update # Runtime dependencies (required) sudo apt-get install \ python3-qtpy \ python3-pyqt5 # Runtime dependencies (optional) sudo apt-get install \ python3-send2trash # Development dependencies sudo apt-get install \ python3-pytest \ python3-setuptools-scm \ python3-sphinx pip install cercis - name: Configure tests run: | git config --global user.name "Git Cola" git config --global user.email git-cola@localhost - name: Run tests and checks run: garden -vv check - name: Code formatting run: garden -vv fmt -- --check windows: name: Windows runs-on: windows-latest steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@0.12.1 - name: Checkout uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: python-version: '3.x' architecture: x64 - name: Pip Cache uses: actions/cache@v4 with: path: ~/AppData/Local/pip/Cache key: ${{ runner.os }}-pip-${{ hashFiles('setup.cfg') }} - name: Install Dependencies run: | pip install '.[build,docs,dev,extras]' # Based on: contrib/win32/run-pynsist.sh - name: Build Installer run: | make doc make htmldir="$PWD/share/doc/git-cola/html" install-doc pynsist pynsist.cfg rm -r share/doc/git-cola/html # Rename executable output cd build/nsis mv git-cola*.exe git-cola-latest-${{github.run_number}}.exe - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: git-cola-latest-${{github.run_number}}-${{runner.os}} path: build/nsis/git-cola*.exe macos: name: macOS runs-on: macos-latest steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@0.12.1 - name: Checkout uses: actions/checkout@v4 - name: Install Rust run: rustup toolchain install stable --profile minimal --no-self-update - name: Install Garden run: cargo install garden-tools - uses: Swatinem/rust-cache@v2 - name: Install Dependencies run: | brew install git-cola - name: Build Bundle run: | garden -vv macos/app mv git-cola.app build/ - name: Zip Artifact run: zip -r git-cola.app.zip build/* - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: git-cola-latest-${{github.run_number}}-${{runner.os}} path: git-cola.app.zip git-cola-4.6.1/.gitignore000066400000000000000000000004741457126473700152360ustar00rootroot00000000000000/.cache /.coverage /build /config.mak /cola/_build_version.py /deb /dist /.eggs /env* /fedora /flatpak /git-cola.app /htmlcov /local /pages /patches /pip-wheel-metadata /pynsist_pkgs /.pytest_cache /README.html /share/locale /test/tmp /todo /tags /.tox __pycache__ .DS_Store *.egg-info *.gz *.py[cod] *.swp *.zip *~ git-cola-4.6.1/.mailmap000066400000000000000000000014411457126473700146620ustar00rootroot00000000000000AJ Bagwell 林博仁(Buo-ren Lin) David Martínez Martí David Aguilar Javier Rodriguez Cuevas Javier Rodriguez Cuevas Mickael Albertus Minarto Margoliono Minarto Margoliono Pilar Molina Lopez Szymon Judasz Szymon Judasz V字龍(Vdragon) Vitor Lobo Vitor Lobo Zhang Han git-cola-4.6.1/.pre-commit-config.yaml000066400000000000000000000011301457126473700175150ustar00rootroot00000000000000ci: autoupdate_schedule: monthly exclude: qtpy/|test/fixtures/|\.rtf$|PkgInfo$ repos: - repo: https://github.com/pre-commit/pre-commit-hooks.git rev: v4.5.0 hooks: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/asottile/pyupgrade rev: v3.15.0 hooks: - id: pyupgrade name: Enforce Python 3.6 idioms args: - --py36-plus - repo: https://github.com/jsh9/cercis rev: 0.2.5 hooks: - id: cercis args: - --line-length=88 - --function-definition-extra-indent=False git-cola-4.6.1/.readthedocs.yml000066400000000000000000000012121457126473700163230ustar00rootroot00000000000000# .readthedocs.yaml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Set the version of Python and other tools you might need build: os: ubuntu-20.04 tools: python: "3.9" # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/conf.py # If using Sphinx, optionally build your docs in additional formats such as PDF # formats: # - pdf # Optionally declare the Python requirements required to build your docs python: install: - method: pip path: . extra_requirements: - docs - pyqt5 git-cola-4.6.1/CHANGES.rst000066400000000000000000004475101457126473700150560ustar00rootroot00000000000000.. _v4.6.1: v4.6.1 ====== Packaging --------- * `launchable` tags were added to the flatpak app metainfo files. .. _v4.6.0: v4.6.0 ====== Usability, bells and whistles ----------------------------- * The Rebase editor (`git-cola-sequence-editor`) can now add "remarks" to commits. Remarks are simple numbered flags (0-9) that allow you to mark commits. This lets you visually highlight commits to aid you when rebasing and grouping related commits across a large patch series. Remarks can be added to a single commit or to all commits that touch a file. (`#1375 `_) (`#1380 `_) * Invalid `commit.template` configuration is now reported in the `Console` tool instead of presenting an error traceback dialog via a `UsageError` exception. (`#1384 `_) Fixes ----- * The file system monitor was corrected to catch `PermissionError` exceptions. (`bz #2260155 `_) Packaging --------- * If the `polib` module (e.g. `sudo apt install python3-polib`) is installed then it will be used instead of the vendored `cola.polib` module. This makes it easier for distributions to remove the vendored module from the `cola` namespace. `polib` is now listed as an install requirement in `pyproject.toml`. (`bz #2264526 `_) * The flatpak metainfo now contains the required developer name field. (`#1382 `_) Development ----------- * The "actions/cache" and "styfle/cancel-workflow-action" github actions were upgraded. * The test suite now uses ``ruff`` to validate python code. ``pylint`` is no longer used. (`#1353 `_) (`#1383 `_) .. _v4.5.0: v4.5.0 ====== Usability, bells and whistles ----------------------------- * "Stage Modified" was added to the available toolbar actions. (`#1371 `_) * "Stage Untracked" no longer stages modified files when the list of untracked files to stage is empty. (`#1371 `_) * `Ctrl + Space` can now be used to display the autocomplete options in input fields that provide autocompletion. * The Diff widget now displays the currently selected filename. Uncheck the "Show filenames" option in the Diff widget's tool menu to disable this feature. (`#1367 `_) * The "Fetch", "Push" and "Pull" dialogs now have an embedded progress bar instead of displaying a progress bar in a separate popup window. * The "Fetch", "Push" and "Pull" dialogs will now stay open after the remote operation completes when the "Close on completion" checkbox is unchecked. These dialogs closed themselves unconditionally before this change. Fixes ----- * PyQt6 compatibility for the "Find in diff" feature. * PyQt6 compatibility for the ``git dag`` Gravatar icons. Translations ------------ * Updated Polish translation. (`#1368 `_) Packaging and Dependencies -------------------------- * The vendored `qtpy` library was updated to `v2.4.1`. * The documentation no longer depends on `jaraco.packaging`. Development ----------- * upload-artifact and setup-python github actions were upgraded. .. _v4.4.1: v4.4.1 ====== Usability, bells and whistles ----------------------------- * The remote messages dialog is now displayed for the Pull and Push actions in the Branches widget only. This dialog is disabled by default and enabled in the main Push and Pull dialog settings. (`#1363 `_) * The whole-file staging actions in the Diff widget's right-click menu are now listed after the selection and hunk staging actions. This helps prevent accidental clicks from clobbering the index for the entire file. (`#1362 `_) * The completion popup no longer reappears after an item is selected in the "Checkout Branch" action and similar dialogs. (`#1360 `_) Fixes ----- * PyQt6 compatibility was improved. .. _v4.4.0: v4.4.0 ====== Usability, bells and whistles ----------------------------- * Git Cola now preserves `# commentary` in commit messages by default. The `commit.cleanup` Git configuration variable can be used to customize this behavior. For example, if you want Git Cola to strip comments (the old behavior before v4.4.0) then you can run `git config --global commit.cleanup strip` or configure the "Commit Message Cleanup" setting in the Preferences window. (`#1330 `_) * `git dag` now includes completions for `git log` options in the text input field. * `git dag` now provides convenient search filters when right-clicking in the text input field. * A `1.25 x` Hi-DPI magnification option mode is now available in the Appearance settings. (`#1313 `_) * MacOS-specific application themes are now available in the Appearance settings when the pyobjc module is installed. (`#905 `_) * Git Cola now runs `git commit` in the background and feedback is provided while the commit is running. This prevents the UI from freezing when running pre-commit hooks that can make `git commit` take a long time to run. (`#1320 `_) * The Diff context menu was reworked to reduce visual clutter and better match the Status context menu. (`#1347 `_) * The standalone `git cola tag` tool now autocompletes the tag name field. (`#706 `_) (`#691 `_) * The "Branches" dock widget now has a "Visualize" right-click menu option. (`#1061 `_) * The "Stash" dialog learned to rename stashes. (`#558 `_) * The "Fetch", "Push" and "Pull" dialogs can now display remote messages from the server. (`#951 `_) Fixes ----- * `git dag` fixed how it was handling refspec arguments. (`#1334 `_) * `git dag` will now properly refresh itself when remote branches are updated. (`#1063 `_) * The `cola.inotify` feature no longer runs into issues when accessing WSL2 filesystems from Windows 11+. (`#1194 `_) Development ----------- * `cercis `_ is now being used to enforce Git Cola's python code style. We were previously disabling quote normalization when using `black`. Use of `cercis` allows us to enable quote normalization under its default single-quote settings. * The test suite now works on Windows. (`#1331 `_) (`#1332 `_) * Pre-commits hooks and code modernization. (`#1333 `_) * Compatibility with Sphinx 7.2.0 was added to the `sphinxtogithub` sphinx documentation plugin. (`#1336 `_) .. _v4.3.2: v4.3.2 ====== Usability, bells and whistles ----------------------------- * The minimum font size can now be set lower, which is helpful for Hi-DPI displays. (`#1342 `_) Fixes ----- * Flashing windows during startup on Windows has been fixed. (`#1329 `_) * `git dag` was not displaying history when refspecs were specified. (`#1334 `_) Development ----------- * Compatibility with Sphinx 7.2.0 was added to the `sphinxtogithub` sphinx documentation plugin. (`#1336 `_) .. _v4.3.1: v4.3.1 ====== Fixes ----- * The pypi wheel was fixed to include `entry_points.txt`. * The "Revert" command was throwing an exception after successfully completing. .. _v4.3.0: v4.3.0 ====== Usability, bells and whistles ----------------------------- * `git dag` now displays commit metadata more similarly to `git log`. The commit date is now displayed and the subject field is displayed directly above the extended description. * `git dag` now supports a `cola.logdate` configuration for controlling the date format. The configured value is passed to `git log --date=`. (`#1319 `_) (`#1312 `_) * The default `patches` directory that is used when exporting patches is now configurable using the `cola.patchesdirectory` configuration variable and the Preferences dialog. * The Diff Editor can now export the diff selection, or the current diff hunk, to a `*.patch` file from the `Patches` context menu action. * Existing patches can be appended to by choosing a patch file from the `Append Patch` sub-menu in the `Patches` context menu action. * Patches can now be applied by dragging and dropping patches files from a file browser onto the diff editor. The "Apply Patches" dialog is launched with the drag-and-dropped patch files. * Shell completions for zsh are now provided in the source distribution. See the `contrib/_git-cola` zsh completion file for more details Fixes ----- * ``QApplication::desktop()`` is no longer available on PyQt6. Git Cola no longer relies on this method. Packaging --------- * Git Cola can now be installed on Windows using `winget`. See the ``README.md`` file for more details. (`#1318 `_) .. _v4.2.1: v4.2.1 ====== Fixes ----- * Diffs for repositories with a single commit have been fixed. (`#1306 `_) * The toolbars follow the Qt toolbar style, as they did prior to `v4.2.0`. (`#1307 `_) * The "Checkout Branch" dialog was fixed to display all completions when first shown. (`#1308 `_) .. _v4.2.0: v4.2.0 ====== Usability, bells and whistles ----------------------------- * The Diff Editor can now send diffs to your favorite editor before the diffs are applied. The right-click "Edit Diff ..." menu actions and the `Ctrl + Shift + S` / `Ctrl + Shift + U` hotkeys send the current diff hunk, or the selected diff, to your editor before they are applied to the worktree / staging area. (`#1290 `_) (`#794 `_) * The Diff Editor and DAG viewer can now search within their diffs using `Ctrl + F` and `Ctrl + G` hotkeys. (`#1116 `_) * A new *Diff Mode* can be used to diff and unstage edits relative to any commit. (`#816 `_) * The Commit Message Editor can now spell-check the summary field. Previously only the "Extended Description..." field supported spell checking. (`#633 `_) (`#1070 `_) * Repositories in your "Recents" and "Favorites" can now be searched using the new "Search" tool button. Quickly switch between these repositories using the `Alt + P` hotkey and "Quick Open..." File menu action. (`#1282 `_) * "Favorites", "Recents" and the startup dialog now display a case-insensitively sorted list of repositories. (`#1047 `_) * The startup dialog now has a right-click context menu that allows you to prune stale entries and other actions that were not previously accessible from the startup dialog. (`#1199 `_) (`#1280 `_) * The "Copy Leading Paths" action in the Status tool's right-click "Copy" sub-menu can now strip off an arbitrary number of leading paths. (`#784 `_) * The "Cherry-Pick" action now reports errors when "git cherry-pick" fails. A new "Abort Cherry-Pick" action has been added for aborting a failed cherry-pick. (`#1062 `_) * The diff text can now be quickly zoomed using `Ctrl + Mouse wheel` scroll. This will quickly change the text size within the current session only. (`#1029 `_) * The Console and Diff widgets learned to open URLs. Right-click on a line that contains http URLs and context-menu actions for opening each URL using your default web browser will be displayed. (`#1139 `_) * Drag-and-drop has been improved when dragging filenames from the Status tool. Dragging multiple files requires special handling to improve usability. Some terminals (such as `kitty`) consume multiple file URLs by separating paths with newlines. This is useful when you'd like to capture raw filenames but is less convenient when dropping filenames onto a command-line. Drag with the `Alt`-modifier held down to drag-and-drop filenames for command-line use. Using the `Alt` modifier omits URLs so that the drag-and-drop payload includes only space-delimited, shell-quoted paths. (`#719 `_) * The DAG viewer now displays the diff between the start and end commits when multiple commits are selected. The diffs are displayed in the DAG's diff viewer. (`#552 `_) * The DAG viewer learned to checkout branches and initiate rebases from its right-click menu. (`#1113 `_) * The DAG diff viewer learned to word-wrap the diff text. (`#1242 `_) * The spelling dictionaries are now discovered dynamically at runtime. `dict/words` and `dict/propernames` are now discovered via `$XDG_DATA_DIRS` by the spell checker. This allows a spelling dictionary to be placed in e.g.. `~/.local/share/dict/words` to override the default `/usr/share/dict/words`. (`#873 `_) * The File menu now has a "Patches" sub-menu with a full set of "git am" Patch actions. * The Diff Editor and various Diff widgets now have a "Copy Diff" action with an `Alt + Shift + C` hotkey that copies the selected diff text to the clipboard with the `+`, `-` and `` diff prefix characters removed. (`#1288 `_) * The "Revert" action for reverting commits from the DAG tool now displays error messages when ``git revert`` fails. (`#885 `_) * The Diff Editor now uses an easier-to-see *block cursor* by default. Disable `cola.blockcursor `_ to continue using original *line cursor* by running ``git config --global cola.blockcursor false``, or by editing the settings in the menu. * The "Unmerged" header item in the Status tool now displays a summary list of unmerged files. * The hotkeys documentation has been updated to clarify that the "Copy Commit ID" action is available in several tools. (`#779 `_) * Saving files when using "Browse Other Branch" now displays errors from ``git show`` when saving files from arbitrary commits. (`#1065 `_) * The Apply Patches dialog now reports errors when patches fail to apply. (`#673 `_) * The "Status" tool now disables "Copy" actions in its context menu when no files have been selected. (`#697 `_) * The "Unstage" menu item in the Status tool now uses a "Remove" icon. (`#1289 `_) Development ----------- * The vendored `qtpy` module was modified to sever its dependency on the `packaging.version` module. This mostly affects users that want to run Git Cola directly from the source tree outside of any virtualenv. (`#1286 `_) .. _v4.1.0: v4.1.0 ====== Usability, bells and whistles ----------------------------- * The rebase editor was taught to handle stacked branch workflows enabled by ``git rebase --update-refs``. The ``git cola rebase`` sub-command now has an ``--update-refs`` option and the menu actions display a prompt that allows you to enable the updating of stacked branches. (`#1261 `_) (`#571 `_) * The status widget now respects `diff.ignoreSubmodules`. (`#1269 `_) Packaging and Dependencies -------------------------- * PyQt6 is now officially supported. (`#1211 `_) (`#1273 `_) * The vendored `qtpy` library was updated to `v2.3.0`. Development ----------- * Fixes and updates to Git Cola's CI actions. (`#1278 `_) (`#1277 `_) .. _v4.0.4: v4.0.4 ====== Fixes ----- * The "T" hotkey for "Find Files" was removed to avoid issues in some configurations. (`#1270 `_) * Some context menus entries were corrected to better handle binary files. (`#1271 `_) .. _v4.0.3: v4.0.3 ====== Usability, bells and whistles ----------------------------- * The branches widget no longer loses its selection state in response to notifications and UI actions. (`#1221 `_) * The use of ``gravatar.com`` to fetch icons associated with author emails can now be disabled by setting `git config --global cola.gravatar false`. (`#933 `_) Fixes ----- * The config reader has been revamped to better read settings when git config files are located in unexpected locations. (`#927 `_) (`#1264 `_) * The preferences dialog no longer throws an error when the editor has not been configured. (`#1263 `_) * Context menu actions for staging files has been added when diffing images. (`#1265 `_) * The stash editor now properly displays stashes with slashes ("/") in their names or messages. (`#1267 `_) * The settings file is now written-to and read-from in a robust manner to avoid data loss when doing an ACPI shutdown or forced shutdown of a machine. (`#1241 `_) * Git Cola now displays an error message when attempting to open a repository that cannot be accessed due to the new `safe.directory` protections in Git v2.30.3. (`#1243 `_) Translations ------------ * The .po and .pot files now contain location information. (`#880 `_) .. _v4.0.2: v4.0.2 ====== Usability, bells and whistles ----------------------------- * The Rebase editor (`git-cola-sequence-editor`) now supports multi-select. Use `Shift-{Up,Down}` to select multiple lines and the keyboard hotkeys listed in the `?` dialog to drive the UI. (`#1257 `_) * The `$GIT_VISUAL` and `$VISUAL` environment variable are now consulted in addition to `$GIT_EDITOR` and `$EDITOR` when the `gui.editor` configuration is unset. (`#1237 `_) * The application window icon is now enabled when running on Wayland. (`#1240 `_) * The Status widget now has an "Open Worktree" action. (`#1245 `_) * The "Open Using Default Application", "Open Directory", "Open Parent Directory" and "Open Worktree" actions are now available on Windows. * The dialog for opening repositories is now a read-only dialog that omits the ability to create folders and modify the filesystem. (`#1168 `_) * A few more `git` calls have been eliminated from the startup sequence. This further improved the startup time for Git Cola. (`#1259 `_) Fixes ----- * Documentation rendering errors have been fixed. (`#1256 `_) * Use of a `~/.config/git-cola/language` file to override the language has been fixed. (`#1246 `_) * We no longer write the `cola.spellcheck` configuration value on launch. (`#1238 `_) Translations ------------ * Updated Spanish translation. (`#1244 `_) * Updated Japanese translation. (`#1249 `_) Packaging --------- * Building documentation offline is supported again. (`#1250 `_) * The Appstream Metadata files were missing in the v4.0.0 release are included again. (`#1254 `_) (`#1253 `_) .. _v4.0.1: v4.0.1 ====== Usability, bells and whistles ----------------------------- * Double-clicking dock widgets no longer creates sub-windows when the layout is locked. (`#1176 `_) (`#1198 `_) Fixes ----- * We now guard against `locale.getdefaultlocale()` returning `None` in some configurations, notably on macOS if none of 'LC_ALL', 'LC_CTYPE', 'LANG' or 'LANGUAGE' are defined. (`#1234 `_) * The preferences dialog has been fixed to properly handle booleans. (`#1235 `_) * The `docs/` directory was restructured to avoid missing `setup.py` errors. `share/doc/git-cola` is now a symlink pointing to `docs/`. (`#1230 `_) * Message boxes could sometimes display off-screen or using geometry that is larger than the current desktop. Message box sizes are now clamped to the desktop size. (`#1228 `_) .. _v4.0.0: v4.0.0 ====== Breaking Changes ---------------- These changes are primarily breaking changes for packagers of Git Cola. For example, Linux distribution and Homebrew package maintainers may need to be aware of these changes. Changes have been made build infrastructure and the resulting filesystem artifacts. * The build system is now Python3-only and has been modernized for PEP-517/518. While Git Cola still builds and runs under Python2, it is no longer officially supported and may stop working in a future release without notice. (`#1201 `_) * The `#!/usr/bin/env python` shebang lines in the `git-cola` and `git-dag` wrapper scripts have been updated to use `python3`. (`#1204 `_) * The build system was switched to `setuptools` and no longer depends on `distutils`. ``python setup.py {build,install,build_pot,build_mo}`` are no longer provided. Use the https://pypa-build.readthedocs.io/en/stable/installation.html ``python -m build`` tool to generate sdist and wheel distributions, and ``pip install .`` to install Git Cola from source. (`#1204 `_) * The `git-cola`, `git-dag` and `git-cola-sequence-editor` commands are now installed using setuptools entry points. * The `bin/` wrapper scripts in the source tree continue to be provided for convenience but they are not the scripts that get installed. * The `qtpy` Python package is no longer installed alongside the `cola` Python package. * The `cola` package is now installed into the standard Python site-packages location. * The `share/git-cola/lib` private Python modules directory no longer exists. * The `NO_VENDOR_LIBS` and `NO_PRIVATE_LIBS` Makefile options are no longer necessary. * The `share/git-cola` filesystem namespace no longer exists. All of cola's package data is distributed alongside the `cola` module as package data. * Building the Sphinx documentation now also requires the `jaraco.packaging` and `rst.linker` packages. See `setup.cfg` for the package requirement details. Usability, bells and whistles ----------------------------- * `Custom UI themes `_ can be used by adding `*.qss` Qt stylesheet files to `~/.config/git-cola/themes/`. (`#1222 `_) (`#1226 `_) * Git Cola now keeps track of child Browser windows and will close all of them when the main window is closed. (`#1200 `_) Fixes ----- * Staging conflicted binary files has been fixed to avoid Unicode decoding errors. (`#1189 `_) * Ensure that secure permissions are used when creating temporary files. (`#1209 `_) * The line numbering in the diff viewer was corrected when displaying merge diffs. (`#1208 `_) * Documentation typo fixes. (`#1193 `_) * Git Cola was revamped to use Qt signals and slots for all of its notifications. This made its notification system more robust. (`#1202 `_) (`#1203 `_) (`#1205 `_) (`#1206 `_) Packaging --------- * `vcruntime140.dll` and `msvcp140.dll` are now included in the Windows installation. (`#1207 `_) .. _v3.12.0: v3.12.0 ======= Usability, bells and whistles ----------------------------- * The git config guitool action can now be grouped under user-defined menus. This is done by using slash (``/``) delimiters in the action name. Entries before the final slash are treated like sub-menus inside the top-level ``Actions`` menu. (`#1150 `_) * Toolbars now have a full set of icons. The icons follow the system theme and can be configured to display text, just icons, or text and icons. (`#1177 `_) * The startup dialog will now open the selected repository when the "enter" key is pressed. (`#1162 `_) * ``Shift+S`` will stage selected lines (in addition to ``s``). (`#1187 `_) Fixes ----- * The vendored qtpy library was patched to retain Python2 compatibility. * The "Unstage" toolbar action was fixed. (`#1178 `_) * We now avoid `QWidget::setWidth(float)` for compatibility with newer Qt versions. (`#1183 `_) * Documentation typo fixes. (`#1185 `_) Translations ------------ * Updated Polish translation. (`#1184 `_) Development ----------- * Git Cola now uses Github Actions for running its continuous integration tests. (`#1179 `_) .. _v3.11.0: v3.11.0 ======= Usability, bells and whistles ----------------------------- * The Status tool was improved to better retain selected files when the state changes and the display is refreshed. (`#1130 `_) (`#1131 `_) * The Diff editor can now stage selected lines for untracked files. Git Cola will detect when a file is untracked and will allow you to partially stage it, just like existing tracked files. (`#1146 `_) (`#1084 `_) * Diffing of staged files has been implemented for repositories that contain no commits. (`#1149 `_) (`#1110 `_) * Documentation improvements and typo fixes. (`#1163 `_) (`#1164 `_) Security -------- * The `FIPS security mode `_ is now supported by Git Cola when running on FIPS-enabled Python (Python 3.9+ or centos8/rhel8's patched Python 3.6). (`#1157 `_) Fixes ----- * The `argparse` usage was adjusted to remain compatible with older Pythons. (`#1155 `_) * The window restoration logic was fixed to properly save/restore settings when different languages are used. (`#1071 `_) (`#1161 `_) (`#382 `_) * `git dag` no longer passes floats to `QPen::setWidth()` for better compatibility. (`bz #2014950 `_) Packaging --------- * The Windows installer was slimmed down by removing unused Qt DLLs. (`#1152 `_) .. _v3.10.1: v3.10.1 ======= Fixes ----- * Patch release to fix a typo in the Interactive Rebase feature. .. _v3.10: v3.10 ===== Usability, bells and whistles ----------------------------- * The git config reader now supports the `include.path` directive for including config files. (`#1136 `_) (`#1137 `_) * The dialog for selecting commits now support filtering. (`#1121 `_) * The diff editor now wraps long lines by default. The diff options menu can be used to enable/disable line wrapping. (`#1123 `_) * Git Cola now honors `core.hooksPath` for configuring custom Git hooks, which was introduced in Git v2.9. (`#1118 `_) * A new `Ctrl + Shift + S` hotkey was added for staging/unstaging all files, both modified and untracked. * The `Status` tool now supports `Ctrl + A` for selecting all files and it behaves more predictably when performing operations when multiple categories of files are selected (e.g. when both modified and untracked header items are selected). (`#1117 `_) Translations ------------ * Updated Hungarian translation. (`#1135 `_) Fixes ----- * The "Interactive Rebase" feature was updated to work with Windows. * `make install-man` was updated to support Sphinx 4.0. (`#1141 `_) * `git cola --help-commands` was updated for newer versions of argparse. (`#1133 `_) Development ----------- * Git Cola can now be started as a Python module. (`#1119 `_) .. _v3.9: v3.9 ==== Usability, bells and whistles ----------------------------- * The startup dialog now detects when Recent and Favorite repositories no longer exist on disk, and offers to remove these entries when selected. (`#1089 `_) * The startup dialog now includes a simpler and more condensed folder view that can be used for selecting Favorites and Recent repositories. (`#1086 `_) * The "Commit" menu now includes an "Undo Last Commit" action. (`#890 `_) * The "Reset" menu was revamped to expose all of Git's reset modes alongside a new "Restore Worktree" action that updates the worktree using "git read-tree". (`#890 `_) Translations ------------ * Updated Polish translation. (`#1107 `_) * Updated Japanese translation. (`#1098 `_) * Updated Brazilian translation. (`#1091 `_) Packaging --------- * The ``--use-env-python`` option for ``setup.py`` is now Python3 compatible. (`#1102 `_) .. _v3.8: v3.8 ==== Usability, bells and whistles ----------------------------- * The submodules widget can now be used to add submodules. Submodules are now updated recursively. (`#534 `_) * The image diff viewer can now be toggled between text and image modes. This is helpful when, for example, diffing .svg files where it can be useful to see diffs in both an image and text representation. (`#859 `_) (`#1035 `_) * The default `ssh-askpass` username + password dialog included with Git Cola can now toggle between showing and masking the password input field. (`#1069 `_) Translations ------------ * Updated Polish translation. (`#1076 `_) * Updated Hungarian translation. (`#1067 `_) Packaging --------- * The `share/appdata` AppStream data was renamed to `share/metainfo` in accordance with `AppStream standard changes from 2016 `_. (`#1079 `_) * The ``cola`` modules are now installed into the Python ``site-packages`` directory by default. This allows distributions to package ``git-cola`` for multiple versions of Python. See the PACKAGING NOTES section in the README for details about suppressing the installation of the private ``share/git-cola/lib/cola`` modules when building cola. (`#181 `_) * Git Cola's rebase / sequence editor, formerly known as ``git-xbase`` and installed as ``share/git-cola/bin/git-xbase``, has been renamed to ``git-cola-sequence-editor`` and is now installed into the default ``bin/git-cola-sequence-editor`` executable location to enable external reuse of this general-purpose tool. * A workaround used by the pynsist installer preamble script was obsoleted by `takluyver/pynsist#149 `_ and has now been removed. (`#1073 `_) Fixes ----- * `git dag` now uses integer widths when initializing its brushes. (`#1080 `_) .. _v3.7: v3.7 ==== Usability, bells and whistles ----------------------------- * The ``git-xbase`` rebase editor now includes a file list for filtering the changes displayed in the diff view. (`#1051 `_) * The fallback `ssh-askpass` script, which provides the Username/Password login dialog when performing remote operations, previously presented both the username and password input fields with ``***`` asterisks. The dialog now uses asterisks for the password field only. (`#1026 `_) * Stashes can now be applied using the `Ctrl + Enter` hotkey, popped with the `Ctrl + Backspace` hotkey, and dropped with the `Ctrl + Shift + Backspace` hotkey when inside the stash dialog. This enables a keyboard-centric mouse-free workflow when using the stash dialog. * When amending a commit, `git cola` will check whether the commit has been published to a remote branch using ``git branch -r --contains HEAD``. This command can be slow when operating on a repository with many remote branches. The new `cola.checkpublishedcommits` configuration variable allows you to opt-out of this check, which improves performance when amending a commit. The settings widget exposes this variable as, "Check Published Commits when Amending". (`#1021 `_) (`#1027 `_) Translations ------------ * Updated Polish translation. (`#1033 `_) Fixes ----- * ``git-dag.appdata.xml`` was updated to allow network access for author icons. (`#1050 `_) * The inotify filesystem monitor now handles `OSError: [Errno 24] Too many open files` errors by disabling inotify. (`#1015 `_) * Typos in various documentation files have been fixed. (`#1025 `_) * The "Recent Repositories" limit was off by one, and now correctly remembers the configured number of repositories in the menu. (`#1024 `_) * The "revert" action in the DAG and other tools now uses ``git revert --no-edit``, which avoids launching an editor when reverting the commit. Use `Ctrl+m` in the commit message editor after reverting a commit to rewrite its commit message. (`#1020 `_) .. _v3.6: v3.6 ==== Usability, bells and whistles ----------------------------- * The remote editor is much faster since it no longer queries remotes, and uses the cached information instead. (`#986 `_) * Commit message templates can now be loaded automatically by setting ``git config cola.autoloadcommittemplate true``. (`#1013 `_) (`#735 `_) * The UI layout can now be reset back to its initial state by selecting the "Reset Layout" action. This reverts the layout to the same state as when the app first launched. (`#1008 `_) (`#994 `_) * Files can now be ignored in either the project's `.gitignore`, or in the repository's private local `.git/info/exclude` ignore file. (`#1006 `_) (`#1000 `_) * New remotes are now selected when they are added in the "Edit Remotes" tool. (`#1002 `_) * The "Recent" repositories list is now saved to disk when opening a repository. Previously, this list was only updated when exiting the app. (`#1001 `_) * The bookmarks tool now has a "Delete" option in its right-click menu. (`#999 `_) * The current repository is no longer listed in the "File/Open Recent" menu. (`#998 `_) Translations ------------ * Updated Hungarian translation. (`#1005 `_) (`#1018 `_) * Updated Turkish translation. (`#1003 `_) (`#1011 `_) Fixes ----- * Better support for Python 3.8's line buffering modes. (`#1014 `_) * The default `ssh-askpass` script now uses a more generic `#!` shebang line. (`#1012 `_) * Fetch, push, and pull operations will now refresh the model and display when operations complete. (`#996 `_) * The branches widget now refreshes its display when changing branches. (`#992 `_) Packaging --------- * The `share/git-cola/bin/git-xbase` script will now have its `#!` lines updated during installation. (`#991 `_) Development ----------- * The unit tests were made more platform-independent. (`#993 `_) .. _v3.5: v3.5 ==== Usability, bells and whistles ----------------------------- * Auto-completion for filenames can now be disabled. This speeds up revision completion when working in large repositories with many files. (`#981 `_) * The Stash dialog now shows the stash date as a tooltip when hovering over a stashed change. (`#982 `_) * Qt HiDPI settings are overridden by the `git cola` HiDPI appearance settings. These overrides can now be disabled by selecting the "Disable" mode. This allows users to control the Qt HiDPI settings through environment variables. Additionally, the "Auto" mode now detects the presence of the Qt HiDPI variables and no longer overrides them when the user has configured their environment explicitly. (`#963 `_) * Confirmation dialogs can now focus buttons using the Tab key. Previously, the "Y" and "N" keys could be used to confirm or deny using the keyboard, but "Tab" is more familiar. (`#965 `_) * Error dialogs (for example, when a commit hook fails) will now always show the details. The details were previously hidden behind a toggle. (`#968 `_) Translations ------------ * Updated Japanese translation. (`#973 `_) (`#974 `_) * Updated Simplified Chinese translation. (`#950 `_) Fixes ----- * The filesystem monitor no longer logs that it has been enabled after the inotify watch limit is reached on Linux. (`#984 `_) * Better Unicode robustness. (`#990 `_) (`#910 `_) * The "Branches" widget did not always update itself when deleting branches (for example, when inotify is disabled or unavailable). (`#978 `_) * Non-ASCII Unicode byte strings are more robustly handled by the log widget. (`#977 `_) * Non-Unicode results from the `gettext` library are more robustly handled. (`#969 `_) * Launching `git cola` from within a directory that has since been deleted would previously result in an error, and is now robustly handled. (`#961 `_) Packaging --------- * The vendored `qtpy` library was updated to `v1.9`. .. _v3.4: v3.4 ==== Usability, bells and whistles ----------------------------- * The file browser now includes "Blame" in its context menu. (`#953 `_) * The "Push" action now uses "git push --force-with-lease" when using the "Force" option with Git v1.8.5 and newer. (`#946 `_) * Updated German translation. (`#936 `_) * The `Status` widget learned to optionally display file counts in its category headers, and indent the files displayed in each category. (`#931 `_) * The `Branches` widget can now sort branches by their most recent commit. (`#930 `_) * `git cola` now includes configurable GUI themes that can be used to style the user interface. Enable the new themes by configuring `cola.theme` in the preferences window. See the `cola.theme documentation `_ for more details. (`#924 `_) * `git cola` now has built-in support for HiDPI displays by enabling the Qt 5.6 `QT_AUTO_SCREEN_SCALE_FACTOR` feature. (`#938 `_) * `git cola` now uses HiDPI pixmaps when rendering icons, and the builtin icons have been updated to look sharp when displayed in HiDPI. (`#932 `_) Fixes ----- * `git cola`'s "Revert Unstaged Edits" previously checked out from "HEAD^", when in "Amend" mode, and removing staged changes. This behavior has been changed to always checkout from the index, which avoids data loss. (`#947 `_) * `git cola` has been updated to work with newer versions of `gnome-terminal` and no longer shell-quotes its arguments when launching `gnome-terminal`. The `cola.terminalshellquote` configuration variable can be set to `true` to get the old behavior, or to handle other terminals that take the command to run as a single string instead of as arguments to `execv()`. (`#935 `_) * `git dag` now properly handles arbitrary input on Python3. Previously, an exception would be raised when entering `--grep=xxx` where `xxx` is a quoted string with a missing end-quote. (`#941 `_) Development ----------- * The contribution guidelines for contributors has been updated to mention how to regenerate the `*.mo` message files. (`#934 `_) .. _v3.3: v3.3 ==== Usability, bells and whistles ----------------------------- * `git dag` improved how it renders parent commits. (`#921 `_) * The `Branches` widget now checks out branches when double-clicked. (`#920 `_) * The new `Submodules` widget makes it easy to interact with submodules. Additionally, submodules can now be updated using the `Status` widget. (`#916 `_) * Updated Japanese translation. (`#914 `_) * The "Open Terminal" action now launches a Git Bash shell on Windows. (`#913 `_) * New menu actions for updating all submodules. (`#911 `_) * The status widget can now update submodules. (`#911 `_) * The "Apply Patch" `git cola am` dialog now includes a diff viewer to display the contents of the selected patch. * The "Alt+D" diffstat hotkey now selects the staged/modified/etc. header in the Status widget, which shows the totality of everything that will be committed. (`#771 `_) * Running "Launch Editor" from the diff editor now opens the editor at the current line. (`#898 `_) * The textwidth and tabwidth configuration values can now be set per-repository, rather than globally only. * Text entry widgets switched to using a block cursor in `v3.2`. This has been reverted to the original line cursor for consistency with other applications and user expectations. (`#889 `_) * The "edit at line" feature, used by the "Grep" tool, now supports the Sublime text editor. (`#894 `_) Fixes ----- * Launching external programs has been improved on Windows. (`#925 `_) * Improve compatibility when using PySide2. (`#912 `_) * The Diff Editor was not honoring the configured tab width on startup. (`#900 `_) * The "Delete Files" feature was creating an unreadable display when many files were selected. Word-wrap the list of files so that the display stays within a sensible size. (`#895 `_) * Spelling and grammar fixes. (`#915 `_) (`#891 `_) Development ----------- * The logo was run through `tidy` to give it a consistent style. Some technical issues with the logo were improved. (`#877 `_) * The entire codebase is now checked by `flake8`, rather than just the module and test directories. This catches things like the pynsist installer scripts. (`#884 `_) (`#882 `_) (`#879 `_) Packaging --------- * The vendored `qtpy` library was updated to `v1.6`. * The Windows installer's wrapper scripts were missing an import. (`#878 `_) .. _v3.2: v3.2 ==== Usability, bells and whistles ----------------------------- * The `git cola dag` DAG window now supports `git revert`. (`#843 `_) * `git stash pop` is now supported by the stash dialog. (`#844 `_) * The status widget now ensures that each item is visible when selection changes. Previously, if you scrolled to the right to see the name of a long filename, and then selected a short filename above it, the widget may not have shown the short filename in the viewport. We now ensure that the filenames are visible when the selection changes. (`#828 `_) * The `git xbase` rebase editor no longer displays an error when cancelling an interactive rebase. (`#814 `_) * The dialog shown when renaming remotes has been simplified. (`#840 `_) (`#838 `_) * The help dialog in the `git-xbase` Rebase editor is now scrollable. (`#855 `_) Translations ------------ * Updated Brazilian translation. (`#845 `_) * Updated Czech translation. (`#854 `_) (`#853 `_) (`#835 `_) (`#813 `_) * Update Spanish translation. (`#862 `_) (`#867 `_) Packaging --------- * The original `#!/usr/bin/env python` shebang lines can now be retained by passing `USE_ENV_PYTHON=1` to `make` when installing. (`#850 `_) * The Makefile is now resilient to DESTDIR and prefix containing whitespace. (`#858 `_) * The vendored `qtpy` library was updated to `v1.4.2`. * `python3-distutils` is needed to build cola on Debian. (`#837 `_) Fixes ----- * The "C" key no longer closes the message dialogs, for example the one that is shown when a commit fails its pre-commit hooks. This allows "Ctrl+C" copy to work, rather than closing the dialog. (`#734 `_) * Dock widgets sizes are now properly saved and restored when the main window is maximized. (`#848 `_) * The spellcheck feature was broken under Python3. (`#857 `_) * A regression when saving stashes was fixed. (`#847 `_) * Diffing image files was not updating the available context menus, which prevented the "Stage" action from being present in the menu. (`#841 `_) * `git cola` now detects when `git lfs uninstall` has been run. This allows you to re-initialize "Git LFS" in an existing repository where it had been previously uninstalled. (`#842 `_) * Custom color values that did not contain any hexadecimal digits in the `a-f` range were being converted into integers by the config reader. This then caused the configured colors to be ignored. These color values are now interpreted correctly. Additionally, color values can now use an optional HTML-like `#` prefix. Example `.gitconfig` snippet:: [cola "color"] text = "#0a0303" (`#836 `_) (`#849 `_) * We now display an error message graphically when `Git` is not installed. Previously, the message went to stderr only. (`#830 `_) * Changing diff options was causing resulting in an exception. (`#833 `_) (`#834 `_) * The DAG window now updates itself when branches and tags are created. (`#814 `_) * The user's `$PATH` environment variable can now contain UTF-8 encoded paths. Previously, launching external commands could lead to errors. (`#807 `_) * Git Cola development sandboxes can now be stored on UTF-8 encoded filesystem paths. Previously, the interactive rebase feature could be broken when running in that environment. (`#825 `_) * The log window now uses an ISO-8601 time stamp, which avoids localized output in the log window. (`#817 `_) Development ----------- * The code base has been thoroughly sanitized using `pylint`, and Travis is now running pylint over the entire project. * Miscellaneous improvements and code improvements. (`#874 `_) .. _v3.1: v3.1 ==== Usability, bells and whistles ----------------------------- * The "Browser" widget learned to rename files using "git mv". (`#239 `_) * The "Diff" widget learned to diff images. Side-by-side and pixel diff modes allow you to inspect changes to common images formats. (`#444 `_) (`#803 `_) * Git LFS and Git Annex are natively supported by the image diff viewer. * Git Annex operations are now included. `git annex init` can be performed on repositories, and `git annex add` can be run on untracked files from the status widget. Install `git-annex` to activate this feature. * Git LFS operations are now included. `git lfs install` can be performed on repositories, and `git lfs track` can be run on untracked files from the status widget. Install `git-lfs` to activate this feature. * The "Stash" tool learned to stash staged changes only. Select the "Stage Index" option and only staged changes will be stashed away. (`#413 `_) * The "Stash" tool learned to use vim-like navigation keyboard shortcuts, shows error messages when things go wrong, and now saves the "Stash Index" and "Keep Index" options across sessions. * The Edit menu's "Copy" and "Select All" actions now forward to either the diff, status, recent, or favorites widgets, based on which widget has focus. * The "File" and "Edit" menu can now be activated using `Alt + {F,E}` hotkeys. (`#759 `_) * It was easy to accidentally trigger the first action in the `Status` tool's context menu when using a quick right-click to bring up the menu. A short sub-second delay was added to ensure that the top-most action is not triggered unless enough time has passed. This prevents accidental activation of the first item (typically "Stage" or "Unstage") without burdening common use cases. (`#755 `_) (`#643 `_) * The "Ctrl+S" hotkey now works for the header items in the Status tool. Selected the "Modified" header item and activating the "Stage" hotkey, for example, will stage all modified files. This works for the "Staged", "Modified", and "Untracked" headers. This is not enabled for the "Unmerged" header by design. (`#772 `_) * The list of "Recent" repositories previously capped the number of repositories shown to 8 repositories. This can be set to a higher value by setting the `cola.maxrecent` configuration variable. (`#752 `_) * The "Create Branch" dialog now prevents invalid branch names. (`#765 `_) * Updated Turkish translation. (`#756 `_) * Updated Ukrainian translation. (`#753 `_) * Updated German translation. (`#802 `_) * Updated Czech translation (`#792 `_) (`#806 `_) * The window title can be configured to not display the absolute path of the repository. (`#775 `_) * The "Edit Remotes" editor learned to edit remote URLS. * Bare repositories can now be created by selecting the "New Bare Repository..." action from the `File` menu. * The "Branches" widget learned to configure upstream branches. * A new `git cola clone` sub-command was added for cloning repositories. Packaging --------- * The vendored `qtpy` library was updated to `v1.3.1`. * The macOS installation was made simpler for better compatibility with Homebrew. (`#636 `_) * The Windows installer is now much simpler. Git Cola now bundles Python and PyQt5, so users need only install the "Git for Windows" and "Git Cola" installers to get things working. Fixes ----- * Uninitialized difftool errors will now be displayed graphically. They were previously going to the shell. (`#457 `_) * Translations marked "fuzzy" will no longer be used when translating strings. (`#782 `_) * Deleted unmerged files will now correctly use a deleted icon. (`#479 `_) * The `Ctrl+C` "Copy" hotkey on the diff viewer has been fixed. (`#767 `_) * The "Create Tag" dialog did not correctly handle the case when a signed tag is requested, but no message is provided, and the user chooses to create a non-annotated tag instead. This convenience fallback will now properly create an unsigned, non-annotated tag. (`#696 `_) * `.gitconfig` and `.git/config` values editable by the Preferences dialog (aka `git cola config`) will now get unset when set to an empty value. For example, setting a different `user.email` in the current repository, followed by a subsequent emptying of that field, would previously result in an empty string getting stored in the config. This has been fixed so that the value will now get unset in the config instead. (`#406 `_) * Spelling and typo fixes. (`#748 `_) * `core.commentChar` is now honored when set in the local repository `.git/config`. (`#766 `_) * The log window was using a format string that did not display correctly in all locales. A locale-aware format is now used. (`#800 `_) * The dialog displayed when prompting for a reference could sometimes lose focus. (`#804 `_) .. _v3.0: v3.0 ==== Usability, bells and whistles ----------------------------- * Updated Simplified Chinese translation. (`#726 `_) * Updated Ukrainian translation. (`#723 `_) * New Czech translation. (`#736 `_) (`#737 `_) (`#740 `_) (`#743 `_) * The "name" field in the "Create Tag" dialog now includes autocompletion, which makes it easy to see which tags currently exist. * `git cola` now has configurable toolbars. Use the `View -> Add toolbar` menu item to add a toolbar. * Setting `cola.expandtab` to `true` will now expand tabs into spaces in the commit message editor. The number of spaces to insert is determined by consulting `cola.tabwidth`, which defaults to `8`. * The "Copy SHA-1" hotkey is now `Alt + Ctrl + C`, to avoid clobbering the ability to copy text from the DAG window. (`#705 `_) * The "Prepare Commit Message" action can now be invoked via the `Ctrl+Shift+Return` shortcut. (`#707 `_) * The `Branches` pane now has a filter field that highlights branches whose names match the string entered into its text field. (`#713 `_) * Actions that are triggered in response to button presses were being triggered when the button was pressed, rather than when it was released, which was a usability flaw. All buttons now respond when clicked rather than when pressed. (`#715 `_) * The DAG window will now only refresh when object IDs change. Previously, the DAG would redraw itself in response to inotify events, such as filesystem operations, which was disruptive when inspecting a large diff in its diff viewer. The DAG will now only redraw when the object IDs corresponding to its query input changes. Furthermore, when redrawing, the scrollbar positions are retained to minimize disruption to the viewport contents. (`#620 `_) (`#724 `_) * The "About" dialog now includes the SHA-1 where Git Cola was built. (`#530 `_) * The "Status" widget now has "Copy Leading Path to Clipboard" and "Copy Basename to Clipboard" actions. (`#435 `_) (`#436 `_) * The "Status" widget now supports custom "Copy xxx to Clipboard" actions. (`#437 `_) * The main menu now has an "Edit" menu. (`#725 `_) * `git dag` learned to checkout commits into a detached HEAD state. (`#698 `_) * The `status` widget's context menus now omit actions selection-dependent actions when no file is selected. (`#731 `_) * The startup dialog now focuses the repository list so that repositories can be selected with the keyboard without mouse intervention. (`#741 `_) Fixes ----- * `git dag` now prevents nodes from overlapping in more situations. (`#689 `_) * Adding untracked Git submodule repo directories previously ran `git add submodule/` but we now call `git add submodule` without the trailing slash (`/`) to avoid staging files that belong to the submodule (which is possibly a `git` bug). By working around the buggy behavior we allow users to recover by issuing the appropriate `git submodule add` command to properly register the submodule. (`#681 `_) * We now avoid `git for-each-ref --sort=version:refname` on versions of `git` older than `v2.7.0`. Previously we only avoided it for versions older than `v2.0.0`, which was a mistake. (`#686 `_) * The error message displayed when `git` is not installed has been fixed. (`#686 `_) * Adding new remotes was silently broken. (`#684 `_) (`#685 `_) * The repo selection dialog had errors during startup when the `cola.refreshonfocus` feature was enabled, as reported on Ubuntu 16.04. (`#690 `_) * Restored support for PyQt 4.6 (Centos 6.8) (`#692 `_) * Switching repositories now resets the "Amend Mode" and other settings when switching. (`#710 `_) * `git rebase` error messages now displayed when rebasing fails or stops via the standalone `git cola rebase` front-end. (`#721 `_) * `git cola` learned to stage broken symlinks. (`#727 `_) * The "View History" feature in the `Browser` tool was fixed, and now disambiguates between refs and paths. (`#732 `_) * The diff editor now has better support for files with CRLF `\r\n` line endings. (`#730 `_) * `cola.inotify` in a repo-local config is now honored when `git cola` is launched from a desktop entry (`git cola --prompt`). (`#695 `_) .. _v2.11: v2.11 ===== Usability, bells and whistles ----------------------------- * New Ukrainian translation. (`#670 `_) (`#672 `_) * New and improved French translations. * The new `Branches` widget makes it easier to checkout, merge, push, and pull branches from a single interface. * `git cola` now includes a dark icon theme. The dark icon theme can be activated either by setting the `GIT_COLA_ICON_THEME` environment variable to `dark`, by configuring `cola.icontheme` to `dark`, or by specifying `--icon-theme=dark` on the command line. (`#638 `_) * Autocompletion was added to the `Fetch`, `Push`, and `Pull` dialogs. * The commit message editor now remembers the "Spellcheck" setting after exiting. (`#645 `_) * `git dag` now uses an improved algorithm for laying out the graph, which avoids collisions under certain graph configurations, and avoids overlapping tag with commits. (`#648 `_) (`#651 `_) (`#654 `_) (`#656 `_) (`#659 `_) * `git dag` now remembers its column sizes across sessions. (`#674 `_) * `Grep` now shows a preview of the selected file's content in a split window below the grep results. * `Grep` now includes line numbers in the preview pane's output. * `Edit Remotes` now remembers its window settings after exiting. * `Diff` now has an option to display line numbers in the editor. (`#136 `_) * `Amend Last Commit` can now be triggered via the `Commit` menu in addition to the commit message editor's options. (`#640 `_) * The `File Browser` tool was made much faster and can now operate on much larger repositories. (`#499 `_) * A new "turbo" mode was added that allows you to opt-out of operations that can slow `git cola` on large repositories. The turbo mode is enabled by configuring `git config cola.turbo true`. Turbo mode disables the background loading of Git commit messages and other details in the `File Browser` widget. * A new GitIgnore dialog allows adding custom gitignore patterns. (`#653 `_) * The spellchecker in `git cola` can now use an additional dictionary by configuring `cola.dictionary` to the path to a file containing a newline-separated list of words. (`#663 `_) * The stash, export patches, diff, and gitignore dialogs now remember their window sizes. * A new `git cola recent` sub-command was added for finding recently edited files. * The `Fetch` dialog now allows pruning remote branches. (`#639 `_) (`#680 `_) Fixes ----- * `git cola`'s spellchecker now supports the new `dict-common` filesystem layout, and prefers the `/usr/share/dict/cracklib-small` file over the `/usr/share/dict/words` provided on older distributions. This makes the spellchecker compatible with Arch, which does not provide a `words` symlink like Debian. (`#663 `_) * Properly handle the case where an existing file is untracked using the File Browser. * Fix a quirk where the "Create Branch" dialog sometimes required clicking twice on the radio buttons. (`#662 `_) * Fixed a focus issue to ensure that "Push", "Fetch", and "Pull" can be executed with the press of a single enter key after being shown. (`#661 `_) * Committing is now allowed in when resolving a merge results in no changes. This state was previously prevented by the commit message editor, which prevented users from resolving merges that result in no changes. (`#679 `_) * The filesystem monitor would sometimes emit backtraces when directories are modified. This has been fixed. (`bz #1438522 `_) * Absolute paths are now returned when querying for `.git`-relative paths from within a submodule, which uses `.git`-files. This fixes launching `git cola` from within a subdirectory of a submodule. (`#675 `_) .. _v2.10: v2.10 ===== Usability, bells and whistles ----------------------------- * `git cola` can now invoke the `.git/hooks/cola-prepare-commit-msg` hook to update the commit message. This hook takes the same parameters as Git's `prepare-commit-message` hook. The default path to this hook can be overridden by setting the `cola.prepareCommitMessageHook` configuration variable. (`Documentation `_) * `git cola diff` (and the corresponding `Diff` menu actions) can now launch difftool with the standard `Ctrl+D` hotkey. The `Ctrl+E` hotkey was also added for launching an editor. * Traditional Chinese (Taiwan) translation updates. Fixes ----- * `git cola` now works when installed in non-ASCII, UTF-8-encoded paths. (`#629 `_) * Styling issues that caused black backgrounds in various widgets when using PyQt5 on Mac OS X have been fixed. (`#624 `_) * The "Open Recent" menu action was broken and has been fixed. (`#634 `_) * Exiting `git cola` with a maximized main window would hang when reopened on Linux. (`#641 `_) Packaging --------- * `appdata.xml` files are now provided at `share/appdata/git-cola.xml` and `share/appdata/git-dag.xml` for use by the Linux software gallery. (`#627 `_) (`Appdata `_) .. _v2.9.1: v2.9.1 ====== Fixes ----- * The "Open Recent" menu was updated to new bookmarks format. (`#628 `_) .. _v2.9: v2.9 ==== Usability, bells and whistles ----------------------------- * New Polish translation thanks to Łukasz Wojniłowicz (`#598 `_) * The `Bypass Commit Hooks` feature now disables itself automatically when a new commit is created. The new behavior turns the option into a single-use flag, which helps prevent users from accidentally leaving it active longer than intended. (`#595 `_) * `git dag` learned to launch an external diff viewer on selected commits. The standard `Ctrl+D` shortcut can be used to view diffs. (`#468 `_) * `git dag` learned to launch directory diffs via `git difftool --dir-diff`. The `Ctrl+Shift+D` shortcut launches difftool in directory-diff mode. (`#468 `_) * Items in the "Favorites" list can now be renamed, which makes it easier to differentiate between several checkouts of the same repository. (`#599 `_) (`#601 `_) * The startup screen now includes a logo and `git cola` version information. (`#526 `_) * The `About` page was revamped to contain multiple tabs. A new tab was added that provides details about `git cola`''s dependencies. New tabs were also added for giving credit to `git cola`'s authors and translators. * The `About` page can now be accessed via `git cola about`. * The "Fast-forward only" and "No fast-forward" options supported by `git pull` are now accessible via `git cola pull`. * Doing a forced push no longer requires selecting the remote branch. (`#618 `_) * `git cola push` now has an option to suppress the prompt that is shown when pushing would create new remote branches. (`#605 `_) * `git dag` now shows commit messages in a more readable color. (`#574 `_) * `git cola browse` and the `status` widget learned to launch the OS-specified default action for a file. When used on directories via `git cola browse`, or when "Open Parent Directory" is used on files, the OS-specified file browser will typically be used. * `git cola browse` and the `status` widget learned to launch terminals. Fixes ----- * `git cola browse` was not updating when expanding items. (`#588 `_) * Typo fixes in comments, naming, and strings have been applied. (`#593 `_) * The inotify and win32 filesystem monitoring no longer refreshes when updates are made to ignored files. (`#517 `_) (`#516 `_) * The `Refresh` button on the actions panel no longer raises an exception when using PyQt5. (`#604 `_) * Fixed a typo in the inotify back-end that is triggered when files are removed. (`#607 `_) * Fixed a typo when recovering from a failed attempt to open a repository. (`#606 `_) * `git dag` now properly updates itself when launched from the menu bar. (`#613 `_) * If git-cola is invoked on Windows using `start pythonw git-cola`, a console window will briefly flash on the screen each time `git cola` invokes `git`. The console window is now suppressed. * We now avoid some problematic Popen flags on Windows which were breaking the `git rebase` feature on Windows. * The `Save` button in `git dag`'s "Grab File..." feature now properly prompts for a filename when saving files. (`#617 `_) Development ----------- * The `qtpy` symlink in the source tree has been removed to allow for easier development on Windows. (`#626 `_) .. _v2.8: v2.8 ==== Usability, bells and whistles ----------------------------- * `git cola push` learned to configure upstream branches. (`#563 `_) Fixes ----- * The diffstat view is now properly updated when notifications are received via inotify filesystem monitoring. (`#577 `_) * Python3 with PyQt5 had a bug that prevented `git cola` from starting. (`#589 `_) .. _v2.7: v2.7 ==== Fixes ----- * When repositories stored in non-ASCII, UTF-8-encoded filesystem paths were operated upon with `LC_ALL=C` set in the environment, Unicode errors would occur when using `python2`. `git cola` was made more robust and will now operate correctly within this environment. (`#581 `_) * Support for the `GIT_WORK_TREE` environment variable was fixed. (`#582 `_) Development ----------- * The `unittest.mock` module is now used instead of the original `mock` module when running the `git cola` test suite using Python3. (`#569 `_) Packaging --------- * `git cola` is now compatible with *PyQt5*, *PyQt4*, and *Pyside*. `git cola` previously supported *PyQt4* only, but will now use whichever library is available. Users are not required to upgrade at this time, but *PyQt5* support can be enabled anytime by making its python modules available. (`#232 `_) *NOTE*: We do not yet recommend using *PyQt5* because there are known exit-on-segfault bugs in *Qt5* that have not yet been addressed. `git cola` is sensitive to this bug and is known to crash on exit when using `git dag` or the interactive rebase feature on *PyQt5*. https://bugreports.qt.io/browse/QTBUG-52988 *PyQt4* is stable and there are no known issues when using it so we recommend using it until the Qt5 bugs have been resolved. * `git cola` now depends on *QtPy* and includes a bundled copy of the `qtpy` library. If you are packaging `git cola` and would prefer to use `qtpy` from your distribution instead of the built-in version then use `make NO_VENDOR_LIBS=1` when building `git cola`. This will prevent vendored libraries from being installed. .. _v2.6: v2.6 ==== Usability, bells and whistles ----------------------------- * A new "Reset" sub-menu provides access to running "git reset --mixed" when resetting branch heads and "git reset --merge" when resetting worktrees. (`#542 `_) * `git cola` now supports linked worktrees, i.e. worktrees created by `git worktree`. (`#554 `_) Fixes ----- * Diff highlighting is now robust to the user having diff.supressBlankEmpty=true in their git config. (`#541 `_) * The filesystem monitor now properly handles repositories that use `.git`-files, e.g. when using submodules. (`#545 `_) (`#546 `_) * Per-repository git configuration is now properly detected when launching `git cola` from an application launcher. (`#548 `_) * `git cola` now cleans up after itself immediately to avoid leaving behind empty `/tmp/git-cola-XXXXXX` directories when the user uses `Ctrl+C` to quit the app. (`#566 `_) Packaging --------- * It is now possible to install `git cola` to and from UTF-8-encoded filesystem paths. Previously, Python's stdlib would throw an encoding error during installation. We workaround the stdlib by forcing python2 to use UTF-8, thus fixing assumptions in the stdlib library code. (`#551 `_) .. _v2.5: v2.5 ==== Usability, bells and whistles ----------------------------- * The icon for untracked files was adjusted to better differentiate between files and the "Untracked" header. (`#509 `_) * Ctrl+O was added as a hotkey for opening repositories. (`#507 `_) * `git dag` now uses consistent edge colors across updates. (`#512 `_) * `git cola`'s Bookmarks widget can now be used to set a "Default Repository". Under the hood, we set the `cola.defaultrepo` configuration variable. The default repository is used whenever `git cola` is launched outside of a Git repository. When unset, or when set to a bogus value, `git cola` will prompt for a repository, as it previously did. (`#513 `_) * `git cola`'s Russian and Spanish translations were improved thanks to Vaiz and Zeioth. (`#514 `_) (`#515 `_) (`#523 `_) * `git cola` was translated to Turkish thanks to Barış ÇELİK. (`#520 `_) * The status view now supports launching `git gui blame`. It can be configured to use a different command by setting `cola.blameviewer`. (`#521 `_) * `git dag` now allows selecting non-contiguous ranges in the log widget. (`#468 `_) * Any font can now be chosen for the diff editor, not just mono-space fonts. (`#525 `_) Fixes ----- * `xfce4-terminal` and `gnome-terminal` are now supported when launching `git mergetool` to resolve merges. These terminals require that the command to execute is shell-quoted and passed as a single string argument to `-e` rather than as additional command line arguments. (`#524 `_) * Fixed a Unicode problem when formatting the error message that is shown when `gitk` is not installed. We now handle Unicode data in tracebacks generated by python itself. (`#528 `_) * The `New repository` feature was fixed. (`#533 `_) * We now use omit the extended description when creating "fixup!" commits, for consistency with the Git CLI. We now include only the one-line summary in the final commit message. (`#522 `_) .. _v2.4: v2.4 ==== Usability, bells and whistles ----------------------------- * The user interface is now HiDPI-capable. Git Cola now uses SVG icons, and its interface can be scaled by setting the `GIT_COLA_SCALE` environment variable. * `git dag` now supports the standard editor, difftool, and history hotkeys. It is now possible to invoke these actions from file widget's context menu and through the standard hotkeys. (`#473 `_) * The `Status` tool also learned about the history hotkey. Additionally, the `Alt + {J,K}` aliases are also supported in the `Status` tool for consistency with the other tools where the non-Alt hotkeys are not available. (`#488 `_) * The `File Browser` tool now has better default column sizes, and remembers its window size and placement. * The `File Browser` now supports the refresh hotkey, and has better behavior when refreshing. The selection is now retained, and new and removed files are found when refreshing. * A new `git-cola-completion.bash` completion script is provided in the `contrib/` directory. It must be used alongside Git's completion script. Source it from your `~/.bashrc` (or `~/.zshrc`, etc) after sourcing the `git-completion.bash` script and you will have command-line completion support for the `git cola` and `git dag` sub-commands. * The "checkout" dialog now offers completion for remote branches and other git refs. This makes it easier to checkout remote branches in a detached head state. Additionally, the checkout dialog also offers completion for remote branches that have not yet been checked out, which makes it easier to create a local tracking branch by just completing for that potential name. (`#390 `_) * The "create branch" and "create tag" dialogs now save and restore their window settings. * The "status" widget can now be configured to use a bold font with a darker background for the header items. (`#506 `_) * The "status" widget now remembers its horizontal scrollbar position across updates. This is helpful when working on projects with long paths. (`#494 `_) Fixes ----- * When using *Git for Windows*, a `git` window would appear when running *Windows 8*. We now pass additional flags to `subprocess.Popen` to prevent a `git` window from appearing. (`#477 `_) (`#486 `_) * Launching difftool with `.PY` in `$PATHEXT` on Windows was fixed. (`#492 `_) * Creating a local branch tracking a remote branch that contains slashes in its name is now properly handled. (`#496 `_) * The "Browse Other Branch" feature was broken by Python3, and is now fixed. (`#501 `_) * We now avoid `long` for better Python3 compatibility. (`#502 `_) * We now use Git's default merge message when merging branches. (`#508 `_) * Miscellaneous fixes (`#485 `_) Packaging --------- * git-cola's documentation no longer uses an inter-sphinx link mapping to docs.python.org. This fixes warnings when building RPMs using koji, where network access is prevented. https://bugzilla.redhat.com/show_bug.cgi?id=1231812 .. _v2.3: v2.3 ==== Usability, bells and whistles ----------------------------- * The Interactive Rebase feature now works on Windows! (`#463 `_) * The `diff` editor now understands vim-style `hjkl` navigation hotkeys. (`#476 `_) * `Alt + {J,K}` navigation hotkeys were added to allow changing to the next/previous file from the diff and commit editors. * The `Rename branch` menu action is now disabled in empty repositories. (`#475 `_) (`#459 `_) * `git cola` now checks unmerged files for conflict markers before staging them. This feature can be disabled in the preferences. (`#464 `_) * `git dag` now remembers which commits were selected when refreshing so that it can restore the selection afterwards. (`#480 `_) * "Launch Editor", "Launch Difftool", "Stage/Unstage", and "Move Up/Down" hotkeys now work when the commit message editor has focus. (`#453 `_) * The diff editor now supports the `Ctrl+u` hotkey for reverting diff hunks and selected lines. * The `core.commentChar` Git configuration value is now honored. Commit messages and rebase instruction sheets will now use the configured character for comments. This allows having commit messages that start with `#` when `core.commentChar` is configured to its non-default value. (`#446 `_) Fixes ----- * Diff syntax highlighting was improved to handle more edge cases and false positives. (`#467 `_) * Setting commands in the interactive rebase editor was fixed. (`#472 `_) * git-cola no longer clobbers the Ctrl+Backspace text editing shortcut in the commit message editor. (`#453 `_) * The copy/paste clipboard now persists after `git cola` exits. (`#484 `_) .. _v2.2.1: v2.2.1 ====== Fixes ----- * Fixed the "Sign off" feature in the commit message editor. .. _v2.2: v2.2 ==== Usability, bells and whistles ----------------------------- * Double-click will now choose a commit in the "Select commit" dialog. * `git cola` has a feature that reads `.git/MERGE_MSG` and friends for the commit message when a merge is in-progress. Upon refresh, `git cola` will now detect when a merge has completed and reset the commit message back to its previous state. It is only reset if the editor contains a message that was read from the file and has not been manually edited by the user. * The commit message editor's context menu now has a "Clear..." action for clearing the message across both the summary and description fields. * Traditional Chinese (Taiwan) translation updates. * The system theme's icons are now used wherever possible. (`#458 `_) Fixes ----- * The stash viewer now uses ``git show --no-ext-diff`` to avoid running user-configured diff tools. * `git cola` now uses the `setsid()` system call to ensure that the `GIT_ASKPASS` and `SSH_ASKPASS` helper programs are used when pushing changes using `git`. The askpass helpers will now be used even when `git cola` is launched from a terminal. The behavior without `setsid()` is that `git cola` can appear to hang while pushing changes. The hang happens when `git` prompts the user for a password using the terminal, but the user never sees the prompt. `setsid()` detaches the terminal, which ensures that the askpass helpers are used. (`#218 `_) (`#262 `_) (`#377 `_) * `git dag`'s file list tool was updated to properly handle Unicode paths. * `gnome-terminal` is no longer used by default when `cola.terminal` is unset. It is broken, as was detailed in #456. (`#456 `_) * The interactive rebase feature was not always setting `$GIT_EDITOR` to the value of `gui.editor`, thus there could be instances where rebase will seem to not stop, or hang, when performing "reword" actions. We now set the `$GIT_EDITOR` environment variable when performing the "Continue", "Skip", and "Edit Todo" rebase actions so that the correct editor is used during the rebase. (`#445 `_) Packaging --------- * `git cola` moved from a 3-part version number to a simpler 2-part "vX.Y" version number. Most of our releases tend to contain new features. .. _v2.1.2: v2.1.2 ====== Usability, bells and whistles ----------------------------- * Updated zh_TW translations. * `git cola rebase` now defaults to `@{upstream}`, and generally uses the same CLI syntax as `git rebase`. * The commit message editor now allows you to bypass commit hooks by selecting the "Bypass Commit Hooks" option. This is equivalent to passing the `--no-verify` option to `git commit`. (`#357 `_) * We now prevent the "Delete Files" action from creating a dialog that does not fit on screen. (`#378 `_) * `git xbase` learned to edit rebase instruction sheets that contain `exec` commands. * The diff colors are now configurable. `cola.color.{text,add,remove,header}` can now be set with 6-digit hexadecimal colors. See the `git cola manual _` for more details. * Improved hotkey documentation. Fixes ----- * `git cola` will now allow starting an interactive rebase with a dirty worktree when `rebase.autostash` is set. (`#360 `_) .. _v2.1.1: v2.1.1 ====== Usability, bells and whistles ----------------------------- * A new "Find files" widget was added, and can be activated by using the `Ctrl+t` or `t` hotkeys. * A new `git cola find` sub-command was added for finding files. * `git cola` now remembers the text cursor's position when staging interactively with the keyboard. This makes it easier to use the keyboard arrows to select and stage lines. * The completion widgets will now select the top completion item when `Enter` or `Return` are pressed. * You can now refresh using `F5` in addition to the existing `Ctrl+R` hotkey. Fixes ----- * `git cola` now passes `--no-abbrev-commit` to `git log` to override having `log.abbrevCommit = true` set in `.gitconfig`. .. _v2.1.0: v2.1.0 ====== Usability, bells and whistles ----------------------------- * `git dag` now forwards all unknown arguments along to `git log`. (`#389 `_) * Line-by-line interactive staging was made more robust. (`#399 `_) * "Bookmarks" was renamed to "Favorites". (`#392 `_) * Untracked files are now displayed using a unique icon. (`#388 `_) Fixes ----- * `git dag` was triggering a traceback on Fedora when parsing Git logs. (`bz #181676 `_) * inotify expects Unicode paths on Python3. (`#393 `_) * Untracked files are now assumed to be UTF-8 encoded. (`#401 `_) .. _v2.0.8: v2.0.8 ====== Usability, bells and whistles ----------------------------- * `git cola` can now create GPG-signed commits and merges. See the documentation for details about setting up a GPG agent. (`#149 `_) * The status widget learned to copy relative paths when `Ctrl+x` is pressed. (`#358 `_) * Custom GUI actions can now define their own keyboard shortcuts by setting `guitool.$name.shortcut` to a string understood by the Qt `QKeySequence` API, e.g. `Alt+X`. See the `Qt docs `_ for more details about the supported values. * `git cola` learned to rename branches. (`#364 `_) (`#278 `_) * `git dag` now has a "Show history" context menu which can be used to filter history using the selected paths. Fixes ----- * `sphinxtogithub.py` was fixed for Python3. (`#353 `_) * The commit that changed how we read remotes from `git remote` to parsing `git config` was reverted since it created problems for some users. * Fixed a crash when using the `rebase edit` feature. (`#351 `_) * Better drag-and-drop behavior when dropping into gnome-terminal. (`#373 `_) Packaging --------- * The `git-cola-folder-handler.desktop` file handler was fixed to pass validation by `desktop-file-validate`. (`#356 `_) * The `git.svg` icon was renamed to `git-cola.svg`, and `git cola` was taught to prefer icons from the desktop theme when available. .. _v2.0.7: v2.0.7 ====== Usability, bells and whistles ----------------------------- * New hotkey: `Ctrl+Shift+M` merges branches. * New hotkey: `Ctrl+R` refreshes the DAG viewer. (`#347 `_) Fixes ----- * We now use `git config` to parse the list of remotes instead of parsing the output of `git remote`, which is a Git porcelain and should not be used by scripts. * Avoid "C++ object has been deleted" errors from PyQt4. (`#346 `_) Packaging --------- * The `make install` target now uses `install` instead of `cp`. .. _v2.0.6: v2.0.6 ====== Usability, bells and whistles ----------------------------- * Updated Brazilian Portuguese translation. * The status and browse widgets now allow drag-and-drop into external applications. (`#335 `_) * We now show a progress bar when cloning repositories. (`#312 `_) * The bookmarks widget was simplified to not need a separate dialog. (`#289 `_) * Updated Traditional Chinese translation. * We now display a warning when trying to rebase with uncommitted changes. (`#338 `_) * The status widget learned to filter paths. `Ctrl+Shift+S` toggles the filter widget. (`#337 `_) (`#339 `_) * The status widget learned to move files to the trash when the `send2trash `_ module is installed. (`#341 `_) * "Recent repositories" is now a dedicated widget. (`#342 `_) * New Spanish translation thanks to Pilar Molina Lopez. (`#344 `_) Fixes ----- * Newly added remotes are now properly seen by the fetch/push/pull dialogs. (`#343 `_) .. _v2.0.5: v2.0.5 ====== Usability, bells and whistles ----------------------------- * New Brazilian Portuguese translation thanks to Vitor Lobo. * New Indonesian translation thanks to Samsul Ma'arif. * Updated Simplified Chinese translation thanks to Zhang Han. * `Ctrl+Backspace` is now a hotkey for "delete untracked files" in the status widget. * Fetch/Push/Pull dialogs now use the configured remote of the current branch by default. (`#324 `_) Fixes ----- * We now use `os.getcwd()` on Python3. (`#316 `_) (`#326 `_) * The `Ctrl+P` hotkey was overloaded to both "push" and "cherry-pick", so "cherry-pick" was moved to `Ctrl+Shift+C`. * Custom GUI tools with mixed-case names are now properly supported. * "Diff Region" is now referred to as "Diff Hunk" for consistency with common terminology from diff/patch tools. (`#328 `_) * git-cola's test suite is now portable to MS Windows. (`#332 `_) .. _v2.0.4: v2.0.4 ====== Usability, bells and whistles ----------------------------- * We now handle the case when inotify `add_watch()` fails and display instructions on how to increase the number of watches. (`#263 `_) * New and improved zh_TW localization thanks to V字龍(Vdragon). (`#265 `_) (`#267 `_) (`#268 `_) (`#269 `_) (`#270 `_) (`#271 `_) (`#272 `_) * New hotkeys: `Ctrl+F` for fetch, `Ctrl+P` for push, and `Ctrl+Shift+P` for pull. * The bookmarks widget's context menu actions were made clearer. (`#281 `_) * The term "Staging Area" is used consistently in the UI to allow for better localization. (`#283 `_) * The "Section" term is now referred to as "Diff Region" in the UI. (`#297 `_) * The localization documentation related to the LANGUAGE environment variable was improved. (`#293 `_) * The "Actions" panel now contains tooltips for each button in case the button labels gets truncated by Qt. (`#292 `_) * Custom `git config`-defined actions can now be run in the background by setting `guitool..background` to `true`. Fixes ----- * We now use bold fonts instead of SmallCaps to avoid artifacts on several configurations. * We now pickup `user.email`, `cola.tabwidth`, and similar settings when defined in /etc/gitconfig. (`#259 `_) * Better support for Unicode paths when using inotify. (`bz #1104181 `_) * Unicode fixes for non-ASCII locales. (`#266 `_) (`#273 `_) (`#276 `_) (`#282 `_) (`#298 `_) (`#302 `_) (`#303 `_) (`#305 `_) * Viewing history from the file browser was fixed for Python3. (`#274 `_) * setup.py was fixed to install the `*.rst` documentation. (`#279 `_) * Patch export was fixed for Python3. (`#290 `_) * Fixed adding a bookmark with trailing slashes. (`#295 `_) * The default `git dag` layout is now setup so that its widgets can be freely resized on Linux. (`#299 `_) * Invalid tag names are now reported when creating tags. (`#296 `_) .. _v2.0.3: v2.0.3 ====== Usability, bells and whistles ----------------------------- * `git cola` no longer prompts after successfully creating a new branch. (`#251 `_) * Hitting enter on simple dialogs now accepts them. (`#255 `_) Fixes ----- * `git dag` no longer relies on `sys.maxint`, which is not available in Python3. (`#249 `_) * Python3-related fixes. (`#254 `_) * Python3-on-Windows-related fixes. (`#250 `_) (`#252 `_) (`#253 `_) * Switching repositories using the bookmarks widget was not refreshing the inotify watcher. (`#256 `_) * Special commit messages trailers (e.g. "Acked-by:") are now special-cased to fix word wrapping lines that start with "foo:". (`#257 `_) * `git dag` sometimes left behind selection artifacts. We now refresh the view to avoid them. (`#204 `_) .. _v2.0.2: v2.0.2 ====== Usability, bells and whistles ----------------------------- * Better inotify support for file creation and deletion. (`#240 `_) * `git cola` now supports the X11 Session Management Protocol and remembers its state across logout/reboot. (`#164 `_) * `git cola` has a new icon. (`#190 `_) Packaging --------- * Building the documentation no longer requires `asciidoc`. We now use `Sphinx `_ for building html documentation and man pages. Fixes ----- * Reworked the git-dag gravatar icon code to avoid a Unicode error in Python 2. * Commit message line-wrapping was made to better match the GUI editor. (`#242 `_) * Better support for Python3 on Windows (`#246 `_) Packaging --------- * git-cola no longer depends on Asciidoc for building its documentation and man-pages. We now depend on [Sphinx](https://www.sphinx-doc.org) only. .. _v2.0.1: v2.0.1 ====== Usability, bells and whistles ----------------------------- * Some context menu actions are now hidden when selected files do not exist. (`#238 `_) Fixes ----- * The build-git-cola.sh contrib script was improved. (`#235 `_) * Non-ASCII worktrees work properly again. (`#234 `_) * The browser now guards itself against missing files. (`bz #1041378 `_) * Saving widget state now works under Python3. (`#236 `_) .. _v2.0.0: v2.0.0 ====== Portability ----------- * git-cola now runs on Python 3 thanks to Virgil Dupras. (`#233 `_) * Python 2.6, 2.7, and 3.2+ are now supported. Python 2.5 is no longer supported. Fixes ----- * i18n test fixes thanks to Virgil Dupras. (`#231 `_) * git-cola.app build fixes thanks to Maicon D. Filippsen. (`#230 `_) * Lots of pylint improvements thanks to Alex Chernetz. (`#229 `_) .. _v1.9.4: v1.9.4 ====== Usability, bells and whistles ----------------------------- * The new `Bookmarks` tool makes it really easy to switch between repositories. * There is now a dedicated dialog for applying patches. See the ``File -> Apply Patches`` menu item. (`#215 `_) * A new `git cola am` sub-command was added for applying patches. Fixes ----- * Fixed a typo that caused inotify events to be silently ignored. * Fixed the sys.path setup for Mac OS X (Homebrew). (`#221 `_) * Lots of pylint fixes thanks to Alex Chernetz. .. _v1.9.3: v1.9.3 ====== Usability, bells and whistles ----------------------------- * `git cola --amend` now starts the editor in `amend` mode. (`#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. (`#212 `_) Fixes ----- * Stray whitespace in `.git` files is now ignored. (`#213 `_) * Fix "known incorrect sRGB profile" in `staged-item.png`. (`gentoo-devel message #85066 `_) .. _v1.9.2: v1.9.2 ====== Fixes ----- * Fix a traceback when `git push` fails. (`bz #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`. (`#209 `_) .. _v1.9.1: 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. .. _v1.9.0: 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`. (`#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. (`#202 `_) * You can now push to several remotes simultaneously by selecting multiple remotes in the "Push" dialog. (`#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`. .. _v1.8.5: v1.8.5 ====== Usability, bells and whistles ----------------------------- * We now detect when the editor or history browser are misconfigured. (`#197 `_) (`bz #886826 `_) * Display of untracked files can be disabled from the Preferences dialog or by setting the `gui.displayuntracked` configuration variable to `false`. (`Git Mailing List on 2013-08-21 `_) Fixes ----- * Unicode stash names are now supported (`#198 `_) * The diffs produced when reverting workspace changes were made more robust. .. _v1.8.4: 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 laid-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. (`#194 `_) .. _v1.8.3: 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. (`#150 `_) * `git cola` now remembers your commit message and will restore it when `git cola` is restarted. (`#175 `_) * `Ctrl+M` can now be used to toggle the "Amend last commit" checkbox in the commit message editor. (`#161 `_) * Deleting remote branches can now be done from the "Branch" menu. (`#152 `_) * The commit message editor now has a built-in spell checker. Fixes ----- * We now avoid invoking external diffs when showing diffstats. (`#163 `_) * The `Status` tool learned to reselect files when refreshing. (`#165 `_) * `git cola` now remembers whether it has been maximized and will restore the maximized state when `git cola` is restarted. (`#172 `_) * Performance is now vastly improved when staging hundreds or thousands of files. * `git cola` was not correctly saving repo-specific configuration. (`#174 `_) * Fix a UnicodeDecode in sphinxtogithub when building from source. .. _v1.8.2: v1.8.2 ====== Usability, bells and whistles ----------------------------- * We now automatically remove missing repositories from the "Select Repository" dialog. (`#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. (`#155 `_) * More strings have been marked for l10n. (`#157 `_) * Fixed the Alt+D Diffstat shortcut. (`#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. (`#156 `_) .. _v1.8.1: 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`` (`#140 `_) * A new `git cola merge` sub-command was added for merging branches. * Less blocking in the main UI Fixes ----- * Autocomplete issues on KDE (`#144 `_) * The "recently opened repositories" startup dialog did not display itself in the absence of bookmarks. (`#139 `_) .. _v1.8.0: 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. (`#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. (`#133 `_) * A new "Open Recent" sub-menu was added to the "File" menu. This makes it easy to open a recently-edited repository. (`#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. .. _v1.7.7: 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. (`#120 `_) .. _v1.7.6: v1.7.6 ====== Usability, bells and whistles ----------------------------- * `git dag` learned to color-code branch 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. .. _v1.7.5: 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. .. _v1.7.4.1: v1.7.4.1 ======== Fixes ----- * Detect Homebrew so that OS X users do not need to set PYTHONPATH. * `git dag` can export patches again. .. _v1.7.4: 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. .. _v1.7.3: 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 type change (e.g. symlinks that become files, etc.) are now correctly identified as being modified. Packaging --------- * The `cola.controllers` and `cola.views` packages were removed. .. _v1.7.2: 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 `Alt + Shift + #`. * 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`. (`#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. .. _v1.7.1.1: v1.7.1.1 ======== Fixes ----- * Further enhanced the staging/unstaging behavior in the status widget. (`#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. .. _v1.7.1: v1.7.1 ====== Usability, bells and whistles ----------------------------- * Refined the staging/unstaging behavior for code reviews. (`#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. .. _v1.7.0: 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. (`#90 `_) (`#89 `_) * Previous commit messages can be re-loaded from the message editor. (`#33 `_) Fixes ----- * Display commits with no file changes. (`#82 `_) * Improved the diff editor's copy/paste behavior (`#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. .. _v1.4.3.5: 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. (`#82 `_) * Show the configured remote.$remote.pushurl in the GUI (`#83 `_) * Removed usage of the "user" module. (`#86 `_) * Avoids an extra `git update-index` call during startup. .. _v1.4.3.4: v1.4.3.4 ======== Usability, bells and whistles ----------------------------- * We now provide better feedback when `git push` fails. (`#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 .. _v1.4.3.3: 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. .. _v1.4.3.2: 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. (`#74 `_) (`bz #694806 `_) .. _v1.4.3.1: v1.4.3.1 ======== Usability, bells and whistles ----------------------------- * The `cola classic` tool can be now configured to be dock-able. (`#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 an error when trying to use "Get Commit Message Template" with an undefined "commit.template" git config variable. (`bz #67521 `_) (`#72 `_) * 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. .. _v1.4.3: 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. (`#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. .. _v1.4.2.5: 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. (`#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. .. _v1.4.2.4: 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`. .. _v1.4.2.3: v1.4.2.3 ======== Usability, bells and whistles ----------------------------- * Allow un/staging by right-clicking top-level items (`#57 `_) * Running 'commit' with no staged changes prompts to allow staging all files. (`#55 `_) * Fetch, Push, and Pull are now available via the menus (`#58 `_) Fixes ----- * Simplified the actions widget to work around a regression in PyQt4 4.7.4. (`#62 `_) .. _v1.4.2.2: 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...'. (`#51 `_) * Fixed a hang-on-exit bug in the cola-provided 'ssh-askpass' implementation. .. _v1.4.2.1: v1.4.2.1 ======== Usability, bells and whistles ----------------------------- * Staging and unstaging is faster. (`#48 `_) * `git dag` reads history in a background thread. Portability ----------- * Added `cola.compat.hashlib` for `Python 2.4` compatibility * Improved `PyQt 4.1.x` compatibility. Fixes ----- * Configured menu actions use ``sh -c`` for Windows portability. .. _v1.4.2: v1.4.2 ====== Usability, bells and whistles ----------------------------- * Added support for the configurable ``guitool..*`` actions as described in the ``git config`` documentation. (`git-config(1) `_) (`#44 `_) 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`. (`#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. (`#45 `_) * Log internal ``git`` commands when ``GIT_COLA_TRACE`` is defined. (`#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`.. (`#43 `_) Packaging --------- * Removed colon (`:`) from the application name on Windows (`#41 `_) * Fixed bugs with the Windows installer (`#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 accommodate Mac OS X 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. .. _v1.4.1.2: 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 every time ``git cola version`` is run. * Don't try to watch non-existent 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``. .. _v1.4.1.1: 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`. .. _v1.4.1: 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` (`#3 `_) * A dialog to allow opening or cloning a repository is presented when `git cola` is launched outside of a git repository. (`#22 `_) * Warn when `push` is used to create a new branch (`#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 repo browser data * Added more tests .. _v1.4.0.5: 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 .. _v1.4.0.4: v1.4.0.4 ======== Packaging --------- * Fix Lintian warnings .. _v1.4.0.3: v1.4.0.3 ======== Fixes ----- * Fix X11 warnings on application startup .. _v1.4.0.2: v1.4.0.2 ======== Fixes ----- * Added missing 'Exit Diff Mode' button for 'Diff Expression' mode (`#31 `_) * Fix a bug when initializing fonts on Windows (`#32 `_) .. _v1.4.0.1: v1.4.0.1 ======== Fixes ----- * Keep entries in sorted order in the `cola classic` tool * Fix staging untracked files (`#27 `_) * Fix the `show` command in the Stash dialog (`#29 `_) * Fix a typo when loading merge commit messages (`#30 `_) .. _v1.4.0: 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 .. _v1.3.9: 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 .. _v1.3.8: 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 `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 OS X application bundles to the download page .. _v1.3.7: 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 --------- * More of the code base was updated to follow the `PEP-8` coding style * Added more tests Packaging --------- * All resources are now installed into `$prefix/share/git-cola`. Closed Debian bug #519972 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=519972 .. _v1.3.6: 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-4.6.1/CONTRIBUTING.md000066400000000000000000000157501457126473700155020ustar00rootroot00000000000000# CONTRIBUTING GUIDELINES Here are some guidelines for people who want to contribute their code to this software. ## Make separate commits for logically separate changes. ## Run the pre-commit checks before committing * `garden check` ## Write tests When adding new features or fixing defects, extend the unit tests to cover the new behavior. See the `tests/` directory for examples. Find an appropriate test suite and extend it whenever possible. ## Be picky about whitespace This project is very picky about code style. The style here is the standard Python PEP-8 style: https://www.python.org/dev/peps/pep-0008/ * Use the `garden fmt` command to format the source code using `cercis`. * Follow the same style as the existing code. * Use 4-space indents. * Use `variable_names_with_underscores` AKA "snake case" naming. 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". * If you use SublimeText, configure `newline_at_eof_on_save` to true. * Avoid "No newline at end of file" [in your diffs](https://robots.thoughtbot.com/no-newline-at-end-of-file). ## 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, in other words, what is wrong with the current code without the change. * justifies the way the change solves the problem, in other words, 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 an 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, or using the `Ctrl+i` hotkey in git-cola's commit message editor. 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. ## Reporting Bugs Please read [How to Report Bugs Effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html) for some general tips on bug reporting. ## Internationalization and Localization Git Cola is translated to several languages. When strings are presented to the user they must use the `N_('')` function so that `` is translated into a localized string. The translation message files are the `*.po` files in the `cola/i18n/` directory. Adding a new translation entails creating a new language-specific `.po` file. Please note - it is preferred that git command jargon will be left untranslated. When new (untranslated) strings are added to the project, the `git-cola.pot` base template and the language-specific message files need to be updated with the new strings. To regenerate `git-cola.pot` and update `.po` files with new strings run: garden pot This will update `.po` files with untranslated strings which translators can use to translate `git-cola`. Untranslated strings are denoted by an empty "" string. Alternate translations can be tested by setting `$LANG` when running, e.g. env LANG=zh_TW ./bin/git-cola The [Gettext Language Code](https://www.gnu.org/software/gettext/manual/gettext.html#Language-Codes) corresponds to the `.po` filename. Country-specific suffixes use the [Gettext country code](https://www.gnu.org/software/gettext/manual/gettext.html#Country-Codes). We happily welcome pull requests with improvements to `git-cola`'s translations. ## Fork the repo on Github and create a pull request. git-cola-4.6.1/COPYING000066400000000000000000000431031457126473700142750ustar00rootroot00000000000000 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-4.6.1/COPYRIGHT000066400000000000000000000000671457126473700145370ustar00rootroot00000000000000Copyright (C) 2007-2024 David Aguilar and contributors git-cola-4.6.1/Makefile000066400000000000000000000111271457126473700147030ustar00rootroot00000000000000# The default target of this Makefile is... .PHONY: all all:: # Usage # ----- # make prefix= install # Install git-cola # # make doc # Build documentation # make prefix= install-doc # Install documentation # # Variables # --------- # prefix - Installation prefix. # DESTDIR - Temporary staging directory. # # The external commands used by this Makefile are... CP = cp FIND = find MKDIR_P = mkdir -p PIP = pip PYTHON ?= python3 RM = rm -f RM_R = rm -fr RMDIR = rmdir XARGS = xargs # These values can be overridden on the command-line or via config.mak # DESTDIR = prefix = $(HOME) python_version := $(shell $(PYTHON) -c 'import sys; print("%s.%s" % sys.version_info[:2])') python_lib = python$(python_version)/site-packages pythondir = $(prefix)/lib/$(python_lib) cola_base := git-cola cola_app_base= $(cola_base).app cola_app = $(CURDIR)/$(cola_app_base) cola_app_resources = $(cola_app)/Contents/Resources # Read $(VERSION) from cola/_version.py and strip quotes. include cola/_version.py cola_version := $(subst ',,$(VERSION)) install_args = ifdef DESTDIR install_args += --root="$(DESTDIR)" export DESTDIR endif install_args += --prefix="$(prefix)" install_args += --disable-pip-version-check install_args += --ignore-installed install_args += --no-deps export prefix PYTHON_DIRS = cola PYTHON_DIRS += test ALL_PYTHON_DIRS = $(PYTHON_DIRS) # User customizations -include config.mak all:: .PHONY: install install:: all $(PIP) install $(install_args) . .PHONY: doc doc:: $(MAKE) -C docs all .PHONY: html html:: $(MAKE) -C docs html .PHONY: man man:: $(MAKE) -C docs man .PHONY: install-doc install-doc:: $(MAKE) -C docs install .PHONY: install-html install-html:: $(MAKE) -C docs install-html .PHONY: install-man install-man:: $(MAKE) -C docs install-man .PHONY: uninstall uninstall:: $(RM) "$(DESTDIR)$(prefix)"/bin/cola $(RM) "$(DESTDIR)$(prefix)"/bin/git-cola $(RM) "$(DESTDIR)$(prefix)"/bin/git-cola-sequence-editor $(RM) "$(DESTDIR)$(prefix)"/bin/git-dag $(RM) "$(DESTDIR)$(prefix)"/share/applications/git-cola.desktop $(RM) "$(DESTDIR)$(prefix)"/share/applications/git-cola-folder-handler.desktop $(RM) "$(DESTDIR)$(prefix)"/share/applications/git-dag.desktop $(RM) "$(DESTDIR)$(prefix)"/share/metainfo/git-dag.appdata.xml $(RM) "$(DESTDIR)$(prefix)"/share/metainfo/git-cola.appdata.xml $(RM) "$(DESTDIR)$(prefix)"/share/icons/hicolor/scalable/apps/git-cola.svg $(RM_R) "$(DESTDIR)$(prefix)"/share/doc/git-cola $(RM_R) "$(DESTDIR)$(pythondir)"/git_cola-* $(RM_R) "$(DESTDIR)$(pythondir)"/cola $(RMDIR) -p "$(DESTDIR)$(pythondir)" 2>/dev/null || true $(RMDIR) "$(DESTDIR)$(prefix)"/share/applications 2>/dev/null || true $(RMDIR) "$(DESTDIR)$(prefix)"/share/metainfo 2>/dev/null || true $(RMDIR) "$(DESTDIR)$(prefix)"/share/doc 2>/dev/null || true $(RMDIR) "$(DESTDIR)$(prefix)"/share/icons/hicolor/scalable/apps 2>/dev/null || true $(RMDIR) "$(DESTDIR)$(prefix)"/share/icons/hicolor/scalable 2>/dev/null || true $(RMDIR) "$(DESTDIR)$(prefix)"/share/icons/hicolor 2>/dev/null || true $(RMDIR) "$(DESTDIR)$(prefix)"/share/icons 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 .PHONY: clean clean:: $(FIND) $(ALL_PYTHON_DIRS) -name '*.py[cod]' -print0 | $(XARGS) -0 $(RM) $(FIND) $(ALL_PYTHON_DIRS) -name __pycache__ -print0 | $(XARGS) -0 $(RM_R) $(RM_R) build dist git-cola.app $(MAKE) -C docs clean # Build a git-cola.app bundle. .PHONY: git-cola.app git-cola.app:: cola_full_version := $(shell ./bin/git-cola version --brief) git-cola.app:: $(MKDIR_P) $(cola_app)/Contents/MacOS $(MKDIR_P) $(cola_app_resources) $(PYTHON) -m venv $(cola_app_resources) $(cola_app_resources)/bin/pip install '.[docs,extras,pyqt6]' $(CP) contrib/darwin/Info.plist contrib/darwin/PkgInfo $(cola_app)/Contents ifneq ($(cola_full_version),) sed -i -e s/0.0.0.0/$(cola_full_version)/ $(cola_app)/Contents/Info.plist endif sed -i -e s/0.0.0/$(cola_version)/ $(cola_app)/Contents/Info.plist $(CP) contrib/darwin/git-cola $(cola_app)/Contents/MacOS $(CP) contrib/darwin/git-cola.icns $(cola_app)/Contents/Resources $(MAKE) PIP=$(cola_app_resources)/bin/pip \ prefix=$(cola_app_resources) install $(MAKE) SPHINXBUILD=$(cola_app_resources)/bin/sphinx-build \ prefix=$(cola_app_resources) install-doc .PHONY: test test:: @if type garden >/dev/null 2>&1; then \ garden test; \ else \ echo 'warning: "make test" requires "garden" https://gitlab.com/garden-rs/garden'; \ echo 'tip: run "cargo install garden-tools" to install "garden".'; \ fi git-cola-4.6.1/README.md000066400000000000000000000367361457126473700145370ustar00rootroot00000000000000# git-cola: The highly caffeinated Git GUI Git Cola is a powerful Git GUI with a slick and intuitive user interface. git clone https://github.com/git-cola/git-cola.git [![License](https://img.shields.io/:license-GPL-green.svg)](LICENSE) [![Build status](https://github.com/git-cola/git-cola/actions/workflows/ci.yml/badge.svg?event=push)](https://github.com/git-cola/git-cola/actions/workflows/main.yml) [![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/251/badge)](https://bestpractices.coreinfrastructure.org/projects/251) [![pre-commit.ci](https://results.pre-commit.ci/badge/github/git-cola/git-cola/main.svg)](https://results.pre-commit.ci/latest/github/git-cola/git-cola/main) * [Screenshots](https://git-cola.github.io/screenshots.html) * [Downloads](https://git-cola.github.io/downloads.html) # Documentation * [Keyboard shortcuts](https://git-cola.github.io/share/doc/git-cola/hotkeys.html) * [HTML documentation](https://git-cola.readthedocs.io/en/latest/) * [Git Cola documentation](docs/git-cola.rst) * [Git DAG documentation](docs/git-dag.rst) * [Contributing guidelines](CONTRIBUTING.md) # Requirements ## Build * [Sphinx](http://sphinx-doc.org/) is used to generate the documentation. ## Runtime * [Git](https://git-scm.com/) 2.2.0 or newer. * [Python](https://python.org/) 3.6 or newer. * [QtPy](https://github.com/spyder-ide/qtpy) 2.0.0 or newer. Git Cola uses QtPy, so you can choose between PyQt6, PyQt5 and PySide2 by setting the `QT_API` environment variable to `pyqt6`, `pyqt5` or `pyside2` as desired. `qtpy` defaults to `pyqt5` and falls back to `pyqt6` and `pyside2` if `pyqt5` is not installed. Any of the following Python Qt libraries must be installed: * [PyQt5 / PyQt6](https://www.riverbankcomputing.com/software/pyqt/download5) 5.9 or newer is required. Qt 6.2 or newer is also supported via QtPy. * [PySide2](https://github.com/PySide/PySide) 5.12.0 or newer. ## Optional Features Git Cola enables additional features when the following Python modules are installed. [Send2Trash](https://pypi.org/project/Send2Trash/) enables cross-platform "Send to Trash" functionality. ([source](https://github.com/hsoft/send2trash)) [pyobjc](https://pypi.org/project/pyobjc/) enables macOS-specific application themes on macOS. ([source](https://github.com/ronaldoussoren/pyobjc)) # Installation There are several ways to install Git Cola but you do not need to "install" Git Cola in order to run it. Git Cola is designed to run directly from its source tree. Installation is optional. ## From Source The recommended approach for running the latest Git Cola version is to install its PyQt dependencies using your distribution's package manager and then run `./bin/git-cola` directly from source. ## Installing PyQt dependencies on Debian / Ubuntu systems Git Cola works with either PyQt5 or PyQt6 because it uses the [qtpy](https://github.com/spyder-ide/qtpy) library for PyQt compatibility. ### PyQt5 Users on newer Debian/Ubuntu version can install a single package to run from source. ```bash sudo apt install python3-qtpy ``` If you are on an older version that does not have `python3-qtpy` available then you can install the following packages directly. ```bash sudo apt install python3-pyqt5 python3-pyqt5.qtopengl python3-pyqt5.qtwebengine python3-pyqt5.qtsvg ``` ### PyQt6 If you'd like to use Git Cola with the newer PyQt6 ecosystem then you can install these packages instead of PyQt5. ```bash sudo apt install python3-pyqt6 python3-pyqt6.qtsvg python3-pyqt6.qtwebengine ``` At this point you should be able to launch `./bin/git-cola` from the source tree and there is nothing more to do. The further instructions below detail how to install Git Cola from PyPI or how to install it into a location separate from the source tree. ## Linux Linux is it! Your distro has probably already packaged `git-cola`. If not, please file a bug against your distribution ;-) ### Arch Available in the [AUR](https://aur.archlinux.org/packages/git-cola/). ### Debian, Ubuntu apt install git-cola ### Fedora dnf install git-cola ### Gentoo emerge git-cola ### OpenSUSE, SLE zypper install git-cola ### Slackware Available in [SlackBuilds.org](http://slackbuilds.org/result/?search=git-cola). ### Ubuntu [See here](https://packages.ubuntu.com/search?keywords=git-cola) for the versions that are available in Ubuntu's repositories. ## FreeBSD # Install from official binary packages pkg install -r FreeBSD devel/git-cola # Build from source cd /usr/ports/devel/git-cola && make clean install ## Install into a Python Virtualenv from PyPI using pip **IMPORTANT**: never run `pip install` or `garden install` outside of a Python virtualenv or as root! **IMPORTANT**: if you are on Linux distributions where PyQt6 or PyQt5 are available from your package manager then it is highly recommended to install those dependencies using your system's package manager. See the section above for details. One way to install the latest released version is to use `venv` (virtualenv) and `pip`. This installs [git-cola from pypi.org](https://pypi.org/project/git-cola/). python3 -m venv --system-site-packages env3 ./env3/bin/pip install git-cola ./env3/bin/git-cola Add the `env3/bin` directory to your `PATH` or symlink to `bin/git-cola` from somewhere in your `PATH` such as `~/.local/bin/git-cola`, and you can launch Git Cola like any other built-in `git` command: git cola git dag ## Install into a Python Virtualenv from Source If you don't have PyQt installed then the easiest way to get it is to use a Python virtualenv and install Git Cola into it in "editable" mode. This install method lets you upgrade Git Cola by running `git pull`. # Create a virtualenv called "env3" and activate it. python3 -m venv --system-site-packages env3 # Install PyQt and (optional) extra packages to enable all features. ./env3/bin/pip install --editable '.[extras,pyqt6]' # Run Git Cola via the "git-cola" Git subcommand. source env3/bin/activate git cola If you add `env3/bin` (or symlink to `env3/bin/git-cola` ) somewhere in your `$PATH` then you can run `git cola` as if it were a builtin `git` command from outside of the virtualenv (e.g. after running "deactivate" or when opening a new shell). ## Standalone Installation from Source Running `garden -D prefix=$HOME/.local install` will install Git Cola in your `$HOME/.local` directory (`$HOME/.local/bin/git-cola`, `$HOME/.local/lib`, etc). This installation method assumes that the `qtpy` and `PyQt*` dependencies have been pre-installed. The Garden recipe also supports `DESTDIR` to support creating packages for Linux package managers: garden -D DESTDIR=/tmp/stage -D prefix=/usr/local install If you do not have `garden` available then `make` can be used instead. The `Makefile` supports staged installs using the conventional [DESTDIR](https://www.gnu.org/software/make/manual/html_node/DESTDIR.html) and [prefix](https://www.gnu.org/software/make/manual/html_node/Directory-Variables.html) variables. make DESTDIR=/tmp/stage prefix=/usr/local install ## macOS For most end-users we recommend using either Homebrew or installing into a Python virtualenv as described above. You can install Git Cola from source using the same steps as above. ### Homebrew An easy way to install Git Cola is to use [Homebrew](https://brew.sh/) . Use Homebrew to install the git-cola recipe: brew install git-cola If you install using Homebrew you can stop at this step. You don't need to clone the repo or anything. ### git-cola.app If you have all of the dependencies installed, either via `pip` or `brew` then you can build a shell `git-cola.app` app bundle wrapper for use in `/Applications`. If you'd like to build a `git-cola.app` bundle for `/Applications` run this command: garden macos/app You will need to periodically rebuild the app wrapper whenever Python is upgraded. ### Updating macOS and Homebrew Updating macOS can often break Homebrew-managed software. If you upgrade your macOS version and Git Cola no longer runs then then it is recommended that you re-install Git Cola's dependencies after upgrading. A quick fix when upgrading to newer versions of XCode or macOS is to reinstall PyQt6. brew reinstall pyqt@6 You may also need to relink your pyqt installation: brew link pyqt@6 This is required when upgrading to a modern (post-10.11 El Capitan) Mac OS X. Homebrew now bundles its own Python3 installation instead of using the system-provided default Python. If the "brew reinstall" command above does not work then re-installing from scratch using the instructions below should get things back in shape. # update homebrew brew update # uninstall git-cola and its dependencies brew uninstall git-cola brew uninstall pyqt5 brew uninstall sip # re-install git-cola and its dependencies brew install git-cola ## Windows IMPORTANT If you have a 64-bit machine, install the 64-bit versions only. Do not mix 32-bit and 64-bit versions. Download and install the following: * [Git for Windows](https://git-for-windows.github.io/) * [Git Cola](https://github.com/git-cola/git-cola/releases) Once these are installed you can run Git Cola from the Start menu. See "Windows (Continued)" below for more details. If you'd like to install Git Cola with [winget](https://github.com/microsoft/winget-cli) run the following command: winget install git-cola.git-cola As there is no dependency resolution yet you have to install Git as well with: winget install Git.Git # Goodies Git Cola ships with an interactive rebase editor called `git-cola-sequence-editor`. `git-cola-sequence-editor` is used to reorder and choose commits when rebasing. Start an interactive rebase through the "Rebase" menu, or through the `git cola rebase` sub-command to use the `git-cola-sequence-editor`: git cola rebase @{upstream} `git-cola-sequence-editor` can be launched independently of git cola by telling `git rebase` to use it as its editor through the `GIT_SEQUENCE_EDITOR` environment variable: export GIT_SEQUENCE_EDITOR="$HOME/git-cola/bin/git-cola-sequence-editor" git rebase -i @{upstream} ## Shell Completions Shell completion scripts are available for bash and zsh. Each script contains instructions on how to install and activate the completions. * [bash completion script](contrib/git-cola-completion.bash) * [zsh completion script](contrib/_git-cola) # Git Cola Sub-commands The `git-cola` command exposes various sub-commands that allow you to quickly launch tools that are available from within the git-cola interface. For example, `git cola find` launches the file finder, and `git cola grep` launches the grep tool. See `git cola --help-commands` for the full list of commands. $ git cola --help-commands usage: git-cola [-h] {cola,am,archive,branch,browse,config, dag,diff,fetch,find,grep,merge,pull,push, rebase,remote,search,stash,tag,version} ... valid commands: {cola,am,archive,branch,browse,config, dag,diff,fetch,find,grep,merge,pull,push, rebase,remote,search,stash,tag,version} cola start git-cola am apply patches using "git am" archive save an archive branch create a branch browse browse repository config edit configuration dag start git-dag diff view diffs fetch fetch remotes find find files grep grep source merge merge branches pull pull remote branches push push remote branches rebase interactive rebase remote edit remotes search search commits stash stash and unstash changes tag create tags version print the version ## Development If you already have Git Cola's dependencies installed then you can start `cola` as a Python module if you have the source code available. python -m cola python -m cola dag The following commands should be run during development: # Run the unit tests $ garden test # Run tests and doc checks $ garden check # Run tests against multiple python interpreters using tox $ garden tox The test suite can be found in the [test](test) directory. Commits and pull requests are automatically tested for code quality using [GitHub Actions](https://github.com/git-cola/git-cola/actions/workflows/main.yml). Auto-format `cola/i18n/*.po` files before committing when updating translations: $ garden po When submitting patches, consult the [contributing guidelines](CONTRIBUTING.md). ## Packaging Notes Git Cola installs its modules into the default Python site-packages directory (e.g. `lib/python3.7/site-packages`) using setuptools. While end-users can use `pip install git-cola` to install Git Cola, distribution packagers should use the `garden -D prefix=/usr install` process. Git Cola's Garden recipe wraps `pip install --prefix=` to provide a packaging-friendly `garden install` target. # Windows (Continued) ## Microsoft Visual C++ 2015 Redistributable Earlier versions of Git Cola may have shipped without `vcruntime140.dll` and may not run on machines that are missing this DLL. To fix this, download the [Microsoft Visual C++ 2015 Redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=52685) and install it Git Cola v4.0.0 and newer include this DLL and do not require this to be installed separately. ## Development In order to develop Git Cola on Windows you will need to install Python3 and pip. Install PyQt5 using `pip install PyQt5` to make the PyQt5 bindings available to Python. Once these are installed you can use `python.exe` to run directly from the source tree. For example, from a Git Bash terminal: /c/Python39/python.exe ./bin/git-cola ## Multiple Python versions If you have multiple versions of Python installed, the `contrib/win32/cola` launcher script might choose the newer version instead of the python that has PyQt installed. In order to resolve this, you can set the `cola.pythonlocation` git configuration variable to tell cola where to find python. For example: git config --global cola.pythonlocation /c/Python39 ## Building Windows Installers Windows installers are built using * [Pynsist](https://pynsist.readthedocs.io/en/latest/). * [NSIS](http://nsis.sourceforge.net/Main_Page) is also needed. To build the installer using Pynsist run: ./contrib/win32/run-pynsist.sh This will generate an installer in `build/nsis/`. ## Windows "History Browser" Configuration Upgrade You may need to configure your history browser if you are upgrading from an older version of Git Cola on Windows. `gitk` was originally the default history browser, but `gitk` cannot be launched as-is on Windows because `gitk` is a shell script. If you are configured to use `gitk`, then change your configuration to go through Git's `sh.exe` on Windows. Similarly, we must go through `python.exe` if we want to use `git-dag`. If you want to use gitk as your history browser open the Preferences screen and change the history browser command to: "C:/Program Files/Git/bin/sh.exe" --login -i C:/Git/bin/gitk `git-dag` became the default history browser on Windows in `v2.3`, so new users do not need to configure anything. git-cola-4.6.1/bin/000077500000000000000000000000001457126473700140115ustar00rootroot00000000000000git-cola-4.6.1/bin/README.md000066400000000000000000000011041457126473700152640ustar00rootroot00000000000000# Command-line Wrappers The scripts in this directory are provided for convenience. They allow running `git-cola` directly from the source tree without needing to use a virtualenv or `pip install --editable .` to generate the entry point scripts. The `git cola`, `git cola-rebase-editor` and `git dag` Git sub-commands are provided by the `git-cola`, `git-cola-rebase-editor` and `git-dag` setuptools entry point scripts. The entry points are the real commands that get installed by `make install` and are configured in the `entry_points` section in [setup.cfg](../setup.cfg). git-cola-4.6.1/bin/git-cola000077500000000000000000000003651457126473700154420ustar00rootroot00000000000000#!/usr/bin/env python3 import os import sys realpath = os.path.abspath(os.path.realpath(__file__)) sys.path.insert(1, os.path.dirname(os.path.dirname(realpath))) if __name__ == '__main__': from cola.main import main sys.exit(main()) git-cola-4.6.1/bin/git-cola-sequence-editor000077500000000000000000000004111457126473700205240ustar00rootroot00000000000000#!/usr/bin/env python3 import os import sys realpath = os.path.abspath(os.path.realpath(__file__)) sys.path.insert(1, os.path.dirname(os.path.dirname(realpath))) if __name__ == '__main__': from cola import sequenceeditor sys.exit(sequenceeditor.main()) git-cola-4.6.1/bin/git-dag000077500000000000000000000003631457126473700152550ustar00rootroot00000000000000#!/usr/bin/env python3 import os import sys realpath = os.path.abspath(os.path.realpath(__file__)) sys.path.insert(1, os.path.dirname(os.path.dirname(realpath))) if __name__ == '__main__': from cola import dag sys.exit(dag.main()) git-cola-4.6.1/cola/000077500000000000000000000000001457126473700141575ustar00rootroot00000000000000git-cola-4.6.1/cola/__init__.py000066400000000000000000000000001457126473700162560ustar00rootroot00000000000000git-cola-4.6.1/cola/__main__.py000066400000000000000000000003021457126473700162440ustar00rootroot00000000000000"""Run cola as a Python module. Usage: python -m cola """ from cola import main def run(): """Start the command-line interface.""" main.main() if __name__ == '__main__': run() git-cola-4.6.1/cola/_version.py000066400000000000000000000000221457126473700163470ustar00rootroot00000000000000VERSION = '4.6.1' git-cola-4.6.1/cola/actions.py000066400000000000000000000036001457126473700161700ustar00rootroot00000000000000"""QAction creator functions""" from . import cmds from . import difftool from . import hotkeys from . import icons from . import qtutils from .i18n import N_ def cmd_action(widget, cmd, context, icon, *shortcuts): """Wrap a generic ContextCommand in a QAction""" action = qtutils.add_action(widget, cmd.name(), cmds.run(cmd, context), *shortcuts) action.setIcon(icon) return action def launch_editor(context, widget, *shortcuts): """Create a QAction to launch an editor""" icon = icons.edit() return cmd_action( widget, cmds.LaunchEditor, context, icon, hotkeys.EDIT, *shortcuts ) def launch_editor_at_line(context, widget, *shortcuts): """Create a QAction to launch an editor at the current line""" icon = icons.edit() return cmd_action( widget, cmds.LaunchEditorAtLine, context, icon, hotkeys.EDIT, *shortcuts ) def launch_difftool(context, widget): """Create a QAction to launch git-difftool(1)""" icon = icons.diff() cmd = difftool.LaunchDifftool action = qtutils.add_action( widget, cmd.name(), cmds.run(cmd, context), hotkeys.DIFF ) action.setIcon(icon) return action def stage_or_unstage(context, widget): """Create a QAction to stage or unstage the selection""" icon = icons.add() return cmd_action( widget, cmds.StageOrUnstage, context, icon, hotkeys.STAGE_SELECTION ) def move_down(widget): """Create a QAction to select the next item""" action = qtutils.add_action( widget, N_('Next File'), widget.down.emit, hotkeys.MOVE_DOWN_SECONDARY ) action.setIcon(icons.move_down()) return action def move_up(widget): """Create a QAction to select the previous/above item""" action = qtutils.add_action( widget, N_('Previous File'), widget.up.emit, hotkeys.MOVE_UP_SECONDARY ) action.setIcon(icons.move_up()) return action git-cola-4.6.1/cola/app.py000066400000000000000000000501611457126473700153140ustar00rootroot00000000000000"""Provides the main() routine and ColaApplication""" from functools import partial import argparse import os import signal import sys import time try: from qtpy import QtCore except ImportError as error: sys.stderr.write( """ Your Python environment does not have qtpy and PyQt (or PySide). The following error was encountered when importing "qtpy": ImportError: {err} Install qtpy and PyQt (or PySide) into your Python environment. On a Debian/Ubuntu system you can install these modules using apt: sudo apt install python3-pyqt5 python3-pyqt5.qtwebengine python3-qtpy """.format( err=error ) ) sys.exit(1) from qtpy import QtWidgets from qtpy.QtCore import Qt try: # Qt 5.12 / PyQt 5.13 is unable to use QtWebEngineWidgets unless it is # imported before QApplication is constructed. from qtpy import QtWebEngineWidgets # noqa except ImportError: # QtWebEngineWidgets / QtWebKit is not available -- no big deal. pass # Import cola modules from .i18n import N_ from .interaction import Interaction from .models import main from .models import selection from .widgets import cfgactions from .widgets import standard from .widgets import startup from .settings import Session from .settings import Settings from . import cmds from . import core from . import compat from . import fsmonitor from . import git from . import gitcfg from . import guicmds from . import hidpi from . import icons from . import i18n from . import qtcompat from . import qtutils from . import resources from . import themes from . import utils from . import version def setup_environment(): """Set environment variables to control git's behavior""" # Allow Ctrl-C to exit signal.signal(signal.SIGINT, signal.SIG_DFL) # Session management wants an absolute path when restarting sys.argv[0] = sys_argv0 = os.path.abspath(sys.argv[0]) # Spoof an X11 display for SSH os.environ.setdefault('DISPLAY', ':0') if not core.getenv('SHELL', ''): for shell in ('/bin/zsh', '/bin/bash', '/bin/sh'): if os.path.exists(shell): compat.setenv('SHELL', shell) break # Setup the path so that git finds us when we run 'git cola' path_entries = core.getenv('PATH', '').split(os.pathsep) bindir = core.decode(os.path.dirname(sys_argv0)) path_entries.append(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.package_command('ssh-askpass-darwin') else: askpass = resources.package_command('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') def get_icon_themes(context): """Return the default icon theme names""" result = [] icon_themes_env = core.getenv('GIT_COLA_ICON_THEME') if icon_themes_env: result.extend([x for x in icon_themes_env.split(':') if x]) icon_themes_cfg = list(reversed(context.cfg.get_all('cola.icontheme'))) if icon_themes_cfg: result.extend(icon_themes_cfg) if not result: result.append('light') return result # style note: we use camelCase here since we're masquerading a Qt class class ColaApplication: """The main cola application ColaApplication handles i18n of user-visible data """ def __init__(self, context, argv, locale=None, icon_themes=None, gui_theme=None): cfgactions.install() i18n.install(locale) qtcompat.install() guicmds.install() standard.install() icons.install(icon_themes or get_icon_themes(context)) self.context = context self.theme = None self._install_hidpi_config() self._app = ColaQApplication(context, list(argv)) self._app.setWindowIcon(icons.cola()) self._app.setDesktopFileName('git-cola') self._install_style(gui_theme) def _install_style(self, theme_str): """Generate and apply a stylesheet to the app""" if theme_str is None: theme_str = self.context.cfg.get('cola.theme', default='default') theme = themes.find_theme(theme_str) self.theme = theme self._app.setStyleSheet(theme.build_style_sheet(self._app.palette())) is_macos_theme = theme_str.startswith('macos-') if is_macos_theme: themes.apply_platform_theme(theme_str) elif theme_str != 'default': self._app.setPalette(theme.build_palette(self._app.palette())) def _install_hidpi_config(self): """Sets QT HiDPI scaling (requires Qt 5.6)""" value = self.context.cfg.get('cola.hidpi', default=hidpi.Option.AUTO) hidpi.apply_choice(value) def activeWindow(self): """QApplication::activeWindow() pass-through""" return self._app.activeWindow() def palette(self): """QApplication::palette() pass-through""" return self._app.palette() def start(self): """Wrap exec_() and start the application""" # Defer connection so that local cola.inotify is honored context = self.context monitor = context.fsmonitor monitor.files_changed.connect( cmds.run(cmds.Refresh, context), type=Qt.QueuedConnection ) monitor.config_changed.connect( cmds.run(cmds.RefreshConfig, context), type=Qt.QueuedConnection ) # Start the filesystem monitor thread monitor.start() return self._app.exec_() def stop(self): """Finalize the application""" self.context.fsmonitor.stop() # Workaround QTBUG-52988 by deleting the app manually to prevent a # crash during app shutdown. # https://bugreports.qt.io/browse/QTBUG-52988 try: del self._app except (AttributeError, RuntimeError): pass self._app = None def exit(self, status): """QApplication::exit(status) pass-through""" return self._app.exit(status) class ColaQApplication(QtWidgets.QApplication): """QApplication implementation for handling custom events""" def __init__(self, context, argv): super().__init__(argv) self.context = context # Make icons sharp in HiDPI screen if hasattr(Qt, 'AA_UseHighDpiPixmaps'): self.setAttribute(Qt.AA_UseHighDpiPixmaps, True) def event(self, e): """Respond to focus events for the cola.refreshonfocus feature""" if e.type() == QtCore.QEvent.ApplicationActivate: context = self.context if context: cfg = context.cfg if context.git.is_valid() and cfg.get( 'cola.refreshonfocus', default=False ): cmds.do(cmds.Refresh, context) return super().event(e) def commitData(self, session_mgr): """Save session data""" if not self.context or not self.context.view: return view = self.context.view if not hasattr(view, 'save_state'): return sid = session_mgr.sessionId() skey = session_mgr.sessionKey() session_id = f'{sid}_{skey}' session = Session(session_id, repo=core.getcwd()) session.update() view.save_state(settings=session) def process_args(args): """Process and verify command-line arguments""" if args.version: # Accept 'git cola --version' or 'git cola version' version.print_version() sys.exit(core.EXIT_SUCCESS) # Handle session management restore_session(args) # 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): errmsg = ( N_( 'fatal: "%s" is not a directory. ' 'Please specify a correct --repo .' ) % repo ) core.print_stderr(errmsg) sys.exit(core.EXIT_USAGE) def restore_session(args): """Load a session based on the window-manager provided arguments""" # args.settings is provided when restoring from a session. args.settings = None if args.session is None: return session = Session(args.session) if session.load(): args.settings = session args.repo = session.repo def application_init(args, update=False): """Parses the command-line arguments and starts git-cola""" # Ensure that we're working in a valid git repository. # If not, try to find one. When found, chdir there. setup_environment() process_args(args) context = new_context(args) timer = context.timer timer.start('init') new_worktree(context, args.repo, args.prompt) if update: context.model.update_status() timer.stop('init') if args.perf: timer.display('init') return context def new_context(args): """Create top-level ApplicationContext objects""" context = ApplicationContext(args) context.settings = args.settings or Settings.read() context.git = git.create() context.cfg = gitcfg.create(context) context.fsmonitor = fsmonitor.create(context) context.selection = selection.create() context.model = main.create(context) context.app = new_application(context, args) context.timer = Timer() return context def application_run(context, view, start=None, stop=None): """Run the application main loop""" initialize_view(context, view) # Startup callbacks if start: start(context, view) # Start the event loop result = context.app.start() # Finish if stop: stop(context, view) context.app.stop() return result def initialize_view(context, view): """Register the main widget and display it""" context.set_view(view) view.show() if sys.platform == 'darwin': view.raise_() def application_start(context, view): """Show the GUI and start the main event loop""" # Store the view for session management return application_run(context, view, start=default_start, stop=default_stop) def default_start(context, _view): """Scan for the first time""" QtCore.QTimer.singleShot(0, startup_message) QtCore.QTimer.singleShot(0, lambda: async_update(context)) def default_stop(_context, _view): """All done, cleanup""" QtCore.QThreadPool.globalInstance().waitForDone() def add_common_arguments(parser): """Add command arguments to the ArgumentParser""" # We also accept 'git cola version' parser.add_argument( '--version', default=False, action='store_true', help='print version number' ) # Specifies a git repository to open parser.add_argument( '-r', '--repo', metavar='', default=core.getcwd(), help='open the specified git repository', ) # Specifies that we should prompt for a repository at startup parser.add_argument( '--prompt', action='store_true', default=False, help='prompt for a repository' ) # Specify the icon theme parser.add_argument( '--icon-theme', metavar='', dest='icon_themes', action='append', default=[], help='specify an icon theme (name or directory)', ) # Resume an X Session Management session parser.add_argument( '-session', metavar='', default=None, help=argparse.SUPPRESS ) # Enable timing information parser.add_argument( '--perf', action='store_true', default=False, help=argparse.SUPPRESS ) # Specify the GUI theme parser.add_argument( '--theme', metavar='', default=None, help='specify an GUI theme name' ) def new_application(context, args): """Create a new ColaApplication""" return ColaApplication( context, sys.argv, icon_themes=args.icon_themes, gui_theme=args.theme ) def new_worktree(context, repo, prompt): """Find a Git repository, or prompt for one when not found""" model = context.model cfg = context.cfg parent = qtutils.active_window() valid = False if not prompt: valid = model.set_worktree(repo) if not valid: # We are not currently in a git repository so we need to find one. # Before prompting the user for a repository, check if they've # configured a default repository and attempt to use it. default_repo = cfg.get('cola.defaultrepo') if default_repo: valid = model.set_worktree(default_repo) while not valid: # If we've gotten into this loop then that means that neither the # current directory nor the default repository were available. # Prompt the user for a repository. startup_dlg = startup.StartupDialog(context, parent) gitdir = startup_dlg.find_git_repo() if not gitdir: sys.exit(core.EXIT_NOINPUT) if not core.exists(os.path.join(gitdir, '.git')): offer_to_create_repo(context, gitdir) valid = model.set_worktree(gitdir) continue valid = model.set_worktree(gitdir) if not valid: err = model.error standard.critical( N_('Error Opening Repository'), message=N_('Could not open %s.' % gitdir), details=err, ) def offer_to_create_repo(context, gitdir): """Offer to create a new repo""" title = N_('Repository Not Found') text = N_('%s is not a Git repository.') % gitdir informative_text = N_('Create a new repository at that location?') if standard.confirm(title, text, informative_text, N_('Create')): status, out, err = context.git.init(gitdir) title = N_('Error Creating Repository') if status != 0: Interaction.command_error(title, 'git init', status, out, err) def async_update(context): """Update the model in the background git-cola should startup as quickly as possible. """ update_status = partial(context.model.update_status, update_index=True) task = qtutils.SimpleTask(update_status) context.runtask.start(task) def startup_message(): """Print debug startup messages""" trace = git.GIT_COLA_TRACE if trace in ('2', 'trace'): msg1 = 'info: debug level 2: trace mode enabled' msg2 = 'info: set GIT_COLA_TRACE=1 for less-verbose output' Interaction.log(msg1) Interaction.log(msg2) elif trace: msg1 = 'info: debug level 1' msg2 = 'info: set GIT_COLA_TRACE=2 for trace mode' Interaction.log(msg1) Interaction.log(msg2) def initialize(): """System-level initialization""" # We support ~/.config/git-cola/git-bindir on Windows for configuring # a custom location for finding the "git" executable. git_path = find_git() if git_path: prepend_path(git_path) # The current directory may have been deleted while we are still # in that directory. We rectify this situation by walking up the # directory tree and retrying. # # This is needed because because Python throws exceptions in lots of # stdlib functions when in this situation, e.g. os.path.abspath() and # os.path.realpath(), so it's simpler to mitigate the damage by changing # the current directory to one that actually exists. while True: try: return core.getcwd() except OSError: os.chdir('..') class Timer: """Simple performance timer""" def __init__(self): self._data = {} def start(self, key): """Start a timer""" now = time.time() self._data[key] = [now, now] def stop(self, key): """Stop a timer and return its elapsed time""" entry = self._data[key] entry[1] = time.time() return self.elapsed(key) def elapsed(self, key): """Return the elapsed time for a timer""" entry = self._data[key] return entry[1] - entry[0] def display(self, key): """Display a timer""" elapsed = self.elapsed(key) sys.stdout.write(f'{key}: {elapsed:.5f}s\n') class NullArgs: """Stub arguments for interactive API use""" def __init__(self): self.icon_themes = [] self.perf = False self.prompt = False self.repo = core.getcwd() self.session = None self.settings = None self.theme = None self.version = False def null_args(): """Create a new instance of application arguments""" return NullArgs() class ApplicationContext: """Context for performing operations on Git and related data models""" def __init__(self, args): self.args = args self.app = None # ColaApplication self.git = None # git.Git self.cfg = None # gitcfg.GitConfig self.model = None # main.MainModel self.timer = None # Timer self.runtask = None # qtutils.RunTask self.settings = None # settings.Settings self.selection = None # selection.SelectionModel self.fsmonitor = None # fsmonitor self.view = None # QWidget self.browser_windows = [] # list of browse.Browser def set_view(self, view): """Initialize view-specific members""" self.view = view self.runtask = qtutils.RunTask(parent=view) def find_git(): """Return the path of git.exe, or None if we can't find it.""" if not utils.is_win32(): return None # UNIX systems have git in their $PATH # If the user wants to use a Git/bin/ directory from a non-standard # directory then they can write its location into # ~/.config/git-cola/git-bindir git_bindir = resources.config_home('git-bindir') if core.exists(git_bindir): custom_path = core.read(git_bindir).strip() if custom_path and core.exists(custom_path): return custom_path # Try to find Git's bin/ directory in one of the typical locations pf = os.environ.get('ProgramFiles', 'C:\\Program Files') pf32 = os.environ.get('ProgramFiles(x86)', 'C:\\Program Files (x86)') pf64 = os.environ.get('ProgramW6432', 'C:\\Program Files') for p in [pf64, pf32, pf, 'C:\\']: candidate = os.path.join(p, 'Git\\bin') if os.path.isdir(candidate): return candidate return None def prepend_path(path): """Adds git to the PATH. This is needed on Windows.""" path = core.decode(path) path_entries = core.getenv('PATH', '').split(os.pathsep) if path not in path_entries: path_entries.insert(0, path) compat.setenv('PATH', os.pathsep.join(path_entries)) git-cola-4.6.1/cola/bin/000077500000000000000000000000001457126473700147275ustar00rootroot00000000000000git-cola-4.6.1/cola/bin/ssh-askpass000077500000000000000000000033661457126473700171250ustar00rootroot00000000000000#!/usr/bin/env tclsh # Tcl ignores the next line -*- tcl -*- \ exec wish "$0" -- "$@" # This is a trivial implementation of a GIT_ASKPASS / 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 password / 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 proc on_hide_input_changed {args} { global hide_input if {$hide_input} { .e configure -show "*" } else { .e configure -show "" } } trace add variable hide_input write "on_hide_input_changed" set hide_input 0 if {!$yesno} { if {"Password" in $prompt || "passphrase" in $prompt} { set hide_input 1 } checkbutton .cb_hide -text "Hide input" -variable hide_input pack .cb_hide -side top -anchor nw } 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 . "Git Authentication" tk::PlaceWindow . vwait rc exit $rc git-cola-4.6.1/cola/bin/ssh-askpass-darwin000077500000000000000000000014311457126473700203760ustar00rootroot00000000000000#! /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' 2>/dev/null) if test -z "$result" then exit 1 fi # The beginning of the output can be either "text returned:" # or "button returned:", and is Mac OS X version-dependent. # Account for both output styles. printf '%s\n' "$result" | sed -e 's/^text returned://' -e 's/, button returned:.*$//' \ -e 's/^button returned:OK, text returned://' exit 0 git-cola-4.6.1/cola/cmd.py000066400000000000000000000014251457126473700152760ustar00rootroot00000000000000"""Base Command class""" class Command: """Mixin interface for commands""" UNDOABLE = False @staticmethod def name(): """Return the command's name""" return '(undefined)' @classmethod def is_undoable(cls): """Can this be undone?""" return cls.UNDOABLE def do(self): """Execute the command""" return def undo(self): """Undo the command""" return class ContextCommand(Command): """Base class for commands that operate on a context""" def __init__(self, context): self.context = context self.model = context.model self.cfg = context.cfg self.git = context.git self.selection = context.selection self.fsmonitor = context.fsmonitor git-cola-4.6.1/cola/cmds.py000066400000000000000000002703401457126473700154650ustar00rootroot00000000000000"""Editor commands""" import os import re import sys from fnmatch import fnmatch from io import StringIO try: from send2trash import send2trash except ImportError: send2trash = None from . import compat from . import core from . import gitcmds from . import icons from . import resources from . import textwrap from . import utils from . import version from .cmd import ContextCommand from .git import STDOUT from .git import MISSING_BLOB_OID from .i18n import N_ from .interaction import Interaction from .models import main from .models import prefs class UsageError(Exception): """Exception class for usage errors.""" def __init__(self, title, message): Exception.__init__(self, message) self.title = title self.msg = message class EditModel(ContextCommand): """Commands that mutate the main model diff data""" UNDOABLE = True def __init__(self, context): """Common edit operations on the main model""" super().__init__(context) self.old_diff_text = self.model.diff_text self.old_filename = self.model.filename self.old_mode = self.model.mode self.old_diff_type = self.model.diff_type self.old_file_type = self.model.file_type self.new_diff_text = self.old_diff_text self.new_filename = self.old_filename self.new_mode = self.old_mode self.new_diff_type = self.old_diff_type self.new_file_type = self.old_file_type def do(self): """Perform the operation.""" self.model.filename = self.new_filename self.model.set_mode(self.new_mode) self.model.set_diff_text(self.new_diff_text) self.model.set_diff_type(self.new_diff_type) self.model.set_file_type(self.new_file_type) def undo(self): """Undo the operation.""" self.model.filename = self.old_filename self.model.set_mode(self.old_mode) self.model.set_diff_text(self.old_diff_text) self.model.set_diff_type(self.old_diff_type) self.model.set_file_type(self.old_file_type) class ConfirmAction(ContextCommand): """Confirm an action before running it""" def ok_to_run(self): """Return True when the command is okay to run""" return True def confirm(self): """Prompt for confirmation""" return True def action(self): """Run the command and return (status, out, err)""" return (-1, '', '') def success(self): """Callback run on success""" return def command(self): """Command name, for error messages""" return 'git' def error_message(self): """Command error message""" return '' def do(self): """Prompt for confirmation before running a command""" status = -1 out = err = '' ok = self.ok_to_run() and self.confirm() if ok: status, out, err = self.action() if status == 0: self.success() title = self.error_message() cmd = self.command() Interaction.command(title, cmd, status, out, err) return ok, status, out, err class AbortApplyPatch(ConfirmAction): """Reset an in-progress "git am" patch application""" def confirm(self): title = N_('Abort Applying Patch...') question = N_('Aborting applying the current patch?') info = N_( 'Aborting a patch can cause uncommitted changes to be lost.\n' 'Recovering uncommitted changes is not possible.' ) ok_txt = N_('Abort Applying Patch') return Interaction.confirm( title, question, info, ok_txt, default=False, icon=icons.undo() ) def action(self): status, out, err = gitcmds.abort_apply_patch(self.context) self.model.update_file_merge_status() return status, out, err def success(self): self.model.set_commitmsg('') def error_message(self): return N_('Error') def command(self): return 'git am --abort' class AbortCherryPick(ConfirmAction): """Reset an in-progress cherry-pick""" def confirm(self): title = N_('Abort Cherry-Pick...') question = N_('Aborting the current cherry-pick?') info = N_( 'Aborting a cherry-pick can cause uncommitted changes to be lost.\n' 'Recovering uncommitted changes is not possible.' ) ok_txt = N_('Abort Cherry-Pick') return Interaction.confirm( title, question, info, ok_txt, default=False, icon=icons.undo() ) def action(self): status, out, err = gitcmds.abort_cherry_pick(self.context) self.model.update_file_merge_status() return status, out, err def success(self): self.model.set_commitmsg('') def error_message(self): return N_('Error') def command(self): return 'git cherry-pick --abort' class AbortMerge(ConfirmAction): """Reset an in-progress merge back to HEAD""" def confirm(self): title = N_('Abort Merge...') question = N_('Aborting the current merge?') info = N_( 'Aborting the current merge will cause ' '*ALL* uncommitted changes to be lost.\n' 'Recovering uncommitted changes is not possible.' ) ok_txt = N_('Abort Merge') return Interaction.confirm( title, question, info, ok_txt, default=False, icon=icons.undo() ) def action(self): status, out, err = gitcmds.abort_merge(self.context) self.model.update_file_merge_status() return status, out, err def success(self): self.model.set_commitmsg('') def error_message(self): return N_('Error') def command(self): return 'git merge' class AmendMode(EditModel): """Try to amend a commit.""" UNDOABLE = True LAST_MESSAGE = None @staticmethod def name(): return N_('Amend') def __init__(self, context, amend=True): super().__init__(context) 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 = gitcmds.prev_commitmsg(context) 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 super().do() self.model.set_commitmsg(self.new_commitmsg) self.model.update_file_status() self.context.selection.reset(emit=True) def undo(self): if self.skip: return self.model.set_commitmsg(self.old_commitmsg) super().undo() self.model.update_file_status() self.context.selection.reset(emit=True) class AnnexAdd(ContextCommand): """Add to Git Annex""" def __init__(self, context): super().__init__(context) self.filename = self.selection.filename() def do(self): status, out, err = self.git.annex('add', self.filename) Interaction.command(N_('Error'), 'git annex add', status, out, err) self.model.update_status() class AnnexInit(ContextCommand): """Initialize Git Annex""" def do(self): status, out, err = self.git.annex('init') Interaction.command(N_('Error'), 'git annex init', status, out, err) self.model.cfg.reset() self.model.emit_updated() class LFSTrack(ContextCommand): """Add a file to git lfs""" def __init__(self, context): super().__init__(context) self.filename = self.selection.filename() self.stage_cmd = Stage(context, [self.filename]) def do(self): status, out, err = self.git.lfs('track', self.filename) Interaction.command(N_('Error'), 'git lfs track', status, out, err) if status == 0: self.stage_cmd.do() class LFSInstall(ContextCommand): """Initialize git lfs""" def do(self): status, out, err = self.git.lfs('install') Interaction.command(N_('Error'), 'git lfs install', status, out, err) self.model.update_config(reset=True, emit=True) class ApplyPatch(ContextCommand): """Apply the specified patch to the worktree or index""" def __init__( self, context, patch, encoding, apply_to_worktree, ): super().__init__(context) self.patch = patch self.encoding = encoding self.apply_to_worktree = apply_to_worktree def do(self): context = self.context tmp_file = utils.tmp_filename('apply', suffix='.patch') try: core.write(tmp_file, self.patch.as_text(), encoding=self.encoding) if self.apply_to_worktree: status, out, err = gitcmds.apply_diff_to_worktree(context, tmp_file) else: status, out, err = gitcmds.apply_diff(context, tmp_file) finally: core.unlink(tmp_file) Interaction.log_status(status, out, err) self.model.update_file_status(update_index=True) class ApplyPatches(ContextCommand): """Apply patches using the "git am" command""" def __init__(self, context, patches): super().__init__(context) self.patches = patches def do(self): status, output, err = self.git.am('-3', *self.patches) out = f'# git am -3 {core.list2cmdline(self.patches)}\n\n{output}' Interaction.command(N_('Patch failed to apply'), 'git am -3', status, out, err) # Display a diffstat self.model.update_file_status() patch_basenames = [os.path.basename(p) for p in self.patches] if len(patch_basenames) > 25: patch_basenames = patch_basenames[:25] patch_basenames.append('...') basenames = '\n'.join(patch_basenames) if status == 0: Interaction.information( N_('Patch(es) Applied'), (N_('%d patch(es) applied.') + '\n\n%s') % (len(self.patches), basenames), ) class ApplyPatchesContinue(ContextCommand): """Run "git am --continue" to continue on the next patch in a "git am" session""" def do(self): status, out, err = self.git.am('--continue') Interaction.command( N_('Failed to commit and continue applying patches'), 'git am --continue', status, out, err, ) self.model.update_status() return status, out, err class ApplyPatchesSkip(ContextCommand): """Run "git am --skip" to continue on the next patch in a "git am" session""" def do(self): status, out, err = self.git.am(skip=True) Interaction.command( N_('Failed to continue applying patches after skipping the current patch'), 'git am --skip', status, out, err, ) self.model.update_status() return status, out, err class Archive(ContextCommand): """ "Export archives using the "git archive" command""" def __init__(self, context, ref, fmt, prefix, filename): super().__init__(context) 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(EditModel): """A command object for git-checkout. The argv list is forwarded directly to git. """ def __init__(self, context, argv, checkout_branch=False): super().__init__(context) self.argv = argv self.checkout_branch = checkout_branch self.new_diff_text = '' self.new_diff_type = main.Types.TEXT self.new_file_type = main.Types.TEXT def do(self): super().do() status, out, err = self.git.checkout(*self.argv) if self.checkout_branch: self.model.update_status() else: self.model.update_file_status() Interaction.command(N_('Error'), 'git checkout', status, out, err) return status, out, err class CheckoutTheirs(ConfirmAction): """Checkout "their" version of a file when performing a merge""" @staticmethod def name(): return N_('Checkout files from their branch (MERGE_HEAD)') def confirm(self): title = self.name() question = N_('Checkout files from their branch?') info = N_( 'This operation will replace the selected unmerged files with content ' 'from the branch being merged using "git checkout --theirs".\n' '*ALL* uncommitted changes will be lost.\n' 'Recovering uncommitted changes is not possible.' ) ok_txt = N_('Checkout Files') return Interaction.confirm( title, question, info, ok_txt, default=True, icon=icons.merge() ) def action(self): selection = self.selection.selection() paths = selection.unmerged if not paths: return 0, '', '' argv = ['--theirs', '--'] + paths cmd = Checkout(self.context, argv) return cmd.do() def error_message(self): return N_('Error') def command(self): return 'git checkout --theirs' class CheckoutOurs(ConfirmAction): """Checkout "our" version of a file when performing a merge""" @staticmethod def name(): return N_('Checkout files from our branch (HEAD)') def confirm(self): title = self.name() question = N_('Checkout files from our branch?') info = N_( 'This operation will replace the selected unmerged files with content ' 'from your current branch using "git checkout --ours".\n' '*ALL* uncommitted changes will be lost.\n' 'Recovering uncommitted changes is not possible.' ) ok_txt = N_('Checkout Files') return Interaction.confirm( title, question, info, ok_txt, default=True, icon=icons.merge() ) def action(self): selection = self.selection.selection() paths = selection.unmerged if not paths: return 0, '', '' argv = ['--ours', '--'] + paths cmd = Checkout(self.context, argv) return cmd.do() def error_message(self): return N_('Error') def command(self): return 'git checkout --ours' class BlamePaths(ContextCommand): """Blame view for paths.""" @staticmethod def name(): return N_('Blame...') def __init__(self, context, paths=None): super().__init__(context) if not paths: paths = context.selection.union() viewer = utils.shell_split(prefs.blame_viewer(context)) self.argv = viewer + list(paths) def do(self): try: core.fork(self.argv) except OSError as e: _, details = utils.format_exception(e) title = N_('Error Launching Blame Viewer') msg = N_('Cannot exec "%s": please configure a blame viewer') % ' '.join( self.argv ) Interaction.critical(title, message=msg, details=details) class CheckoutBranch(Checkout): """Checkout a branch.""" def __init__(self, context, branch): args = [branch] super().__init__(context, args, checkout_branch=True) class CherryPick(ContextCommand): """Cherry pick commits into the current branch.""" def __init__(self, context, commits): super().__init__(context) self.commits = commits def do(self): status, out, err = gitcmds.cherry_pick(self.context, self.commits) self.model.update_file_merge_status() title = N_('Cherry-pick failed') Interaction.command(title, 'git cherry-pick', status, out, err) class Revert(ContextCommand): """Revert a commit""" def __init__(self, context, oid): super().__init__(context) self.oid = oid def do(self): status, out, err = self.git.revert(self.oid, no_edit=True) self.model.update_file_status() title = N_('Revert failed') out = '# git revert %s\n\n' % self.oid Interaction.command(title, 'git revert', status, out, err) class ResetMode(EditModel): """Reset the mode and clear the model's diff text.""" def __init__(self, context): super().__init__(context) self.new_mode = self.model.mode_none self.new_diff_text = '' self.new_diff_type = main.Types.TEXT self.new_file_type = main.Types.TEXT self.new_filename = '' def do(self): super().do() self.model.update_file_status() self.context.selection.reset(emit=True) class ResetCommand(ConfirmAction): """Reset state using the "git reset" command""" def __init__(self, context, ref): super().__init__(context) self.ref = ref def action(self): return self.reset() def command(self): return 'git reset' def error_message(self): return N_('Error') def success(self): self.model.update_file_status() def confirm(self): raise NotImplementedError('confirm() must be overridden') def reset(self): raise NotImplementedError('reset() must be overridden') class ResetMixed(ResetCommand): @staticmethod def tooltip(ref): tooltip = N_('The branch will be reset using "git reset --mixed %s"') return tooltip % ref def confirm(self): title = N_('Reset Branch and Stage (Mixed)') question = N_('Point the current branch head to a new commit?') info = self.tooltip(self.ref) ok_text = N_('Reset Branch') return Interaction.confirm(title, question, info, ok_text) def reset(self): return self.git.reset(self.ref, '--', mixed=True) class ResetKeep(ResetCommand): @staticmethod def tooltip(ref): tooltip = N_('The repository will be reset using "git reset --keep %s"') return tooltip % ref def confirm(self): title = N_('Restore Worktree and Reset All (Keep Unstaged Changes)') question = N_('Restore worktree, reset, and preserve unstaged edits?') info = self.tooltip(self.ref) ok_text = N_('Reset and Restore') return Interaction.confirm(title, question, info, ok_text) def reset(self): return self.git.reset(self.ref, '--', keep=True) class ResetMerge(ResetCommand): @staticmethod def tooltip(ref): tooltip = N_('The repository will be reset using "git reset --merge %s"') return tooltip % ref def confirm(self): title = N_('Restore Worktree and Reset All (Merge)') question = N_('Reset Worktree and Reset All?') info = self.tooltip(self.ref) ok_text = N_('Reset and Restore') return Interaction.confirm(title, question, info, ok_text) def reset(self): return self.git.reset(self.ref, '--', merge=True) class ResetSoft(ResetCommand): @staticmethod def tooltip(ref): tooltip = N_('The branch will be reset using "git reset --soft %s"') return tooltip % ref def confirm(self): title = N_('Reset Branch (Soft)') question = N_('Reset branch?') info = self.tooltip(self.ref) ok_text = N_('Reset Branch') return Interaction.confirm(title, question, info, ok_text) def reset(self): return self.git.reset(self.ref, '--', soft=True) class ResetHard(ResetCommand): @staticmethod def tooltip(ref): tooltip = N_('The repository will be reset using "git reset --hard %s"') return tooltip % ref def confirm(self): title = N_('Restore Worktree and Reset All (Hard)') question = N_('Restore Worktree and Reset All?') info = self.tooltip(self.ref) ok_text = N_('Reset and Restore') return Interaction.confirm(title, question, info, ok_text) def reset(self): return self.git.reset(self.ref, '--', hard=True) class RestoreWorktree(ConfirmAction): """Reset the worktree using the "git read-tree" command""" @staticmethod def tooltip(ref): tooltip = N_( 'The worktree will be restored using "git read-tree --reset -u %s"' ) return tooltip % ref def __init__(self, context, ref): super().__init__(context) self.ref = ref def action(self): return self.git.read_tree(self.ref, reset=True, u=True) def command(self): return 'git read-tree --reset -u %s' % self.ref def error_message(self): return N_('Error') def success(self): self.model.update_file_status() def confirm(self): title = N_('Restore Worktree') question = N_('Restore Worktree to %s?') % self.ref info = self.tooltip(self.ref) ok_text = N_('Restore Worktree') return Interaction.confirm(title, question, info, ok_text) class UndoLastCommit(ResetCommand): """Undo the last commit""" # NOTE: this is the similar to ResetSoft() with an additional check for # published commits and different messages. def __init__(self, context): super().__init__(context, 'HEAD^') def confirm(self): check_published = prefs.check_published_commits(self.context) if check_published and self.model.is_commit_published(): return Interaction.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_('Undo the published commit?'), N_('Undo Last Commit'), default=False, icon=icons.save(), ) title = N_('Undo Last Commit') question = N_('Undo last commit?') info = N_('The branch will be reset using "git reset --soft %s"') ok_text = N_('Undo Last Commit') info_text = info % self.ref return Interaction.confirm(title, question, info_text, ok_text) def reset(self): return self.git.reset('HEAD^', '--', soft=True) class Commit(ResetMode): """Attempt to create a new commit.""" def __init__(self, context, amend, msg, sign, no_verify=False): super().__init__(context) self.amend = amend self.msg = msg self.sign = sign self.no_verify = no_verify self.old_commitmsg = self.model.commitmsg self.new_commitmsg = '' def do(self): # Create the commit message file context = self.context msg = self.msg tmp_file = utils.tmp_filename('commit-message') try: core.write(tmp_file, msg) # Run 'git commit' status, out, err = self.git.commit( F=tmp_file, v=True, gpg_sign=self.sign, amend=self.amend, no_verify=self.no_verify, ) finally: core.unlink(tmp_file) if status == 0: super().do() if context.cfg.get(prefs.AUTOTEMPLATE): template_loader = LoadCommitMessageFromTemplate(context) template_loader.do() else: self.model.set_commitmsg(self.new_commitmsg) return status, out, err @staticmethod def strip_comments(msg, comment_char='#'): # Strip off comments message_lines = [ line for line in msg.split('\n') if not line.startswith(comment_char) ] msg = '\n'.join(message_lines) if not msg.endswith('\n'): msg += '\n' return msg class CycleReferenceSort(ContextCommand): """Choose the next reference sort type""" def do(self): self.model.cycle_ref_sort() class Ignore(ContextCommand): """Add files to an exclusion file""" def __init__(self, context, filenames, local=False): super().__init__(context) self.filenames = list(filenames) self.local = local def do(self): if not self.filenames: return new_additions = '\n'.join(self.filenames) + '\n' for_status = new_additions if self.local: filename = os.path.join('.git', 'info', 'exclude') else: filename = '.gitignore' if core.exists(filename): current_list = core.read(filename) new_additions = current_list.rstrip() + '\n' + new_additions core.write(filename, new_additions) Interaction.log_status(0, f'Added to {filename}:\n{for_status}', '') self.model.update_file_status() def file_summary(files): txt = core.list2cmdline(files) if len(txt) > 768: txt = txt[:768].rstrip() + '...' wrap = textwrap.TextWrapper() return '\n'.join(wrap.wrap(txt)) class RemoteCommand(ConfirmAction): def __init__(self, context, remote): super().__init__(context) self.remote = remote def success(self): self.cfg.reset() self.model.update_remotes() class RemoteAdd(RemoteCommand): def __init__(self, context, remote, url): super().__init__(context, remote) self.url = url def action(self): return self.git.remote('add', self.remote, self.url) def error_message(self): return N_('Error creating remote "%s"') % self.remote def command(self): return f'git remote add "{self.remote}" "{self.url}"' class RemoteRemove(RemoteCommand): def confirm(self): title = N_('Delete Remote') question = N_('Delete remote?') info = N_('Delete remote "%s"') % self.remote ok_text = N_('Delete') return Interaction.confirm(title, question, info, ok_text) def action(self): return self.git.remote('rm', self.remote) def error_message(self): return N_('Error deleting remote "%s"') % self.remote def command(self): return 'git remote rm "%s"' % self.remote class RemoteRename(RemoteCommand): def __init__(self, context, remote, new_name): super().__init__(context, remote) self.new_name = new_name def confirm(self): title = N_('Rename Remote') text = N_('Rename remote "%(current)s" to "%(new)s"?') % { 'current': self.remote, 'new': self.new_name, } info_text = '' ok_text = title return Interaction.confirm(title, text, info_text, ok_text) def action(self): return self.git.remote('rename', self.remote, self.new_name) def error_message(self): return N_('Error renaming "%(name)s" to "%(new_name)s"') % { 'name': self.remote, 'new_name': self.new_name, } def command(self): return f'git remote rename "{self.remote}" "{self.new_name}"' class RemoteSetURL(RemoteCommand): def __init__(self, context, remote, url): super().__init__(context, remote) self.url = url def action(self): return self.git.remote('set-url', self.remote, self.url) def error_message(self): return N_('Unable to set URL for "%(name)s" to "%(url)s"') % { 'name': self.remote, 'url': self.url, } def command(self): return f'git remote set-url "{self.remote}" "{self.url}"' class RemoteEdit(ContextCommand): """Combine RemoteRename and RemoteSetURL""" def __init__(self, context, old_name, remote, url): super().__init__(context) self.rename = RemoteRename(context, old_name, remote) self.set_url = RemoteSetURL(context, remote, url) def do(self): result = self.rename.do() name_ok = result[0] url_ok = False if name_ok: result = self.set_url.do() url_ok = result[0] return name_ok, url_ok class RemoveFromSettings(ConfirmAction): def __init__(self, context, repo, entry, icon=None): super().__init__(context) self.context = context self.repo = repo self.entry = entry self.icon = icon def success(self): self.context.settings.save() class RemoveBookmark(RemoveFromSettings): def confirm(self): entry = self.entry title = msg = N_('Delete Bookmark?') info = N_('%s will be removed from your bookmarks.') % entry ok_text = N_('Delete Bookmark') return Interaction.confirm(title, msg, info, ok_text, icon=self.icon) def action(self): self.context.settings.remove_bookmark(self.repo, self.entry) return (0, '', '') class RemoveRecent(RemoveFromSettings): def confirm(self): repo = self.repo title = msg = N_('Remove %s from the recent list?') % repo info = N_('%s will be removed from your recent repositories.') % repo ok_text = N_('Remove') return Interaction.confirm(title, msg, info, ok_text, icon=self.icon) def action(self): self.context.settings.remove_recent(self.repo) return (0, '', '') class RemoveFiles(ContextCommand): """Removes files""" def __init__(self, context, remover, filenames): super().__init__(context) if remover is None: remover = os.remove self.remover = remover self.filenames = filenames # We could git-hash-object stuff and provide undo-ability # as an option. Heh. def do(self): files = self.filenames if not files: return rescan = False bad_filenames = [] remove = self.remover for filename in files: if filename: try: remove(filename) rescan = True except OSError: bad_filenames.append(filename) if bad_filenames: Interaction.information( N_('Error'), N_('Deleting "%s" failed') % file_summary(bad_filenames) ) if rescan: self.model.update_file_status() class Delete(RemoveFiles): """Delete files.""" def __init__(self, context, filenames): super().__init__(context, os.remove, filenames) def do(self): files = self.filenames if not files: return title = N_('Delete Files?') msg = N_('The following files will be deleted:') + '\n\n' msg += file_summary(files) info_txt = N_('Delete %d file(s)?') % len(files) ok_txt = N_('Delete Files') if Interaction.confirm( title, msg, info_txt, ok_txt, default=True, icon=icons.remove() ): super().do() class MoveToTrash(RemoveFiles): """Move files to the trash using send2trash""" AVAILABLE = send2trash is not None def __init__(self, context, filenames): super().__init__(context, send2trash, filenames) class DeleteBranch(ConfirmAction): """Delete a git branch.""" def __init__(self, context, branch): super().__init__(context) self.branch = branch def confirm(self): title = N_('Delete Branch') question = N_('Delete branch "%s"?') % self.branch info = N_('The branch will be no longer available.') ok_txt = N_('Delete Branch') return Interaction.confirm( title, question, info, ok_txt, default=True, icon=icons.discard() ) def action(self): return self.model.delete_branch(self.branch) def error_message(self): return N_('Error deleting branch "%s"' % self.branch) def command(self): command = 'git branch -D %s' return command % self.branch class Rename(ContextCommand): """Rename a set of paths.""" def __init__(self, context, paths): super().__init__(context) self.paths = paths def do(self): msg = N_('Untracking: %s') % (', '.join(self.paths)) Interaction.log(msg) for path in self.paths: ok = self.rename(path) if not ok: return self.model.update_status() def rename(self, path): git = self.git title = N_('Rename "%s"') % path if os.path.isdir(path): base_path = os.path.dirname(path) else: base_path = path new_path = Interaction.save_as(base_path, title) if not new_path: return False status, out, err = git.mv(path, new_path, force=True, verbose=True) Interaction.command(N_('Error'), 'git mv', status, out, err) return status == 0 class RenameBranch(ContextCommand): """Rename a git branch.""" def __init__(self, context, branch, new_branch): super().__init__(context) self.branch = branch self.new_branch = new_branch def do(self): branch = self.branch new_branch = self.new_branch status, out, err = self.model.rename_branch(branch, new_branch) Interaction.log_status(status, out, err) class DeleteRemoteBranch(DeleteBranch): """Delete a remote git branch.""" def __init__(self, context, remote, branch): super().__init__(context, branch) self.remote = remote def action(self): return self.git.push(self.remote, self.branch, delete=True) def success(self): self.model.update_status() Interaction.information( N_('Remote Branch Deleted'), N_('"%(branch)s" has been deleted from "%(remote)s".') % { 'branch': self.branch, 'remote': self.remote, }, ) def error_message(self): return N_('Error Deleting Remote Branch') def command(self): command = 'git push --delete %s %s' return command % (self.remote, self.branch) def get_mode(context, filename, staged, modified, unmerged, untracked): model = context.model if staged: mode = model.mode_index elif modified or unmerged: mode = model.mode_worktree elif untracked: if gitcmds.is_binary(context, filename): mode = model.mode_untracked else: mode = model.mode_untracked_diff else: mode = model.mode return mode class DiffAgainstCommitMode(ContextCommand): """Diff against arbitrary commits""" def __init__(self, context, oid): super().__init__(context) self.oid = oid def do(self): self.model.set_mode(self.model.mode_diff, head=self.oid) self.model.update_file_status() class DiffText(EditModel): """Set the diff type to text""" def __init__(self, context): super().__init__(context) self.new_file_type = main.Types.TEXT self.new_diff_type = main.Types.TEXT class ToggleDiffType(ContextCommand): """Toggle the diff type between image and text""" def __init__(self, context): super().__init__(context) if self.model.diff_type == main.Types.IMAGE: self.new_diff_type = main.Types.TEXT self.new_value = False else: self.new_diff_type = main.Types.IMAGE self.new_value = True def do(self): diff_type = self.new_diff_type value = self.new_value self.model.set_diff_type(diff_type) filename = self.model.filename _, ext = os.path.splitext(filename) if ext.startswith('.'): cfg = 'cola.imagediff' + ext self.cfg.set_repo(cfg, value) class DiffImage(EditModel): def __init__( self, context, filename, deleted, staged, modified, unmerged, untracked ): super().__init__(context) self.new_filename = filename self.new_diff_type = self.get_diff_type(filename) self.new_file_type = main.Types.IMAGE self.new_mode = get_mode( context, filename, staged, modified, unmerged, untracked ) self.staged = staged self.modified = modified self.unmerged = unmerged self.untracked = untracked self.deleted = deleted self.annex = self.cfg.is_annex() def get_diff_type(self, filename): """Query the diff type to use based on cola.imagediff.""" _, ext = os.path.splitext(filename) if ext.startswith('.'): # Check e.g. "cola.imagediff.svg" to see if we should imagediff. cfg = 'cola.imagediff' + ext if self.cfg.get(cfg, True): result = main.Types.IMAGE else: result = main.Types.TEXT else: result = main.Types.IMAGE return result def do(self): filename = self.new_filename if self.staged: images = self.staged_images() elif self.modified: images = self.modified_images() elif self.unmerged: images = self.unmerged_images() elif self.untracked: images = [(filename, False)] else: images = [] self.model.set_images(images) super().do() def staged_images(self): context = self.context git = self.git head = self.model.head filename = self.new_filename annex = self.annex images = [] index = git.diff_index(head, '--', filename, cached=True)[STDOUT] if index: # Example: # :100644 100644 fabadb8... 4866510... M describe.c parts = index.split(' ') if len(parts) > 3: old_oid = parts[2] new_oid = parts[3] if old_oid != MISSING_BLOB_OID: # First, check if we can get a pre-image from git-annex annex_image = None if annex: annex_image = gitcmds.annex_path(context, head, filename) if annex_image: images.append((annex_image, False)) # git annex HEAD else: image = gitcmds.write_blob_path(context, head, old_oid, filename) if image: images.append((image, True)) if new_oid != MISSING_BLOB_OID: found_in_annex = False if annex and core.islink(filename): status, out, _ = git.annex('status', '--', filename) if status == 0: details = out.split(' ') if details and details[0] == 'A': # newly added file images.append((filename, False)) found_in_annex = True if not found_in_annex: image = gitcmds.write_blob(context, new_oid, filename) if image: images.append((image, True)) return images def unmerged_images(self): context = self.context git = self.git head = self.model.head filename = self.new_filename annex = self.annex candidate_merge_heads = ('HEAD', 'CHERRY_HEAD', 'MERGE_HEAD') merge_heads = [ merge_head for merge_head in candidate_merge_heads if core.exists(git.git_path(merge_head)) ] if annex: # Attempt to find files in git-annex annex_images = [] for merge_head in merge_heads: image = gitcmds.annex_path(context, merge_head, filename) if image: annex_images.append((image, False)) if annex_images: annex_images.append((filename, False)) return annex_images # DIFF FORMAT FOR MERGES # "git-diff-tree", "git-diff-files" and "git-diff --raw" # can take -c or --cc option to generate diff output also # for merge commits. The output differs from the format # described above in the following way: # # 1. there is a colon for each parent # 2. there are more "src" modes and "src" sha1 # 3. status is concatenated status characters for each parent # 4. no optional "score" number # 5. single path, only for "dst" # Example: # ::100644 100644 100644 fabadb8... cc95eb0... 4866510... \ # MM describe.c images = [] index = git.diff_index(head, '--', filename, cached=True, cc=True)[STDOUT] if index: parts = index.split(' ') if len(parts) > 3: first_mode = parts[0] num_parents = first_mode.count(':') # colon for each parent, but for the index, the "parents" # are really entries in stages 1,2,3 (head, base, remote) # remote, base, head for i in range(num_parents): offset = num_parents + i + 1 oid = parts[offset] try: merge_head = merge_heads[i] except IndexError: merge_head = 'HEAD' if oid != MISSING_BLOB_OID: image = gitcmds.write_blob_path( context, merge_head, oid, filename ) if image: images.append((image, True)) images.append((filename, False)) return images def modified_images(self): context = self.context git = self.git head = self.model.head filename = self.new_filename annex = self.annex images = [] annex_image = None if annex: # Check for a pre-image from git-annex annex_image = gitcmds.annex_path(context, head, filename) if annex_image: images.append((annex_image, False)) # git annex HEAD else: worktree = git.diff_files('--', filename)[STDOUT] parts = worktree.split(' ') if len(parts) > 3: oid = parts[2] if oid != MISSING_BLOB_OID: image = gitcmds.write_blob_path(context, head, oid, filename) if image: images.append((image, True)) # HEAD images.append((filename, False)) # worktree return images class Diff(EditModel): """Perform a diff and set the model's current text.""" def __init__(self, context, filename, cached=False, deleted=False): super().__init__(context) opts = {} if cached and gitcmds.is_valid_ref(context, self.model.head): opts['ref'] = self.model.head self.new_filename = filename self.new_mode = self.model.mode_worktree self.new_diff_text = gitcmds.diff_helper( self.context, filename=filename, cached=cached, deleted=deleted, **opts ) class Diffstat(EditModel): """Perform a diffstat and set the model's diff text.""" def __init__(self, context): super().__init__(context) cfg = self.cfg diff_context = cfg.get('diff.context', 3) diff = self.git.diff( self.model.head, unified=diff_context, no_ext_diff=True, no_color=True, M=True, stat=True, )[STDOUT] self.new_diff_text = diff self.new_diff_type = main.Types.TEXT self.new_file_type = main.Types.TEXT self.new_mode = self.model.mode_diffstat class DiffStaged(Diff): """Perform a staged diff on a file.""" def __init__(self, context, filename, deleted=None): super().__init__(context, filename, cached=True, deleted=deleted) self.new_mode = self.model.mode_index class DiffStagedSummary(EditModel): def __init__(self, context): super().__init__(context) diff = self.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_diff_type = main.Types.TEXT self.new_file_type = main.Types.TEXT self.new_mode = self.model.mode_index class Edit(ContextCommand): """Edit a file using the configured gui.editor.""" @staticmethod def name(): return N_('Launch Editor') def __init__(self, context, filenames, line_number=None, background_editor=False): super().__init__(context) self.filenames = filenames self.line_number = line_number self.background_editor = background_editor def do(self): context = self.context if not self.filenames: return filename = self.filenames[0] if not core.exists(filename): return if self.background_editor: editor = prefs.background_editor(context) else: editor = prefs.editor(context) opts = [] if self.line_number is None: opts = self.filenames else: # Single-file w/ line-numbers (likely from grep) editor_opts = { '*vim*': [filename, '+%s' % self.line_number], '*emacs*': ['+%s' % self.line_number, filename], '*textpad*': [f'{filename}({self.line_number},0)'], '*notepad++*': ['-n%s' % self.line_number, filename], '*subl*': [f'{filename}:{self.line_number}'], } 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 (OSError, ValueError) as e: message = N_('Cannot exec "%s": please configure your editor') % editor _, details = utils.format_exception(e) Interaction.critical(N_('Error Editing File'), message, details) class FormatPatch(ContextCommand): """Output a patch series given all revisions and a selected subset.""" def __init__(self, context, to_export, revs, output='patches'): super().__init__(context) self.to_export = list(to_export) self.revs = list(revs) self.output = output def do(self): context = self.context status, out, err = gitcmds.format_patchsets( context, self.to_export, self.revs, self.output ) Interaction.log_status(status, out, err) class LaunchTerminal(ContextCommand): @staticmethod def name(): return N_('Launch Terminal') @staticmethod def is_available(context): return context.cfg.terminal() is not None def __init__(self, context, path): super().__init__(context) self.path = path def do(self): cmd = self.context.cfg.terminal() if cmd is None: return if utils.is_win32(): argv = ['start', '', cmd, '--login'] shell = True else: argv = utils.shell_split(cmd) command = '/bin/sh' shells = ('zsh', 'fish', 'bash', 'sh') for basename in shells: executable = core.find_executable(basename) if executable: command = executable break argv.append(os.getenv('SHELL', command)) shell = False core.fork(argv, cwd=self.path, shell=shell) class LaunchEditor(Edit): @staticmethod def name(): return N_('Launch Editor') def __init__(self, context): s = context.selection.selection() filenames = s.staged + s.unmerged + s.modified + s.untracked super().__init__(context, filenames, background_editor=True) class LaunchEditorAtLine(LaunchEditor): """Launch an editor at the specified line""" def __init__(self, context): super().__init__(context) self.line_number = context.selection.line_number class LoadCommitMessageFromFile(ContextCommand): """Loads a commit message from a path.""" UNDOABLE = True def __init__(self, context, path): super().__init__(context) self.path = path self.old_commitmsg = self.model.commitmsg self.old_directory = self.model.directory def do(self): path = os.path.expanduser(self.path) if not path or not core.isfile(path): Interaction.log(N_('Error: Cannot find commit template')) Interaction.log(N_('%s: No such file or directory.') % path) return 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, context): cfg = context.cfg template = cfg.get('commit.template') super().__init__(context, template) def do(self): if self.path is None: Interaction.log(N_('Error: Unconfigured commit template')) Interaction.log( 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 return LoadCommitMessageFromFile.do(self) class LoadCommitMessageFromOID(ContextCommand): """Load a previous commit message""" UNDOABLE = True def __init__(self, context, oid, prefix=''): super().__init__(context) self.oid = oid self.old_commitmsg = self.model.commitmsg self.new_commitmsg = prefix + gitcmds.prev_commitmsg(context, oid) def do(self): self.model.set_commitmsg(self.new_commitmsg) def undo(self): self.model.set_commitmsg(self.old_commitmsg) class PrepareCommitMessageHook(ContextCommand): """Use the cola-prepare-commit-msg hook to prepare the commit message""" UNDOABLE = True def __init__(self, context): super().__init__(context) self.old_commitmsg = self.model.commitmsg def get_message(self): title = N_('Error running prepare-commitmsg hook') hook = gitcmds.prepare_commit_message_hook(self.context) if os.path.exists(hook): filename = self.model.save_commitmsg() status, out, err = core.run_command([hook, filename]) if status == 0: result = core.read(filename) else: result = self.old_commitmsg Interaction.command_error(title, hook, status, out, err) else: message = N_('A hook must be provided at "%s"') % hook Interaction.critical(title, message=message) result = self.old_commitmsg return result def do(self): msg = self.get_message() self.model.set_commitmsg(msg) def undo(self): self.model.set_commitmsg(self.old_commitmsg) class LoadFixupMessage(LoadCommitMessageFromOID): """Load a fixup message""" def __init__(self, context, oid): super().__init__(context, oid, prefix='fixup! ') if self.new_commitmsg: self.new_commitmsg = self.new_commitmsg.splitlines()[0] class Merge(ContextCommand): """Merge commits""" def __init__(self, context, revision, no_commit, squash, no_ff, sign): super().__init__(context) self.revision = revision self.no_ff = no_ff self.no_commit = no_commit self.squash = squash self.sign = sign def do(self): squash = self.squash revision = self.revision no_ff = self.no_ff no_commit = self.no_commit sign = self.sign status, out, err = self.git.merge( revision, gpg_sign=sign, no_ff=no_ff, no_commit=no_commit, squash=squash ) self.model.update_status() title = N_('Merge failed. Conflict resolution is required.') Interaction.command(title, 'git merge', status, out, err) return status, out, err class OpenDefaultApp(ContextCommand): """Open a file using the OS default.""" @staticmethod def name(): return N_('Open Using Default Application') def __init__(self, context, filenames): super().__init__(context) self.filenames = filenames def do(self): if not self.filenames: return utils.launch_default_app(self.filenames) class OpenDir(OpenDefaultApp): """Open directories using the OS default.""" @staticmethod def name(): return N_('Open Directory') @property def _dirnames(self): return self.filenames def do(self): dirnames = self._dirnames if not dirnames: return # An empty dirname defaults to to the current directory. dirs = [(dirname or core.getcwd()) for dirname in dirnames] utils.launch_default_app(dirs) class OpenParentDir(OpenDir): """Open parent directories using the OS default.""" @staticmethod def name(): return N_('Open Parent Directory') @property def _dirnames(self): dirnames = list({os.path.dirname(x) for x in self.filenames}) return dirnames class OpenWorktree(OpenDir): """Open worktree directory using the OS default.""" @staticmethod def name(): return N_('Open Worktree') # The _unused parameter is needed by worktree_dir_action() -> common.cmd_action(). def __init__(self, context, _unused=None): dirnames = [context.git.worktree()] super().__init__(context, dirnames) class OpenNewRepo(ContextCommand): """Launches git-cola on a repo.""" def __init__(self, context, repo_path): super().__init__(context) 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 OpenRepo(EditModel): def __init__(self, context, repo_path): super().__init__(context) self.repo_path = repo_path self.new_mode = self.model.mode_none self.new_diff_text = '' self.new_diff_type = main.Types.TEXT self.new_file_type = main.Types.TEXT self.new_commitmsg = '' self.new_filename = '' def do(self): old_repo = self.git.getcwd() if self.model.set_worktree(self.repo_path): self.fsmonitor.stop() self.fsmonitor.start() self.model.update_status(reset=True) # Check if template should be loaded if self.context.cfg.get(prefs.AUTOTEMPLATE): template_loader = LoadCommitMessageFromTemplate(self.context) template_loader.do() else: self.model.set_commitmsg(self.new_commitmsg) settings = self.context.settings settings.load() settings.add_recent(self.repo_path, prefs.maxrecent(self.context)) settings.save() super().do() else: self.model.set_worktree(old_repo) class OpenParentRepo(OpenRepo): def __init__(self, context): path = '' if version.check_git(context, 'show-superproject-working-tree'): status, out, _ = context.git.rev_parse(show_superproject_working_tree=True) if status == 0: path = out if not path: path = os.path.dirname(core.getcwd()) super().__init__(context, path) class Clone(ContextCommand): """Clones a repository and optionally spawns a new cola session.""" def __init__( self, context, url, new_directory, submodules=False, shallow=False, spawn=True ): super().__init__(context) self.url = url self.new_directory = new_directory self.submodules = submodules self.shallow = shallow self.spawn = spawn self.status = -1 self.out = '' self.err = '' def do(self): kwargs = {} if self.shallow: kwargs['depth'] = 1 recurse_submodules = self.submodules shallow_submodules = self.submodules and self.shallow status, out, err = self.git.clone( self.url, self.new_directory, recurse_submodules=recurse_submodules, shallow_submodules=shallow_submodules, **kwargs, ) self.status = status self.out = out self.err = err if status == 0 and self.spawn: executable = sys.executable core.fork([executable, sys.argv[0], '--repo', self.new_directory]) return self class NewBareRepo(ContextCommand): """Create a new shared bare repository""" def __init__(self, context, path): super().__init__(context) self.path = path def do(self): path = self.path status, out, err = self.git.init(path, bare=True, shared=True) Interaction.command( N_('Error'), 'git init --bare --shared "%s"' % path, status, out, err ) return status == 0 def unix_path(path, is_win32=utils.is_win32): """Git for Windows requires Unix paths, so force them here""" if is_win32(): path = path.replace('\\', '/') first = path[0] second = path[1] if second == ':': # sanity check, this better be a Windows-style path path = '/' + first + path[2:] return path def sequence_editor(): """Set GIT_SEQUENCE_EDITOR for running git-cola-sequence-editor""" xbase = unix_path(resources.command('git-cola-sequence-editor')) if utils.is_win32(): editor = core.list2cmdline([unix_path(sys.executable), xbase]) else: editor = core.list2cmdline([xbase]) return editor class SequenceEditorEnvironment: """Set environment variables to enable git-cola-sequence-editor""" def __init__(self, context, **kwargs): self.env = { 'GIT_EDITOR': prefs.editor(context), 'GIT_SEQUENCE_EDITOR': sequence_editor(), } self.env.update(kwargs) def __enter__(self): for var, value in self.env.items(): compat.setenv(var, value) return self def __exit__(self, exc_type, exc_val, exc_tb): for var in self.env: compat.unsetenv(var) class Rebase(ContextCommand): def __init__(self, context, upstream=None, branch=None, **kwargs): """Start an interactive rebase session :param upstream: upstream branch :param branch: optional branch to checkout :param kwargs: forwarded directly to `git.rebase()` """ super().__init__(context) self.upstream = upstream self.branch = branch self.kwargs = kwargs def prepare_arguments(self, upstream): args = [] kwargs = {} # Rebase actions must be the only option specified for action in ('continue', 'abort', 'skip', 'edit_todo'): if self.kwargs.get(action, False): kwargs[action] = self.kwargs[action] return args, kwargs kwargs['interactive'] = True kwargs['autosquash'] = self.kwargs.get('autosquash', True) kwargs.update(self.kwargs) # Prompt to determine whether or not to use "git rebase --update-refs". has_update_refs = version.check_git(self.context, 'rebase-update-refs') if has_update_refs and not kwargs.get('update_refs', False): title = N_('Update stacked branches when rebasing?') text = N_( '"git rebase --update-refs" automatically force-updates any\n' 'branches that point to commits that are being rebased.\n\n' 'Any branches that are checked out in a worktree are not updated.\n\n' 'Using this feature is helpful for "stacked" branch workflows.' ) info = N_('Update stacked branches when rebasing?') ok_text = N_('Update stacked branches') cancel_text = N_('Do not update stacked branches') update_refs = Interaction.confirm( title, text, info, ok_text, default=True, cancel_text=cancel_text, ) if update_refs: kwargs['update_refs'] = True if upstream: args.append(upstream) if self.branch: args.append(self.branch) return args, kwargs def do(self): (status, out, err) = (1, '', '') context = self.context cfg = self.cfg model = self.model if not cfg.get('rebase.autostash', False): if model.staged or model.unmerged or model.modified: Interaction.information( N_('Unable to rebase'), N_('You cannot rebase with uncommitted changes.'), ) return status, out, err upstream = self.upstream or Interaction.choose_ref( context, N_('Select New Upstream'), N_('Interactive Rebase'), default='@{upstream}', ) if not upstream: return status, out, err self.model.is_rebasing = True self.model.emit_updated() args, kwargs = self.prepare_arguments(upstream) upstream_title = upstream or '@{upstream}' with SequenceEditorEnvironment( self.context, GIT_COLA_SEQ_EDITOR_TITLE=N_('Rebase onto %s') % upstream_title, GIT_COLA_SEQ_EDITOR_ACTION=N_('Rebase'), ): # This blocks the user interface window for the duration # of git-cola-sequence-editor. We would need to run the command # in a QRunnable task to avoid blocking the main thread. # Alternatively, we can hide the main window while rebasing, # which doesn't require as much effort. status, out, err = self.git.rebase( *args, _no_win32_startupinfo=True, **kwargs ) self.model.update_status() if err.strip() != 'Nothing to do': title = N_('Rebase stopped') Interaction.command(title, 'git rebase', status, out, err) return status, out, err class RebaseEditTodo(ContextCommand): def do(self): (status, out, err) = (1, '', '') with SequenceEditorEnvironment( self.context, GIT_COLA_SEQ_EDITOR_TITLE=N_('Edit Rebase'), GIT_COLA_SEQ_EDITOR_ACTION=N_('Save'), ): status, out, err = self.git.rebase(edit_todo=True) Interaction.log_status(status, out, err) self.model.update_status() return status, out, err class RebaseContinue(ContextCommand): def do(self): (status, out, err) = (1, '', '') with SequenceEditorEnvironment( self.context, GIT_COLA_SEQ_EDITOR_TITLE=N_('Rebase'), GIT_COLA_SEQ_EDITOR_ACTION=N_('Rebase'), ): status, out, err = self.git.rebase('--continue') Interaction.log_status(status, out, err) self.model.update_status() return status, out, err class RebaseSkip(ContextCommand): def do(self): (status, out, err) = (1, '', '') with SequenceEditorEnvironment( self.context, GIT_COLA_SEQ_EDITOR_TITLE=N_('Rebase'), GIT_COLA_SEQ_EDITOR_ACTION=N_('Rebase'), ): status, out, err = self.git.rebase(skip=True) Interaction.log_status(status, out, err) self.model.update_status() return status, out, err class RebaseAbort(ContextCommand): def do(self): status, out, err = self.git.rebase(abort=True) Interaction.log_status(status, out, err) self.model.update_status() class Rescan(ContextCommand): """Rescan for changes""" def do(self): self.model.update_status() class Refresh(ContextCommand): """Update refs, refresh the index, and update config""" @staticmethod def name(): return N_('Refresh') def do(self): self.model.update_status(update_index=True) self.cfg.update() self.fsmonitor.refresh() class RefreshConfig(ContextCommand): """Refresh the git config cache""" def do(self): self.cfg.update() class RevertEditsCommand(ConfirmAction): def __init__(self, context): super().__init__(context) self.icon = icons.undo() def ok_to_run(self): return self.model.is_undoable() def checkout_from_head(self): return False def checkout_args(self): args = [] s = self.selection.selection() if self.checkout_from_head(): args.append(self.model.head) args.append('--') if s.staged: items = s.staged else: items = s.modified args.extend(items) return args def action(self): checkout_args = self.checkout_args() return self.git.checkout(*checkout_args) def success(self): self.model.set_diff_type(main.Types.TEXT) self.model.update_file_status() class RevertUnstagedEdits(RevertEditsCommand): @staticmethod def name(): return N_('Revert Unstaged Edits...') def checkout_from_head(self): # Being in amend mode should not affect the behavior of this command. # The only sensible thing to do is to checkout from the index. return False def confirm(self): title = N_('Revert Unstaged Changes?') text = N_( 'This operation removes unstaged edits from selected files.\n' 'These changes cannot be recovered.' ) info = N_('Revert the unstaged changes?') ok_text = N_('Revert Unstaged Changes') return Interaction.confirm( title, text, info, ok_text, default=True, icon=self.icon ) class RevertUncommittedEdits(RevertEditsCommand): @staticmethod def name(): return N_('Revert Uncommitted Edits...') def checkout_from_head(self): return True def confirm(self): """Prompt for reverting changes""" title = N_('Revert Uncommitted Changes?') text = N_( 'This operation removes uncommitted edits from selected files.\n' 'These changes cannot be recovered.' ) info = N_('Revert the uncommitted changes?') ok_text = N_('Revert Uncommitted Changes') return Interaction.confirm( title, text, info, ok_text, default=True, icon=self.icon ) class RunConfigAction(ContextCommand): """Run a user-configured action, typically from the "Tools" menu""" def __init__(self, context, action_name): super().__init__(context) self.action_name = action_name def do(self): """Run the user-configured action""" for env in ('ARGS', 'DIRNAME', 'FILENAME', 'REVISION'): try: compat.unsetenv(env) except KeyError: pass rev = None args = None context = self.context cfg = self.cfg opts = cfg.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 = self.selection.filename() if not filename: Interaction.information( N_('Please select a file'), N_('"%s" requires a selected file.') % cmd, ) return False dirname = utils.dirname(filename, current_dir='.') compat.setenv('FILENAME', filename) compat.setenv('DIRNAME', dirname) if opts.get('revprompt') or opts.get('argprompt'): while True: ok = Interaction.confirm_config_action(context, 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 not Interaction.question(title, prompt): return False 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('background'): core.fork(cmd) status, out, err = (0, '', '') elif opts.get('noconsole'): status, out, err = core.run_command(cmd) else: status, out, err = Interaction.run_command(title, cmd) if not opts.get('background') and not opts.get('norescan'): self.model.update_status() title = N_('Error') Interaction.command(title, cmd, status, out, err) return status == 0 class SetDefaultRepo(ContextCommand): """Set the default repository""" def __init__(self, context, repo): super().__init__(context) self.repo = repo def do(self): self.cfg.set_user('cola.defaultrepo', self.repo) class SetDiffText(EditModel): """Set the diff text""" UNDOABLE = True def __init__(self, context, text): super().__init__(context) self.new_diff_text = text self.new_diff_type = main.Types.TEXT self.new_file_type = main.Types.TEXT class SetUpstreamBranch(ContextCommand): """Set the upstream branch""" def __init__(self, context, branch, remote, remote_branch): super().__init__(context) self.branch = branch self.remote = remote self.remote_branch = remote_branch def do(self): cfg = self.cfg remote = self.remote branch = self.branch remote_branch = self.remote_branch cfg.set_repo('branch.%s.remote' % branch, remote) cfg.set_repo('branch.%s.merge' % branch, 'refs/heads/' + remote_branch) def format_hex(data): """Translate binary data into a hex dump""" hexdigits = '0123456789ABCDEF' result = '' offset = 0 byte_offset_to_int = compat.byte_offset_to_int_converter() while offset < len(data): result += '%04u |' % offset textpart = '' for i in range(0, 16): if i > 0 and i % 4 == 0: result += ' ' if offset < len(data): v = byte_offset_to_int(data[offset]) result += ' ' + hexdigits[v >> 4] + hexdigits[v & 0xF] textpart += chr(v) if 32 <= v < 127 else '.' offset += 1 else: result += ' ' textpart += ' ' result += ' | ' + textpart + ' |\n' return result class ShowUntracked(EditModel): """Show an untracked file.""" def __init__(self, context, filename): super().__init__(context) self.new_filename = filename if gitcmds.is_binary(context, filename): self.new_mode = self.model.mode_untracked self.new_diff_text = self.read(filename) else: self.new_mode = self.model.mode_untracked_diff self.new_diff_text = gitcmds.diff_helper( self.context, filename=filename, cached=False, untracked=True ) self.new_diff_type = main.Types.TEXT self.new_file_type = main.Types.TEXT def read(self, filename): """Read file contents""" cfg = self.cfg size = cfg.get('cola.readsize', 2048) try: result = core.read(filename, size=size, encoding='bytes') except OSError: result = '' truncated = len(result) == size encoding = cfg.file_encoding(filename) or core.ENCODING try: text_result = core.decode_maybe(result, encoding) except UnicodeError: text_result = format_hex(result) if truncated: text_result += '...' return text_result class SignOff(ContextCommand): """Append a sign-off to the commit message""" UNDOABLE = True @staticmethod def name(): return N_('Sign Off') def __init__(self, context): super().__init__(context) self.old_commitmsg = self.model.commitmsg def do(self): """Add a sign-off to the commit message""" signoff = self.signoff() if signoff in self.model.commitmsg: return msg = self.model.commitmsg.rstrip() self.model.set_commitmsg(msg + '\n' + signoff) def undo(self): """Restore the commit message""" self.model.set_commitmsg(self.old_commitmsg) def signoff(self): """Generate the sign-off string""" name, email = self.cfg.get_author() return f'\nSigned-off-by: {name} <{email}>' def check_conflicts(context, unmerged): """Check paths for conflicts Conflicting files can be filtered out one-by-one. """ if prefs.check_conflicts(context): unmerged = [path for path in unmerged if is_conflict_free(path)] return unmerged def is_conflict_free(path): """Return True if `path` contains no conflict markers""" rgx = re.compile(r'^(<<<<<<<|\|\|\|\|\|\|\||>>>>>>>) ') try: with core.xopen(path, 'rb') as f: for line in f: line = core.decode(line, errors='ignore') if rgx.match(line): return should_stage_conflicts(path) except OSError: # We can't read this file ~ we may be staging a removal pass return True def should_stage_conflicts(path): """Inform the user that a file contains merge conflicts Return `True` if we should stage the path nonetheless. """ title = msg = N_('Stage conflicts?') info = ( N_( '%s appears to contain merge conflicts.\n\n' 'You should probably skip this file.\n' 'Stage it anyways?' ) % path ) ok_text = N_('Stage conflicts') cancel_text = N_('Skip') return Interaction.confirm( title, msg, info, ok_text, default=False, cancel_text=cancel_text ) class Stage(ContextCommand): """Stage a set of paths.""" @staticmethod def name(): return N_('Stage') def __init__(self, context, paths): super().__init__(context) self.paths = paths def do(self): msg = N_('Staging: %s') % (', '.join(self.paths)) Interaction.log(msg) return self.stage_paths() def stage_paths(self): """Stages add/removals to git.""" context = self.context paths = self.paths if not paths: if self.model.cfg.get('cola.safemode', False): return (0, '', '') return self.stage_all() add = [] remove = [] status = 0 out = '' err = '' for path in set(paths): if core.exists(path) or core.islink(path): if path.endswith('/'): path = path.rstrip('/') add.append(path) else: remove.append(path) self.model.emit_about_to_update() # `git add -u` doesn't work on untracked files if add: status, out, err = gitcmds.add(context, add) Interaction.command(N_('Error'), 'git add', status, out, err) # 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: status, out, err = gitcmds.add(context, remove, u=True) Interaction.command(N_('Error'), 'git add -u', status, out, err) self.model.update_files(emit=True) return status, out, err def stage_all(self): """Stage all files""" status, out, err = self.git.add(v=True, u=True) Interaction.command(N_('Error'), 'git add -u', status, out, err) self.model.update_file_status() return (status, out, err) class StageCarefully(Stage): """Only stage when the path list is non-empty We use "git add -u -- " to stage, and it stages everything by default when no pathspec is specified, so this class ensures that paths are specified before calling git. When no paths are specified, the command does nothing. """ def __init__(self, context): super().__init__(context, None) self.init_paths() def init_paths(self): """Initialize path data""" return def ok_to_run(self): """Prevent catch-all "git add -u" from adding unmerged files""" return self.paths or not self.model.unmerged def do(self): """Stage files when ok_to_run() return True""" if self.ok_to_run(): return super().do() return (0, '', '') class StageModified(StageCarefully): """Stage all modified files.""" @staticmethod def name(): return N_('Stage Modified') def init_paths(self): self.paths = self.model.modified class StageUnmerged(StageCarefully): """Stage unmerged files.""" @staticmethod def name(): return N_('Stage Unmerged') def init_paths(self): self.paths = check_conflicts(self.context, self.model.unmerged) class StageUntracked(StageCarefully): """Stage all untracked files.""" @staticmethod def name(): return N_('Stage Untracked') def init_paths(self): self.paths = self.model.untracked def stage_all(self): """Disable the stage_all() behavior for untracked files""" return (0, '', '') class StageModifiedAndUntracked(StageCarefully): """Stage all untracked files.""" @staticmethod def name(): return N_('Stage Modified and Untracked') def init_paths(self): self.paths = self.model.modified + self.model.untracked class StageOrUnstageAll(ContextCommand): """If the selection is staged, unstage it, otherwise stage""" @staticmethod def name(): return N_('Stage / Unstage All') def do(self): if self.model.staged: do(Unstage, self.context, self.model.staged) else: if self.cfg.get('cola.safemode', False): unstaged = self.model.modified else: unstaged = self.model.modified + self.model.untracked do(Stage, self.context, unstaged) class StageOrUnstage(ContextCommand): """If the selection is staged, unstage it, otherwise stage""" @staticmethod def name(): return N_('Stage / Unstage') def do(self): s = self.selection.selection() if s.staged: do(Unstage, self.context, s.staged) unstaged = [] unmerged = check_conflicts(self.context, s.unmerged) if unmerged: unstaged.extend(unmerged) if s.modified: unstaged.extend(s.modified) if s.untracked: unstaged.extend(s.untracked) if unstaged: do(Stage, self.context, unstaged) class Tag(ContextCommand): """Create a tag object.""" def __init__(self, context, name, revision, sign=False, message=''): super().__init__(context) self._name = name self._message = message self._revision = revision self._sign = sign def do(self): result = False git = self.git revision = self._revision tag_name = self._name tag_message = self._message if not revision: Interaction.critical( N_('Missing Revision'), N_('Please specify a revision to tag.') ) return result if not tag_name: Interaction.critical( N_('Missing Name'), N_('Please specify a name for the new tag.') ) return result title = N_('Missing Tag Message') message = N_('Tag-signing was requested but the tag message is empty.') info = N_( 'An unsigned, lightweight tag will be created instead.\n' 'Create an unsigned tag?' ) ok_text = N_('Create Unsigned Tag') sign = self._sign if sign and not tag_message: # We require a message in order to sign the tag, so if they # choose to create an unsigned tag we have to clear the sign flag. if not Interaction.confirm( title, message, info, ok_text, default=False, icon=icons.save() ): return result sign = False opts = {} tmp_file = None try: if tag_message: tmp_file = utils.tmp_filename('tag-message') opts['file'] = tmp_file core.write(tmp_file, tag_message) if sign: opts['sign'] = True if tag_message: opts['annotate'] = True status, out, err = git.tag(tag_name, revision, **opts) finally: if tmp_file: core.unlink(tmp_file) title = N_('Error: could not create tag "%s"') % tag_name Interaction.command(title, 'git tag', status, out, err) if status == 0: result = True self.model.update_status() Interaction.information( N_('Tag Created'), N_('Created a new tag named "%s"') % tag_name, details=tag_message or None, ) return result class Unstage(ContextCommand): """Unstage a set of paths.""" @staticmethod def name(): return N_('Unstage') def __init__(self, context, paths): super().__init__(context) self.paths = paths def do(self): """Unstage paths""" context = self.context head = self.model.head paths = self.paths msg = N_('Unstaging: %s') % (', '.join(paths)) Interaction.log(msg) if not paths: return unstage_all(context) status, out, err = gitcmds.unstage_paths(context, paths, head=head) Interaction.command(N_('Error'), 'git reset', status, out, err) self.model.update_file_status() return (status, out, err) class UnstageAll(ContextCommand): """Unstage all files; resets the index.""" def do(self): return unstage_all(self.context) def unstage_all(context): """Unstage all files, even while amending""" model = context.model git = context.git head = model.head status, out, err = git.reset(head, '--', '.') Interaction.command(N_('Error'), 'git reset', status, out, err) model.update_file_status() return (status, out, err) class StageSelected(ContextCommand): """Stage selected files, or all files if no selection exists.""" def do(self): context = self.context paths = self.selection.unstaged if paths: do(Stage, context, paths) elif self.cfg.get('cola.safemode', False): do(StageModified, context) class UnstageSelected(Unstage): """Unstage selected files.""" def __init__(self, context): staged = context.selection.staged super().__init__(context, staged) class Untrack(ContextCommand): """Unstage a set of paths.""" def __init__(self, context, paths): super().__init__(context) self.paths = paths def do(self): msg = N_('Untracking: %s') % (', '.join(self.paths)) Interaction.log(msg) status, out, err = self.model.untrack_paths(self.paths) Interaction.log_status(status, out, err) class UnmergedSummary(EditModel): """List unmerged files in the diff text.""" def __init__(self, context): super().__init__(context) unmerged = self.model.unmerged io = StringIO() io.write('# %s unmerged file(s)\n' % len(unmerged)) if unmerged: io.write('\n'.join(unmerged) + '\n') self.new_diff_text = io.getvalue() self.new_diff_type = main.Types.TEXT self.new_file_type = main.Types.TEXT self.new_mode = self.model.mode_display class UntrackedSummary(EditModel): """List possible .gitignore rules as the diff text.""" def __init__(self, context): super().__init__(context) untracked = self.model.untracked io = StringIO() io.write('# %s untracked file(s)\n' % len(untracked)) if untracked: io.write('# Add these lines to ".gitignore" to ignore these files:\n') io.write('\n'.join('/' + filename for filename in untracked) + '\n') self.new_diff_text = io.getvalue() self.new_diff_type = main.Types.TEXT self.new_file_type = main.Types.TEXT self.new_mode = self.model.mode_display class VisualizeAll(ContextCommand): """Visualize all branches.""" def do(self): context = self.context browser = utils.shell_split(prefs.history_browser(context)) launch_history_browser(browser + ['--all']) class VisualizeCurrent(ContextCommand): """Visualize all branches.""" def do(self): context = self.context browser = utils.shell_split(prefs.history_browser(context)) launch_history_browser(browser + [self.model.currentbranch] + ['--']) class VisualizePaths(ContextCommand): """Path-limited visualization.""" def __init__(self, context, paths): super().__init__(context) context = self.context browser = utils.shell_split(prefs.history_browser(context)) if paths: self.argv = browser + ['--'] + list(paths) else: self.argv = browser def do(self): launch_history_browser(self.argv) class VisualizeRevision(ContextCommand): """Visualize a specific revision.""" def __init__(self, context, revision, paths=None): super().__init__(context) self.revision = revision self.paths = paths def do(self): context = self.context argv = utils.shell_split(prefs.history_browser(context)) if self.revision: argv.append(self.revision) if self.paths: argv.append('--') argv.extend(self.paths) launch_history_browser(argv) class SubmoduleAdd(ConfirmAction): """Add specified submodules""" def __init__(self, context, url, path, branch, depth, reference): super().__init__(context) self.url = url self.path = path self.branch = branch self.depth = depth self.reference = reference def confirm(self): title = N_('Add Submodule...') question = N_('Add this submodule?') info = N_('The submodule will be added using\n' '"%s"' % self.command()) ok_txt = N_('Add Submodule') return Interaction.confirm(title, question, info, ok_txt, icon=icons.ok()) def action(self): context = self.context args = self.get_args() return context.git.submodule('add', *args) def success(self): self.model.update_file_status() self.model.update_submodules_list() def error_message(self): return N_('Error updating submodule %s' % self.path) def command(self): cmd = ['git', 'submodule', 'add'] cmd.extend(self.get_args()) return core.list2cmdline(cmd) def get_args(self): args = [] if self.branch: args.extend(['--branch', self.branch]) if self.reference: args.extend(['--reference', self.reference]) if self.depth: args.extend(['--depth', '%d' % self.depth]) args.extend(['--', self.url]) if self.path: args.append(self.path) return args class SubmoduleUpdate(ConfirmAction): """Update specified submodule""" def __init__(self, context, path): super().__init__(context) self.path = path def confirm(self): title = N_('Update Submodule...') question = N_('Update this submodule?') info = N_('The submodule will be updated using\n' '"%s"' % self.command()) ok_txt = N_('Update Submodule') return Interaction.confirm( title, question, info, ok_txt, default=False, icon=icons.pull() ) def action(self): context = self.context args = self.get_args() return context.git.submodule(*args) def success(self): self.model.update_file_status() def error_message(self): return N_('Error updating submodule %s' % self.path) def command(self): cmd = ['git', 'submodule'] cmd.extend(self.get_args()) return core.list2cmdline(cmd) def get_args(self): cmd = ['update'] if version.check_git(self.context, 'submodule-update-recursive'): cmd.append('--recursive') cmd.extend(['--', self.path]) return cmd class SubmodulesUpdate(ConfirmAction): """Update all submodules""" def confirm(self): title = N_('Update submodules...') question = N_('Update all submodules?') info = N_('All submodules will be updated using\n' '"%s"' % self.command()) ok_txt = N_('Update Submodules') return Interaction.confirm( title, question, info, ok_txt, default=False, icon=icons.pull() ) def action(self): context = self.context args = self.get_args() return context.git.submodule(*args) def success(self): self.model.update_file_status() def error_message(self): return N_('Error updating submodules') def command(self): cmd = ['git', 'submodule'] cmd.extend(self.get_args()) return core.list2cmdline(cmd) def get_args(self): cmd = ['update'] if version.check_git(self.context, 'submodule-update-recursive'): cmd.append('--recursive') return cmd def launch_history_browser(argv): """Launch the configured history browser""" try: core.fork(argv) except OSError 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): """Closure return by run() which runs the command""" if args or opts: return do(cls, *args, **opts) return do(cls, *local_args, **local_opts) return runner def do(cls, *args, **opts): """Run a command in-place""" try: cmd = cls(*args, **opts) return cmd.do() except Exception as e: msg, details = utils.format_exception(e) if hasattr(cls, '__name__'): msg = f'{cls.__name__} exception:\n{msg}' Interaction.critical(N_('Error'), message=msg, details=details) return None git-cola-4.6.1/cola/compat.py000066400000000000000000000035271457126473700160230ustar00rootroot00000000000000import os import sys try: import urllib2 as parse # noqa except ImportError: # Python 3 from urllib import parse # noqa PY_VERSION = sys.version_info[:2] # (2, 7) PY_VERSION_MAJOR = PY_VERSION[0] PY2 = PY_VERSION_MAJOR == 2 PY3 = PY_VERSION_MAJOR >= 3 PY26_PLUS = PY2 and sys.version_info[1] >= 6 WIN32 = sys.platform in {'win32', 'cygwin'} ENCODING = 'utf-8' if PY3: def bstr(value, encoding=ENCODING): return bytes(value, encoding=encoding) elif PY26_PLUS: bstr = bytes else: # Python <= 2.5 bstr = str if PY3: def bchr(i): return bytes([i]) int_types = (int,) maxsize = sys.maxsize ustr = str uchr = chr else: bchr = chr maxsize = 2**31 ustr = unicode # noqa uchr = unichr # noqa int_types = (int, long) # noqa # The max 32-bit signed integer range for Qt is (-2147483648 to 2147483647) maxint = (2**31) - 1 def setenv(key, value): """Compatibility wrapper for setting environment variables Windows requires putenv(). Unix only requires os.environ. """ if not PY3 and isinstance(value, ustr): value = value.encode(ENCODING, 'replace') os.environ[key] = value os.putenv(key, value) def unsetenv(key): """Compatibility wrapper for clearing environment variables""" os.environ.pop(key, None) if hasattr(os, 'unsetenv'): os.unsetenv(key) def no_op(value): """Return the value as-is""" return value def byte_offset_to_int_converter(): """Return a function to convert byte string offsets into integers Indexing into python3 bytes returns integers. Python2 returns str. Thus, on Python2 we need to use `ord()` to convert the byte into an integer. It's already an int on Python3, so we use no_op there. """ if PY2: result = ord else: result = no_op return result git-cola-4.6.1/cola/core.py000066400000000000000000000356731457126473700154770ustar00rootroot00000000000000"""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 functools import itertools import mimetypes import os import platform import subprocess import sys from .decorators import interruptable from .compat import ustr from .compat import PY2 from .compat import PY3 from .compat import WIN32 # /usr/include/stdlib.h # #define EXIT_SUCCESS 0 /* Successful exit status. */ # #define EXIT_FAILURE 1 /* Failing exit status. */ EXIT_SUCCESS = 0 EXIT_FAILURE = 1 # /usr/include/sysexits.h # #define EX_USAGE 64 /* command line usage error */ # #define EX_NOINPUT 66 /* cannot open input */ # #define EX_UNAVAILABLE 69 /* service unavailable */ EXIT_USAGE = 64 EXIT_NOINPUT = 66 EXIT_UNAVAILABLE = 69 # Default encoding ENCODING = 'utf-8' # 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 = [ ENCODING, 'iso-8859-15', 'windows1252', 'ascii', # <-- add encodings here ] class UStr(ustr): """Unicode string wrapper that remembers its encoding UStr wraps Unicode strings to provide the `encoding` attribute. UStr is used when decoding strings of an unknown encoding. In order to generate patches that contain the original byte sequences, we must preserve the original encoding when calling decode() so that it can later be used when reconstructing the original byte sequences. """ def __new__(cls, string, encoding): if isinstance(string, UStr): if encoding != string.encoding: raise ValueError(f'Encoding conflict: {string.encoding} vs. {encoding}') string = ustr(string) obj = ustr.__new__(cls, string) obj.encoding = encoding return obj def decode_maybe(value, encoding, errors='strict'): """Decode a value when the "decode" method exists""" if hasattr(value, 'decode'): result = value.decode(encoding, errors=errors) else: result = value return result def decode(value, encoding=None, errors='strict'): """decode(encoded_string) returns an un-encoded Unicode string""" if value is None: result = None elif isinstance(value, ustr): result = UStr(value, ENCODING) elif encoding == 'bytes': result = value else: result = None if encoding is None: encoding_tests = _encoding_tests else: encoding_tests = itertools.chain([encoding], _encoding_tests) for enc in encoding_tests: try: decoded = value.decode(enc, errors) result = UStr(decoded, enc) break except ValueError: pass if result is None: decoded = value.decode(ENCODING, errors='ignore') result = UStr(decoded, ENCODING) return result def encode(string, encoding=None): """encode(string) returns a byte string encoded to UTF-8""" if not isinstance(string, ustr): return string return string.encode(encoding or ENCODING, 'replace') def mkpath(path, encoding=None): # The Windows API requires Unicode strings regardless of python version if WIN32: return decode(path, encoding=encoding) # UNIX prefers bytes return encode(path, encoding=encoding) def decode_seq(seq, encoding=None): """Decode a sequence of values""" return [decode(x, encoding=encoding) for x in seq] def list2cmdline(cmd): return subprocess.list2cmdline([decode(c) for c in cmd]) def read(filename, size=-1, encoding=None, errors='strict'): """Read filename and return contents""" with xopen(filename, 'rb') as fh: return xread(fh, size=size, encoding=encoding, errors=errors) def write(path, contents, encoding=None, append=False): """Writes a Unicode string to a file""" if append: mode = 'ab' else: mode = 'wb' with xopen(path, mode) as fh: return xwrite(fh, contents, encoding=encoding) @interruptable def xread(fh, size=-1, encoding=None, errors='strict'): """Read from a file handle and retry when interrupted""" return decode(fh.read(size), encoding=encoding, errors=errors) @interruptable def xwrite(fh, content, encoding=None): """Write to a file handle 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, add_env=None, universal_newlines=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, no_win32_startupinfo=False, stderr=subprocess.PIPE, **extra, ): """Start the given command, and return a subprocess object. This provides a simpler interface to the subprocess module. """ env = extra.pop('env', None) if add_env is not None: env = os.environ.copy() env.update(add_env) # Python3 on windows always goes through list2cmdline() internally inside # of subprocess.py so we must provide Unicode strings here otherwise # Python3 breaks when bytes are provided. # # Additionally, the preferred usage on Python3 is to pass Unicode # strings to subprocess. Python will automatically encode into the # default encoding (UTF-8) when it gets Unicode strings. shell = extra.get('shell', False) cmd = prep_for_subprocess(cmd, shell=shell) if WIN32 and cwd == getcwd(): # Windows cannot deal with passing a cwd that contains Unicode # but we luckily can pass None when the supplied cwd is the same # as our current directory and get the same effect. # Not doing this causes Unicode encoding errors when launching # the subprocess. cwd = None if PY2 and cwd: cwd = encode(cwd) if WIN32: # If git-cola is invoked on Windows using "start pythonw git-cola", # a console window will briefly flash on the screen each time # git-cola invokes git, which is very annoying. The code below # prevents this by ensuring that any window will be hidden. startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW extra['startupinfo'] = startupinfo if WIN32 and not no_win32_startupinfo: CREATE_NO_WINDOW = 0x08000000 extra['creationflags'] = CREATE_NO_WINDOW # Use line buffering when in text/universal_newlines mode, # otherwise use the system default buffer size. bufsize = 1 if universal_newlines else -1 return subprocess.Popen( cmd, bufsize=bufsize, stdin=stdin, stdout=stdout, stderr=stderr, cwd=cwd, env=env, universal_newlines=universal_newlines, **extra, ) def prep_for_subprocess(cmd, shell=False): """Decode on Python3, encode on Python2""" # See the comment in start_command() if shell: if PY3: cmd = decode(cmd) else: cmd = encode(cmd) else: if PY3: cmd = [decode(c) for c in cmd] else: cmd = [encode(c) for c in cmd] return cmd @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(). """ encoding = kwargs.pop('encoding', None) process = start_command(cmd, *args, **kwargs) (output, errors) = communicate(process) output = decode(output, encoding=encoding) errors = decode(errors, encoding=encoding) exit_code = process.returncode return (exit_code, output or UStr('', ENCODING), errors or UStr('', ENCODING)) @interruptable def _fork_posix(args, cwd=None, shell=False): """Launch a process in the background.""" encoded_args = [encode(arg) for arg in args] return subprocess.Popen(encoded_args, cwd=cwd, shell=shell).pid def _fork_win32(args, cwd=None, shell=False): """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 if not shell: args[0] = _win32_find_exe(args[0]) if PY3: # see comment in start_command() argv = [decode(arg) for arg in args] else: argv = [encode(arg) for arg in args] DETACHED_PROCESS = 0x00000008 # Amazing! return subprocess.Popen( argv, cwd=cwd, creationflags=DETACHED_PROCESS, shell=shell ).pid def _win32_find_exe(exe): """Find the actual file for a Windows executable. This function goes through the same process that the Windows shell uses to locate an executable, taking into account the PATH and PATHEXT environment variables. This allows us to avoid passing shell=True to subprocess.Popen. For reference, see: https://technet.microsoft.com/en-us/library/cc723564.aspx#XSLTsection127121120120 """ # try the argument itself candidates = [exe] # if argument does not have an extension, also try it with each of the # extensions specified in PATHEXT if '.' not in exe: extensions = getenv('PATHEXT', '').split(os.pathsep) candidates.extend([(exe + ext) for ext in extensions if ext.startswith('.')]) # search the current directory first for candidate in candidates: if exists(candidate): return candidate # if the argument does not include a path separator, search each of the # directories on the PATH if not os.path.dirname(exe): for path in getenv('PATH').split(os.pathsep): if path: for candidate in candidates: full_path = os.path.join(path, candidate) if exists(full_path): return full_path # not found, punt and return the argument unchanged return exe # Portability wrappers if sys.platform in {'win32', 'cygwin'}: fork = _fork_win32 else: fork = _fork_posix def _decorator_noop(x): return x def wrap(action, func, decorator=None): """Wrap arguments with `action`, optionally decorate the result""" if decorator is None: decorator = _decorator_noop @functools.wraps(func) def wrapped(*args, **kwargs): return decorator(func(action(*args, **kwargs))) return wrapped def decorate(decorator, func): """Decorate the result of `func` with `action`""" @functools.wraps(func) def decorated(*args, **kwargs): return decorator(func(*args, **kwargs)) return decorated def getenv(name, default=None): return decode(os.getenv(name, default)) def guess_mimetype(filename): """Robustly guess a filename's mimetype""" mimetype = None try: mimetype = mimetypes.guess_type(filename)[0] except UnicodeEncodeError: mimetype = mimetypes.guess_type(encode(filename))[0] except (TypeError, ValueError): mimetype = mimetypes.guess_type(decode(filename))[0] return mimetype def xopen(path, mode='r', encoding=None): """Open a file with the specified mode and encoding The path is decoded into Unicode on Windows and encoded into bytes on Unix. """ return open(mkpath(path, encoding=encoding), mode) def open_append(path, encoding=None): """Open a file for appending in UTF-8 text mode""" return open(mkpath(path, encoding=encoding), 'a', encoding='utf-8') def open_read(path, encoding=None): """Open a file for reading in UTF-8 text mode""" return open(mkpath(path, encoding=encoding), encoding='utf-8') def open_write(path, encoding=None): """Open a file for writing in UTF-8 text mode""" return open(mkpath(path, encoding=encoding), 'w', encoding='utf-8') def print_stdout(msg, linesep='\n'): msg = msg + linesep if PY2: msg = encode(msg, encoding=ENCODING) sys.stdout.write(msg) def print_stderr(msg, linesep='\n'): msg = msg + linesep if PY2: msg = encode(msg, encoding=ENCODING) sys.stderr.write(msg) def error(msg, status=EXIT_FAILURE, linesep='\n'): print_stderr(msg, linesep=linesep) sys.exit(status) @interruptable def node(): return platform.node() abspath = wrap(mkpath, os.path.abspath, decorator=decode) chdir = wrap(mkpath, os.chdir) exists = wrap(mkpath, os.path.exists) expanduser = wrap(encode, os.path.expanduser, decorator=decode) if PY2: if hasattr(os, 'getcwdu'): getcwd = os.getcwdu else: getcwd = decorate(decode, os.getcwd) else: getcwd = os.getcwd # NOTE: find_executable() is originally from the stdlib, but starting with # python3.7 the stdlib no longer bundles distutils. def _find_executable(executable, path=None): """Tries to find 'executable' in the directories listed in 'path'. A string listing directories separated by 'os.pathsep'; defaults to os.environ['PATH']. Returns the complete filename or None if not found. """ if path is None: path = os.environ['PATH'] paths = path.split(os.pathsep) _, ext = os.path.splitext(executable) if (sys.platform == 'win32') and (ext != '.exe'): executable = executable + '.exe' if not os.path.isfile(executable): for dirname in paths: filename = os.path.join(dirname, executable) if os.path.isfile(filename): # the file exists, we have a shot at spawn working return filename return None return executable def sync(): """Force writing of everything to disk. No-op on systems without os.sync()""" if hasattr(os, 'sync'): os.sync() def rename(old, new): """Rename a path. Transform arguments to handle non-ASCII file paths""" os.rename(mkpath(old), mkpath(new)) if PY2: find_executable = wrap(mkpath, _find_executable, decorator=decode) else: find_executable = wrap(decode, _find_executable, decorator=decode) isdir = wrap(mkpath, os.path.isdir) isfile = wrap(mkpath, os.path.isfile) islink = wrap(mkpath, os.path.islink) listdir = wrap(mkpath, os.listdir, decorator=decode_seq) makedirs = wrap(mkpath, os.makedirs) try: readlink = wrap(mkpath, os.readlink, decorator=decode) except AttributeError: def _readlink_noop(p): return p readlink = _readlink_noop realpath = wrap(mkpath, os.path.realpath, decorator=decode) relpath = wrap(mkpath, os.path.relpath, decorator=decode) remove = wrap(mkpath, os.remove) stat = wrap(mkpath, os.stat) unlink = wrap(mkpath, os.unlink) if PY2: walk = wrap(mkpath, os.walk) else: walk = os.walk git-cola-4.6.1/cola/dag.py000066400000000000000000000024141457126473700152650ustar00rootroot00000000000000import argparse import sys from cola import app from cola.widgets.dag import git_dag def main(argv=None): """Run git-dag""" app.initialize() args = parse_args(argv=argv) return args.func(args) def shortcut_launch(): """Run git-dag from a Windows shortcut""" return main(argv=['--prompt']) def parse_args(argv=None): """Parse command-line arguments""" if argv is None: argv = sys.argv[1:] parser = argparse.ArgumentParser() parser.set_defaults(func=cmd_dag) app.add_common_arguments(parser) parser.add_argument( '-c', '--count', '--max-count', metavar='', type=int, default=1000, help='number of commits to display', ) parser.add_argument( 'args', nargs=argparse.REMAINDER, metavar='', help='git log arguments' ) args, rest = parser.parse_known_args(args=argv) if rest: # splice unknown arguments to the beginning ~ # these are forwarded to git-log(1). args.args[:0] = rest return args def cmd_dag(args): """Run git-dag via the `git cola dag` sub-command""" context = app.application_init(args) view = git_dag(context, args=args, show=False) return app.application_start(context, view) git-cola-4.6.1/cola/decorators.py000066400000000000000000000037071457126473700167050ustar00rootroot00000000000000import errno import functools __all__ = ('decorator', 'memoize', 'interruptable') 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 @functools.wraps(caller) def _decorator(func, *dummy_args, **dummy_opts): @functools.wraps(func) def _caller(*args, **opts): return caller(func, *args, **opts) return _caller _decorator.func = caller return _decorator # return a decorated function @functools.wraps(func) def _decorated(*args, **opts): return caller(func, *args, **opts) _decorated.func = func return _decorated def memoize(func): """ A decorator for memoizing function calls https://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(list(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 interruptible system calls macOS and others are known to interrupt system calls https://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 OSError as e: if e.errno in (errno.EINTR, errno.EINVAL): continue raise e break return result git-cola-4.6.1/cola/diffparse.py000066400000000000000000000355021457126473700165010ustar00rootroot00000000000000import math import re from collections import Counter from itertools import groupby from . import compat DIFF_CONTEXT = ' ' DIFF_ADDITION = '+' DIFF_DELETION = '-' DIFF_NO_NEWLINE = '\\' def parse_range_str(range_str): if ',' in range_str: begin, end = range_str.split(',', 1) return int(begin), int(end) return int(range_str), 1 def _format_range(start, count): if count == 1: return str(start) return '%d,%d' % (start, count) def _format_hunk_header(old_start, old_count, new_start, new_count, heading=''): return '@@ -{} +{} @@{}\n'.format( _format_range(old_start, old_count), _format_range(new_start, new_count), heading, ) def digits(number): """Return the number of digits needed to display a number""" if number >= 0: result = int(math.log10(number)) + 1 else: result = 1 return result class LineCounter: """Keep track of a diff range's values""" def __init__(self, value=0, max_value=-1): self.value = value self.max_value = max_value self._initial_max_value = max_value def reset(self): """Reset the max counter and return self for convenience""" self.max_value = self._initial_max_value return self def parse(self, range_str): """Parse a diff range and setup internal state""" start, count = parse_range_str(range_str) self.value = start self.max_value = max(start + count - 1, self.max_value) def tick(self, amount=1): """Return the current value and increment to the next""" value = self.value self.value += amount return value class DiffLines: """Parse diffs and gather line numbers""" EMPTY = -1 DASH = -2 def __init__(self): self.merge = False # diff # merge self.old = LineCounter() self.new = LineCounter() self.ours = LineCounter() self.theirs = LineCounter() def digits(self): return digits( max( self.old.max_value, self.new.max_value, self.ours.max_value, self.theirs.max_value, ) ) def parse(self, diff_text): lines = [] diff_state = 1 state = initial_state = 0 merge = self.merge = False no_newline = r'\ No newline at end of file' old = self.old.reset() new = self.new.reset() ours = self.ours.reset() theirs = self.theirs.reset() for text in diff_text.split('\n'): if text.startswith('@@ -'): parts = text.split(' ', 4) if parts[0] == '@@' and parts[3] == '@@': state = diff_state old.parse(parts[1][1:]) new.parse(parts[2][1:]) lines.append((self.DASH, self.DASH)) continue if text.startswith('@@@ -'): self.merge = merge = True parts = text.split(' ', 5) if parts[0] == '@@@' and parts[4] == '@@@': state = diff_state ours.parse(parts[1][1:]) theirs.parse(parts[2][1:]) new.parse(parts[3][1:]) lines.append((self.DASH, self.DASH, self.DASH)) continue if state == initial_state or text.rstrip() == no_newline: if merge: lines.append((self.EMPTY, self.EMPTY, self.EMPTY)) else: lines.append((self.EMPTY, self.EMPTY)) elif not merge and text.startswith('-'): lines.append((old.tick(), self.EMPTY)) elif merge and text.startswith('- '): lines.append((ours.tick(), self.EMPTY, self.EMPTY)) elif merge and text.startswith(' -'): lines.append((self.EMPTY, theirs.tick(), self.EMPTY)) elif merge and text.startswith('--'): lines.append((ours.tick(), theirs.tick(), self.EMPTY)) elif not merge and text.startswith('+'): lines.append((self.EMPTY, new.tick())) elif merge and text.startswith('++'): lines.append((self.EMPTY, self.EMPTY, new.tick())) elif merge and text.startswith('+ '): lines.append((self.EMPTY, theirs.tick(), new.tick())) elif merge and text.startswith(' +'): lines.append((ours.tick(), self.EMPTY, new.tick())) elif not merge and text.startswith(' '): lines.append((old.tick(), new.tick())) elif merge and text.startswith(' '): lines.append((ours.tick(), theirs.tick(), new.tick())) elif not text: new.tick() old.tick() ours.tick() theirs.tick() else: state = initial_state if merge: lines.append((self.EMPTY, self.EMPTY, self.EMPTY)) else: lines.append((self.EMPTY, self.EMPTY)) return lines class FormatDigits: """Format numbers for use in diff line numbers""" DASH = DiffLines.DASH EMPTY = DiffLines.EMPTY def __init__(self, dash='', empty=''): self.fmt = '' self.empty = '' self.dash = '' self._dash = dash or compat.uchr(0xB7) self._empty = empty or ' ' def set_digits(self, value): self.fmt = '%%0%dd' % value self.empty = self._empty * value self.dash = self._dash * value def value(self, old, new): old_str = self._format(old) new_str = self._format(new) return f'{old_str} {new_str}' def merge_value(self, old, base, new): old_str = self._format(old) base_str = self._format(base) new_str = self._format(new) return f'{old_str} {base_str} {new_str}' def number(self, value): return self.fmt % value def _format(self, value): if value == self.DASH: result = self.dash elif value == self.EMPTY: result = self.empty else: result = self.number(value) return result class _HunkGrouper: _HUNK_HEADER_RE = re.compile(r'^@@ -([0-9,]+) \+([0-9,]+) @@(.*)') def __init__(self): self.match = None def __call__(self, line): match = self._HUNK_HEADER_RE.match(line) if match is not None: self.match = match return self.match class _DiffHunk: def __init__(self, old_start, start_offset, heading, content_lines): type_counts = Counter(line[:1] for line in content_lines) self.old_count = type_counts[DIFF_CONTEXT] + type_counts[DIFF_DELETION] self.new_count = type_counts[DIFF_CONTEXT] + type_counts[DIFF_ADDITION] if self.old_count == 0: self.old_start = 0 else: self.old_start = old_start if self.new_count == 0: self.new_start = 0 elif self.old_start == 0: self.new_start = 1 else: self.new_start = self.old_start + start_offset self.heading = heading self.lines = [ _format_hunk_header( self.old_start, self.old_count, self.new_start, self.new_count, heading, ), *content_lines, ] self.content_lines = content_lines self.changes = type_counts[DIFF_DELETION] + type_counts[DIFF_ADDITION] def has_changes(self): return bool(self.changes) def line_delta(self): return self.new_count - self.old_count class Patch: """Parse and rewrite diffs to produce edited patches This parser is used for modifying the worktree and index by constructing temporary patches that are applied using "git apply". """ def __init__(self, filename, hunks, header_line_count=0): self.filename = filename self.hunks = hunks self.header_line_count = header_line_count @classmethod def parse(cls, filename, diff_text): header_line_count = 0 hunks = [] start_offset = 0 for match, hunk_lines in groupby(diff_text.split('\n'), _HunkGrouper()): if match is not None: # Skip the hunk range header line as it will be regenerated by the # _DiffHunk. next(hunk_lines) hunk = _DiffHunk( old_start=parse_range_str(match.group(1))[0], start_offset=start_offset, heading=match.group(3), content_lines=[line + '\n' for line in hunk_lines if line], ) if hunk.has_changes(): hunks.append(hunk) start_offset += hunk.line_delta() else: header_line_count = len(list(hunk_lines)) return cls(filename, hunks, header_line_count) def has_changes(self): return bool(self.hunks) def as_text(self, *, file_headers=True): lines = [] if self.hunks: if file_headers: lines.append('--- a/%s\n' % self.filename) lines.append('+++ b/%s\n' % self.filename) for hunk in self.hunks: lines.extend(hunk.lines) return ''.join(lines) def _hunk_iter(self): hunk_last_line_idx = self.header_line_count - 1 for hunk in self.hunks: hunk_first_line_idx = hunk_last_line_idx + 1 hunk_last_line_idx += len(hunk.lines) yield hunk_first_line_idx, hunk_last_line_idx, hunk @staticmethod def _reverse_content_lines(content_lines): # Normally in a diff, deletions come before additions. In order to preserve # this property in reverse patches, when this function encounters a deletion # line and switches it to addition, it appends the line to the pending_additions # list, while additions that get switched to deletions are appended directly to # the content_lines list. Each time a context line is encountered, any pending # additions are then appended to the content_lines list immediately before the # context line and the pending_additions list is cleared. new_content_lines = [] pending_additions = [] line_type = None for line in content_lines: prev_line_type = line_type line_type = line[:1] if line_type == DIFF_ADDITION: new_content_lines.append(DIFF_DELETION + line[1:]) elif line_type == DIFF_DELETION: pending_additions.append(DIFF_ADDITION + line[1:]) elif line_type == DIFF_NO_NEWLINE: if prev_line_type == DIFF_DELETION: # Previous line was a deletion that was switched to an # addition, so the "No newline" line goes with it. pending_additions.append(line) else: new_content_lines.append(line) else: new_content_lines.extend(pending_additions) new_content_lines.append(line) pending_additions = [] new_content_lines.extend(pending_additions) return new_content_lines def extract_subset(self, first_line_idx, last_line_idx, *, reverse=False): new_hunks = [] start_offset = 0 for hunk_first_line_idx, hunk_last_line_idx, hunk in self._hunk_iter(): # Skip hunks until reaching the one that contains the first selected line. if hunk_last_line_idx < first_line_idx: continue # Stop once the hunk that contains the last selected line has been # processed. if hunk_first_line_idx > last_line_idx: break content_lines = [] prev_skipped = False for hunk_line_idx, line in enumerate( hunk.content_lines, start=hunk_first_line_idx + 1 ): line_type = line[:1] if not first_line_idx <= hunk_line_idx <= last_line_idx: if line_type == DIFF_ADDITION: if reverse: # Change unselected additions to context for reverse diffs. line = DIFF_CONTEXT + line[1:] else: # Skip unselected additions for normal diffs. prev_skipped = True continue elif line_type == DIFF_DELETION: if not reverse: # Change unselected deletions to context for normal diffs. line = DIFF_CONTEXT + line[1:] else: # Skip unselected deletions for reverse diffs. prev_skipped = True continue if line_type == DIFF_NO_NEWLINE and prev_skipped: # If the line immediately before a "No newline" line was skipped # (e.g. because it was an unselected addition) skip the "No # newline" line as well continue content_lines.append(line) if reverse: old_start = hunk.new_start content_lines = self._reverse_content_lines(content_lines) else: old_start = hunk.old_start new_hunk = _DiffHunk( old_start=old_start, start_offset=start_offset, heading=hunk.heading, content_lines=content_lines, ) if new_hunk.has_changes(): new_hunks.append(new_hunk) start_offset += new_hunk.line_delta() return Patch(self.filename, new_hunks) def extract_hunk(self, line_idx, *, reverse=False): """Return a new patch containing only the hunk containing the specified line""" new_hunks = [] for _, hunk_last_line_idx, hunk in self._hunk_iter(): if line_idx <= hunk_last_line_idx: if reverse: old_start = hunk.new_start content_lines = self._reverse_content_lines(hunk.content_lines) else: old_start = hunk.old_start content_lines = hunk.content_lines new_hunks = [ _DiffHunk( old_start=old_start, start_offset=0, heading=hunk.heading, content_lines=content_lines, ) ] break return Patch(self.filename, new_hunks) git-cola-4.6.1/cola/difftool.py000066400000000000000000000231111457126473700163350ustar00rootroot00000000000000import os from qtpy import QtWidgets from qtpy.QtCore import Qt from . import cmds from . import core from . import gitcmds from . import hotkeys from . import icons from . import qtutils from . import utils from .git import EMPTY_TREE_OID from .i18n import N_ from .interaction import Interaction from .widgets import completion from .widgets import defs from .widgets import filetree from .widgets import standard class LaunchDifftool(cmds.ContextCommand): """Launch "git difftool" with the currently selected files""" @staticmethod def name(): return N_('Launch Diff Tool') def do(self): s = self.selection.selection() if s.unmerged: paths = s.unmerged if utils.is_win32(): core.fork(['git', 'mergetool', '--no-prompt', '--'] + paths) else: cfg = self.cfg cmd = cfg.terminal() argv = utils.shell_split(cmd) terminal = os.path.basename(argv[0]) shellquote_terms = {'xfce4-terminal'} shellquote_default = terminal in shellquote_terms mergetool = ['git', 'mergetool', '--no-prompt', '--'] mergetool.extend(paths) needs_shellquote = cfg.get( 'cola.terminalshellquote', shellquote_default ) if needs_shellquote: argv.append(core.list2cmdline(mergetool)) else: argv.extend(mergetool) core.fork(argv) else: difftool_run(self.context) class Difftool(standard.Dialog): def __init__( self, context, parent, a=None, b=None, expr=None, title=None, hide_expr=False, focus_tree=False, ): """Show files with differences and launch difftool""" standard.Dialog.__init__(self, parent=parent) self.context = context self.a = a self.b = b self.diff_expr = expr if title is None: title = N_('git-cola diff') self.setWindowTitle(title) self.setWindowModality(Qt.WindowModal) self.expr = completion.GitRefLineEdit(context, parent=self) if expr is not None: self.expr.setText(expr) if expr is None or hide_expr: self.expr.hide() self.tree = filetree.FileTree(parent=self) self.diff_button = qtutils.create_button( text=N_('Compare'), icon=icons.diff(), enabled=False, default=True ) self.diff_button.setShortcut(hotkeys.DIFF) self.diff_all_button = qtutils.create_button( text=N_('Compare All'), icon=icons.diff() ) self.edit_button = qtutils.edit_button() self.edit_button.setShortcut(hotkeys.EDIT) self.close_button = qtutils.close_button() self.button_layout = qtutils.hbox( defs.no_margin, defs.spacing, qtutils.STRETCH, self.close_button, self.edit_button, self.diff_all_button, self.diff_button, ) self.main_layout = qtutils.vbox( defs.margin, defs.spacing, self.expr, self.tree, self.button_layout ) self.setLayout(self.main_layout) self.tree.itemSelectionChanged.connect(self.tree_selection_changed) self.tree.itemDoubleClicked.connect(self.tree_double_clicked) self.tree.up.connect(self.focus_input) self.expr.textChanged.connect(self.text_changed) self.expr.activated.connect(self.focus_tree) self.expr.down.connect(self.focus_tree) self.expr.enter.connect(self.focus_tree) qtutils.connect_button(self.diff_button, self.diff) qtutils.connect_button(self.diff_all_button, lambda: self.diff(dir_diff=True)) qtutils.connect_button(self.edit_button, self.edit) qtutils.connect_button(self.close_button, self.close) qtutils.add_action(self, 'Focus Input', self.focus_input, hotkeys.FOCUS) qtutils.add_action( self, 'Diff All', lambda: self.diff(dir_diff=True), hotkeys.CTRL_ENTER, hotkeys.CTRL_RETURN, ) qtutils.add_close_action(self) self.init_state(None, self.resize_widget, parent) self.refresh() if focus_tree: self.focus_tree() def resize_widget(self, parent): """Set the initial size of the widget""" width, height = qtutils.default_size(parent, 720, 420) self.resize(width, height) def focus_tree(self): """Focus the files tree""" self.tree.setFocus() def focus_input(self): """Focus the expression input""" self.expr.setFocus() def text_changed(self, txt): self.diff_expr = txt self.refresh() def refresh(self): """Redo the diff when the expression changes""" if self.diff_expr is not None: self.diff_arg = utils.shell_split(self.diff_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): context = self.context if self.a and self.b is None: filenames = gitcmds.diff_index_filenames(context, self.a) else: filenames = gitcmds.diff(context, self.diff_arg) self.tree.set_filenames(filenames, select=True) def tree_selection_changed(self): has_selection = self.tree.has_selection() self.diff_button.setEnabled(has_selection) self.diff_all_button.setEnabled(has_selection) def tree_double_clicked(self, item, _column): path = filetree.filename_from_item(item) left, right = self._left_right_args() difftool_launch(self.context, left=left, right=right, paths=[path]) def diff(self, dir_diff=False): paths = self.tree.selected_filenames() left, right = self._left_right_args() difftool_launch( self.context, left=left, right=right, paths=paths, dir_diff=dir_diff ) def _left_right_args(self): if self.diff_arg: left = self.diff_arg[0] else: left = None if len(self.diff_arg) > 1: right = self.diff_arg[1] else: right = None return (left, right) def edit(self): paths = self.tree.selected_filenames() cmds.do(cmds.Edit, self.context, paths) def diff_commits(context, parent, a, b): """Show a dialog for diffing two commits""" dlg = Difftool(context, parent, a=a, b=b) dlg.show() dlg.raise_() return dlg.exec_() == QtWidgets.QDialog.Accepted def diff_expression( context, parent, expr, create_widget=False, hide_expr=False, focus_tree=False ): """Show a diff dialog for diff expressions""" dlg = Difftool( context, parent, expr=expr, hide_expr=hide_expr, focus_tree=focus_tree ) if create_widget: return dlg dlg.show() dlg.raise_() return dlg.exec_() == QtWidgets.QDialog.Accepted def difftool_run(context): """Start a default difftool session""" selection = context.selection files = selection.group() if not files: return s = selection.selection() head = context.model.head difftool_launch_with_head(context, files, bool(s.staged), head) def difftool_launch_with_head(context, filenames, staged, head): """Launch difftool against the provided head""" if head == 'HEAD': left = None else: left = head difftool_launch(context, left=left, staged=staged, paths=filenames) def difftool_launch( context, left=None, right=None, paths=None, staged=False, dir_diff=False, left_take_magic=False, left_take_parent=False, ): """Launches 'git difftool' with given parameters :param left: first argument to difftool :param right: second argument to difftool_args :param paths: paths to diff :param staged: activate `git difftool --staged` :param dir_diff: activate `git difftool --dir-diff` :param left_take_magic: whether to append the magic "^!" diff expression :param left_take_parent: whether to append the first-parent ~ for diffing """ difftool_args = ['git', 'difftool', '--no-prompt'] if staged: difftool_args.append('--cached') if dir_diff: difftool_args.append('--dir-diff') if left: if left_take_parent or left_take_magic: suffix = '^!' if left_take_magic else '~' # Check root commit (no parents and thus cannot execute '~') git = context.git status, out, err = git.rev_list(left, parents=True, n=1, _readonly=True) Interaction.log_status(status, out, err) if status: raise OSError('git rev-list command failed') if len(out.split()) >= 2: # Commit has a parent, so we can take its child as requested left += suffix else: # No parent, assume it's the root commit, so we have to diff # against the empty tree. left = EMPTY_TREE_OID if not right and left_take_magic: right = left difftool_args.append(left) if right: difftool_args.append(right) if paths: difftool_args.append('--') difftool_args.extend(paths) runtask = context.runtask if runtask: Interaction.async_command(N_('Difftool'), difftool_args, runtask) else: core.fork(difftool_args) git-cola-4.6.1/cola/display.py000066400000000000000000000035201457126473700161760ustar00rootroot00000000000000"""Display models and utility functions""" import collections def shorten_paths(source_paths): """Shorten a sequence of paths into unique strings for display""" result = {} # Start by assuming that all paths are in conflict. # On each iteration we will collect all the path suffixes, move the newly # unique entries to the result, and repeat until no conflicts remain. count = 0 conflicts = list(source_paths) in_conflict = True while in_conflict: count += 1 # Gather the suffixes for the current paths in conflict suffixes = collections.defaultdict(list) for path in conflicts: suffix = path_suffix(path, count) suffixes[suffix].append(path) # Loop over the suffixes to gather new conflicts and unique entries. conflicts = [] in_conflict = False for suffix, paths in suffixes.items(): # If only a single path exists for the suffix then no conflict # exists, and the suffix is valid. if len(paths) == 1: result[paths[0]] = suffix # If this loop runs too long then bail out by using the full path. elif count >= 128: for path in paths: result[path] = path # If multiple paths map to the same suffix then the paths are # considered in conflict, and will be reprocessed. else: conflicts.extend(paths) in_conflict = True return result def path_suffix(path, count): """Return `count` number of trailing path components""" path = normalize_path(path) components = path.split('/')[-count:] return '/'.join(components) def normalize_path(path): """Normalize a path so that only "/" is used as a separator""" return path.replace('\\', '/') git-cola-4.6.1/cola/editpatch.py000066400000000000000000000055561457126473700165110ustar00rootroot00000000000000import textwrap from . import core from . import diffparse from . import utils from .i18n import N_ from .interaction import Interaction from .models import prefs def wrap_comment(context, text): indent = prefs.comment_char(context) + ' ' return ( textwrap.fill( text, width=80, initial_indent=indent, subsequent_indent=indent, ) + '\n' ) def strip_comments(context, text): comment_char = prefs.comment_char(context) return '\n'.join( line for line in text.split('\n') if not line.startswith(comment_char) ) def patch_edit_header(context, *, reverse, apply_to_worktree): if apply_to_worktree: header = N_( 'Edit the following patch, which will then be applied to the worktree to' ' revert the changes:' ) else: if reverse: header = N_( 'Edit the following patch, which will then be applied to the staging' ' area to unstage the changes:' ) else: header = N_( 'Edit the following patch, which will then be applied to the staging' ' area to stage the changes:' ) return wrap_comment(context, header) def patch_edit_footer(context): parts = [ '---', N_( "To avoid applying removal lines ('-'), change them to context lines (' ')." ), N_("To avoid applying addition lines ('+'), delete them."), N_('To abort applying this patch, remove all lines.'), N_("Lines starting with '%s' will be ignored.") % prefs.comment_char(context), N_( 'It is not necessary to update the hunk header lines as they will be' ' regenerated automatically.' ), ] return ''.join(wrap_comment(context, part) for part in parts) def edit_patch(patch, encoding, context, *, reverse, apply_to_worktree): patch_file_path = utils.tmp_filename('edit', '.patch') try: content_parts = [ patch_edit_header( context, reverse=reverse, apply_to_worktree=apply_to_worktree ), patch.as_text(file_headers=False), patch_edit_footer(context), ] core.write(patch_file_path, ''.join(content_parts), encoding=encoding) status, _, _ = core.run_command( [*utils.shell_split(prefs.editor(context)), patch_file_path] ) if status == 0: patch_text = strip_comments( context, core.read(patch_file_path, encoding=encoding) ) else: Interaction.log( N_('Editor returned %s exit code. Not applying patch.') % status ) patch_text = '' return diffparse.Patch.parse(patch.filename, patch_text) finally: core.unlink(patch_file_path) git-cola-4.6.1/cola/fsmonitor.py000066400000000000000000000467211457126473700165630ustar00rootroot00000000000000# Copyright (C) 2008-2024 David Aguilar # Copyright (C) 2015 Daniel Harding """Filesystem monitor for Linux and Windows Linux monitoring uses using inotify. Windows monitoring uses pywin32 and the ReadDirectoryChanges function. """ import errno import os import os.path import select from threading import Lock from qtpy import QtCore from qtpy.QtCore import Signal from . import utils from . import core from . import gitcmds from . import version from .compat import bchr from .i18n import N_ from .interaction import Interaction AVAILABLE = None pywintypes = None win32file = None win32con = None win32event = None if utils.is_win32(): try: import pywintypes import win32con import win32event import win32file AVAILABLE = 'pywin32' except ImportError: pass elif utils.is_linux(): try: from . import inotify except ImportError: pass else: AVAILABLE = 'inotify' class _Monitor(QtCore.QObject): files_changed = Signal() config_changed = Signal() def __init__(self, context, thread_class): QtCore.QObject.__init__(self) self.context = context self._thread_class = thread_class self._thread = None def start(self): if self._thread_class is not None: assert self._thread is None self._thread = self._thread_class(self.context, self) self._thread.start() def stop(self): if self._thread_class is not None: assert self._thread is not None self._thread.stop() self._thread.wait() self._thread = None def refresh(self): if self._thread is not None: self._thread.refresh() class _BaseThread(QtCore.QThread): #: The delay, in milliseconds, between detecting file system modification #: and triggering the 'files_changed' signal, to coalesce multiple #: modifications into a single signal. _NOTIFICATION_DELAY = 888 def __init__(self, context, monitor): QtCore.QThread.__init__(self) self.context = context self._monitor = monitor self._running = True self._use_check_ignore = version.check_git(context, 'check-ignore') self._force_notify = False self._force_config = False self._file_paths = set() @property def _pending(self): return self._force_notify or self._file_paths or self._force_config def refresh(self): """Do any housekeeping necessary in response to repository changes.""" return def notify(self): """Notifies all observers""" do_notify = False do_config = False if self._force_config: do_config = True if self._force_notify: do_notify = True elif self._file_paths: proc = core.start_command( ['git', 'check-ignore', '--verbose', '--non-matching', '-z', '--stdin'] ) path_list = bchr(0).join(core.encode(path) for path in self._file_paths) out, _ = proc.communicate(path_list) if proc.returncode: do_notify = True else: # Each output record is four fields separated by NULL # characters (records are also separated by NULL characters): # # For paths which are not ignored, all fields will be empty # except for . So to see if we have any non-ignored # files, we simply check every fourth field to see if any of # them are empty. source_fields = out.split(bchr(0))[0:-1:4] do_notify = not all(source_fields) self._force_notify = False self._force_config = False self._file_paths = set() # "files changed" is a bigger hammer than "config changed". # and is a superset relative to what is done in response to the # signal. Thus, the "elif" below avoids repeated work that # would be done if it were a simple "if" check instead. if do_notify: self._monitor.files_changed.emit() elif do_config: self._monitor.config_changed.emit() @staticmethod def _log_enabled_message(): msg = N_('File system change monitoring: enabled.\n') Interaction.log(msg) if AVAILABLE == 'inotify': class _InotifyThread(_BaseThread): _TRIGGER_MASK = ( inotify.IN_ATTRIB | inotify.IN_CLOSE_WRITE | inotify.IN_CREATE | inotify.IN_DELETE | inotify.IN_MODIFY | inotify.IN_MOVED_FROM | inotify.IN_MOVED_TO ) _ADD_MASK = _TRIGGER_MASK | inotify.IN_EXCL_UNLINK | inotify.IN_ONLYDIR def __init__(self, context, monitor): _BaseThread.__init__(self, context, monitor) git = context.git worktree = git.worktree() if worktree is not None: worktree = core.abspath(worktree) self._worktree = worktree self._git_dir = git.git_path() self._lock = Lock() self._inotify_fd = None self._pipe_r = None self._pipe_w = None self._worktree_wd_to_path_map = {} self._worktree_path_to_wd_map = {} self._git_dir_wd_to_path_map = {} self._git_dir_path_to_wd_map = {} self._git_dir_wd = None @staticmethod def _log_out_of_wds_message(): msg = N_( 'File system change monitoring: disabled because the' ' limit on the total number of inotify watches was' ' reached. You may be able to increase the limit on' ' the number of watches by running:\n' '\n' ' echo fs.inotify.max_user_watches=100000 |' ' sudo tee -a /etc/sysctl.conf &&' ' sudo sysctl -p\n' ) Interaction.log(msg) def run(self): try: with self._lock: try: self._inotify_fd = inotify.init() except OSError as e: self._inotify_fd = None self._running = False if e.errno == errno.EMFILE: self._log_out_of_wds_message() return self._pipe_r, self._pipe_w = os.pipe() poll_obj = select.poll() poll_obj.register(self._inotify_fd, select.POLLIN) poll_obj.register(self._pipe_r, select.POLLIN) self.refresh() if self._running: self._log_enabled_message() self._process_events(poll_obj) finally: self._close_fds() def _process_events(self, poll_obj): while self._running: if self._pending: timeout = self._NOTIFICATION_DELAY else: timeout = None try: events = poll_obj.poll(timeout) except OSError: continue else: if not self._running: break if not events: self.notify() else: for fd, _ in events: if fd == self._inotify_fd: self._handle_events() def _close_fds(self): with self._lock: if self._inotify_fd is not None: os.close(self._inotify_fd) self._inotify_fd = None if self._pipe_r is not None: os.close(self._pipe_r) self._pipe_r = None os.close(self._pipe_w) self._pipe_w = None def refresh(self): with self._lock: self._refresh() def _refresh(self): if self._inotify_fd is None: return context = self.context try: if self._worktree is not None: tracked_dirs = { os.path.dirname(os.path.join(self._worktree, path)) for path in gitcmds.tracked_files(context) } self._refresh_watches( tracked_dirs, self._worktree_wd_to_path_map, self._worktree_path_to_wd_map, ) git_dirs = set() git_dirs.add(self._git_dir) for dirpath, _, _ in core.walk(os.path.join(self._git_dir, 'refs')): git_dirs.add(dirpath) self._refresh_watches( git_dirs, self._git_dir_wd_to_path_map, self._git_dir_path_to_wd_map ) self._git_dir_wd = self._git_dir_path_to_wd_map.get(self._git_dir) except OSError as e: if e.errno in (errno.ENOSPC, errno.EMFILE): self._log_out_of_wds_message() self._running = False else: raise def _refresh_watches(self, paths_to_watch, wd_to_path_map, path_to_wd_map): watched_paths = set(path_to_wd_map) for path in watched_paths - paths_to_watch: wd = path_to_wd_map.pop(path) wd_to_path_map.pop(wd) try: inotify.rm_watch(self._inotify_fd, wd) except OSError as e: if e.errno == errno.EINVAL: # This error can occur if the target of the watch was # removed on the filesystem before we call # inotify.rm_watch() so ignore it. continue raise e for path in paths_to_watch - watched_paths: try: wd = inotify.add_watch( self._inotify_fd, core.encode(path), self._ADD_MASK ) except PermissionError: continue except OSError as e: if e.errno in (errno.ENOENT, errno.ENOTDIR): # These two errors should only occur as a result of # race conditions: the first if the directory # referenced by path was removed or renamed before the # call to inotify.add_watch(); the second if the # directory referenced by path was replaced with a file # before the call to inotify.add_watch(). Therefore we # simply ignore them. continue raise e wd_to_path_map[wd] = path path_to_wd_map[path] = wd def _check_event(self, wd, mask, name): if mask & inotify.IN_Q_OVERFLOW: self._force_notify = True elif not mask & self._TRIGGER_MASK: pass elif mask & inotify.IN_ISDIR: pass elif wd in self._worktree_wd_to_path_map: if self._use_check_ignore and name: path = os.path.join( self._worktree_wd_to_path_map[wd], core.decode(name) ) self._file_paths.add(path) else: self._force_notify = True elif wd == self._git_dir_wd: name = core.decode(name) if name in ('HEAD', 'index'): self._force_notify = True elif name == 'config': self._force_config = True elif wd in self._git_dir_wd_to_path_map and not core.decode(name).endswith( '.lock' ): self._force_notify = True def _handle_events(self): for wd, mask, _, name in inotify.read_events(self._inotify_fd): if not self._force_notify: self._check_event(wd, mask, name) def stop(self): self._running = False with self._lock: if self._pipe_w is not None: os.write(self._pipe_w, bchr(0)) self.wait() if AVAILABLE == 'pywin32': class _Win32Watch: def __init__(self, path, flags): self.flags = flags self.handle = None self.event = None try: self.handle = win32file.CreateFileW( path, 0x0001, # FILE_LIST_DIRECTORY win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, None, win32con.OPEN_EXISTING, win32con.FILE_FLAG_BACKUP_SEMANTICS | win32con.FILE_FLAG_OVERLAPPED, None, ) self.buffer = win32file.AllocateReadBuffer(8192) self.event = win32event.CreateEvent(None, True, False, None) self.overlapped = pywintypes.OVERLAPPED() self.overlapped.hEvent = self.event self._start() except Exception: self.close() def append(self, events): """Append our event to the events list when valid""" if self.event is not None: events.append(self.event) def _start(self): if self.handle is None: return win32file.ReadDirectoryChangesW( self.handle, self.buffer, True, self.flags, self.overlapped ) def read(self): if self.handle is None or self.event is None: return [] if win32event.WaitForSingleObject(self.event, 0) == win32event.WAIT_TIMEOUT: result = [] else: nbytes = win32file.GetOverlappedResult( self.handle, self.overlapped, False ) result = win32file.FILE_NOTIFY_INFORMATION(self.buffer, nbytes) self._start() return result def close(self): if self.handle is not None: win32file.CancelIo(self.handle) win32file.CloseHandle(self.handle) if self.event is not None: win32file.CloseHandle(self.event) class _Win32Thread(_BaseThread): _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 ) def __init__(self, context, monitor): _BaseThread.__init__(self, context, monitor) git = context.git worktree = git.worktree() if worktree is not None: worktree = self._transform_path(core.abspath(worktree)) self._worktree = worktree self._worktree_watch = None self._git_dir = self._transform_path(core.abspath(git.git_path())) self._git_dir_watch = None self._stop_event_lock = Lock() self._stop_event = None @staticmethod def _transform_path(path): return path.replace('\\', '/').lower() def run(self): try: with self._stop_event_lock: self._stop_event = win32event.CreateEvent(None, True, False, None) events = [self._stop_event] if self._worktree is not None: self._worktree_watch = _Win32Watch(self._worktree, self._FLAGS) self._worktree_watch.append(events) self._git_dir_watch = _Win32Watch(self._git_dir, self._FLAGS) self._git_dir_watch.append(events) self._log_enabled_message() while self._running: if self._pending: timeout = self._NOTIFICATION_DELAY else: timeout = win32event.INFINITE status = win32event.WaitForMultipleObjects(events, False, timeout) if not self._running: break if status == win32event.WAIT_TIMEOUT: self.notify() else: self._handle_results() finally: with self._stop_event_lock: if self._stop_event is not None: win32file.CloseHandle(self._stop_event) self._stop_event = None if self._worktree_watch is not None: self._worktree_watch.close() if self._git_dir_watch is not None: self._git_dir_watch.close() def _handle_results(self): if self._worktree_watch is not None: for _, path in self._worktree_watch.read(): if not self._running: break if self._force_notify: continue path = self._worktree + '/' + self._transform_path(path) if ( path != self._git_dir and not path.startswith(self._git_dir + '/') and not os.path.isdir(path) ): if self._use_check_ignore: self._file_paths.add(path) else: self._force_notify = True for _, path in self._git_dir_watch.read(): if not self._running: break if self._force_notify: continue path = self._transform_path(path) if path.endswith('.lock'): continue if path == 'config': self._force_config = True continue if path == 'head' or path == 'index' or path.startswith('refs/'): self._force_notify = True def stop(self): self._running = False with self._stop_event_lock: if self._stop_event is not None: win32event.SetEvent(self._stop_event) self.wait() def create(context): thread_class = None cfg = context.cfg if not cfg.get('cola.inotify', default=True): msg = N_( 'File system change monitoring: disabled because' ' "cola.inotify" is false.\n' ) Interaction.log(msg) elif AVAILABLE == 'inotify': thread_class = _InotifyThread elif AVAILABLE == 'pywin32': thread_class = _Win32Thread else: if utils.is_win32(): msg = N_( 'File system change monitoring: disabled because pywin32' ' is not installed.\n' ) Interaction.log(msg) elif utils.is_linux(): msg = N_( 'File system change monitoring: disabled because libc' ' does not support the inotify system calls.\n' ) Interaction.log(msg) return _Monitor(context, thread_class) git-cola-4.6.1/cola/git.py000066400000000000000000000340641457126473700153230ustar00rootroot00000000000000from functools import partial import errno import os from os.path import join import subprocess import threading import time from . import core from .compat import int_types from .compat import ustr from .compat import WIN32 from .decorators import memoize from .interaction import Interaction GIT_COLA_TRACE = core.getenv('GIT_COLA_TRACE', '') GIT = core.getenv('GIT_COLA_GIT', 'git') STATUS = 0 STDOUT = 1 STDERR = 2 # Object ID / SHA-1-related constants # Git's empty tree is a built-in constant object name. EMPTY_TREE_OID = '4b825dc642cb6eb9a060e54bf8d69288fbee4904' # Git's diff machinery returns zeroes for modified files whose content exists # in the worktree only. MISSING_BLOB_OID = '0000000000000000000000000000000000000000' # Git's SHA-1 object IDs are 40 characters long. # This will need to change when Git moves away from SHA-1. # When that happens we'll have to detect and update this at runtime in # order to support both old and new git. OID_LENGTH = 40 _index_lock = threading.Lock() def dashify(value): return value.replace('_', '-') def is_git_dir(git_dir): """From git's setup.c:is_git_directory().""" result = False if git_dir: headref = join(git_dir, 'HEAD') if ( core.isdir(git_dir) and ( core.isdir(join(git_dir, 'objects')) and core.isdir(join(git_dir, 'refs')) ) or ( core.isfile(join(git_dir, 'gitdir')) and core.isfile(join(git_dir, 'commondir')) ) ): result = core.isfile(headref) or ( core.islink(headref) and core.readlink(headref).startswith('refs/') ) else: result = is_git_file(git_dir) return result def is_git_file(filename): return core.isfile(filename) and os.path.basename(filename) == '.git' def is_git_worktree(dirname): return is_git_dir(join(dirname, '.git')) def is_git_repository(path): return is_git_worktree(path) or is_git_dir(path) def read_git_file(path): """Read the path from a .git-file `None` is returned when is not a .git-file. """ result = None if path and is_git_file(path): header = 'gitdir: ' data = core.read(path).strip() if data.startswith(header): result = data[len(header) :] if result and not os.path.isabs(result): path_folder = os.path.dirname(path) repo_relative = join(path_folder, result) result = os.path.normpath(repo_relative) return result class Paths: """Git repository paths of interest""" def __init__(self, git_dir=None, git_file=None, worktree=None, common_dir=None): if git_dir and not is_git_dir(git_dir): git_dir = None self.git_dir = git_dir self.git_file = git_file self.worktree = worktree self.common_dir = common_dir def get(self, path): ceiling_dirs = set() ceiling = core.getenv('GIT_CEILING_DIRECTORIES') if ceiling: ceiling_dirs.update([x for x in ceiling.split(os.pathsep) if x]) if path: path = core.abspath(path) if not self.git_dir or not self.worktree: # Search for a .git directory while path: if path in ceiling_dirs: break if is_git_dir(path): if not self.git_dir: self.git_dir = path basename = os.path.basename(path) if not self.worktree and basename == '.git': self.worktree = os.path.dirname(path) # We are either in a bare repository, or someone set GIT_DIR # but did not set GIT_WORK_TREE. if self.git_dir: if not self.worktree: basename = os.path.basename(self.git_dir) if basename == '.git': self.worktree = os.path.dirname(self.git_dir) elif path and not is_git_dir(path): self.worktree = path break gitpath = join(path, '.git') if is_git_dir(gitpath): if not self.git_dir: self.git_dir = gitpath if not self.worktree: self.worktree = path break path, dummy = os.path.split(path) if not dummy: break if self.git_dir: git_dir_path = read_git_file(self.git_dir) if git_dir_path: self.git_file = self.git_dir self.git_dir = git_dir_path commondir_file = join(git_dir_path, 'commondir') if core.exists(commondir_file): common_path = core.read(commondir_file).strip() if common_path: if os.path.isabs(common_path): common_dir = common_path else: common_dir = join(git_dir_path, common_path) common_dir = os.path.normpath(common_dir) self.common_dir = common_dir # usage: Paths().get() return self def find_git_directory(path): """Perform Git repository discovery""" return Paths( git_dir=core.getenv('GIT_DIR'), worktree=core.getenv('GIT_WORK_TREE') ).get(path) class Git: """ The Git class manages communication with the Git binary """ def __init__(self): self.paths = Paths() self._valid = {} #: Store the result of is_git_dir() for performance self.set_worktree(core.getcwd()) def is_git_repository(self, path): return is_git_repository(path) def getcwd(self): """Return the working directory used by git()""" return self.paths.worktree or self.paths.git_dir def set_worktree(self, path): path = core.decode(path) self.paths = find_git_directory(path) return self.paths.worktree def worktree(self): if not self.paths.worktree: path = core.abspath(core.getcwd()) self.paths = find_git_directory(path) return self.paths.worktree def is_valid(self): """Is this a valid git repository? Cache the result to avoid hitting the filesystem. """ git_dir = self.paths.git_dir try: valid = bool(git_dir) and self._valid[git_dir] except KeyError: valid = self._valid[git_dir] = is_git_dir(git_dir) return valid def git_path(self, *paths): result = None if self.paths.git_dir: result = join(self.paths.git_dir, *paths) if result and self.paths.common_dir and not core.exists(result): common_result = join(self.paths.common_dir, *paths) if core.exists(common_result): result = common_result return result def git_dir(self): if not self.paths.git_dir: path = core.abspath(core.getcwd()) self.paths = find_git_directory(path) return self.paths.git_dir def __getattr__(self, name): git_cmd = partial(self.git, name) setattr(self, name, git_cmd) return git_cmd @staticmethod def execute( command, _cwd=None, _decode=True, _encoding=None, _raw=False, _stdin=None, _stderr=subprocess.PIPE, _stdout=subprocess.PIPE, _readonly=False, _no_win32_startupinfo=False, ): """ 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 _readonly: avoid taking the index lock. Assume the command is read-only. :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 hasattr(os, 'setsid'): # SSH uses the SSH_ASKPASS variable only if the process is really # detached from the TTY (stdin redirection and setting the # SSH_ASKPASS environment variable is not enough). To detach a # process from the console it should fork and call os.setsid(). extra['preexec_fn'] = os.setsid start_time = time.time() # Start the process # Guard against thread-unsafe .git/index.lock files if not _readonly: _index_lock.acquire() try: status, out, err = core.run_command( command, cwd=_cwd, encoding=_encoding, stdin=_stdin, stdout=_stdout, stderr=_stderr, no_win32_startupinfo=_no_win32_startupinfo, **extra, ) finally: # Let the next thread in if not _readonly: _index_lock.release() end_time = time.time() elapsed_time = abs(end_time - start_time) if not _raw and out is not None: out = core.UStr(out.rstrip('\n'), out.encoding) cola_trace = GIT_COLA_TRACE if cola_trace == 'trace': msg = f'trace: {elapsed_time:.3f}s: {core.list2cmdline(command)}' Interaction.log_status(status, msg, '') elif cola_trace == 'full': if out or err: core.print_stderr( "# %.3fs: %s -> %d: '%s' '%s'" % (elapsed_time, ' '.join(command), status, out, err) ) else: core.print_stderr( '# %.3fs: %s -> %d' % (elapsed_time, ' '.join(command), status) ) elif cola_trace: core.print_stderr('# {:.3f}s: {}'.format(elapsed_time, ' '.join(command))) # Allow access to the command's status code return (status, out, err) def git(self, cmd, *args, **kwargs): # Handle optional arguments prior to calling transform_kwargs # otherwise they'll end up in args, which is bad. _kwargs = {'_cwd': self.getcwd()} execute_kwargs = ( '_cwd', '_decode', '_encoding', '_stdin', '_stdout', '_stderr', '_raw', '_readonly', '_no_win32_startupinfo', ) for kwarg in execute_kwargs: if kwarg in kwargs: _kwargs[kwarg] = kwargs.pop(kwarg) # Prepare the argument list git_args = [ GIT, '-c', 'diff.suppressBlankEmpty=false', '-c', 'log.showSignature=false', dashify(cmd), ] opt_args = transform_kwargs(**kwargs) call = git_args + opt_args call.extend(args) try: result = self.execute(call, **_kwargs) except OSError as exc: if WIN32 and exc.errno == errno.ENOENT: # see if git exists at all. On win32 it can fail with ENOENT in # case of argv overflow. We should be safe from that but use # defensive coding for the worst-case scenario. On UNIX # we have ENAMETOOLONG but that doesn't exist on Windows. if _git_is_installed(): raise exc _print_win32_git_hint() result = (1, '', "error: unable to execute '%s'" % GIT) return result def _git_is_installed(): """Return True if git is installed""" # On win32 Git commands can fail with ENOENT in case of argv overflow. We # should be safe from that but use defensive coding for the worst-case # scenario. On UNIX we have ENAMETOOLONG but that doesn't exist on # Windows. try: status, _, _ = Git.execute([GIT, '--version']) result = status == 0 except OSError: result = False return result def transform_kwargs(**kwargs): """Transform kwargs into git command line options Callers can assume the following behavior: Passing foo=None ignores foo, so that callers can use default values of None that are ignored unless set explicitly. Passing foo=False ignore foo, for the same reason. Passing foo={string-or-number} results in ['--foo='] in the resulting arguments. """ args = [] types_to_stringify = (ustr, float, str) + int_types for k, value in kwargs.items(): if len(k) == 1: dashes = '-' equals = '' else: dashes = '--' equals = '=' # isinstance(False, int) is True, so we have to check bool first if isinstance(value, bool): if value: args.append(f'{dashes}{dashify(k)}') # else: pass # False is ignored; flag=False inhibits --flag elif isinstance(value, types_to_stringify): args.append(f'{dashes}{dashify(k)}{equals}{value}') return args def win32_git_error_hint(): return ( '\n' 'NOTE: If you have Git installed in a custom location, e.g.\n' 'C:\\Tools\\Git, then you can create a file at\n' '~/.config/git-cola/git-bindir with following text\n' 'and git-cola will add the specified location to your $PATH\n' 'automatically when starting cola:\n' '\n' r'C:\Tools\Git\bin' ) @memoize def _print_win32_git_hint(): hint = '\n' + win32_git_error_hint() + '\n' core.print_stderr("error: unable to execute 'git'" + hint) def create(): """Create Git instances >>> git = create() >>> status, out, err = git.version() >>> 'git' == out[:3].lower() True """ return Git() git-cola-4.6.1/cola/gitcfg.py000066400000000000000000000540471457126473700160060ustar00rootroot00000000000000from binascii import unhexlify import collections import copy import fnmatch import os import struct try: import pwd _use_pwd = True except ImportError: _use_pwd = False from qtpy import QtCore from qtpy.QtCore import Signal from . import core from . import utils from . import version from . import resources from .compat import int_types from .compat import ustr def create(context): """Create GitConfig instances""" return GitConfig(context) def _cache_key_from_paths(paths): """Return a stat cache from the given paths""" if not paths: return None mtimes = [] for path in sorted(paths): try: mtimes.append(core.stat(path).st_mtime) except OSError: continue if mtimes: return mtimes return None def _config_to_python(value): """Convert a Git config string into a Python value""" if value in ('true', 'yes'): value = True elif value in ('false', 'no'): value = False else: try: value = int(value) except ValueError: pass return value def unhex(value): """Convert a value (int or hex string) into bytes""" if isinstance(value, int_types): # If the value is an integer then it's a value that was converted # by the config reader. Zero-pad it into a 6-digit hex number. value = '%06d' % value return unhexlify(core.encode(value.lstrip('#'))) def _config_key_value(line, splitchar): """Split a config line into a (key, value) pair""" try: k, v = line.split(splitchar, 1) except ValueError: # the user has an empty entry in their git config, # which Git interprets as meaning "true" k = line v = 'true' return k, _config_to_python(v) def _append_tab(value): """Return a value and the same value with tab appended""" return (value, value + '\t') class GitConfig(QtCore.QObject): """Encapsulate access to git-config values.""" user_config_changed = Signal(str, object) repo_config_changed = Signal(str, object) updated = Signal() def __init__(self, context): super().__init__() self.context = context self.git = context.git self._system = {} self._global = {} self._global_or_system = {} self._local = {} self._all = {} self._renamed_keys = {} self._multi_values = collections.defaultdict(list) self._cache_key = None self._cache_paths = [] self._attr_cache = {} self._binary_cache = {} def reset(self): self._cache_key = None self._cache_paths = [] self._attr_cache.clear() self._binary_cache.clear() self.reset_values() def reset_values(self): self._system.clear() self._global.clear() self._global_or_system.clear() self._local.clear() self._all.clear() self._renamed_keys.clear() self._multi_values.clear() def user(self): return copy.deepcopy(self._global) def repo(self): return copy.deepcopy(self._local) def all(self): return copy.deepcopy(self._all) def _is_cached(self): """ Return True when the cache matches. Updates the cache and returns False when the cache does not match. """ cache_key = _cache_key_from_paths(self._cache_paths) return self._cache_key and cache_key == self._cache_key def update(self): """Read git config value into the system, user and repo dicts.""" if self._is_cached(): return self.reset_values() show_scope = version.check_git(self.context, 'config-show-scope') show_origin = version.check_git(self.context, 'config-show-origin') if show_scope: reader = _read_config_with_scope elif show_origin: reader = _read_config_with_origin else: reader = _read_config_fallback unknown_scope = 'unknown' system_scope = 'system' global_scope = 'global' local_scope = 'local' worktree_scope = 'worktree' cache_paths = set() for current_scope, current_key, current_value, continuation in reader( self.context, cache_paths, self._renamed_keys ): # Store the values for fast cached lookup. self._all[current_key] = current_value # macOS has credential.helper=osxkeychain in the "unknown" scope from # /Applications/Xcode.app/Contents/Developer/usr/share/git-core/gitconfig. # Treat "unknown" as equivalent to "system" (lowest priority). if current_scope in (system_scope, unknown_scope): self._system[current_key] = current_value self._global_or_system[current_key] = current_value elif current_scope == global_scope: self._global[current_key] = current_value self._global_or_system[current_key] = current_value # "worktree" is treated as equivalent to "local". elif current_scope in (local_scope, worktree_scope): self._local[current_key] = current_value # Add this value to the multi-values storage used by get_all(). # This allows us to handle keys that store multiple values. if continuation: # If this is a continuation line then we should *not* append to its # multi-values list. We should update it in-place. self._multi_values[current_key][-1] = current_value else: self._multi_values[current_key].append(current_value) # Update the cache self._cache_paths = sorted(cache_paths) self._cache_key = _cache_key_from_paths(self._cache_paths) # Send a notification that the configuration has been updated. self.updated.emit() def _get(self, src, key, default, func=None, cached=True): if not cached or not src: self.update() try: value = self._get_value(src, key) except KeyError: if func: value = func() else: value = default return value def _get_value(self, src, key): """Return a value from the map""" try: return src[key] except KeyError: pass # Try the original key name. key = self._renamed_keys.get(key.lower(), key) try: return src[key] except KeyError: pass # Allow the final KeyError to bubble up return src[key.lower()] def get(self, key, default=None, func=None, cached=True): """Return the string value for a config key.""" return self._get(self._all, key, default, func=func, cached=cached) def get_all(self, key): """Return all values for a key sorted in priority order The purpose of this function is to group the values returned by `git config --show-origin --list` so that the relative order is preserved and can be overridden at each level. One use case is the `cola.icontheme` variable, which is an ordered list of icon themes to load. This value can be set both in ~/.gitconfig as well as .git/config, and we want to allow a relative order to be defined in either file. The problem is that git will read the system /etc/gitconfig, global ~/.gitconfig, and then the local .git/config settings and return them in that order, so we must post-process them to get them in an order which makes sense for use for our values. Otherwise, we cannot replace the order, or make a specific theme used first, in our local .git/config since the native order returned by git will always list the global config before the local one. get_all() allows for this use case by reading from a defaultdict that contains all of the per-config values separately so that the caller can order them according to its preferred precedence. """ if not self._multi_values: self.update() # Check for this key as-is. if key in self._multi_values: return self._multi_values[key] # Check for a renamed version of this key (x.kittycat -> x.kittyCat) renamed_key = self._renamed_keys.get(key.lower(), key) if renamed_key in self._multi_values: return self._multi_values[renamed_key] key_lower = key.lower() if key_lower in self._multi_values: return self._multi_values[key_lower] # Nothing found -> empty list. return [] def get_user(self, key, default=None): return self._get(self._global, key, default) def get_repo(self, key, default=None): return self._get(self._local, key, default) def get_user_or_system(self, key, default=None): return self._get(self._global_or_system, key, default) def set_user(self, key, value): if value in (None, ''): self.git.config('--global', key, unset=True, _readonly=True) else: self.git.config('--global', key, python_to_git(value), _readonly=True) self.update() self.user_config_changed.emit(key, value) def set_repo(self, key, value): if value in (None, ''): self.git.config(key, unset=True, _readonly=True) else: self.git.config(key, python_to_git(value), _readonly=True) self.update() self.repo_config_changed.emit(key, value) def find(self, pat): """Return a dict of values for all keys matching the specified pattern""" pat = pat.lower() match = fnmatch.fnmatch result = {} if not self._all: self.update() for key, val in self._all.items(): if match(key.lower(), pat): result[key] = val return result def is_annex(self): """Return True when git-annex is enabled""" return bool(self.get('annex.uuid', default=False)) def gui_encoding(self): return self.get('gui.encoding', default=None) def is_per_file_attrs_enabled(self): return self.get( 'cola.fileattributes', func=lambda: os.path.exists('.gitattributes') ) def is_binary(self, path): """Return True if the file has the binary attribute set""" if not self.is_per_file_attrs_enabled(): return None cache = self._binary_cache try: value = cache[path] except KeyError: value = cache[path] = self._is_binary(path) return value def _is_binary(self, path): """Return the file encoding for a path""" value = self.check_attr('binary', path) return value == 'set' def file_encoding(self, path): if not self.is_per_file_attrs_enabled(): return self.gui_encoding() cache = self._attr_cache try: value = cache[path] except KeyError: value = cache[path] = self._file_encoding(path) or self.gui_encoding() return value def _file_encoding(self, path): """Return the file encoding for a path""" encoding = self.check_attr('encoding', path) if encoding in ('unspecified', 'unset', 'set'): result = None else: result = encoding return result def check_attr(self, attr, path): """Check file attributes for a path""" value = None status, out, _ = self.git.check_attr(attr, '--', path, _readonly=True) if status == 0: header = f'{path}: {attr}: ' if out.startswith(header): value = out[len(header) :].strip() return value def get_author(self): """Return (name, email) for authoring commits""" if _use_pwd: user = pwd.getpwuid(os.getuid()).pw_name else: user = os.getenv('USER', 'unknown') name = self.get('user.name', user) email = self.get('user.email', f'{user}@{core.node()}') return (name, email) def get_guitool_opts(self, name): """Return the guitool. namespace as a dict The dict keys are simplified so that "guitool.$name.cmd" is accessible as `opts[cmd]`. """ prefix = len('guitool.%s.' % name) guitools = self.find('guitool.%s.*' % name) return {key[prefix:]: value for (key, value) in guitools.items()} def get_guitool_names(self): guitools = self.find('guitool.*.cmd') prefix = len('guitool.') suffix = len('.cmd') return sorted([name[prefix:-suffix] for (name, _) in guitools.items()]) def get_guitool_names_and_shortcuts(self): """Return guitool names and their configured shortcut""" names = self.get_guitool_names() return [(name, self.get('guitool.%s.shortcut' % name)) for name in names] def terminal(self): """Return a suitable terminal command for running a shell""" term = self.get('cola.terminal', default=None) if term: return term # find a suitable default terminal if utils.is_win32(): # Try to find Git's sh.exe directory in # one of the typical locations pf = os.environ.get('ProgramFiles', r'C:\Program Files') pf32 = os.environ.get('ProgramFiles(x86)', r'C:\Program Files (x86)') pf64 = os.environ.get('ProgramW6432', r'C:\Program Files') for p in [pf64, pf32, pf, 'C:\\']: candidate = os.path.join(p, r'Git\bin\sh.exe') if os.path.isfile(candidate): return candidate return None # If no terminal has been configured then we'll look for the following programs # and use the first one we find. terminals = ( # (, for running arbitrary commands) ('kitty', 'kitty'), ('alacritty', 'alacritty -e'), ('uxterm', 'uxterm -e'), ('konsole', 'konsole -e'), ('gnome-terminal', 'gnome-terminal --'), ('mate-terminal', 'mate-terminal --'), ('xterm', 'xterm -e'), ) for executable, command in terminals: if core.find_executable(executable): return command return None def color(self, key, default): value = self.get('cola.color.%s' % key, default=default) struct_layout = core.encode('BBB') try: red, green, blue = struct.unpack(struct_layout, unhex(value)) except (struct.error, TypeError): red, green, blue = struct.unpack(struct_layout, unhex(default)) return (red, green, blue) def hooks(self): """Return the path to the git hooks directory""" gitdir_hooks = self.git.git_path('hooks') return self.get('core.hookspath', default=gitdir_hooks) def hooks_path(self, *paths): """Return a path from within the git hooks directory""" return os.path.join(self.hooks(), *paths) def _read_config_with_scope(context, cache_paths, renamed_keys): """Read the output from "git config --show-scope --show-origin --list ``--show-scope`` was introduced in Git v2.26.0. """ unknown_key = 'unknown\t' system_key = 'system\t' global_key = 'global\t' local_key = 'local\t' worktree_key = 'worktree\t' command_scope, command_key = _append_tab('command') command_line = 'command line:' file_scheme = 'file:' current_value = '' current_key = '' current_scope = '' current_path = '' status, config_output, _ = context.git.config( show_origin=True, show_scope=True, list=True, includes=True ) if status != 0: return for line in config_output.splitlines(): if not line: continue if ( line.startswith(system_key) or line.startswith(global_key) or line.startswith(local_key) or line.startswith(command_key) or line.startswith(worktree_key) # worktree and unknown are uncommon. or line.startswith(unknown_key) ): continuation = False current_scope, current_path, rest = line.split('\t', 2) if current_scope == command_scope: continue current_key, current_value = _config_key_value(rest, '=') if current_path.startswith(file_scheme): cache_paths.add(current_path[len(file_scheme) :]) elif current_path == command_line: continue renamed_keys[current_key.lower()] = current_key else: # Values are allowed to span multiple lines when \n is embedded # in the value. Detect this and append to the previous value. continuation = True if current_value and isinstance(current_value, str): current_value += '\n' current_value += line else: current_value = line yield current_scope, current_key, current_value, continuation def _read_config_with_origin(context, cache_paths, renamed_keys): """Read the output from "git config --show-origin --list ``--show-origin`` was introduced in Git v2.8.0. """ command_line = 'command line:\t' system_scope = 'system' global_scope = 'global' local_scope = 'local' file_scheme = 'file:' system_scope_id = 0 global_scope_id = 1 local_scope_id = 2 current_value = '' current_key = '' current_path = '' current_scope = system_scope current_scope_id = system_scope_id status, config_output, _ = context.git.config( show_origin=True, list=True, includes=True ) if status != 0: return for line in config_output.splitlines(): if not line or line.startswith(command_line): continue try: tab_index = line.index('\t') except ValueError: tab_index = 0 if line.startswith(file_scheme) and tab_index > 5: continuation = False current_path = line[:tab_index] rest = line[tab_index + 1 :] cache_paths.add(current_path) current_key, current_value = _config_key_value(rest, '=') renamed_keys[current_key.lower()] = current_key # The valid state machine transitions are system -> global, # system -> local and global -> local. We start from the system state. basename = os.path.basename(current_path) if current_scope_id == system_scope_id and basename == '.gitconfig': # system -> global current_scope_id = global_scope_id current_scope = global_scope elif current_scope_id < local_scope_id and basename == 'config': # system -> local, global -> local current_scope_id = local_scope_id current_scope = local_scope else: # Values are allowed to span multiple lines when \n is embedded # in the value. Detect this and append to the previous value. continuation = True if current_value and isinstance(current_value, str): current_value += '\n' current_value += line else: current_value = line yield current_scope, current_key, current_value, continuation def _read_config_fallback(context, cache_paths, renamed_keys): """Fallback config reader for Git < 2.8.0""" system_scope = 'system' global_scope = 'global' local_scope = 'local' includes = version.check_git(context, 'config-includes') current_path = '/etc/gitconfig' if os.path.exists(current_path): cache_paths.add(current_path) status, config_output, _ = context.git.config( z=True, list=True, includes=includes, system=True, ) if status == 0: for key, value in _read_config_from_null_list(config_output): renamed_keys[key.lower()] = key yield system_scope, key, value, False gitconfig_home = core.expanduser(os.path.join('~', '.gitconfig')) gitconfig_xdg = resources.xdg_config_home('git', 'config') if os.path.exists(gitconfig_home): gitconfig = gitconfig_home elif os.path.exists(gitconfig_xdg): gitconfig = gitconfig_xdg else: gitconfig = None if gitconfig: cache_paths.add(gitconfig) status, config_output, _ = context.git.config( z=True, list=True, includes=includes, **{'global': True} ) if status == 0: for key, value in _read_config_from_null_list(config_output): renamed_keys[key.lower()] = key yield global_scope, key, value, False local_config = context.git.git_path('config') if local_config and os.path.exists(local_config): cache_paths.add(gitconfig) status, config_output, _ = context.git.config( z=True, list=True, includes=includes, local=True, ) if status == 0: for key, value in _read_config_from_null_list(config_output): renamed_keys[key.lower()] = key yield local_scope, key, value, False def _read_config_from_null_list(config_output): """Parse the "git config --list -z" records""" for record in config_output.rstrip('\0').split('\0'): try: name, value = record.split('\n', 1) except ValueError: name = record value = 'true' yield (name, _config_to_python(value)) def python_to_git(value): if isinstance(value, bool): return 'true' if value else 'false' if isinstance(value, int_types): return ustr(value) return value def get_remotes(cfg): """Get all of the configured git remotes""" # Gather all of the remote.*.url entries. prefix = len('remote.') suffix = len('.url') return sorted(key[prefix:-suffix] for key in cfg.find('remote.*.url')) git-cola-4.6.1/cola/gitcmds.py000066400000000000000000000760741457126473700162010ustar00rootroot00000000000000"""Git commands and queries for Git""" import json import os import re from io import StringIO from . import core from . import utils from . import version from .git import STDOUT from .git import EMPTY_TREE_OID from .git import OID_LENGTH from .i18n import N_ from .interaction import Interaction from .models import prefs def add(context, items, u=False): """Run "git add" while preventing argument overflow""" git_add = context.git.add return utils.slice_func( items, lambda paths: git_add('--', force=True, verbose=True, u=u, *paths) ) def apply_diff(context, filename): """Use "git apply" to apply the patch in `filename` to the staging area""" git = context.git return git.apply(filename, index=True, cached=True) def apply_diff_to_worktree(context, filename): """Use "git apply" to apply the patch in `filename` to the worktree""" git = context.git return git.apply(filename) def get_branch(context, branch): """Get the current branch""" if branch is None: branch = current_branch(context) return branch def upstream_remote(context, branch=None): """Return the remote associated with the specified branch""" config = context.cfg branch = get_branch(context, branch) return config.get('branch.%s.remote' % branch) def remote_url(context, remote, push=False): """Return the URL for the specified remote""" config = context.cfg url = config.get('remote.%s.url' % remote, '') if push: url = config.get('remote.%s.pushurl' % remote, url) return url def diff_index_filenames(context, ref): """ Return a diff of filenames that have been modified relative to the index """ git = context.git out = git.diff_index(ref, name_only=True, z=True, _readonly=True)[STDOUT] return _parse_diff_filenames(out) def diff_filenames(context, *args): """Return a list of filenames that have been modified""" out = diff_tree(context, *args)[STDOUT] return _parse_diff_filenames(out) def changed_files(context, oid): """Return the list of filenames that changed in a given commit oid""" status, out, _ = diff_tree(context, oid + '~', oid) if status != 0: # git init status, out, _ = diff_tree(context, EMPTY_TREE_OID, oid) if status == 0: result = _parse_diff_filenames(out) else: result = [] return result def diff_tree(context, *args): """Return a list of filenames that have been modified""" git = context.git return git_diff_tree(git, *args) def git_diff_tree(git, *args): return git.diff_tree( name_only=True, no_commit_id=True, r=True, z=True, _readonly=True, *args ) def listdir(context, dirname, ref='HEAD'): """Get the contents of a directory according to Git Query Git for the content of a directory, taking ignored files into account. """ dirs = [] files = [] # first, parse git ls-tree to get the tracked files # in a list of (type, path) tuples entries = ls_tree(context, dirname, ref=ref) for entry in entries: if entry[0][0] == 't': # tree dirs.append(entry[1]) else: files.append(entry[1]) # gather untracked files untracked = untracked_files(context, paths=[dirname], directory=True) for path in untracked: if path.endswith('/'): dirs.append(path[:-1]) else: files.append(path) dirs.sort() files.sort() return (dirs, files) def diff(context, args): """Return a list of filenames for the given diff arguments :param args: list of arguments to pass to "git diff --name-only" """ git = context.git out = git.diff(name_only=True, z=True, _readonly=True, *args)[STDOUT] return _parse_diff_filenames(out) def _parse_diff_filenames(out): if out: return out[:-1].split('\0') return [] def tracked_files(context, *args): """Return the names of all files in the repository""" git = context.git out = git.ls_files('--', *args, z=True, _readonly=True)[STDOUT] if out: return sorted(out[:-1].split('\0')) return [] def all_files(context, *args): """Returns a sorted list of all files, including untracked files.""" git = context.git ls_files = git.ls_files( '--', *args, z=True, cached=True, others=True, exclude_standard=True, _readonly=True, )[STDOUT] return sorted([f for f in ls_files.split('\0') if f]) class CurrentBranchCache: """Cache for current_branch()""" key = None value = None def reset(): """Reset cached value in this module (e.g. the cached current branch)""" CurrentBranchCache.key = None def current_branch(context): """Return the current branch""" git = context.git head = git.git_path('HEAD') try: key = core.stat(head).st_mtime if CurrentBranchCache.key == key: return CurrentBranchCache.value except OSError: # OSError means we can't use the stat cache key = 0 status, data, _ = git.rev_parse('HEAD', symbolic_full_name=True, _readonly=True) if status != 0: # git init -- read .git/HEAD. We could do this unconditionally... data = _read_git_head(context, head) for refs_prefix in ('refs/heads/', 'refs/remotes/', 'refs/tags/'): if data.startswith(refs_prefix): value = data[len(refs_prefix) :] CurrentBranchCache.key = key CurrentBranchCache.value = value return value # Detached head return data def _read_git_head(context, head, default='main'): """Pure-python .git/HEAD reader""" # Common .git/HEAD "ref: refs/heads/main" files git = context.git islink = core.islink(head) if core.isfile(head) and not islink: data = core.read(head).rstrip() ref_prefix = 'ref: ' if data.startswith(ref_prefix): return data[len(ref_prefix) :] # Detached head return data # Legacy .git/HEAD symlinks if islink: 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 :] return default def branch_list(context, 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(context, 'refs/remotes') return for_each_ref_basename(context, 'refs/heads') def _version_sort(context, key='version:refname'): if version.check_git(context, 'version-sort'): sort = key else: sort = False return sort def for_each_ref_basename(context, refs): """Return refs starting with 'refs'.""" git = context.git sort = _version_sort(context) _, out, _ = git.for_each_ref(refs, format='%(refname)', sort=sort, _readonly=True) output = out.splitlines() non_heads = [x for x in output if not x.endswith('/HEAD')] offset = len(refs) + 1 return [x[offset:] for x in non_heads] def _prefix_and_size(prefix, values): """Return a tuple of (prefix, len(prefix) + 1, y) for / stripping""" return (prefix, len(prefix) + 1, values) def all_refs(context, split=False, sort_key='version:refname'): """Return a tuple of (local branches, remote branches, tags).""" git = context.git local_branches = [] remote_branches = [] tags = [] query = ( _prefix_and_size('refs/tags', tags), _prefix_and_size('refs/heads', local_branches), _prefix_and_size('refs/remotes', remote_branches), ) sort = _version_sort(context, key=sort_key) _, out, _ = git.for_each_ref(format='%(refname)', sort=sort, _readonly=True) 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 tags.reverse() if split: return local_branches, remote_branches, tags return local_branches + remote_branches + tags def tracked_branch(context, branch=None): """Return the remote branch associated with 'branch'.""" if branch is None: branch = current_branch(context) if branch is None: return None config = context.cfg 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 parse_remote_branch(branch): """Split a remote branch apart into (remote, name) components""" rgx = re.compile(r'^(?P[^/]+)/(?P.+)$') match = rgx.match(branch) remote = '' branch = '' if match: remote = match.group('remote') branch = match.group('branch') return (remote, branch) def untracked_files(context, paths=None, **kwargs): """Returns a sorted list of untracked files.""" git = context.git if paths is None: paths = [] args = ['--'] + paths out = git.ls_files( z=True, others=True, exclude_standard=True, _readonly=True, *args, **kwargs )[STDOUT] if out: return out[:-1].split('\0') return [] def tag_list(context): """Return a list of tags.""" result = for_each_ref_basename(context, 'refs/tags') result.reverse() return result def log(git, *args, **kwargs): return git.log( no_color=True, no_abbrev_commit=True, no_ext_diff=True, _readonly=True, *args, **kwargs, )[STDOUT] def commit_diff(context, oid): git = context.git return log(git, '-1', oid, '--') + '\n\n' + oid_diff(context, oid) _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(context): config = context.cfg # Default to --patience when diff.algorithm is unset patience = not config.get('diff.algorithm', default='') submodule = version.check_git(context, 'diff-submodule') opts = { 'patience': patience, 'submodule': submodule, 'no_color': True, 'no_ext_diff': True, 'unified': config.get('gui.diffcontext', default=3), '_raw': True, '_readonly': True, } opts.update(_diff_overrides) return opts def _add_filename(args, filename): if filename: args.extend(['--', filename]) def oid_diff(context, oid, filename=None): """Return the diff for an oid""" # Naively "$oid^!" is what we'd like to use but that doesn't # give the correct result for merges--the diff is reversed. # Be explicit and compare oid against its first parent. return oid_diff_range(context, oid + '~', oid, filename=filename) def oid_diff_range(context, start, end, filename=None): """Return the diff for a commit range""" args = [start, end] git = context.git opts = common_diff_opts(context) _add_filename(args, filename) status, out, _ = git.diff(*args, **opts) if status != 0: # We probably don't have "$oid~" because this is the root commit. # "git show" is clever enough to handle the root commit. args = [end + '^!'] _add_filename(args, filename) _, out, _ = git.show(pretty='format:', *args, **opts) out = out.lstrip() return out def diff_info(context, oid, filename=None): """Return the diff for the specified oid""" return diff_range(context, oid + '~', oid, filename=filename) def diff_range(context, start, end, filename=None): """Return the diff for the specified commit range""" git = context.git decoded = log(git, '-1', end, '--', pretty='format:%b').strip() if decoded: decoded += '\n\n' return decoded + oid_diff_range(context, start, end, filename=filename) def diff_helper( context, commit=None, ref=None, endref=None, filename=None, cached=True, deleted=False, head=None, amending=False, with_diff_header=False, suppress_header=True, reverse=False, untracked=False, ): """Invoke git diff on a path""" git = context.git cfg = context.cfg if commit: ref, endref = commit + '^', commit argv = [] if ref and endref: argv.append(f'{ref}..{endref}') elif ref: argv.extend(utils.shell_split(ref.strip())) elif head and amending and cached: argv.append(head) encoding = None if untracked: argv.append('--no-index') argv.append(os.devnull) argv.append(filename) elif filename: argv.append('--') if isinstance(filename, (list, tuple)): argv.extend(filename) else: argv.append(filename) encoding = cfg.file_encoding(filename) status, out, _ = git.diff( R=reverse, M=True, cached=cached, _encoding=encoding, *argv, **common_diff_opts(context), ) success = status == 0 # Diff will return 1 when comparing untracked file and it has change, # therefore we will check for diff header from output to differentiate # from actual error such as file not found. if untracked and status == 1: try: _, second, _ = out.split('\n', 2) except ValueError: second = '' success = second.startswith('new file mode ') if not success: # git init if with_diff_header: return ('', '') return '' result = extract_diff_header(deleted, with_diff_header, suppress_header, out) return core.UStr(result, out.encoding) def extract_diff_header(deleted, with_diff_header, suppress_header, diffoutput): """Split a diff into a header section and payload section""" if diffoutput.startswith('Submodule'): if with_diff_header: return ('', diffoutput) return diffoutput start = False del_tag = 'deleted file mode ' output = StringIO() headers = StringIO() for line in diffoutput.split('\n'): if not start and line[:2] == '@@' and '@@' in line[2:]: start = True if start or (deleted and del_tag in line): output.write(line + '\n') else: if with_diff_header: headers.write(line + '\n') elif not suppress_header: output.write(line + '\n') output_text = output.getvalue() output.close() headers_text = headers.getvalue() headers.close() if with_diff_header: return (headers_text, output_text) return output_text def format_patchsets(context, to_export, revs, output='patches'): """ Group contiguous revision selection into patch sets 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_rev_idx = revs.index(cur_rev) patches_to_export = [[cur_rev]] patchset_idx = 0 # Group the patches into continuous sets for rev in to_export[1:]: # Limit the search to the current neighborhood for efficiency try: rev_idx = revs[cur_rev_idx:].index(rev) rev_idx += cur_rev_idx except ValueError: rev_idx = revs.index(rev) if rev_idx == cur_rev_idx + 1: patches_to_export[patchset_idx].append(rev) cur_rev_idx += 1 else: patches_to_export.append([rev]) cur_rev_idx = rev_idx patchset_idx += 1 # Export each patch set status = 0 for patchset in patches_to_export: stat, out, err = export_patchset( context, patchset[0], patchset[-1], output=output, 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(context, start, end, output='patches', **kwargs): """Export patches from start^ to end.""" git = context.git return git.format_patch('-o', output, start + '^..' + end, **kwargs) def reset_paths(context, head, items): """Run "git reset" while preventing argument overflow""" items = list(set(items)) func = context.git.reset status, out, err = utils.slice_func(items, lambda paths: func(head, '--', *paths)) return (status, out, err) def unstage_paths(context, args, head='HEAD'): """Unstage paths while accounting for git init""" status, out, err = reset_paths(context, head, 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(context, args) return (status, out, err) def untrack_paths(context, args): if not args: return (-1, N_('Nothing to do'), '') git = context.git return git.update_index('--', force_remove=True, *set(args)) def worktree_state( context, head='HEAD', update_index=False, display_untracked=True, paths=None ): """Return a dict of files in various states of being :rtype: dict, keys are staged, unstaged, untracked, unmerged, changed_upstream, and submodule. """ git = context.git if update_index: git.update_index(refresh=True) staged, unmerged, staged_deleted, staged_submods = diff_index( context, head, paths=paths ) modified, unstaged_deleted, modified_submods = diff_worktree(context, paths) if display_untracked: untracked = untracked_files(context, paths=paths) else: untracked = [] # Remove unmerged paths from the modified list if unmerged: unmerged_set = set(unmerged) modified = [path for path in modified if path not in unmerged_set] # Look for upstream modified files if this is a tracking branch upstream_changed = diff_upstream(context, 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, 'staged_deleted': staged_deleted, 'unstaged_deleted': unstaged_deleted, 'submodules': staged_submods | modified_submods, } def _parse_raw_diff(out): while out: info, path, out = out.split('\0', 2) status = info[-1] is_submodule = '160000' in info[1:14] yield (path, status, is_submodule) def diff_index(context, head, cached=True, paths=None): git = context.git staged = [] unmerged = [] deleted = set() submodules = set() if paths is None: paths = [] args = [head, '--'] + paths status, out, _ = git.diff_index(cached=cached, z=True, _readonly=True, *args) if status != 0: # handle git init args[0] = EMPTY_TREE_OID status, out, _ = git.diff_index(cached=cached, z=True, _readonly=True, *args) for path, status, is_submodule in _parse_raw_diff(out): if is_submodule: submodules.add(path) if status in 'DAMT': staged.append(path) if status == 'D': deleted.add(path) elif status == 'U': unmerged.append(path) return staged, unmerged, deleted, submodules def diff_worktree(context, paths=None): git = context.git ignore_submodules_value = context.cfg.get('diff.ignoresubmodules', 'none') ignore_submodules = ignore_submodules_value in {'all', 'dirty', 'untracked'} modified = [] deleted = set() submodules = set() if paths is None: paths = [] args = ['--'] + paths status, out, _ = git.diff_files(z=True, _readonly=True, *args) for path, status, is_submodule in _parse_raw_diff(out): if is_submodule: submodules.add(path) if ignore_submodules: continue if status in 'DAMT': modified.append(path) if status == 'D': deleted.add(path) return modified, deleted, submodules def diff_upstream(context, head): """Given `ref`, return $(git merge-base ref HEAD)..ref.""" tracked = tracked_branch(context) if not tracked: return [] base = merge_base(context, head, tracked) return diff_filenames(context, base, tracked) def list_submodule(context): """Return submodules in the format(state, sha_1, path, describe)""" git = context.git status, data, _ = git.submodule('status') ret = [] if status == 0 and data: data = data.splitlines() # see git submodule status for line in data: state = line[0].strip() sha1 = line[1 : OID_LENGTH + 1] left_bracket = line.find('(', OID_LENGTH + 3) if left_bracket == -1: left_bracket = len(line) + 1 path = line[OID_LENGTH + 2 : left_bracket - 1] describe = line[left_bracket + 1 : -1] ret.append((state, sha1, path, describe)) return ret def merge_base(context, head, ref): """Return the merge-base of head and ref""" git = context.git return git.merge_base(head, ref, _readonly=True)[STDOUT] def merge_base_parent(context, branch): tracked = tracked_branch(context, branch=branch) if tracked: return tracked return 'HEAD' def ls_tree(context, path, ref='HEAD'): """Return a parsed git ls-tree result for a single directory""" git = context.git result = [] status, out, _ = git.ls_tree( ref, '--', path, z=True, full_tree=True, _readonly=True ) if status == 0 and out: path_offset = 6 + 1 + 4 + 1 + OID_LENGTH + 1 for line in out[:-1].split('\0'): # 1 1 1 # .....6 ...4 ......................................40 # 040000 tree c127cde9a0c644a3a8fef449a244f47d5272dfa6 relative # 100644 blob 139e42bf4acaa4927ec9be1ec55a252b97d3f1e2 relative/path # 0..... 7... 12...................................... 53 # path_offset = 6 + 1 + 4 + 1 + OID_LENGTH(40) + 1 objtype = line[7:11] relpath = line[path_offset:] result.append((objtype, relpath)) return result # 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 (oid, 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(context, all=False, extra_args=None): """Return parallel arrays containing oids and summaries.""" revs = [] summaries = [] args = [] if extra_args: args = extra_args git = context.git 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(context, start, end): """Return (oid, summary) pairs between start and end.""" git = context.git revrange = f'{start}..{end}' out = git.rev_list(revrange, pretty='oneline', _readonly=True)[STDOUT] return parse_rev_list(out) def commit_message_path(context): """Return the path to .git/GIT_COLA_MSG""" git = context.git path = git.git_path('GIT_COLA_MSG') if core.exists(path): return path return None def merge_message_path(context): """Return the path to .git/MERGE_MSG or .git/SQUASH_MSG.""" git = context.git for basename in ('MERGE_MSG', 'SQUASH_MSG'): path = git.git_path(basename) if core.exists(path): return path return None def read_merge_commit_message(context, path): """Read a merge commit message from disk while stripping commentary""" content = core.read(path) cleanup_mode = prefs.commit_cleanup(context) if cleanup_mode in ('verbatim', 'scissors', 'whitespace'): return content comment_char = prefs.comment_char(context) return '\n'.join( line for line in content.splitlines() if not line.startswith(comment_char) ) def prepare_commit_message_hook(context): """Run the cola.preparecommitmessagehook to prepare the commit message""" config = context.cfg default_hook = config.hooks_path('cola-prepare-commit-msg') return config.get('cola.preparecommitmessagehook', default=default_hook) def cherry_pick(context, revs): """Cherry-picks each revision into the current branch. Returns (0, out, err) where stdout and stderr across all "git cherry-pick" invocations are combined into single values when all cherry-picks succeed. Returns a combined (status, out, err) of the first failing "git cherry-pick" in the event of a non-zero exit status. """ if not revs: return [] outs = [] errs = [] status = 0 for rev in revs: status, out, err = context.git.cherry_pick(rev) if status != 0: details = N_( 'Hint: The "Actions > Abort Cherry-Pick" menu action can be used to ' 'cancel the current cherry-pick.' ) output = f'# git cherry-pick {rev}\n# {details}\n\n{out}' return (status, output, err) outs.append(out) errs.append(err) return (0, '\n'.join(outs), '\n'.join(errs)) def abort_apply_patch(context): """Abort a "git am" session.""" # Reset the worktree git = context.git status, out, err = git.am(abort=True) return status, out, err def abort_cherry_pick(context): """Abort a cherry-pick.""" # Reset the worktree git = context.git status, out, err = git.cherry_pick(abort=True) return status, out, err def abort_merge(context): """Abort a merge""" # Reset the worktree git = context.git status, out, err = git.merge(abort=True) return status, out, err def strip_remote(remotes, remote_branch): """Get branch names with the "/" prefix removed""" for remote in remotes: prefix = remote + '/' if remote_branch.startswith(prefix): return remote_branch[len(prefix) :] return remote_branch.split('/', 1)[-1] def parse_refs(context, argv): """Parse command-line arguments into object IDs""" git = context.git status, out, _ = git.rev_parse(_readonly=True, *argv) if status == 0: oids = [oid for oid in out.splitlines() if oid] else: oids = argv return oids def prev_commitmsg(context, *args): """Queries git for the latest commit message.""" git = context.git return git.log( '-1', no_color=True, pretty='format:%s%n%n%b', _readonly=True, *args )[STDOUT] def rev_parse(context, name): """Call git rev-parse and return the output""" git = context.git status, out, _ = git.rev_parse(name, _readonly=True) if status == 0: result = out.strip() else: result = name return result def write_blob(context, oid, filename): """Write a blob to a temporary file and return the path Modern versions of Git allow invoking filters. Older versions get the object content as-is. """ if version.check_git(context, 'cat-file-filters-path'): return cat_file_to_path(context, filename, oid) return cat_file_blob(context, filename, oid) def cat_file_blob(context, filename, oid): """Write a blob from git to the specified filename""" return cat_file(context, filename, 'blob', oid) def cat_file_to_path(context, filename, oid): """Extract a file from an commit ref and a write it to the specified filename""" return cat_file(context, filename, oid, path=filename, filters=True) def cat_file(context, filename, *args, **kwargs): """Redirect git cat-file output to a path""" result = None git = context.git # Use the original filename in the suffix so that the generated filename # has the correct extension, and so that it resembles the original name. basename = os.path.basename(filename) suffix = '-' + basename # ensures the correct filename extension path = utils.tmp_filename('blob', suffix=suffix) with open(path, 'wb') as tmp_file: status, out, err = git.cat_file( _raw=True, _readonly=True, _stdout=tmp_file, *args, **kwargs ) Interaction.command(N_('Error'), 'git cat-file', status, out, err) if status == 0: result = path if not result: core.unlink(path) return result def write_blob_path(context, head, oid, filename): """Use write_blob() when modern git is available""" if version.check_git(context, 'cat-file-filters-path'): return write_blob(context, oid, filename) return cat_file_blob(context, filename, head + ':' + filename) def annex_path(context, head, filename): """Return the git-annex path for a filename at the specified commit""" git = context.git path = None annex_info = {} # unfortunately there's no way to filter this down to a single path # so we just have to scan all reported paths status, out, _ = git.annex('findref', '--json', head, _readonly=True) if status == 0: for line in out.splitlines(): info = json.loads(line) try: annex_file = info['file'] except (ValueError, KeyError): continue # we only care about this file so we can skip the rest if annex_file == filename: annex_info = info break key = annex_info.get('key', '') if key: status, out, _ = git.annex('contentlocation', key, _readonly=True) if status == 0 and os.path.exists(out): path = out return path def is_binary(context, filename): """A heuristic to determine whether `filename` contains (non-text) binary content""" cfg_is_binary = context.cfg.is_binary(filename) if cfg_is_binary is not None: return cfg_is_binary # This is the same heuristic as xdiff-interface.c:buffer_is_binary(). size = 8000 try: result = core.read(filename, size=size, encoding='bytes') except OSError: result = b'' return b'\0' in result def is_valid_ref(context, ref): """Is the provided Git ref a valid refname?""" status, _, _ = context.git.rev_parse(ref, quiet=True, verify=True, _readonly=True) return status == 0 git-cola-4.6.1/cola/gravatar.py000066400000000000000000000122651457126473700163460ustar00rootroot00000000000000import time import hashlib from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from qtpy import QtNetwork from . import core from . import icons from . import qtutils from .compat import parse from .models import prefs from .widgets import defs class Gravatar: @staticmethod def url_for_email(email, imgsize): email_hash = md5_hexdigest(email) # Python2.6 requires byte strings for urllib2.quote() so we have # to force default_url = 'https://git-cola.github.io/images/git-64x64.jpg' encoded_url = parse.quote(core.encode(default_url), core.encode('')) query = '?s=%d&d=%s' % (imgsize, core.decode(encoded_url)) url = 'https://gravatar.com/avatar/' + email_hash + query return url def md5_hexdigest(value): """Return the md5 hexdigest for a value. Used for implementing the gravatar API. Not used for security purposes. """ # https://github.com/git-cola/git-cola/issues/1157 # ValueError: error:060800A3: # digital envelope routines: EVP_DigestInit_ex: disabled for fips # # Newer versions of Python, including Centos8's patched Python3.6 and # mainline Python 3.9+ have a "usedoforsecurity" parameter which allows us # to continue using hashlib.md5(). encoded_value = core.encode(value) result = '' try: # This could raise ValueError in theory but we always use encoded bytes # so that does not happen in practice. result = hashlib.md5(encoded_value, usedforsecurity=False).hexdigest() except TypeError: # Fallback to trying hashlib.md5 directly. result = hashlib.md5(encoded_value).hexdigest() return core.decode(result) class GravatarLabel(QtWidgets.QLabel): def __init__(self, context, parent=None): QtWidgets.QLabel.__init__(self, parent) self.context = context self.email = None self.response = None self.timeout = 0 self.imgsize = defs.medium_icon self.pixmaps = {} self._default_pixmap_bytes = None self.network = QtNetwork.QNetworkAccessManager() self.network.finished.connect(self.network_finished) def set_email(self, email): """Update the author icon based on the specified email""" pixmap = self.pixmaps.get(email, None) if pixmap is not None: self.setPixmap(pixmap) 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): if prefs.enable_gravatar(self.context): url = Gravatar.url_for_email(email, self.imgsize) self.network.get(QtNetwork.QNetworkRequest(QtCore.QUrl(url))) else: self.pixmaps[email] = self.set_pixmap_from_response() def default_pixmap_as_bytes(self): if self._default_pixmap_bytes is None: xres = self.imgsize pixmap = icons.cola().pixmap(xres) byte_array = QtCore.QByteArray() buf = QtCore.QBuffer(byte_array) buf.open(QtCore.QIODevice.WriteOnly) pixmap.save(buf, 'PNG') buf.close() self._default_pixmap_bytes = byte_array else: byte_array = self._default_pixmap_bytes return byte_array def network_finished(self, reply): email = self.email header = QtCore.QByteArray(b'Location') location = core.decode(bytes(reply.rawHeader(header))).strip() if location: request_location = Gravatar.url_for_email(self.email, self.imgsize) relocated = location != request_location else: relocated = False no_error = qtutils.enum_value(QtNetwork.QNetworkReply.NetworkError.NoError) reply_error = qtutils.enum_value(reply.error()) if reply_error == no_error: if relocated: # We could do get_url(parse.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 == reply.url().toString(): self.pixmaps[email] = pixmap def set_pixmap_from_response(self): if self.response is None: self.response = self.default_pixmap_as_bytes() pixmap = QtGui.QPixmap() pixmap.loadFromData(self.response) self.setPixmap(pixmap) return pixmap git-cola-4.6.1/cola/guicmds.py000066400000000000000000000276751457126473700162050ustar00rootroot00000000000000import os from qtpy import QtGui from . import cmds from . import core from . import difftool from . import display from . import gitcmds from . import icons from . import qtutils from .i18n import N_ from .interaction import Interaction from .widgets import completion from .widgets import editremotes from .widgets import switcher from .widgets.browse import BrowseBranch from .widgets.selectcommits import select_commits from .widgets.selectcommits import select_commits_and_output def delete_branch(context): """Launch the 'Delete Branch' dialog.""" icon = icons.discard() branch = choose_branch(context, N_('Delete Branch'), N_('Delete'), icon=icon) if not branch: return cmds.do(cmds.DeleteBranch, context, branch) def delete_remote_branch(context): """Launch the 'Delete Remote Branch' dialog.""" remote_branch = choose_remote_branch( context, N_('Delete Remote Branch'), N_('Delete'), icon=icons.discard() ) if not remote_branch: return remote, branch = gitcmds.parse_remote_branch(remote_branch) if remote and branch: cmds.do(cmds.DeleteRemoteBranch, context, remote, branch) def browse_current(context): """Launch the 'Browse Current Branch' dialog.""" branch = gitcmds.current_branch(context) BrowseBranch.browse(context, branch) def browse_other(context): """Prompt for a branch and inspect content at that point in time.""" # Prompt for a branch to browse branch = choose_ref(context, N_('Browse Commits...'), N_('Browse')) if not branch: return BrowseBranch.browse(context, branch) def checkout_branch(context, default=None): """Launch the 'Checkout Branch' dialog.""" branch = choose_potential_branch( context, N_('Checkout Branch'), N_('Checkout'), default=default ) if not branch: return cmds.do(cmds.CheckoutBranch, context, branch) def cherry_pick(context): """Launch the 'Cherry-Pick' dialog.""" revs, summaries = gitcmds.log_helper(context, all=True) commits = select_commits( context, N_('Cherry-Pick Commit'), revs, summaries, multiselect=False ) if not commits: return cmds.do(cmds.CherryPick, context, commits) def new_repo(context): """Prompt for a new directory and create a new Git repository :returns str: repository path or None if no repository was created. """ git = context.git path = qtutils.opendir_dialog(N_('New Repository...'), core.getcwd()) if not path: return None # Avoid needlessly calling `git init`. if git.is_git_repository(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 = git.init(path) if status == 0: return path title = N_('Error Creating Repository') Interaction.command_error(title, 'git init', status, out, err) return None def open_new_repo(context): """Create a new repository and open it""" dirname = new_repo(context) if not dirname: return cmds.do(cmds.OpenRepo, context, dirname) def new_bare_repo(context): """Create a bare repository and configure a remote pointing to it""" result = None repo = prompt_for_new_bare_repo() if not repo: return result # Create bare repo ok = cmds.do(cmds.NewBareRepo, context, repo) if not ok: return result # Add a new remote pointing to the bare repo parent = qtutils.active_window() add_remote = editremotes.add_remote( context, parent, name=os.path.basename(repo), url=repo, readonly_url=True ) if add_remote: result = repo return result def prompt_for_new_bare_repo(): """Prompt for a directory and name for a new bare repository""" path = qtutils.opendir_dialog(N_('Select Directory...'), core.getcwd()) if not path: return None bare_repo = None default = os.path.basename(core.getcwd()) if not default.endswith('.git'): default += '.git' while not bare_repo: name, ok = qtutils.prompt( N_('Enter a name for the new bare repo'), title=N_('New Bare Repository...'), text=default, ) if not name or not ok: return None if not name.endswith('.git'): name += '.git' repo = os.path.join(path, name) if core.isdir(repo): Interaction.critical(N_('Error'), N_('"%s" already exists') % repo) else: bare_repo = repo return bare_repo def export_patches(context): """Run 'git format-patch' on a list of commits.""" revs, summaries = gitcmds.log_helper(context) to_export_and_output = select_commits_and_output( context, N_('Export Patches'), revs, summaries ) if not to_export_and_output['to_export']: return cmds.do( cmds.FormatPatch, context, reversed(to_export_and_output['to_export']), reversed(revs), output=to_export_and_output['output'], ) def diff_against_commit(context): """Diff against any commit and checkout changes using the Diff Editor""" icon = icons.compare() ref = choose_ref(context, N_('Diff Against Commit'), N_('Diff'), icon=icon) if not ref: return cmds.do(cmds.DiffAgainstCommitMode, context, ref) def diff_expression(context): """Diff using an arbitrary expression.""" tracked = gitcmds.tracked_branch(context) current = gitcmds.current_branch(context) if tracked and current: ref = tracked + '..' + current else: ref = '@{upstream}..' difftool.diff_expression(context, qtutils.active_window(), ref) def open_repo(context): """Open a repository in the current window""" model = context.model dirname = qtutils.opendir_dialog(N_('Open Git Repository'), model.getcwd()) if not dirname: return cmds.do(cmds.OpenRepo, context, dirname) def open_repo_in_new_window(context): """Spawn a new cola session.""" model = context.model dirname = qtutils.opendir_dialog(N_('Open Git Repository'), model.getcwd()) if not dirname: return cmds.do(cmds.OpenNewRepo, context, dirname) def open_quick_repo_search(context, parent=None): """Open a Quick Repository Search dialog""" if parent is None: parent = qtutils.active_window() settings = context.settings items = settings.bookmarks + settings.recent if items: cfg = context.cfg default_repo = cfg.get('cola.defaultrepo') entries = QtGui.QStandardItemModel() added = set() normalize = display.normalize_path star_icon = icons.star() folder_icon = icons.folder() for item in items: key = normalize(item['path']) if key in added: continue name = item['name'] if default_repo == item['path']: icon = star_icon else: icon = folder_icon entry = switcher.switcher_item(key, icon, name) entries.appendRow(entry) added.add(key) title = N_('Quick Open Repository') place_holder = N_('Search repositories by name...') switcher.switcher_inner_view( context, entries, title, place_holder=place_holder, enter_action=lambda entry: cmds.do(cmds.OpenRepo, context, entry.key), parent=parent, ) def load_commitmsg(context): """Load a commit message from a file.""" model = context.model filename = qtutils.open_file(N_('Load Commit Message'), directory=model.getcwd()) if filename: cmds.do(cmds.LoadCommitMessageFromFile, context, filename) def choose_from_dialog(get, context, title, button_text, default, icon=None): """Choose a value from a dialog using the `get` method""" parent = qtutils.active_window() return get(context, title, button_text, parent, default=default, icon=icon) def choose_ref(context, title, button_text, default=None, icon=None): """Choose a Git ref and return it""" return choose_from_dialog( completion.GitRefDialog.get, context, title, button_text, default, icon=icon ) def choose_branch(context, title, button_text, default=None, icon=None): """Choose a branch and return either the chosen branch or an empty value""" return choose_from_dialog( completion.GitBranchDialog.get, context, title, button_text, default, icon=icon ) def choose_potential_branch(context, title, button_text, default=None, icon=None): """Choose a "potential" branch for checking out. This dialog includes remote branches from which new local branches can be created. """ return choose_from_dialog( completion.GitCheckoutBranchDialog.get, context, title, button_text, default, icon=icon, ) def choose_remote_branch(context, title, button_text, default=None, icon=None): """Choose a remote branch""" return choose_from_dialog( completion.GitRemoteBranchDialog.get, context, title, button_text, default, icon=icon, ) def review_branch(context): """Diff against an arbitrary revision, branch, tag, etc.""" branch = choose_ref(context, N_('Select Branch to Review'), N_('Review')) if not branch: return merge_base = gitcmds.merge_base_parent(context, branch) difftool.diff_commits(context, qtutils.active_window(), merge_base, branch) def rename_branch(context): """Launch the 'Rename Branch' dialogs.""" branch = choose_branch(context, N_('Rename Existing Branch'), N_('Select')) if not branch: return new_branch = choose_branch(context, N_('Enter New Branch Name'), N_('Rename')) if not new_branch: return cmds.do(cmds.RenameBranch, context, branch, new_branch) def reset_soft(context): """Run "git reset --soft" to reset the branch HEAD""" title = N_('Reset Branch (Soft)') ok_text = N_('Reset Branch') ref = choose_ref(context, title, ok_text, default='HEAD^') if ref: cmds.do(cmds.ResetSoft, context, ref) def reset_mixed(context): """Run "git reset --mixed" to reset the branch HEAD and staging area""" title = N_('Reset Branch and Stage (Mixed)') ok_text = N_('Reset') ref = choose_ref(context, title, ok_text, default='HEAD^') if ref: cmds.do(cmds.ResetMixed, context, ref) def reset_keep(context): """Run "git reset --keep" safe reset to avoid clobbering local changes""" title = N_('Reset All (Keep Unstaged Changes)') ref = choose_ref(context, title, N_('Reset and Restore')) if ref: cmds.do(cmds.ResetKeep, context, ref) def reset_merge(context): """Run "git reset --merge" to reset the working tree and staging area The staging area is allowed to carry forward unmerged index entries, but if any unstaged changes would be clobbered by the reset then the reset is aborted. """ title = N_('Restore Worktree and Reset All (Merge)') ok_text = N_('Reset and Restore') ref = choose_ref(context, title, ok_text, default='HEAD^') if ref: cmds.do(cmds.ResetMerge, context, ref) def reset_hard(context): """Run "git reset --hard" to fully reset the working tree and staging area""" title = N_('Restore Worktree and Reset All (Hard)') ok_text = N_('Reset and Restore') ref = choose_ref(context, title, ok_text, default='HEAD^') if ref: cmds.do(cmds.ResetHard, context, ref) def restore_worktree(context): """Restore the worktree to the content from the specified commit""" title = N_('Restore Worktree') ok_text = N_('Restore Worktree') ref = choose_ref(context, title, ok_text, default='HEAD^') if ref: cmds.do(cmds.RestoreWorktree, context, ref) def install(): """Install the GUI-model interaction hooks""" Interaction.choose_ref = staticmethod(choose_ref) git-cola-4.6.1/cola/hidpi.py000066400000000000000000000023211457126473700156240ustar00rootroot00000000000000"""Provides High DPI support by wrapping Qt options""" from qtpy import QtCore from .i18n import N_ from . import core from . import compat from . import version class Option: AUTO = '0' DISABLE = 'disable' TIMES_1 = '1' TIMES_1_25 = '1.25' TIMES_1_5 = '1.5' TIMES_2 = '2' def is_supported(): return version.check('qt-hidpi-scale', QtCore.__version__) def apply_choice(value): value = compat.ustr(value) if value == Option.AUTO: # Do not override the configuration when either of these # two environment variables are defined. if not core.getenv('QT_AUTO_SCREEN_SCALE_FACTOR') and not core.getenv( 'QT_SCALE_FACTOR' ): compat.setenv('QT_AUTO_SCREEN_SCALE_FACTOR', '1') compat.unsetenv('QT_SCALE_FACTOR') elif value and value != Option.DISABLE: compat.unsetenv('QT_AUTO_SCREEN_SCALE_FACTOR') compat.setenv('QT_SCALE_FACTOR', value) def options(): return ( (N_('Auto'), Option.AUTO), (N_('Disable'), Option.DISABLE), (N_('x 1'), Option.TIMES_1), (N_('x 1.25'), Option.TIMES_1_25), (N_('x 1.5'), Option.TIMES_1_5), (N_('x 2'), Option.TIMES_2), ) git-cola-4.6.1/cola/hotkeys.py000066400000000000000000000112341457126473700162200ustar00rootroot00000000000000from qtpy.QtGui import QKeySequence from qtpy.QtCore import Qt def hotkey(*seq): return QKeySequence(*seq) # A-G STAGE_MODIFIED = hotkey(Qt.ALT | Qt.Key_A) WORD_LEFT = hotkey(Qt.Key_B) BLAME = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_B) BRANCH = hotkey(Qt.CTRL | Qt.Key_B) CHECKOUT = hotkey(Qt.ALT | Qt.Key_B) CHERRY_PICK = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_C) COPY_DIFF = hotkey(Qt.ALT | Qt.SHIFT | Qt.Key_C) COPY_SHA1 = hotkey(Qt.CTRL | Qt.ALT | Qt.Key_C) DIFFSTAT = hotkey(Qt.ALT | Qt.Key_D) DIFF = hotkey(Qt.CTRL | Qt.Key_D) DIFF_SECONDARY = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_D) EDIT_SHORT = hotkey(Qt.Key_E) EDIT = hotkey(Qt.CTRL | Qt.Key_E) EDIT_SECONDARY = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_E) EXPORT = hotkey(Qt.ALT | Qt.SHIFT | Qt.Key_E) FIT = hotkey(Qt.Key_F) FETCH = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_F) FILTER = hotkey(Qt.ALT | Qt.SHIFT | Qt.Key_F) GOTO_END = hotkey(Qt.SHIFT | Qt.Key_G) GOTO_START = hotkey(Qt.Key_G, Qt.Key_G) # gg GREP = hotkey(Qt.ALT | Qt.Key_G) # H-P MOVE_LEFT = hotkey(Qt.Key_H) MOVE_LEFT_SHIFT = hotkey(Qt.SHIFT | Qt.Key_H) HISTORY = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_H) SIGNOFF = hotkey(Qt.CTRL | Qt.Key_I) MOVE_DOWN = hotkey(Qt.Key_J) MOVE_DOWN_SHIFT = hotkey(Qt.SHIFT | Qt.Key_J) MOVE_DOWN_SECONDARY = hotkey(Qt.ALT | Qt.Key_J) MOVE_DOWN_TERTIARY = hotkey(Qt.SHIFT | Qt.Key_J) MOVE_UP = hotkey(Qt.Key_K) MOVE_UP_SHIFT = hotkey(Qt.SHIFT | Qt.Key_K) MOVE_UP_SECONDARY = hotkey(Qt.ALT | Qt.Key_K) MOVE_UP_TERTIARY = hotkey(Qt.SHIFT | Qt.Key_K) MOVE_RIGHT = hotkey(Qt.Key_L) MOVE_RIGHT_SHIFT = hotkey(Qt.SHIFT | Qt.Key_L) FOCUS = hotkey(Qt.CTRL | Qt.Key_L) FOCUS_DIFF = hotkey(Qt.CTRL | Qt.Key_J) FOCUS_INPUT = hotkey(Qt.CTRL | Qt.Key_L) FOCUS_STATUS = hotkey(Qt.CTRL | Qt.Key_K) FOCUS_TREE = hotkey(Qt.CTRL | Qt.Key_K) AMEND = hotkey(Qt.CTRL | Qt.Key_M) MERGE = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_M) PUSH = hotkey(Qt.CTRL | Qt.Key_P) PULL = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_P) OPEN_REPO_SEARCH = hotkey(Qt.ALT | Qt.Key_P) # Q-Z QUIT = hotkey(Qt.CTRL | Qt.Key_Q) REFRESH = hotkey(Qt.CTRL | Qt.Key_R) REFRESH_SECONDARY = hotkey(Qt.Key_F5) REFRESH_HOTKEYS = (REFRESH, REFRESH_SECONDARY) STAGE_DIFF = hotkey(Qt.Key_S) EDIT_AND_STAGE_DIFF = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_S) SEARCH = hotkey(Qt.CTRL | Qt.Key_F) SEARCH_NEXT = hotkey(Qt.CTRL | Qt.Key_G) SEARCH_PREV = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_G) STAGE_DIFF_ALT = hotkey(Qt.SHIFT | Qt.Key_S) STAGE_SELECTION = hotkey(Qt.CTRL | Qt.Key_S) STAGE_ALL = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_S) STASH = hotkey(Qt.ALT | Qt.SHIFT | Qt.Key_S) FINDER = hotkey(Qt.CTRL | Qt.Key_T) FINDER_SECONDARY = hotkey(Qt.Key_T) TERMINAL = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_T) STAGE_UNTRACKED = hotkey(Qt.ALT | Qt.Key_U) REVERT = hotkey(Qt.CTRL | Qt.Key_U) REVERT_ALT = hotkey(Qt.ALT | Qt.SHIFT | Qt.Key_R) EDIT_AND_REVERT = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_U) WORD_RIGHT = hotkey(Qt.Key_W) # Numbers START_OF_LINE = hotkey(Qt.Key_0) # Special keys BACKSPACE = hotkey(Qt.Key_Backspace) TRASH = hotkey(Qt.CTRL | Qt.Key_Backspace) DELETE_FILE = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_Backspace) DELETE_FILE_SECONDARY = hotkey(Qt.CTRL | Qt.Key_Backspace) PREFERENCES = hotkey(Qt.CTRL | Qt.Key_Comma) END_OF_LINE = hotkey(Qt.Key_Dollar) DOWN = hotkey(Qt.Key_Down) ENTER = hotkey(Qt.Key_Enter) ZOOM_OUT = hotkey(Qt.Key_Minus) REMOVE_ITEM = hotkey(Qt.Key_Minus) ADD_ITEM = hotkey(Qt.Key_Plus) ZOOM_IN = hotkey(Qt.Key_Plus) ZOOM_IN_SECONDARY = hotkey(Qt.Key_Equal) QUESTION = hotkey(Qt.Key_Question) RETURN = hotkey(Qt.Key_Return) ACCEPT = (ENTER, RETURN) APPLY = hotkey(Qt.CTRL | Qt.Key_Return) PREPARE_COMMIT_MESSAGE = hotkey(Qt.CTRL | Qt.SHIFT | Qt.Key_Return) PRIMARY_ACTION = hotkey(hotkey(Qt.Key_Space)) SECONDARY_ACTION = hotkey(Qt.SHIFT | Qt.Key_Space) LEAVE = hotkey(Qt.SHIFT | Qt.Key_Tab) UP = hotkey(Qt.Key_Up) CTRL_RETURN = hotkey(Qt.CTRL | Qt.Key_Return) CTRL_ENTER = hotkey(Qt.CTRL | Qt.Key_Enter) # Rebase REBASE_START_AND_CONTINUE = hotkey(Qt.ALT | Qt.Key_R) REBASE_PICK = (hotkey(Qt.Key_1), hotkey(Qt.Key_P)) REBASE_REWORD = (hotkey(Qt.Key_2), hotkey(Qt.Key_R)) REBASE_EDIT = (hotkey(Qt.Key_3), hotkey(Qt.Key_E)) REBASE_FIXUP = (hotkey(Qt.Key_4), hotkey(Qt.Key_F)) REBASE_SQUASH = (hotkey(Qt.Key_5), hotkey(Qt.Key_S)) UNDO = hotkey(Qt.CTRL | Qt.Key_Z) REDO = hotkey(Qt.SHIFT | Qt.CTRL | Qt.Key_Z) # Key Sequences COPY = QKeySequence.Copy CLOSE = QKeySequence.Close CUT = QKeySequence.Cut PASTE = QKeySequence.Paste DELETE = QKeySequence.Delete NEW = QKeySequence.New OPEN = QKeySequence.Open SELECT_ALL = QKeySequence.SelectAll # Text navigation TEXT_DOWN = hotkey(Qt.Key_D) TEXT_UP = hotkey(Qt.Key_U) SELECT_FORWARD = hotkey(Qt.SHIFT | Qt.Key_F) SELECT_BACK = hotkey(Qt.SHIFT | Qt.Key_B) SELECT_DOWN = hotkey(Qt.SHIFT | Qt.Key_D) SELECT_UP = hotkey(Qt.SHIFT | Qt.Key_U) git-cola-4.6.1/cola/i18n.py000066400000000000000000000072361457126473700153200ustar00rootroot00000000000000"""i18n and l10n support for git-cola""" import locale import os try: import polib except ImportError: from . import polib import sys from . import core from . import resources class NullTranslation: """This is a pass-through object that does nothing""" def gettext(self, value): return value class State: """The application-wide current translation state""" translation = NullTranslation() @classmethod def reset(cls): cls.translation = NullTranslation() @classmethod def update(cls, lang): cls.translation = Translation(lang) @classmethod def gettext(cls, value): """Return a translated value""" return cls.translation.gettext(value) class Translation: def __init__(self, lang): self.lang = lang self.messages = {} self.filename = get_filename_for_locale(lang) if self.filename: self.load() def load(self): """Read the .po file content into memory""" po = polib.pofile(self.filename, encoding='utf-8') messages = self.messages for entry in po.translated_entries(): messages[entry.msgid] = entry.msgstr def gettext(self, value): return self.messages.get(value, value) def gettext(value): """Translate a string""" txt = State.gettext(value) # handle @@verb / @@noun if txt[-6:-4] == '@@': txt = txt.replace('@@verb', '').replace('@@noun', '') return txt def N_(value): """Marker function for translated values N_("Some string value") is used to mark strings for translation. """ return gettext(value) def get_filename_for_locale(name): """Return the .po file for the specified locale""" # When is "foo_BAR.UTF-8", the name is truncated to "foo_BAR". # When is "foo_BAR", the is "foo" # Try the following locations: # cola/i18n/.po # cola/i18n/.po if not name: # If no locale was specified then try the current locale. name = locale.getdefaultlocale()[0] if not name: return None name = name.split('.', 1)[0] # foo_BAR.UTF-8 -> foo_BAR filename = resources.i18n('%s.po' % name) if os.path.exists(filename): return filename short_name = name.split('_', 1)[0] filename = resources.i18n('%s.po' % short_name) if os.path.exists(filename): return filename return None def install(lang): if sys.platform == 'win32' and not lang: lang = _get_win32_default_locale() lang = _install_custom_language(lang) State.update(lang) def uninstall(): State.reset() def _install_custom_language(lang): """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 lang try: lang = core.read(lang_file).strip() except OSError: return lang return lang def _get_win32_default_locale(): """Get the default locale on Windows""" for name in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'): lang = os.environ.get(name) if lang: return lang try: import ctypes except ImportError: # use only user's default locale return locale.getdefaultlocale()[0] # using ctypes to determine all locales lcid_user = ctypes.windll.kernel32.GetUserDefaultLCID() lcid_system = ctypes.windll.kernel32.GetSystemDefaultLCID() lang_user = locale.windows_locale.get(lcid_user) lang_system = locale.windows_locale.get(lcid_system) if lang_user: lang = lang_user else: lang = lang_system return lang git-cola-4.6.1/cola/i18n/000077500000000000000000000000001457126473700147365ustar00rootroot00000000000000git-cola-4.6.1/cola/i18n/README.md000066400000000000000000000005721457126473700162210ustar00rootroot00000000000000# Internationalization The `*.po` files are the translation files for Git Cola. Git Cola has been translated into different languages thanks to the help of many individuals. Translation is approximate. If you find a mistake, please let us know by opening an issue. We invite you to participate in translation by adding or updating a translation and opening a pull request. git-cola-4.6.1/cola/i18n/cs.po000066400000000000000000003113721457126473700157120ustar00rootroot00000000000000# Translation of git-cola to Czech. # Copyright (C) 2017 Pavel Rehak # This file is distributed under the same license as the git-cola package. # Pavel Rehak , 2017. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-16 17:32+0200\n" "PO-Revision-Date: 2018-07-01 07:25+0200\n" "Last-Translator: Pavel Rehak \n" "Language-Team: \n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.0.4\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " Záplaty přidáte na seznam buď přetažením nebo kliknutím na\n" " Přidat\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" "\n" "
\n" " Git Cola je překládána do různých jazyků díky\n" " pomoci níže uvedených jednotlivců.\n" "\n" "
\n" "

\n" " Může se stát, že něco v překladu nebude správně. Pokud najdete chybu,\n" " oznamte nám to prosím založením hlášení o chybě na portálu Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " Zveme vás, abyste se na překladu podíleli tím, že ho doplníte nebo aktualizujete\n" " překlad, a otevřete pull request.\n" "

\n" "\n" "
\n" "\n" " " #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" "\n" "
\n" " Git Cola verze %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" "\n" "
\n" " K hlášení problémů použijte %(bug_link)s.\n" "
\n" " " #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" "\n" " Proměnné formátovacího řetězce\n" " -----------------------\n" " %(path)s = relativní popis umístění souboru\n" " %(abspath)s = absolutní popis umístění souboru\n" " %(dirname)s = relativní popis umístění složky\n" " %(absdirname)s = absolutní popis umístění složky\n" " %(filename)s = název souboru\n" " %(basename)s = název souboru bez přípony\n" " %(ext)s = přípona souboru\n" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr " – DAG" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr " zápisů před" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "„%(branch)s“ byla smazána z „%(remote)s“." #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "„%(command)s“ vrátil návratový kód „%(status)d“" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "„%(command)s“ vrátil návratový kód %(status)d" #: cola/guicmds.py:156 #, python-format msgid "\"%s\" already exists" msgstr "„%s“ už existuje" #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "„%s“ už existuje, cola vytvoří novou složku" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "„%s“ vyžaduje označený soubor." #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "č." #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s: %(branch)s – procházet" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "%(project)s: %(ref)s – DAG" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "Před %d dny" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "Před %d hodinami" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "Před %d minutami" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "%d záplaty aplikovány." #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d přeskočeno" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" "Zdá se, že %s obsahuje konflikty začlenění.\n" "\n" "Tento soubor byste nejspíš měli přeskočit.\n" "Odložit ho i tak?" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "%s není Git repozitář." #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "%s bude odstraněn ze záložek." #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "%s bude odstraněn z nedávných repozitářů." #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: Žádný takový soubor nebo složka." #: cola/widgets/main.py:748 msgid "&Edit" msgstr "&Upravit" #: cola/widgets/main.py:690 msgid "&File" msgstr "&Soubor" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(Pozměnit)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** pískoviště ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "100%" #: cola/widgets/diff.py:817 msgid "200%" msgstr "200%" #: cola/widgets/diff.py:814 msgid "25%" msgstr "25%" #: cola/widgets/diff.py:818 msgid "400%" msgstr "400%" #: cola/widgets/diff.py:815 msgid "50%" msgstr "50%" #: cola/widgets/diff.py:819 msgid "800%" msgstr "800%" #: cola/widgets/finder.py:118 msgid " ..." msgstr "…" #: cola/cmds.py:1685 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:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "Zrušit" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "Zrušit akci" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "Zrušit sloučení" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Zrušit sloučení (merge)…" #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "Zrušit akci?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Zrušení současného sloučení způsobí, že *VŠECHNY* nezapsané změny budou ztraceny.\n" "Obnovení nezapsaných změn není možné." #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "Zrušit stávající sloučení?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "O aplikaci" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "O aplikaci git-cola" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "Přijmout" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "Přijmout změny a přeskládat\n" "Klávesová zkratka: Ctrl+Enter" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "Název akce" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "Akce" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "Akce…" #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "Přidat" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "Přidat oblíbený" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "Přidat vzdálený" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "Přidat oddělovač" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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 "" "Přidat a odstranit vzdálené repozitáře pomocí tlačítek \n" "Přidat(+) a Odstranit(-) na levé straně.\n" "\n" "Vzdálené mohou být přejmenovány tak, že se jeden vybere\n" "ze seznamu a stiskne se \"enter\", nebo dvojklikem." #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "Přidat nový vzdálený git repozitář" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "Přidat záplaty (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "Přidat vzdálený" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "Přidat do .gitignore" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "Přidat do Git Annex" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "Přidat do Git LFS" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "Přidáno" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "Pokročilé" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "Stáří" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "Všechny repozitáře" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "Povolit aktualizace Ne rychle vpřed. Použití „vynutit“ může způsobit, že vzdálený repositář ztratí zápisy; používejte obezřetně" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "Vždy vytvořit zápis sloučení, je-li povoleno, a to i v případě, že sloučení je aktualizace Rychle vpřed" #: cola/cmds.py:220 msgid "Amend" msgstr "Pozměnit" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "Pozměnit zápis" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Pozměnit poslední zápis" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "Pozměnit uveřejněný zápis?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "Pozměnit" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "Akce stále probíhá.\n" "Její ukončení by mohlo vést ke ztrátě dat." #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "Místo toho bude vytvořena nepodepsaná prostá značka.\n" "Vytvořit nepodepsanou značku?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "Aplikovat" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "Aplikovat záplaty" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "Aplikovat záplaty…" #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "Aplikovat a zahodit vybraný odklad (git stash pop)" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "Aplikovat vybraný odklad" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "Argumenty" #: cola/qtutils.py:886 msgid "Attach" msgstr "Připnout" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "Autor" #: cola/widgets/about.py:90 msgid "Authors" msgstr "Autoři" #: cola/hidpi.py:41 msgid "Auto" msgstr "" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "Automaticky zalamovat řádky" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "Základní regul. výraz" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "" #: cola/widgets/browse.py:206 msgid "Blame selected paths" msgstr "" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "Blame…" #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "Hlavičky tučným písmem na tmavém pozadí místo kurzívy" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Větev" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "Větev \"%(branch)s\" neexistuje v \"%(remote)s\".\n" "Bude uveřejněna nová vzdálená větev." #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "Větev „%s“ už existuje." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "Diff prohlížeč větví" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "Větev existuje" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Název větve" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "Větev: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "Větve" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "Větve…" #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "Brazilský překlad" #: cola/guicmds.py:52 msgid "Browse" msgstr "Procházet" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "Procházet zápisy…" #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "Procházet stávající větev…" #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "Procházet jinou větev…" #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "Procházet…" #: cola/widgets/main.py:87 msgid "Browser" msgstr "Prohlížeč" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "Prochází se %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "Přemostit háčky nahrání" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "Storno" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "Zrušit přeskládání\n" "Zkratka: Ctrl+Q" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "Není možné amend" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "Nedaří se spustit „%s" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "Nelze spustit \"%s\": prosím nakonfigurujte prohlížeč historie" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "Nelze spustit \"%s\": prosím nakonfigurujte editor" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "Změněno v upstreamu" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "Kontrolovat pravopis" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "Kontrolovat pravopis" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Přepnout" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "Přepnout po vytvoření" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Přepnout větev" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "Přepnout odpojené hlavní" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "Přepnout jako novou větev" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Přepnout…" #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "Sloučit selektivně" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "Sloučit konkrétní nahrání" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "Selektivně sloučit…" #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "Zvolit umístění" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "Zvolte režim regulárního výrazu „git grep“" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "Zrušit výchozí repozitář" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "Vyčistit zprává nahrání" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "Vyčistit zprávu nahrání?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "Vyčístit…" #: cola/widgets/clone.py:124 msgid "Clone" msgstr "Klonovat" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "Klonovat repozitář" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Klonovat…" #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "Klonuje se repozitář na %s" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Zavřít" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "Zavřít…" #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "Sbalit vše" #: cola/sequenceeditor.py:371 msgid "Command" msgstr "Příkaz" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "Zapsat" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "Zapsání se nezdařilo" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "Zapsat připravené změny" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "Zapsat (commit) připravené změny\n" "Klávesová zkratka: Ctrl+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "Souhrn zápisu" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "Zapsat sloučení, pokud nejsou žádné konflikty. Je-li odškrtnuto, sloučení zůstane nezapsáno" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "Zapsat" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "Porovnat" #: cola/difftool.py:102 msgid "Compare All" msgstr "Porovnat vše" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "Upravit nástrojovou lištu" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "Nastavit vzdálenou větev jako nový upstream" #: cola/widgets/main.py:169 msgid "Console" msgstr "Konzole" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Pokračovat" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Kopírovat" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "Kopírovat název souboru do schránky" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "Zkopírovat popis umístění do schránky" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "Zkopírovat popis umístění do schránky" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "Zkopírovat relativní popis umístění do schránky" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "Kopírovat SHA-1" #: cola/widgets/status.py:738 msgid "Copy..." msgstr "Kopírovat…" #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "Nedaří se zpracovat Git URL: „%s“" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Vytvořit větev" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "Vytvořit záplatu" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "Vytvořit vzdálenou větev" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "Vytvořit podepsaný zápis" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "Vytvořit štítek" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "Vytvořit štítek…" #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "Vytvořit nepodepsanou značku" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "Vytvořit zápis sloučení i v případě, že je sloučení vyřešeno jako Rychle vpřed" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "Vytvořit novou vzdálenou větev?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "Vytvořit…" #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "Vytvořena nová značka názvaná „%s“" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "Stávající repozitář" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "Vlastní akce kopírování" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "Přizpůsobit…" #: cola/widgets/main.py:754 msgid "Cut" msgstr "Vyjmout" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "Český překlad" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "DAG…" #: cola/icons.py:54 msgid "Dark Theme" msgstr "" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "Datum, čas" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Odstranit" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "Smazat %d soubory?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "Odstranit záložku" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "Odstranit záložku?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Smazat větev" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "Smazat soubory" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "Smazat soubory…" #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "Smazat soubory?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "Odstranit vzdálený" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "Smazat vzdálenou větev" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "Smazat vzdálenou větev…" #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "Odstranit nástrojovou lištu" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "Odstranit vzdálený" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "Odstranit vzdálený „%s“" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "Odstranit vzdálený?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Smazat…" #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "Odstraňování „%s“ se nezdařilo" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "Odstraněno" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "Odpojit" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "Zjistit značky konfliktů" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "Zjistit značky konfliktů v nesloučených souborech" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "Vývojář" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "Diff" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "Rozdíl oproti předchůdci…" #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "Volby Diff" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "Nástroj Diff" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "Diff vybraný -> tento" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "Diff tento -> vybraný" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "" #: cola/difftool.py:324 msgid "Difftool" msgstr "" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "Složka existuje" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "Zobrazit nesledované soubory" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "Dokumentace" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "Zahodit" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "Zahodit odklad" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "Zahodit odklad?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "Zahodit odklad „%s“?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "Zahodit vybraný odklad" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 msgid "Edit" msgstr "Upravit" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "Upravit přeskládání" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "Upravit vzdálené" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "Upravit vzdálené…" #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "Upravit vzdálené jejich výběrem ze seznamu" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "Upravit označená umístění" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "Upravit…" #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "Editor" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "E-mailová adresa" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "Napsat přispěvateli e-mail" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "Povoleno" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "Zadat nový název větve" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "Zadejte název pro nový holý repozitář" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "Zadat název odkladu" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "Chyba" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "Chyba při klonování" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "Chyba při vytváření větve" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "Chyba při vytváření repozitáře" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "Chyba při odstraňování vzdálené větve" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "Chyba při úpravě souboru" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "Chyba při spouštění blame prohlížeče" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "Chyba při spouštění prohlížeče historie" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "Chyba při vytváření vzdálené \"%s\"" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "Chyba při vytváření stash" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Chyba při odstraňování vzdálené \"%s\"" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "Chyba při přejmenovávání „%(name)s“ na „%(new_name)s“" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "Chyba spouštění háčku prepare-commitmsg" #: cola/cmds.py:2987 cola/cmds.py:3033 #, python-format msgid "Error updating submodule %s" msgstr "" #: cola/cmds.py:3069 msgid "Error updating submodules" msgstr "" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "Chyba: nedaří se nalézt šablonu nahrání" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "Chyba: Nenastavená šablona nahrání" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Chyba: „%s“ nemohl být klonován" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "Chyba: značka „%s“ nemohla být vytvořena" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "Spouští se akce %s" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "Rozbalit vše" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "Exportovat záplaty" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "Exportovat záplaty…" #: cola/widgets/main.py:547 msgid "Expression..." msgstr "Výraz…" #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "Podrobný popis…" #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Pouze rychle vpřed" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "Pouze rychle vpřed" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "Oblíbené repozitáře" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "Oblíbené" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "Vyzvednout" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "Vyzvednout sledovanou větev" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "Vyzvednout (fetch)…" #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "Prohlížeč souborů…" #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "Rozdíly souboru" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "Soubor uložen" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "Soubor uložen jako „%s“" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "Monitorování změn na souborovém systému: vypnuto protože „cola.inotify“ je nastaveno na false.\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "Monitorování změn na souborovém systému: vypnuto protože libc nepodporuje systémová volání inotify.\n" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "Monitorování změn na souborovém systému: vypnuto protože není nainstalováno pywin32.\n" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "Monitorování změn na souborovém systému: zapnuto.\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "Název souboru" #: cola/widgets/dag.py:821 msgid "Files" msgstr "Soubory" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "Filtrovat větve…" #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "Filtrovat umístění…" #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "Hledat soubory" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "Pevný řetězec" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "Písmo s pevnou šířkou" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "Opravit" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "Opravit předchozí zápis" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "" #: cola/themes.py:705 msgid "Flat dark green" msgstr "" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "" #: cola/themes.py:691 msgid "Flat dark red" msgstr "" #: cola/themes.py:656 msgid "Flat light blue" msgstr "" #: cola/themes.py:677 msgid "Flat light green" msgstr "" #: cola/themes.py:670 msgid "Flat light grey" msgstr "" #: cola/themes.py:663 msgid "Flat light red" msgstr "" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Velikost písma" #: cola/widgets/remote.py:197 msgid "Force" msgstr "Vynutit" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "Vynutit vyzvednutí" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "Vynutit vyzvednutí?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "Vynutit odeslání" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "Vynutit odeslání?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "Vynutit vyzvednutí z %s?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "Vynutit odeslání do %s?" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "Formátovací řetězec" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "Francouzský překlad" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "GPG podepsaný zápis sloučení" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "Shromažďování informací pro „%s“…" #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "Německý překlad" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "Získat šablonu zprávy zápisu" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "Jít níže" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "Jít výše" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "Získat soubor…" #: cola/widgets/dag.py:848 msgid "Graph" msgstr "Graf" #: cola/widgets/main.py:354 msgid "Grep" msgstr "Grep" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "Nepřeskládali/nestáhli jste v poslední době?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Nápověda" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "Nápověda – uživatelské akce kopírování" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "Nápověda – najít soubory" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "Nápověda – git-cola-sequence-editor" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "Prohlížeč historie" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "Maďarský překlad" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "Ignorovat všechny mezery" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "Ignorovat změny v počtu mezer" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "Ignorovat změny v mezerách na konci řádků" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "Ignorovat dle šablony" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "Ignorovat přesný název souboru" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "Ignorovat název souboru nebo šablonu" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "" #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "Zahrnout značky " #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "Indonéský překlad" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "Inicializovat Git Annex" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "Inicializovat Git LFS" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "Inicializovat dílčí moduly" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "Vkládat mezery místo tabelátorů" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "Interaktivní přeskládání" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "Neplatná revize" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "Ponechat *.orig zálohy začlenění" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "Zachovat index" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "Klávesové zkratky" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "Spustit nástroj Diff" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "Spustit nástroj pro porovnání rozdílů mezi složkami" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "Spustit editor" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "Spustit terminál" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" "Spustit externí diff nástroj\n" "Zkratka: Ctrl+D" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "Spustit git-cola" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "Spustit git-difftool proti předchozím verzím" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "Spustit git-difftool na stávajícím umístění" #: cola/icons.py:55 msgid "Light Theme" msgstr "" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "Nahrát zprávu zápisu" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "Načíst zprávu zápisu…" #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "Načíst zprávu předchozího zápisu" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "Načítání…" #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "Místní" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Místní větev" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "Místní větev" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "Zamknout rozvržení" #: cola/widgets/dag.py:816 msgid "Log" msgstr "Záznam událostí" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "Správce (od roku 2007) a vývojář" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Sloučit" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "Začlenit „%(revision)s“ do „%(branch)s“" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "Nástroj sloučení" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Výřečnost při sloučení" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "Sloučení se nezdařilo. Je třeba rozhodnout o konfliktech." #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "Začlenit do „%s“" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "Začlenit do současné větve" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "Sloučit (merge)…" #: cola/widgets/main.py:1177 msgid "Merging" msgstr "Slučování" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "Zpráva" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "Chybí zpráva příspěvku" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "Chybí data" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "Chybí název" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "Chybějící revize" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "Zpráva značky chybí" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "Změněno" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "Více…" #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "Posunout dolů" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "Posunout nahoru" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "Přesunout soubory do koše" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "Název" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "Název nového vzdáleného" #: cola/guicmds.py:147 cola/widgets/main.py:281 msgid "New Bare Repository..." msgstr "Nový holý repozitář…" #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "Nový repozitář…" #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "Přidat nástrojovou lištu" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Nový…" #: cola/actions.py:56 msgid "Next File" msgstr "Následující soubor" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "Ne" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "Nezadána žádná revize" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Žádné změny, které by bylo možné zapsat.\n" "\n" "Je potřeba připravit k zapsání alespoň jeden soubor předtím, než ho bude možné zapsat." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "V této větvi nejsou žádné zápisy." #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "Ne rychle vpřed" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "Ne rychle vpřed" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Nevybrán žádný repozitář." #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "Vyzvednutí Ne rychle vpřed přepíše místní historii!" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "Odeslání Ne rychle vpřed přepíše uveřejněnou historii!\n" "(Dali jste nejdříve stáhnout?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "Není co odeslat" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "Není co udělat" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Počet kontextový řádků Diff" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Otevřít" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Otevřít Git repozitář" #: cola/widgets/submodules.py:48 msgid "Open Parent" msgstr "" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "Otevřít nadřazenou složku" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "Otevřít nedávné" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "Otevřít ve výchozí aplikaci" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "Otevřít v novém okně" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "Otevřít v novém okně…" #: cola/widgets/main.py:410 msgid "Open..." msgstr "Otevřít…" #: cola/widgets/branch.py:354 msgid "Other branches" msgstr "Další větve" #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "Přepsat" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "Přepsat „%s“?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "Přepsat soubor?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "Zpracovat argumenty pomocí shellu.\n" "Dotazy s mezerami vyžadují \"dvojité uvozovky\"." #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "Částečně staged" #: cola/widgets/main.py:758 msgid "Paste" msgstr "Vložit" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "Záplaty aplikovány" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "Cesta" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "Cesta nebo URL, která se má klonovat (Env. $VARS okay)" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "Vybrat" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "Pixel XOR" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "Zadejte jak název větve, tak výraz revize." #: cola/cmds.py:2297 msgid "Please select a file" msgstr "Vyberte soubor" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "Zadejte název nové značky." #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "Zadejte štítek revize." #: cola/widgets/commitmsg.py:417 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/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "Umístit současnou hlavu větve na nový zápis?" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "Polský překlad" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "Pop" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Předvolby" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "Předpona" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "Připravit zprávu zápisu" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "Zabránit „Stage“ ze staging všech souborů když není nic vybráno" #: cola/actions.py:65 msgid "Previous File" msgstr "Předchozí soubor" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "Dotázat se při vytvoření" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "Dotázat se když nahrání vytváří nové vzdálené větve" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "Prune" #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "Stáhnout si" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "Stáhnout si (pull)…" #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Odeslat" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Odeslat (push)…" #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Ukončit" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Přeskládat" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "Přeskládat do %s" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "Přeskládání zastaveno" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "Místo sloučení přeskládat současnou větev" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "Přeskládání" #: cola/widgets/main.py:118 msgid "Recent" msgstr "Nedávné" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "Nedávné repozitáře" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "Počet nedávných repozitářů" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "Nedávno změněné soubory" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "Nedávno změněné soubory…" #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "Obnova zahozeného odkladu není možná." #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Obnova ztracených příspěvků nemusí být snadná." #: cola/widgets/main.py:751 msgid "Redo" msgstr "Znovu" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "Omezit historii zápisů na minimum" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Načíst znovu" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "Odmítnout sloučení, jestliže současná HLAVA není již aktualizovaná, nebo sloučení, které nemůže být vyřešeno jako Rychle vpřed" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Vzdálená" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "Vzdálená větev" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "Vzdálená větev smazána" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "Vzdálené git repozitáře – přejmenujete dvojklikem" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "Odstranit" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "Odstranit %s ze seznamu nedávných?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "Odebrat prvek" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "Odstranit odkazy na vzdálené větve, které již neexistují ve vzdáleném" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "Odstranit vybrané (Smazat)" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Přejmenovat" #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "Přejmenovat „%s“" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "Přejmenovat větev" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "Přejmenovat větev…" #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "Přejmenovat stávající větev" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "Přejmenovat vzdálenou" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "Přejmenovat repozitář" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "Přejmenovat větev" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "Přejmenovat vzdálenou „%(current)s“ na „%(new)s“?" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "Přejmenovat vybraná umístění" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "Repozitář: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Resetovat" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "Resetovat \"%(branch)s\" do \"%(revision)s\"?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "Resetovat větev" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "Resetovat větev?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "Resetováním „%(branch)s“ do „%(revision)s“ se ztratí zápisy." #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "Vrátit" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "Vrátit komplex rozdílů" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "Vrátit komplex rozdílů…" #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "Vrátit komplex rozdílů?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "Vrátit vybrané řádky" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "Vrátit vybrané řádky…" #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "Vrátit vybrané řádky?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "Vrátit nezapsané změny" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "Vrátit nezapsané změny?" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "Vrátit nezapsané úpravy…" #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "Vrátit nepřipravené změny" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "Vrátit nepřipravené změny?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "Vrátit nepřipravené úpravy…" #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "Vrátit nezapsané změny?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "Vrátit nepřipravené změny?" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "Vrátit nenahrané změny v označených umístěních" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "Vrátit unstaged změny v značených umístěních" #: cola/guicmds.py:320 msgid "Review" msgstr "Revidovat" #: cola/widgets/main.py:597 msgid "Review..." msgstr "Revidovat…" #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Revize" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Číslo revize:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Revize ke sloučení" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "Přepsat uveřejněný zápis?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "Spustit" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "Spustit „%s“?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "Spustit %s?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "Spustit příkaz „%s“?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "Spuštěný příkaz: %s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "Ruský překlad" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "SHA-1" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "Bezpečný režim" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Uložit" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "Uložit Archiv" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "Uložit jako Tarball/Zip…" #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "Uložit nastavení graf. rozhraní" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "Uložit odklad" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "Uložit modifikovaný stav jako nový odklad" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "Uloženo „%(filename)s“ z „%(ref)s“ do „%(destination)s“" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "Hledat" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "Hledat autory" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "Hledat zprávy zápisů" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "Hledat tvůrce zápisů" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "Hledat datový rozsah" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "Hledat rozdíly" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "Hledat dle výrazu" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "Hledat dle cesty" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "Hledat pevný řetězec" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "Hledat s použitím základních POSIX regulárních výrazů" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "Hledat s použitím rozšířených POSIX regulárních výrazů" #: cola/widgets/main.py:507 msgid "Search..." msgstr "Hledat…" #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Vybrat" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Vybrat vše" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "Vybrat větev k revizi" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "Vybrat podřízený" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "Vybrat zápis" #: cola/guicmds.py:136 msgid "Select Directory..." msgstr "Vybrat složku…" #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "Vybrat nový upstream" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "Vybrat nejnovější podřízený" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "Vybrat nejstarší nadřazený" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "Vybrat nadřazený" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "Vybrat předchozí verzi" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "Vybrat nadřazenou složku pro nový klon" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "Vybrat výstupní složku" #: cola/widgets/selectcommits.py:182 msgid "Select output directory" msgstr "Vybrat výstupní složku" #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "Vybrat soubory se záplatami (patch)…" #: cola/widgets/editremotes.py:434 msgid "Select repository" msgstr "Vybrat repozitář" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "Nastavit výchozí repozitář" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "Nastavit upstream větev" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "Nastavit upstream" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "Nastavení" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "Shell argumenty" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "Posunout dolů" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "Posunout nahoru" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "Klávesové zkratky" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Zobrazit Diffstat po sloučení" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "V nadpisu okna zobrazovat úplné popisy umístění" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "Zobrazit nápovědu" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "Zobrazit historii" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "Zobrazit nápovědu\n" "Zkratka: ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "Zobrazit čísla řádků" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "Zobrazit celé obklopující funkce změn" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "Zobrazit změny před" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "Vedle sebe" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Podepsat" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "Podepsat značku" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "Podepsat na tomto nahrání" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "Překlad do zjednodušené čínštiny" #: cola/cmds.py:2527 msgid "Skip" msgstr "Přeskočit" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "Přeskočit současnou záplatu" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "Záložky řadit abecedně" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "Španělský překlad" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "Určuje SHA-1 štítku" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "Určuje zprávu značky" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "Určuje název značky" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "Doporučení pravopisu" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "Squash sloučené nahrání do jediného nahrání" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "Připravit k zapsání" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "Připravit k zapsání / zrušit přípravu" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "Připravit k zapsání komplex rozdílů" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Změněné připravit k zapsání" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "Vybrané připravit k zapsání" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "Připravit k zapsání vybrané řádky" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "Nesloučené připravit k zapsání" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "Nesledované připravit k zapsání" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "Připravit k zapsání a zapsat" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "Připravit k zapsání a zapsat?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "Konflikty přípravy k zapsání" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "Konflikty přípravy k zapsání?" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "Připravit / zrušit přípravu označených umístění pro nahrání" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "Připraveno k zapsání" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "Připravuje s k zápisu: %s" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "Zahájit interaktivní přeskládání (rebase)…" #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "Počáteční revize" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "Odložit" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "Odložit index" #: cola/widgets/stash.py:79 msgid "Stash staged changes only" msgstr "Odložit pouze připravené změny" #: cola/widgets/stash.py:75 msgid "Stash unstaged changes only, keeping staged changes" msgstr "Odložit pouze nepřipravené změny, zachovat připravené změny" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "Odložit (stash)…" #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "Stav" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "Zastavit sledující umístění" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "Shrnout nahrání sloučení" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "Shrnutí" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Šířka tabelátoru" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Značka" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "Značka vytvořena" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Zpráva značky…" #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "Byl požadován podpis značky, ale zpráva značky je prázdná." #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "Značky" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "Šířka textu" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "Větev nebude již k dispozici." #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "Větev bude resetována za použití \"git reset --mixed %s\"" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "Větev bude resetována za použití \"git reset --soft %s\"" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "Zpráva o nahrání bude vyčištěna." #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "Soubor \"%s\" existuje a bude přepsán." #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "Následující soubory budou smazány:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "Výraz revize nemůže zůstat nevyplněný." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "Tuto akci nelze vzít zpět. Vyčistit zprávu k nahrání?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "Tento zápis už byl zveřejněn.\n" "Tato činnost přepíše uveřejněnou historii.\n" "Pravděpodobně to nechcete udělat." #: cola/widgets/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "Tato akce zahodí nezapsané změny.\n" "Tyto změny nemohou být obnoveny." #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Tato akce zahodí nezapsané změny.\n" "Tyto změny nemohou být obnoveny." #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Tato akce zahodí nepřipravené změny.\n" "Tyto změny nemohou být obnoveny." #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "Zobrazit/skrýt filtr větví" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "Zobrazit/skrýt filtr cest" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Sledovaná větev" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "Sledovaná větev" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "Překlad do tradiční čínštiny (taiwanštiny)" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "Překladatelé" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "Turecký překlad" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "URL: %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "Ukrajinský překlad" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "Nelze přeskládat" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "Nedaří se nastavit URL pro „%(name)s“ na „%(url)s“" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "Zpět" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "Nesloučeno" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "Zrušit přípravu" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "Zrušit veškerou přípravu" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "Zrušit přípravu komplexu rozdílů" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "Zrušit přípravu vybraných" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "Zrušit přípravu vybraných řádků" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "Ruší se příprava: %s" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "Přestat sledovat vybrané" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "Nesledováno" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "Přestává se sledovat: %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Aktualizovat stávající větev:" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "" #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "Aktualizuje se" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Uživatelské jméno" #: cola/widgets/about.py:89 msgid "Version" msgstr "Verze" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "Zobrazit" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "Prohlížet historii…" #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "Zobrazit historii vybraných umístění" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "Vizualizovat" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "Vizualizovat všechny větve…" #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "Vizualizovat stávající větev…" #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "Chcete připravit k zapsání a zapsat všechny změněné soubory?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "Ano" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "Jste vprostřed slučování.\n" "Nelze amend při slučováné." #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "Nelze přeskládat s nezapsanými změnami." #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "Pro sloučení je třeba určit revizi." #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "Je třeba určit kterou revizi zobrazit." #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "Přiblížit" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "Oddálit" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "Přizpůsobit velikosti okna" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "argumenty příkazového řádku" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "chyba: nedaří se spustit git" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "návratový kód %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "" #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "git cola verze %s" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "git-cola diff" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "výsledek z grep…" #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "hotkeys.html" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "vX.Y.Z" #: cola/hidpi.py:43 msgid "x 1" msgstr "" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "" #: cola/hidpi.py:46 msgid "x 2" msgstr "" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "rrrr-mm-dd" #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Odklad s názvem \"%s\" již existuje" #~ msgid "Delete selected branch?" #~ msgstr "Smazat vybranou větev?" #~ msgid "Error: Stash exists" #~ msgstr "Chyba: Odklad existuje" #~ msgid "Hide Details.." #~ msgstr "Skrýt podrobnosti…" #~ msgid "PATCH %(current)d/%(count)d" #~ msgstr "PATCH %(current)d/%(count)d" #~ msgid "Rename remote?" #~ msgstr "Přejmenovat vzdálenou?" #~ msgid "Reset Branch Head" #~ msgstr "Resetovat hlavu větve" #~ msgid "Reset Hard" #~ msgstr "Tvrdý reset" #~ msgid "Reset Merge" #~ msgstr "Resetovat sloučení" #~ msgid "Reset Soft" #~ msgstr "Měkký reset" #~ msgid "Reset Worktree" #~ msgstr "Resetovat pracovní strom" #~ msgid "Reset hard?" #~ msgstr "Tvrdý reset?" #~ msgid "Reset merge?" #~ msgstr "Resetovat sloučení?" #~ msgid "Reset soft?" #~ msgstr "Měkký reset?" #~ msgid "Reset worktree?" #~ msgstr "Resetovat pracovní strom?" #~ msgid "Select File" #~ msgstr "Vybrat soubor" #~ msgid "Select Repository..." #~ msgstr "Vybrat repozitář…" #~ msgid "Select manually..." #~ msgstr "Vybrat ručně…" #~ msgid "Show Details..." #~ msgstr "Zobrazit podrobnosti…" #~ msgid "Show icon? (if available)" #~ msgstr "Zobrazit ikonu? (je-li dostupná)" #~ msgid "Summary:" #~ msgstr "Shrnutí:" #~ msgid "The branch will be reset using \"git reset --hard %s\"" #~ msgstr "Větev bude resetována za použití \"git reset --hard %s\"" #~ msgid "The branch will be reset using \"git reset --merge %s\"" #~ msgstr "Větev bude resetována za použití \"git reset --merge %s\"" #~ msgid "The worktree will be reset using \"git reset --keep %s\"" #~ msgstr "Větev bude resetována za použití \"git reset --keep %s\"" #~ msgid "unknown" #~ msgstr "neznámé" git-cola-4.6.1/cola/i18n/de.po000066400000000000000000004230121457126473700156700ustar00rootroot00000000000000# Translation of git-cola to Deutsch. # Copyright (C) 2007, 2013 Shawn Pearce, et al. # This file is distributed under the same license as the git-cola package. # # Christian Stimming , 2007 # Sven Claussner , 2013 # msgid "" msgstr "" "Project-Id-Version: git-cola VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-04-14 07:38+0200\n" "PO-Revision-Date: 2019-03-07 07:18+0100\n" "Last-Translator: Kai Krakow \n" "Language-Team: German\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.0.6\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-KeywordsList: N_\n" "X-Poedit-Basepath: ../cola\n" "X-Poedit-SearchPath-0: .\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " Ziehen und ablegen oder nutzen Sie den Hinzufügen-Knopf,\n" " um Patches zur Liste hinzuzufügen\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" "\n" "
\n" " Git Cola wurde Dank der Hilfe unten aufgeführter Leute in\n" " verschiedene Sprachen übersetzt.\n" "\n" "
\n" "

\n" " Übersetzungen sind nur eine Annäherung. Falls Sie einen\n" " Fehler finden, lassen Sie es uns wissen, indem Sie auf\n" " Github einen Fehlerbericht eröffnen:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " Wir laden Sie ein, an einer Übersetzung teilzuhaben, indem\n" " Sie Übersetzungen aktualisieren oder hinzufügen und einen\n" " Pull-Request öffnen.\n" "

\n" "\n" "
\n" "\n" " " #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" "\n" "
\n" " Git Cola Version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" "\n" "
\n" " Bitte verwenden Sie %(bug_link)s, um Fehler zu melden.\n" "
\n" " " #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" "\n" " Format-String-Variablen\n" " -----------------------\n" " %(path)s = relativer Dateipfad\n" " %(abspath)s = absoluter Dateipfad\n" " %(dirname)s = relativer Verzeichnispfad\n" " %(absdirname)s = absoluter Verzeichnispfad\n" " %(filename)s = Dateiname\n" " %(basename)s = Dateiname ohne Erweiterung\n" " %(ext)s = Erweiterung\n" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" "\n" "Tastaturkürzel\n" "--------------\n" "J, Runter = Nach unten\n" "K, Hoch = Nach oben\n" "Eingabe = Ausgewählte Dateien bearbeiten\n" "Leertaste = Datei mit Standardanwendung öffnen\n" "Strg + L = Texteingabefeld fokussieren\n" "? = Hilfe anzeigen\n" "\n" "Die Pfeile hoch und runter ändern den Fokus zwischen dem\n" "Texteingabefeld und den Ergebnissen.\n" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr " - Verlauf" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr " Versionen davor" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "\"%(branch)s\" wurde von \"%(remote)s\" gelöscht." #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "\"%(command)s\" wurde beendet mit Status \"%(status)d\"" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "\"%(command)s\" wurde mit Code %(status)d beendet" #: cola/guicmds.py:156 #, python-format msgid "\"%s\" already exists" msgstr "\"%s\" existiert bereits" #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "\"%s\" existiert bereits, cola wird ein neues Verzeichnis anlegen" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "\"%s\" erwartet, dass eine Datei ausgewählt wird." #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "#" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s: %(branch)s - Durchsuchen" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "%(project)s: %(ref)s - DAG" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "vor %d Tagen" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "vor %d Stunden" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "vor %d Minuten" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "%d Patch(es) angewendet." #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d übersprungen" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" "%s scheint Merge-Konflikte zu enthalten.\n" "\n" "Sie sollten diese Datei ggf. überspringen.\n" "Trotzdem vormerken?" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "%s ist kein Git-Repository." #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "%s wird von den Favoriten entfernt." #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "%s wird von den kürzlich verwendeten Repositories entfernt." #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: Datei oder Verzeichnis nicht gefunden." #: cola/widgets/main.py:748 msgid "&Edit" msgstr "Bearbeiten" #: cola/widgets/main.py:690 msgid "&File" msgstr "&Datei" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(Nachbesserung)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "*** Branch-Punkt ***" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** Arbeitsbereich ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "100%" #: cola/widgets/diff.py:817 msgid "200%" msgstr "200%" #: cola/widgets/diff.py:814 msgid "25%" msgstr "25%" #: cola/widgets/diff.py:818 msgid "400%" msgstr "400%" #: cola/widgets/diff.py:815 msgid "50%" msgstr "50%" #: cola/widgets/diff.py:819 msgid "800%" msgstr "800%" #: cola/widgets/finder.py:118 msgid " ..." msgstr " ..." #: cola/cmds.py:1685 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 Commit-Vorlage wurde noch nicht konfiguriert.\n" "Verwenden Sie \"git config\" um \"commit.template\" so zu definieren,\n" "dass es auf eine Commit-Vorlage zeigt." #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "Ein Hook muss bereitgestellt sein für \"%s\"" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "Abbrechen" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "Befehl abbrechen" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "Zusammenführung abbrechen" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Zusammenführung abbrechen..." #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "Möchten Sie den Befehl abbrechen?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Abbrechen der gegenwärtigen Zusammenführung bedeutet den Verlust *ALLER* nicht vorgemerkten Änderungen.\n" "Eine Wiederherstellung nicht vorgemerkter Änderungen ist nicht möglich." #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "Möchten Sie die Zusammenführung abbrechen?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "Über git-cola" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "Über git-cola" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "Akzeptieren" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "Änderungen akzeptieren und Rebase starten\n" "Tastenkürzel: Strg+Enter" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "Befehlsname" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "Befehle" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "Befehle..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "Hinzufügen" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "Favorit hinzufügen" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "Hinzufügen" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "Trenner hinzufügen" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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 Hinzufügen(+) und Löschen(-) auf der linken\n" "Seite, um externe Repositories zur Liste hinzuzufügen oder zu löschen.\n" "\n" "Externe Referenzen können umbenannt werden, indem Sie sie auswählen\n" "und \"Eingabe\" drücken, oder darauf doppelt klicken." #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "Externes Git-Repository hinzufügen" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "Patches hinzufügen (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "Externe Referenz hinzufügen" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "Zu .gitignore hinzufügen" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "Zu Git Annex hinzufügen" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "Zu Git LFS hinzufügen" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "Hinzufügungen" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "Erweitert" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "Alter" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "Alle Repositories" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "Aktualisierungen ohne schnelles Vorspulen erlauben. Die Nutzung von \"force\" kann dazu führen, dass im externen Repository Commits verloren gehen; seien Sie vorsichtig" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "Immer einen Merge-Commit erzeugen, selbst wenn schnelles Vorspulen möglich ist" #: cola/cmds.py:220 msgid "Amend" msgstr "Ergänzen" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "Letzten Commit nachbessern" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Letzten Commit nachbessern" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "Möchten Sie die veröffentlichten Commit nachbessern?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "Am Nachbessern" #: cola/widgets/cfgactions.py:150 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/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "Stattdessen wird ein einfacher, unsignierter Tag erstellt.\n" "Unsignierten Tag erstellen?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "Anwenden" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "Patches anwenden" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "Patches anwenden..." #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "Die ausgewählte Ablage in den Arbeitsbereich zurück übernehmen" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "Die ausgewählte Ablage in den Arbeitsbereich zurück übernehmen" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "Argumente" #: cola/qtutils.py:886 msgid "Attach" msgstr "Anhängen" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "Autor" #: cola/widgets/about.py:90 msgid "Authors" msgstr "Autoren" #: cola/hidpi.py:41 msgid "Auto" msgstr "" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "Zeilen automatisch umbrechen" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "Einfacher regulärer Ausdruck" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "Verantwortlichkeitsbetrachter" #: cola/widgets/browse.py:206 msgid "Blame selected paths" msgstr "" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "Verantwortlichkeit..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "Fettschrift mit dunklem Hintergrund verwenden anstelle von schräg geschriebenen Überschriften" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Branch" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "Der Branch \"%(branch)s\" existiert nicht in \"%(remote)s\".\n" "Ein neuer externer Branch wird veröffentlicht." #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "Der Branch \"%s\" existiert bereits." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "Branch-Diff-Betrachter" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "Branch existiert" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Branch-Name" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "Branch: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "Branches" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "Branches..." #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "Brasilianische Übersetzung" #: cola/guicmds.py:52 msgid "Browse" msgstr "Ansehen" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "Commits durchsuchen..." #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "Gegenwärtigen Branch durchsuchen..." #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "Anderen Branch durchsuchen..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "..." #: cola/widgets/main.py:87 msgid "Browser" msgstr "Verzeichnisstruktur" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "Durchsuche %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "Commit-Hooks übergehen" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "Abbrechen" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "Rebase abbrechen\n" "Tastenkürzel: Strg+Q" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "Fehler beim Ergänzen" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "Kann \"%s\" nicht ausführen: Bitte Verantwortlichkeiten-Betrachter konfigurieren" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "Kann \"%s\" nicht ausführen: Bitte Verlaufsbetrachter konfigurieren" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "\"%s\" nach nicht ausgeführt werden: Bitte einen Editor konfigurieren" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "In Upstream geändert" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "Rechtschreibung prüfen" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "Rechtschreibung prüfen" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Umstellen" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "Umschalten nach Erstellung" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Zu Branch wechseln" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "Wechseln zu losgelöstem HEAD" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "Als neuen Branch erstellen und wechseln" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Wechseln..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "Einzelne Commits übernehmen" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "Diesen Commit übernehmen" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "Einzelnen Commit übernehmen..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "Pfad wählen" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "Modus für reguläre Ausdrücke für \"git grep\" wählen" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "Standard-Repository vergessen" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "Commit-Beschreibung leeren" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "Commit-Beschreibung leeren?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "Leeren..." #: cola/widgets/clone.py:124 msgid "Clone" msgstr "Klonen" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "Repository klonen" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Klonen..." #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "Klone Repository aus %s" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Schließen" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "Schließen..." #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "Alle zuklappen" #: cola/sequenceeditor.py:371 msgid "Command" msgstr "Kommando" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "Commit" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "Commit fehlgeschlagen" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "Vorgemerkte Änderungen aufnehmen" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "Vorgemerkte Änderungen aufnehmen\n" "Kürzel: Strg+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "Commit-Zusammenfassung" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "Merge eintragen, wenn es keine Konflikte gibt. Haken entfernen, um den Merge offen zu lassen" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "Commit aufnehmen" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "Vergleichen" #: cola/difftool.py:102 msgid "Compare All" msgstr "Alle vergleichen" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "Werkzeugleiste konfigurieren" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "Externen Branch als neuen Upstream konfigurieren" #: cola/widgets/main.py:169 msgid "Console" msgstr "Meldungen" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Fortsetzen" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Kopieren" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "Dateiname in Zwischenablage kopieren" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "Führenden Pfad in Zwischenablage kopieren" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "Kopiere Pfad in Zwischenablage" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "Relativen Pfad in Zwischenablage kopieren" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "SHA-1 kopieren" #: cola/widgets/status.py:738 msgid "Copy..." msgstr "Kopieren..." #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "URL konnte nicht ausgewertet werden: \"%s\"" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Branch erstellen" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "Patch erstellen" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "Externen Branch erstellen" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "Unterzeichneten Commit erstellen" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "Tag erstellen" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "Tag erstellen..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "Unsignierten Tag erstellen" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "Merge-Commit erstellen, selbst wenn der Merge mit schnellem Vorspulen auflösbar ist" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "Neuen externen Branch erstellen?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "Neu..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "Tag erstellt als \"%s\"" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "Gegenwärtiges Repository" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "Benutzerdefinierte Kopier-Befehle" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "Anpassen..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "Ausschneiden" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "Tschechische Übersetzung" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "DAG..." #: cola/icons.py:54 msgid "Dark Theme" msgstr "" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "Datum und Zeit" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Löschen" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "Wollen Sie %d Datei(en) löschen?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "Favoriten löschen" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "Favorit löschen?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Branch löschen" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "Lösche Dateien" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "Lösche Datei(en)..." #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "Datei(en) löschen?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "Externe Referenz löschen" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "Externen Branch löschen" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "Externen Branch löschen..." #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "Werkzeugleiste löschen" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "Externe Referenz löschen" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "Externe Referenz \"%s\" löschen" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "Externe Referenz löschen?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Löschen..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "Löschen von \"%s\" fehlgeschlagen" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "Löschungen" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "Loslösen" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "Konflikt-Markierungen erkennen" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "Konflikt-Markierungen in nicht zusammengeführten Dateien erkennen" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "Entwickler" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "Vergleich" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "Mit einem Vorgänger vergleichen..." #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "Vergleichsoptionen" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "Werkzeug zum Dateivergleich" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "Auswahl mit diesem vergleichen" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "Mit Auswahl vergleichen" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "Vergleichsstatistik" #: cola/difftool.py:324 msgid "Difftool" msgstr "Diff-Werkzeug" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "Verzeichnis existiert" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "Nicht verfolgte Dateien anzeigen" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "Online-Hilfe" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "Löschen" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "Ablage löschen" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "Möchten Sie die Ablage löschen?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "Möchten Sie die Ablage \"%s\" löschen?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "Die ausgewählte Ablage löschen" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 msgid "Edit" msgstr "Bearbeiten" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "Rebase bearbeiten" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "Externe Referenzen bearbeiten" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "Externe Referenzen bearbeiten..." #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "Bearbeiten Sie externe Referenzen, indem Sie sie in der Liste auswählen" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "Ausgewählten Pfad bearbeiten" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "Bearbeiten..." #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "Editor" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "E-Mail-Adresse" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "E-Mail an Beitragenden" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "Aktiviert" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "Namen für neuen Branch vergeben" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "Namen für neues kahles Repository" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "Geben Sie einen Namen für die Ablage an" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "Fehler" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "Fehler beim Klonen" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "Fehler beim Erstellen des Branches" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "Fehler beim Anlegen des Repositories" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "Fehler beim Löschen des externen Branches" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "Fehler beim Bearbeiten der Datei" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "Fehler beim Starten der Verantwortlichkeitansicht" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "Fehler beim Starten der Verlaufsansicht" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "Fehler beim erstellen der externen Referenz \"%s\"" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "Fehler beim Erstellen der Ablage" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Fehler beim Löschen der externen Referenz \"%s\"" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "Fehler beim Umbenennen von \"%(name)s\" in \"%(new_name)s\"" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "Fehler beim Aufrufen der Vor-Eintragen-Kontrolle" #: cola/cmds.py:2987 cola/cmds.py:3033 #, python-format msgid "Error updating submodule %s" msgstr "" #: cola/cmds.py:3069 msgid "Error updating submodules" msgstr "" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "Fehler: Commit-Vorlage nicht gefunden" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "Fehler: Commit-Textvorlage nicht konfiguriert" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Fehler: Konnte \"%s\" nicht klonen" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "Fehler: Konnte Tag \"%s\" nicht erstellen" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "Ausführen von Aktion %s" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "Alles ausklappen" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "Patches exportieren" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "Patches exportieren..." #: cola/widgets/main.py:547 msgid "Expression..." msgstr "Mit Suchausdruck..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "Erweiterte reguläre Ausdrücke" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "Ausführliche Beschreibung..." #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Bei lokalen Änderungen abbrechen" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "Nur schnelles Vorspulen" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "Repository-Favoriten" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "Favoriten" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "Holen" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "Verfolgten Branch holen" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "Holen..." #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "Dateien durchsuchen..." #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "Dateiunterschiede" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "Datei gespeichert" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "Datei gespeichert als \"%s\"" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "Benachrichtigung über Änderungen im Dateisystem: deaktiviert, da \"cola.inotify\" auf falsche gesetzt ist.\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "Überwachung von Dateisystemänderungen: deaktiviert, da libc die entsprechenden Systemaufrufe nicht unterstützt.\n" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "Überwachung von Dateisystemänderungen: deaktiviert, da pywin32 nicht installiert ist.\n" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" "Überwachung von Dateisystemänderungen: deaktiviert, da die Obergrenze an Überwachungen erreicht wurde. Sie können versuchen, die Obergrenze dafür anzuheben, indem Sie folgendes ausführen:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" "\n" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "Benachrichtigungen über Änderungen im Dateisystem: aktiviert.\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "Dateiname" #: cola/widgets/dag.py:821 msgid "Files" msgstr "Dateien" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "Branches filtern..." #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "Pfade filtern..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "Dateien suchen" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "Feste Zeichenkette" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "Schriftart" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "Nachbessern (fixup)" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "Vorherigen Commit nachbessern (fixup)" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "" #: cola/themes.py:705 msgid "Flat dark green" msgstr "" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "" #: cola/themes.py:691 msgid "Flat dark red" msgstr "" #: cola/themes.py:656 msgid "Flat light blue" msgstr "" #: cola/themes.py:677 msgid "Flat light green" msgstr "" #: cola/themes.py:670 msgid "Flat light grey" msgstr "" #: cola/themes.py:663 msgid "Flat light red" msgstr "" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Schriftgröße" #: cola/widgets/remote.py:197 msgid "Force" msgstr "Erzwingen" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "Abruf erzwingen" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "Möchten Sie den Abruf erzwingen?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "Veröffentlichung erzwingen" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "Möchten Sie die Veröffentlichung erzwingen?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "Möchten Sie den Abruf von \"%s\" erzwingen?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "Möchten Sie die Veröffentlichung in \"%s\" erzwingen?" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "Format-String" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "Französische Übersetzung" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "GPG-signierter Merge-Commit" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "Frage Informationen zu »%s« ab..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "Deutsche Übersetzung" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "Commit-Beschreibung aus Vorlage einfügen" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "Nach unten" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "Nach oben" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "Datei extrahieren..." #: cola/widgets/dag.py:848 msgid "Graph" msgstr "Diagramm" #: cola/widgets/main.py:354 msgid "Grep" msgstr "Grep" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "Haben Sie kürzlich einen Rebase oder Pull durchgeführt?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Hilfe" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "Hilfe - Benutzerdefinierte Kopier-Befehle" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "Hilfe - Dateien suchen" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "Hilfe - git-cola-sequence-editor" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "Werkzeug für die Verlaufsansicht" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "Ungarische Übersetzung" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "Alle Leerzeichen ignorieren" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "Anzahl von Leerzeichen ignorieren" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "Leerzeichen am Zeilenende ignorieren" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "Benutzerdefiniertes Muster ignorieren" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "Exakten Dateinamen ignorieren" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "Dateiname oder Muster ignorieren" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "" #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "Übernehmen der Tags " #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "Indonesische Übersetzung" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "Git Annex intialisieren" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "Git LFS initialisieren" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "Submodule initialisieren" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "Leerzeichen statt Tabs einfügen" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "Interaktiver Rebase" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "Unzulässige Revision" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "Sicherheitskopie beim Zusammenführen anlegen (Datei.orig)" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "Vormerkliste unverändert lassen" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "Tastenkürzel" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "Mit direktem Vorgänger vergleichen" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "Werkzeug für Verzeichnis-Diff ausführen" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "Mit Editor bearbeiten" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "Konsole starten" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" "Externen Diff-Betrachter starten\n" "Kürzel: Strg+D" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "Starte git-cola" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "Git-difftool gegen Vorversionen ausführen" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "Gegenwärtigen Pfad im Vergleichswerkzeug öffnen" #: cola/icons.py:55 msgid "Light Theme" msgstr "" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "Commit-Beschreibung laden" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "Commit-Beschreibung laden..." #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "Vorherige Commit-Beschreibung laden" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "Lade..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "Lokal" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Lokaler Branch" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "Lokalem Branch" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "Layout sperren" #: cola/widgets/dag.py:816 msgid "Log" msgstr "Log" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "Pflege (seit 2007) und Entwicklung" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Zusammenführen" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "\"%(revision)s\" in \"%(branch)s\" zusammenführen" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "Werkzeug zum Zusammenführen" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Ausführlichkeit der Meldungen beim Zusammenführen" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "Zusammenführen fehlgeschlagen. Konfliktauflösung ist notwendig." #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "Zusammenführen in »%s«" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "In gegenwärtigen Branch zusammenführen" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "Zusammenführen..." #: cola/widgets/main.py:1177 msgid "Merging" msgstr "Am Zusammenführen" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "Beschreibung" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "Die Commit-Beschreibung fehlt" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "Fehlende Daten" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "Fehlender Name" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "Revision fehlt" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "Tag-Beschreibung fehlt" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "Geändert" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "Mehr..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "Nach unten bewegen" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "Nach oben bewegen" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "Dateien in den Papierkorb schieben" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "Name" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "Name der neuen externen Referenz" #: cola/guicmds.py:147 cola/widgets/main.py:281 msgid "New Bare Repository..." msgstr "Neues kahles Repository..." #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "Neues Repository..." #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "Werkzeugleiste hinzufügen" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Neu..." #: cola/actions.py:56 msgid "Next File" msgstr "Nächste Datei" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "Nein" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "Keine Revision angegeben" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Nichts für einen Commit vorhanden.\n" "\n" "Merken Sie mindestens eine Datei für einen Commit vor." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "In diesem Branch gibt es keine Commits." #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "Kein schnelles Vorspulen" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "Kein schnelles Vorspulen" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Kein Repository ausgewählt." #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "Holen ohne schnelles Vorspulen überschreibt den lokalen Verlauf!" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "Versenden ohne schnelles Vorspulen überschreibt den veröffentlichten Verlauf! (Haben Sie zuvor Änderungen geholt und zusammengeführt?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "Nichts für einen Commit vorhanden" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "Nichts zu tun" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Anzahl der Kontextzeilen beim Vergleich" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Öffnen" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Git-Repository öffnen" #: cola/widgets/submodules.py:48 msgid "Open Parent" msgstr "" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "Übergeordnetes Verzeichnis öffnen" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "Zuletzt verwendet" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "Mit der Standardanwendung öffnen" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "In neuem Fenster öffnen" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "In neuem Fenster öffnen..." #: cola/widgets/main.py:410 msgid "Open..." msgstr "Öffnen..." #: cola/widgets/branch.py:354 msgid "Other branches" msgstr "Andere Branches" #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "Überschreiben" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "Möchten Sie die Datei\"%s\" überschreiben?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "Möchten Sie die Datei überschreiben?" #: cola/widgets/grep.py:142 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/models/browse.py:329 msgid "Partially Staged" msgstr "Teilweise vorgemerkt" #: cola/widgets/main.py:758 msgid "Paste" msgstr "Einfügen" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "Patch(es) angewendet" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "Pfad" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "Quell-Pfad oder -URL" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "Übernehmen" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "Pixel-XOR" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "Bitte geben Sie beides, einen Branch-Namen und Revisionsausdruck, an." #: cola/cmds.py:2297 msgid "Please select a file" msgstr "Bitte wählen Sie eine Datei" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "Bitte geben Sie einen Namen für den neuen Tag an." #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "Bitte geben Sie eine Revision für den Tag an." #: cola/widgets/commitmsg.py:417 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 Commit-Beschreibung ein.\n" "\n" "Eine gute Commit-Beschreibung enthält folgende Abschnitte:\n" "\n" "- Erste Zeile: Zusammenfassung in einem Satz, was gemacht wurde\n" "- Zweite Zeile: Leerzeile\n" "- Rest: Ausführliche Beschreibung, warum diese Änderung hilfreich ist\n" #: cola/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "Soll der Branch-Head auf einen neuen Commit zeigen?" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "Polnische Übersetzung" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Einstellungen" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "Verzeichnis" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "Commit-Beschreibung vorbereiten" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "Bei \"Vormerken\" verhindern, dass alle Dateien vorgemerkt werden, wenn nichts ausgewählt wurde" #: cola/actions.py:65 msgid "Previous File" msgstr "Vorige Datei" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "Beim Erstellen nachfragen" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "Bestätigen, falls das Versenden neue Remote-Branches erzeugt" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "Aufräumen von " #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "Pull" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "Pull..." #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Push" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Push..." #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Beenden" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Rebase" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "Rebase auf %s" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "Rebase angehalten" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "Rebase statt Merge für gegenwärtigen Branch durchführen" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "Rebase im Gange" #: cola/widgets/main.py:118 msgid "Recent" msgstr "Kürzlich" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "Kürzlich verwendete Repositories" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "Anzahl zuletzt verwendeter Repositories" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "Kürzlich geänderte Dateien suchen" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "Kürzlich geänderte Dateien suchen..." #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "Eine gelöschte Ablage kann nicht wiederhergestellt werden." #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Ein Wiederherstellen verlorener Commits könnte schwierig sein." #: cola/widgets/main.py:751 msgid "Redo" msgstr "Wiederholen" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "Commit-Verlauf auf ein Minimum reduzieren" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Ansicht aktualisieren" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "Merge verweigern, außer der gegenwärtige HEAD ist aktuell oder der Merge kann mit schnellem Vorspulen ausgelöst werden" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Externe Referenz" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "Externer Branch" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "Externer Branch gelöscht" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "Externes Git-Repository - Doppelklick zum Umbenennen" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "Entfernen" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "%s aus dem Verlauf entfernen?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "Element entfernen" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "Auswahl entfernen (löschen)" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Umbenennen" #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "\"%s\" umbenennen" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "Branch umbenennen" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "Branch umbenennen..." #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "Existierenden Branch umbenennen" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "Externe Referenz umbenennen" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "Repository umbenennen" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "Branch umbenennen" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "Externe Referenz \"%(current)s\" umbenennen zu \"%(new)s\"?" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "Ausgewählten Pfad umbenennen" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "Repository: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Zurücksetzen" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "Möchten Sie \"%(branch)s\" auf \"%(revision)s\" zurücksetzen?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "Branch zurücksetzen" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "Branch zurücksetzen?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "Das Zurücksetzen von \"%(branch)s\" nach \"%(revision)s\" verwirft Commits." #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "Abschnitt verwerfen" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "Abschnitt verwerfen..." #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "Möchten Sie den Abschnitt verwerfen?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "Änderungen an den ausgewählten Zeilen verwerfen" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "Ausgewählte Zeilen wiederherstellen..." #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "Möchten Sie die Änderungen an den ausgewählten Zeilen verwerfen?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "Nicht vorgemerkte Änderungen verwerfen" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "Möchten Sie die Änderungen verwerfen?" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "Nicht vorgemerkte Änderungen verwerfen..." #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "Nehme nicht vorgemerkte Änderungen zurück" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "Wollen sie die nicht vorgemerkten Änderungen zurücknehmen?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "Nicht vorgemerkte Änderungen zurücknehmen..." #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "Möchten Sie die nicht vorgemerkten Änderungen verwerfen?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "Möchten Sie die nicht vorgemerkten Änderungen zurücknehmen?" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "Änderungen an ausgewählten Pfaden verwerfen" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "Änderungen an ausgewählten Pfaden verwerfen" #: cola/guicmds.py:320 msgid "Review" msgstr "Vergleichen" #: cola/widgets/main.py:597 msgid "Review..." msgstr "Review..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Version" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Revisionsausdruck:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Zusammenzuführende Revision" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "Umformulieren" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "Veröffentlichten Commit umschreiben?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "Ausführen" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "Möchten Sie \"%s\" ausführen?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "Möchten Sie \"%s\" ausführen?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "Möchten Sie den Befehl \"%s\" ausführen?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "Führe Befehl \"%s\" aus" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "Russische Übersetzung" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "SHA-1" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "Abgesicherter Modus" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Speichern" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "Als TAR- oder ZIP-Archiv exportieren" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "Als TAR- oder ZIP-Archiv exportieren..." #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "Einstellungen der Programmoberfläche sichern" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "Ablage speichern" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "Änderungen in einer neuen Ablage speichern" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "\"%(filename)s\" von \"%(ref)s\" in \"%(destination)s\" gespeichert" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "Suchen" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "Autor" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "Commit-Beschreibungen durchsuchen" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "Eintragender" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "Datum von-bis" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "Dateiunterschiede durchsuchen" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "Regulärer Ausdruck" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "Datei" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "Nach einer festen Zeichenkette suchen" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "Suche mit einer einfachen POSIX Regular Expression durchführen" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "Suche mit einer erweiterten POSIX Regular Expression durchführen" #: cola/widgets/main.py:507 msgid "Search..." msgstr "Suchen..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Auswählen" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Alle auswählen" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "Branch für Review auswählen" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "Nachfolger auswählen" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "Wählen Sie einen Commit aus" #: cola/guicmds.py:136 msgid "Select Directory..." msgstr "Verzeichnis wählen..." #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "Neuen Upstream auswählen" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "Jüngsten Nachfolger auswählen" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "Ältesten Vorgänger auswählen" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "Vorgänger Auswählen" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "Vorherige Version auswählen" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "Wählen Sie das übergeordnete Verzeichnis für den Klon" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "Ausgabe-Verzeichnis wählen" #: cola/widgets/selectcommits.py:182 msgid "Select output directory" msgstr "Ausgabe-Verzeichnis wählen" #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "Patch-Datei(en) wählen..." #: cola/widgets/editremotes.py:434 msgid "Select repository" msgstr "Repository wählen" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "Standard-Repository auswählen" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "Upstream-Branch setzen" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "Neuen Upstream setzen" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "Allgemein" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "Als Kommandozeilenargumente" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "Nach unten schieben" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "Nach oben schieben" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "Tastenkürzel" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Vergleichsstatistik nach Zusammenführen anzeigen" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "Vollständige Pfade in Fenstertiteln zeigen" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "Hilfe anzeigen" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "Verlauf anzeigen" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "Hilfe anzeigen\n" "Kurzwahl: ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "Zeilennummern anzeigen" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "Gesamte übergeordnete Funktion anzeigen" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "Änderungen seit" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "Nebeneinander" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Abzeichnen" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "Tag unterzeichnen" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "Diesen Commit abzeichnen" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "Vereinfachte Chinesische Übersetzung" #: cola/cmds.py:2527 msgid "Skip" msgstr "Überspringen" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "Gegenwärtigen Patch überspringen" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "Lesezeichen alphabetisch sortieren" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "Spanische Übersetzung" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "Legt den zu taggenden SHA-1 fest" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "Legt die Tag-Beschreibung fest" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "Legt den Namen des Tags fest" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "Rechtschreibvorschläge" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "Verschmelzen" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "Zusammengeführte Commits in einzelnen Commit vereinen" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "Änderung vormerken" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "Vormerken/Nicht vormerken" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "Änderungen am Abschnitt vormerken" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Vermerke Änderung" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "Auswahl vormerken" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "Änderungen an ausgewählten Zeilen vormerken" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "Nicht zusammengeführte Dateien vormerken" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "Neue Dateien vormerken" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "Vormerken und eintragen" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "Vormerken und eintragen?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "Konflikte beim Vormerken" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "Konflikte vormerken?" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "Vormerken für Commit umschalten für ausgewählte Pfade" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "Vorgemerkt" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "Vermerken: %s" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "Interaktiven Rebase starten..." #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "Start-Revision" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "Git-Zwischenablage" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "Inhalt der Zwischenablage" #: cola/widgets/stash.py:79 msgid "Stash staged changes only" msgstr "Nur vorgemerkte Änderungen in die Zwischenablage" #: cola/widgets/stash.py:75 msgid "Stash unstaged changes only, keeping staged changes" msgstr "Nur nicht vorgemerkte Änderungen in die Zwischenablage, vorgemerkte Änderungen behalten" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "Git-Zwischenablage..." #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "Zustand" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "Versionskontrolle für den ausgewählten Pfad beenden" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "Zusammenfassung beim Zusammenführen anzeigen" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "Zusammenfassung" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Tabulatorweite" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Tag" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "Tag erstellt" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Tag-Beschreibung..." #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "Eine Tag-Signatur wurde angefordert, aber die Tag-Beschreibung fehlt." #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "Tags" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "Textbreite" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "Der Branch wird nicht mehr verfügbar sein." #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "Der Branch wird zurückgesetzt mit \"git reset --mixed %s\"" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "Der Branch wird zurückgesetzt mit \"git reset --soft %s\"" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "Die Commit-Beschreibung wird geleert." #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "Die Datei \"%s\" existiert bereits und wird überschrieben." #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "Die folgenden Zeilen werden gleich gelöscht:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "Der Ausdruck darf nicht leer sein." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "Dies kann nicht rückgängig gemacht werden. Commit-Beschreibung leeren?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "Dieser Commit wurde bereits veröffentlicht.\n" "Dieser Vorgang wird den veröffentlichten Verlauf umschreiben.\n" "Dies wollen Sie womöglich nicht tun." #: cola/widgets/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "Dieser Vorgang verwirft nicht vorgemerkte Änderungen.\n" "Diese Änderung kann nicht rückgängig gemacht werden." #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Dieser Befehl verwirft nicht vorgemerkte Änderungen an den ausgewählten Dateien.\n" "Dieser Schritt kann nicht rückgängig gemacht werden." #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Damit verwerfen Sie nicht vorgemerkte Änderungen.\n" "Diese können nicht mehr wiederhergestellt werden." #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "In diesem Repository ist gerade ein Rebase im Gange.\n" "Lösen Sie die Konflikte aus und committen Sie die Änderungen, dann nutzen Sie:\n" " Rebase > Fortsetzen" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "Dieses Repository befindet sich mitten in einem Merge.\n" "Beheben Sie zunächst die Konflikte und führen einen Commit durch." #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "Aktivierung umschalten" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "Branch-Filter umschalten" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "Pfadfilter umschalten" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Nachverfolgter Branch" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "Nachverfolgtem Branch" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "Traditionell-Chinesische (Taiwan) Übersetzung" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "Übersetzer" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "Türkische Übersetzung" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "URL: %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "Ukrainische Übersetzung" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "Rebase nicht durchführbar" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "Kann URL für \"%(name)s\" nicht auf \"%(url)s\" setzen" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "Rückgängig" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "Nicht zusammengeführt" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "Änderung nicht vormerken" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "Alle Vormerkungen aufheben" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "Änderungen am Abschnitt nicht vormerken" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "Vormerkung für Auswahl aufheben" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "Änderungen an ausgewählten Zeilen nicht mehr vormerken" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "Entferne Datei »%s« aus Vormerkliste" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "Auswahl von Versionskontrolle ausnehmen" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "Nicht unter Versionskontrolle" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "Nicht mehr verfolgen: %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Existierenden Branch aktualisieren:" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "" #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "Aktualisierung" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Benutzername" #: cola/widgets/about.py:89 msgid "Version" msgstr "Version" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "Ansicht" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "Verlauf anzeigen..." #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "Verlauf für ausgewählte Pfade anzeigen" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "In Verlaufsansicht anzeigen" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "Alle Branches visualisieren..." #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "Gegenwärtigen Branch visualisieren..." #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "Den Tag unterzeichnen (siehe git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "Möchten Sie alle veränderten Dateien vormerken und aufnehmen?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "XOR" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "" #: cola/cmds.py:255 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:2072 msgid "You cannot rebase with uncommitted changes." msgstr "Rebase nicht möglich mit ausstehenden Änderungen." #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "Sie müssen eine Revision für die Zusammenführung angeben." #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "Sie müssen eine Revision zum Betrachten angeben." #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "Vergrößern" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "Verkleinern" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "In Ansicht einpassen" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "Kommandozeilenargumente" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "Ende-Code %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "fatal: \"%s\" ist kein Verzeichnis. Bitte gültiges Repository angeben mit --repo ." #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "git cola Version %s" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "git-cola diff" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "Ergebnis von grep..." #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "hotkeys_de.html" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "vX.Y.Z" #: cola/hidpi.py:43 msgid "x 1" msgstr "" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "" #: cola/hidpi.py:46 msgid "x 2" msgstr "" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "dd.MM.yyyy" #~ 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 "" #~ "\n" #~ "Commands\n" #~ "--------\n" #~ "pick = use commit\n" #~ "reword = use commit, but edit the commit message\n" #~ "edit = use commit, but stop for amending\n" #~ "squash = use commit, but meld into previous commit\n" #~ "fixup = like \"squash\", but discard this commit's log message\n" #~ "exec = run command (the rest of the line) using shell\n" #~ "\n" #~ "These lines can be re-ordered; they are executed from top to bottom.\n" #~ "\n" #~ "If you disable a line here THAT COMMIT WILL BE LOST.\n" #~ "\n" #~ "However, if you disable everything, the rebase will be aborted.\n" #~ "\n" #~ "Keyboard Shortcuts\n" #~ "------------------\n" #~ "? = show help\n" #~ "j = move down\n" #~ "k = move up\n" #~ "J = shift row down\n" #~ "K = shift row up\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "spacebar = toggle enabled\n" #~ "\n" #~ "ctrl+enter = accept changes and rebase\n" #~ "ctrl+q = cancel and abort the rebase\n" #~ "ctrl+d = launch difftool\n" #~ msgstr "" #~ "\n" #~ "Befehle\n" #~ "-------\n" #~ "pick = Commit verwenden\n" #~ "reword = Commit verwenden, aber Commit-Beschreibung bearbeiten\n" #~ "edit = Commit verwenden, aber zum Nachbessern anhalten\n" #~ "squash = Commit verwenden, aber mit vorhergehendem Commit verschmelzen\n" #~ "fixup = wie \"squash\", aber diese Commit-Beschreibung verwerfen\n" #~ "exec = Befehl ausführen (Rest der Zeile) unter Verwendung der Befehlszeile\n" #~ "\n" #~ "Diese Zeilen können neu angeordnet werden; die Ausführung läuft von oben nach unten.\n" #~ "\n" #~ "Wenn Sie eine Zeile deaktivieren, GEHT DER COMMIT VERLOREN.\n" #~ "\n" #~ "Wenn Sie jedoch alles deaktivieren, wird der Rebase abgebrochen.\n" #~ "\n" #~ "Tastaturkürzel\n" #~ "--------------\n" #~ "? = Hilfe anzeigen\n" #~ "j = nach unten gehen\n" #~ "k = nach oben gehen\n" #~ "J = Zeile hoch schieben\n" #~ "K = Zeile runter schieben\n" #~ "\n" #~ "1, p = pick (auswählen/verwenden)\n" #~ "2, r = reword (umformulieren)\n" #~ "3, e = edit (bearbeiten)\n" #~ "4, f = fixup (nachbessern)\n" #~ "5, s = squash (verschmelzen)\n" #~ "spacebar = Aktivierung umschalten\n" #~ "\n" #~ "Strg+Eingabe = Akzeptieren und Rebase starten\n" #~ "Strg+q = Verwerfen und Rebase abbrechen\n" #~ "Strg+d = Diff-Betrachter starten\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 "\"%s\" returned exit status %d" #~ msgstr "\"%s\" wurde mit Code %d beendet" #~ msgid "\"git %s\" succeeded." #~ msgstr "\"git %s\" erfolgreich ausgeführt." #~ msgid "\"git commit\" returned exit code %s" #~ msgstr "\"git commit\" wurde mit dem Code %s beendet" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%s ... %*i von %*i %s (%3i%%)" #~ msgid "%s Repository" #~ msgstr "Projektarchiv %s" #~ msgid "%s of %s" #~ msgstr "%s von %s" #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "»%s« ist kein zulässiger Zweigname." #~ msgid "* Binary file (not showing content)." #~ msgstr "* Binärdatei (Inhalt wird nicht angezeigt)" #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "Für »Zusammenführen mit« muss ein Zweig angegeben werden." #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Eine Ablage mit dem Namen \"%s\" existiert bereits" #~ msgid "Abort completed. Ready." #~ msgstr "Abbruch durchgeführt. Bereit." #~ msgid "Abort failed." #~ msgstr "Abbruch fehlgeschlagen." #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "Auf Zweig »%s« umstellen abgebrochen (Zusammenführen der Dateien ist notwendig)." #~ msgid "Already up-to-date." #~ msgstr "Ist bereits aktuell" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "Immer (Keine Zusammenführungsprüfung)" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "Immer (ohne Zusammenführungstest)" #~ 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 "Annotation complete." #~ msgstr "Annotierung vollständig." #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "Alle nicht bereitgestellten Änderungen werden beim Verwerfen verloren gehen." #~ msgid "Apply Diff Selection to Work Tree" #~ msgstr "Auswahl auf den Arbeitsbereich anwenden" #~ msgid "Apply/Reverse Hunk" #~ msgstr "Kontext anwenden/umkehren" #~ msgid "Arbitrary URL:" #~ msgstr "Archiv-URL:" #~ msgid "Bookmarks" #~ msgstr "Favoriten" #~ msgid "Bookmarks Saved" #~ msgstr "Favoriten gesichert" #~ msgid "Bookmarks..." #~ msgstr "Favoriten..." #~ 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 "Branch '%s' does not exist." #~ msgstr "Zweig »%s« existiert nicht." #~ msgid "Branch created" #~ msgstr "Zweig erzeugt" #~ msgid "Browse %s's Files" #~ msgstr "Zweig »%s« durchblättern" #~ msgid "Browse Branch Files" #~ msgstr "Dateien des Zweigs durchblättern" #~ msgid "Browse Revision..." #~ msgstr "Zweig oder Markierung wählen" #~ msgid "Calling commit-msg hook..." #~ msgstr "Aufrufen der Versionsbeschreibungs-Kontrolle..." #~ 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 "" #~ "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 "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 "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 find git in PATH." #~ msgstr "Git kann im PATH nicht gefunden werden." #~ 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 "Cannot move to top of working directory:" #~ msgstr "Es konnte nicht in das oberste Verzeichnis der Arbeitskopie gewechselt werden:" #~ msgid "Cannot parse Git version string:" #~ msgstr "Git Versionsangabe kann nicht erkannt werden:" #~ msgid "Cannot resolve %s as a commit." #~ msgstr "»%s« wurde nicht als Version gefunden." #~ msgid "Cannot use funny .git directory:" #~ msgstr "Unerwartete Struktur des .git Verzeichnis:" #~ msgid "Cannot write shortcut:" #~ msgstr "Fehler beim Schreiben der Verknüpfung:" #~ msgid "Change Font" #~ msgstr "Schriftart ändern" #~ msgid "Checked out '%s'." #~ msgstr "Umgestellt auf »%s«." #~ msgid "Clone Type:" #~ msgstr "Art des Klonens:" #~ msgid "Clone failed." #~ msgstr "Klonen fehlgeschlagen." #~ msgid "Cloning from %s" #~ msgstr "Kopieren von »%s«" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "Version »%s« scheint beschädigt zu sein" #~ msgid "Commit declined by commit-msg hook." #~ msgstr "Eintragen abgelehnt durch Versionsbeschreibungs-Kontrolle (»commit-message hook«)." #~ msgid "Commit declined by pre-commit hook." #~ msgstr "Eintragen abgelehnt durch Vor-Eintragen-Kontrolle (»pre-commit hook«)." #~ msgid "Commit failed: %s" #~ msgstr "Versionierung fehlgeschlagen: %s" #~ msgid "Commit@@noun" #~ msgstr "Version" #~ msgid "Compress Database" #~ msgstr "Datenbank komprimieren" #~ msgid "Compressing the object database" #~ msgstr "Objektdatenbank komprimieren" #~ msgid "Copied Or Moved Here By:" #~ msgstr "Kopiert oder verschoben durch:" #~ msgid "Copying objects" #~ msgstr "Objektdatenbank kopieren" #~ msgid "Counting objects" #~ msgstr "Objekte werden gezählt" #~ msgid "Create Desktop Icon" #~ msgstr "Desktop-Icon erstellen" #~ msgid "Created commit: %s" #~ msgstr "Änderung %s übertragen:" #~ msgid "Creating working directory" #~ msgstr "Arbeitskopie erstellen" #~ msgid "Current Branch:" #~ msgstr "Aktueller Zweig:" #~ msgid "Database Statistics" #~ msgstr "Datenbankstatistik" #~ msgid "Decrease Font Size" #~ msgstr "Schriftgröße verkleinern" #~ msgid "Delete Local Branch" #~ msgstr "Lokalen Zweig löschen" #~ msgid "Delete Only If" #~ msgstr "Nur löschen, wenn" #~ msgid "Delete Only If Merged Into" #~ msgstr "Nur löschen, wenn zusammengeführt nach" #~ msgid "Delete selected branch?" #~ msgstr "Gewählten Branch löschen?" #~ msgid "Destination Repository" #~ msgstr "Ziel-Projektarchiv" #~ msgid "Detach From Local Branch" #~ msgstr "Verbindung zu lokalem Zweig lösen" #~ msgid "Diff/Console Font" #~ msgstr "Vergleich-Schriftart" #~ msgid "Directory %s already exists." #~ msgstr "Verzeichnis »%s« existiert bereits." #~ msgid "Disk space used by loose objects" #~ msgstr "Festplattenplatz von unverknüpften Objekten" #~ msgid "Disk space used by packed objects" #~ msgstr "Festplattenplatz von komprimierten Objekten" #~ msgid "Display" #~ msgstr "Anzeigen" #~ msgid "Do Nothing" #~ msgstr "Nichts tun" #~ msgid "Enter Git Repository" #~ msgstr "Git Projektarchiv:" #~ msgid "Error %s" #~ msgstr "Fehler: %s" #~ msgid "Error loading commit data for amend:" #~ msgstr "Fehler beim Laden der Versionsdaten für Nachbessern:" #~ msgid "Error: Command Failed" #~ msgstr "Fehler: Kommando fehlgeschlagen" #~ msgid "Error: Stash exists" #~ msgstr "Fehler: Diese Ablage existiert bereits" #~ msgid "Errors: %s" #~ msgstr "Fehler: \"%s\"" #~ msgid "Exit code: %s" #~ msgstr "Ende-Code: %s" #~ msgid "Failed to completely save options:" #~ msgstr "Optionen konnten nicht gespeichert werden:" #~ msgid "Failed to configure origin" #~ msgstr "Der Ursprungsort konnte nicht eingerichtet werden" #~ msgid "Failed to create repository %s:" #~ msgstr "Projektarchiv »%s« konnte nicht erstellt werden:" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "Fehler beim Löschen der Zweige:\n" #~ "%s" #~ msgid "Failed to open repository %s:" #~ msgstr "Projektarchiv »%s« konnte nicht geöffnet werden." #~ msgid "Failed to rename '%s'." #~ msgstr "Fehler beim Umbenennen von »%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 "" #~ "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 "Failed to stage selected hunk." #~ msgstr "Fehler beim Bereitstellen des gewählten Kontexts." #~ msgid "Failed to unstage selected hunk." #~ msgstr "Fehler beim Herausnehmen des gewählten Kontexts aus der Bereitstellung." #~ msgid "Failed to update '%s'." #~ msgstr "Aktualisieren von »%s« fehlgeschlagen." #~ msgid "Fast Forward Only " #~ msgstr "Nur Fast Forward" #~ msgid "Fetch from" #~ msgstr "Anfordern von" #~ msgid "Fetching new changes from %s" #~ msgstr "Neue Änderungen von »%s« holen" #~ msgid "File level merge required." #~ msgstr "Zusammenführen der Dateien ist notwendig." #~ msgid "Font Example" #~ msgstr "Schriftbeispiel" #~ msgid "Font Family" #~ msgstr "Schriftfamilie" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "Überschreiben von existierenden Zweigen erzwingen (könnte Änderungen löschen)" #~ msgid "From Repository" #~ msgstr "In Projektarchiv" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "Alles kopieren (langsamer, volle Redundanz)" #~ msgid "GPG-signed" #~ msgstr "mit GPG signiert" #~ msgid "Garbage files" #~ msgstr "Dateien im Mülleimer" #~ msgid "Git Gui" #~ msgstr "Git Gui" #~ msgid "Git Repository (subproject)" #~ msgstr "Git-Projektarchiv (Unterprojekt)" #~ msgid "Git directory not found:" #~ msgstr "Git-Verzeichnis nicht gefunden:" #~ 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 "Hardlinks are unavailable. Falling back to copying." #~ msgstr "Hardlinks nicht verfügbar. Stattdessen wird kopiert." #~ msgid "In File:" #~ msgstr "In Datei:" #~ msgid "Increase Font Size" #~ msgstr "Schriftgröße vergrößern" #~ msgid "Index" #~ msgstr "Vormerkliste" #~ msgid "Index Error" #~ msgstr "Fehler in Bereitstellung" #~ msgid "Initial Commit Message:" #~ msgstr "Erste Versionsbeschreibung:" #~ msgid "Initial file checkout failed." #~ msgstr "Erstellen der Arbeitskopie fehlgeschlagen." #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "Ungültiger Wert von GIT_COMMITTER_INDENT:" #~ msgid "Invalid date from Git: %s" #~ msgstr "Ungültiges Datum von Git: %s" #~ msgid "Invalid font specified in %s:" #~ msgstr "Ungültige Zeichensatz-Angabe in %s:" #~ msgid "Invalid spell checking configuration" #~ msgstr "Unbenutzbare Konfiguration der Rechtschreibprüfung" #~ msgid "KiB" #~ msgstr "KB" #~ 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 "" #~ "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 "" #~ "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 "Linking objects" #~ msgstr "Objekte verlinken" #~ msgid "Loading annotation..." #~ msgstr "Annotierung laden..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "Annotierungen für Kopieren/Verschieben werden geladen..." #~ msgid "Loading original location annotations..." #~ msgstr "Annotierungen für ursprünglichen Ort werden geladen..." #~ msgid "Local Branches" #~ msgstr "Lokale Zweige" #~ msgid "Local Merge..." #~ msgstr "Lokales Zusammenführen..." #~ msgid "Location %s already exists." #~ msgstr "Projektarchiv »%s« existiert bereits." #~ msgid "Main Font" #~ msgstr "Programmschriftart" #~ msgid "Match Tracking Branch Name" #~ msgstr "Passend zu Übernahmezweig-Name" #~ msgid "Match Tracking Branches" #~ msgstr "Passend zu Übernahmezweig" #~ msgid "Merge completed successfully." #~ msgstr "Zusammenführen erfolgreich abgeschlossen." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "Zusammenführungsmethode »%s« nicht unterstützt." #~ msgid "Merged Into:" #~ msgstr "Zusammengeführt mit:" #~ msgid "Merging %s and %s..." #~ msgstr "Zusammenführen von %s und %s..." #~ msgid "Modified, not staged" #~ msgstr "Verändert, nicht bereitgestellt" #~ msgid "New Branch Name Template" #~ msgstr "Namensvorschlag für neue Zweige" #~ msgid "New Commit" #~ msgstr "Neue Version" #~ msgid "New Name:" #~ msgstr "Neuer Name:" #~ 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 "No default branch obtained." #~ msgstr "Kein voreingestellter Zweig gefunden." #~ 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 "No files selected for checkout from HEAD." #~ msgstr "Es sind keine Dateien zum Auschecken von HEAD ausgewählt." #~ msgid "No working directory" #~ msgstr "Kein Arbeitsverzeichnis" #~ msgid "Number of loose objects" #~ msgstr "Anzahl unverknüpfter Objekte" #~ msgid "Number of packed objects" #~ msgstr "Anzahl komprimierter Objekte" #~ msgid "Number of packs" #~ msgstr "Anzahl Komprimierungseinheiten" #~ msgid "On Debian-based systems try: sudo apt-get install python-pyinotify" #~ msgstr "Wenn Sie git-cola auf einem Debian-System gestartet haben, versuchen Sie es mit \"sudo apt-get install python-pyinotify\" " #~ 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 "Options" #~ msgstr "Optionen" #~ msgid "Original File:" #~ msgstr "Ursprüngliche Datei:" #~ msgid "Originally By:" #~ msgstr "Ursprünglich von:" #~ msgid "" #~ "Output:\n" #~ "%s" #~ msgstr "" #~ "Ausgabe:\n" #~ "%s" #~ msgid "Output: %s" #~ msgstr "Ausgabe: \"%s\"" #~ msgid "PATCH %(current)d/%(count)d" #~ msgstr "PATCH %(current)d/%(count)d" #~ msgid "Packed objects waiting for pruning" #~ msgstr "Komprimierte Objekte, die zum Aufräumen vorgesehen sind" #~ msgid "Path to git repository" #~ msgstr "Pfad zum Projektarchiv" #~ msgid "Please select one or more branches to delete." #~ msgstr "Bitte wählen Sie mindestens einen Zweig, der gelöscht werden soll." #~ msgid "Please supply a branch name." #~ msgstr "Bitte geben Sie einen Zweignamen an." #~ msgid "Portions staged for commit" #~ msgstr "Teilweise bereitgestellt zum Eintragen" #~ 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 "Preferences..." #~ msgstr "Einstellungen..." #~ msgid "Process Diff Hunk" #~ msgstr "Abschnitt verarbeiten" #~ msgid "Process Selection" #~ msgstr "Auswahl verarbeiten" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "Übernahmezweige aufräumen während Anforderung" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "Übernahmezweige aufräumen und entfernen, die in »%s« gelöscht wurden" #~ msgid "Push Branches" #~ msgstr "Zweige versenden" #~ msgid "Push to" #~ msgstr "Versenden nach" #~ msgid "Pushing %s %s to %s" #~ msgstr "%s %s nach %s versenden" #~ msgid "Reading %s..." #~ msgstr "%s lesen..." #~ msgid "Ready to commit." #~ msgstr "Bereit zum Eintragen." #~ msgid "Ready." #~ msgstr "Bereit." #~ msgid "Rebase Branch" #~ msgstr "Anfang des Zweigs verschieben" #~ msgid "Rebase..." #~ msgstr "Anfang verschieben..." #~ 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 "" #~ "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 "Refreshing file status..." #~ msgstr "Dateistatus aktualisieren..." #~ msgid "Remote:" #~ msgstr "Anderes Archiv:" #~ msgid "Remove selected paths from the staging area" #~ msgstr "Änderungen am ausgewählten Pfad nicht mehr vormerken" #~ msgid "Rename remote?" #~ msgstr "Möchten Sie die externe Referenz umbenennen?" #~ msgid "Repository" #~ msgstr "Projektarchiv" #~ msgid "Requires merge resolution" #~ msgstr "Konfliktauflösung nötig" #~ msgid "Rescan" #~ msgstr "Ansicht aktualisieren" #~ msgid "Reset Branch Head" #~ msgstr "Branch-Head zurücksetzen" #~ msgid "Reset Worktree" #~ msgstr "Arbeitsbaum zurücksetzen" #~ 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 "Reset worktree?" #~ msgstr "Arbeitsbaum zurücksetzen?" #~ msgid "Revert Uncommitted Changes..." #~ msgstr "Nicht versionierte Änderungen verwerfen" #~ msgid "Revert changes in these %i files?" #~ msgstr "Änderungen in den gewählten %i Dateien verwerfen?" #~ msgid "Select File" #~ msgstr "Wähle Datei aus" #~ msgid "Select Repository..." #~ msgstr "Repository wählen..." #~ msgid "Select file from \"%s\"" #~ msgstr "Datei von \"%s\" auswählen" #~ msgid "Select manually..." #~ msgstr "Selbst auswählen..." #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "Verknüpft (schnell, nicht empfohlen, kein Backup)" #~ msgid "Shared only available for local repository." #~ msgstr "Verknüpft ist nur für lokale Projektarchive verfügbar." #~ msgid "Show Less Context" #~ msgstr "Weniger Zeilen anzeigen" #~ msgid "Show More Context" #~ msgstr "Mehr Zeilen anzeigen" #~ msgid "Show icon? (if available)" #~ msgstr "Symbol anzeigen? (falls verfügbar)" #~ msgid "Source Branches" #~ msgstr "Lokale Zweige" #~ msgid "Spell Checker Failed" #~ msgstr "Rechtschreibprüfung fehlgeschlagen" #~ msgid "Spell checker silently failed on startup" #~ msgstr "Rechtschreibprüfungsprogramm mit Fehler abgebrochen" #~ msgid "Spell checking is unavailable" #~ msgstr "Rechtschreibprüfung nicht verfügbar" #~ msgid "Spelling Dictionary:" #~ msgstr "Wörterbuch Rechtschreibprüfung:" #~ msgid "Stage Hunk For Commit" #~ msgstr "Kontext zur Bereitstellung hinzufügen" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "Bereitstellung (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 "Staging area (index) is already locked." #~ msgstr "Bereitstellung (»index«) ist zur Bearbeitung gesperrt (»locked«)." #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "Standard (schnell, teilweise redundant, Hardlinks)" #~ msgid "Standard only available for local repository." #~ msgstr "Standard ist nur für lokale Projektarchive verfügbar." #~ msgid "Starting gitk... please wait..." #~ msgstr "Gitk wird gestartet... bitte warten." #~ msgid "Staying on branch '%s'." #~ msgstr "Es wird auf Zweig »%s« verblieben." #~ msgid "Success" #~ msgstr "Erfolgreich" #~ msgid "Successfully saved bookmarks" #~ msgstr "Die Favoriten wurden erfolgreich gesichert." #~ msgid "Summary:" #~ msgstr "Zusammenfassung:" #~ msgid "The 'main' branch has not been initialized." #~ msgstr "Der »main«-Zweig wurde noch nicht initialisiert." #~ msgid "The branch will be reset using \"git reset --hard %s\"" #~ msgstr "Der Branch wird zurückgesetzt mit \"git reset --hard %s\"" #~ msgid "The branch will be reset using \"git reset --merge %s\"" #~ msgstr "Der Branch wird zurückgesetzt mit \"git reset --merge %s\"" #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "Folgende Zweige sind noch nicht mit »%s« zusammengeführt:" #~ 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 "The worktree will be reset using \"git reset --keep %s\"" #~ msgstr "Der Arbeitsbaum wird zurückgesetzt mit \"git reset --keep %s\"" #~ 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 "This Detached Checkout" #~ msgstr "Abgetrennte Arbeitskopie-Version" #~ 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." #~ 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 "" #~ "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 "Tools" #~ msgstr "Ansicht" #~ msgid "Tracking branch %s is not a branch in the remote repository." #~ msgstr "Übernahmezweig »%s« ist kein Zweig im anderen Projektarchiv." #~ msgid "Transfer Options" #~ msgstr "Netzwerk-Einstellungen" #~ msgid "Unable to copy object: %s" #~ msgstr "Objekt kann nicht kopiert werden: %s" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "Kopien von Objekten/Info/Alternates konnten nicht erstellt werden: %s" #~ msgid "Unable to display %s" #~ msgstr "Datei »%s« kann nicht angezeigt werden" #~ msgid "Unable to hardlink object: %s" #~ msgstr "Für Objekt konnte kein Hardlink erstellt werden: %s" #~ msgid "Unable to obtain your identity:" #~ msgstr "Benutzername konnte nicht bestimmt werden:" #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "Gitk kann nicht gestartet werden:\n" #~ "\n" #~ "%s existiert nicht" #~ msgid "Unable to unlock the index." #~ msgstr "Bereitstellung kann nicht wieder freigegeben werden." #~ msgid "Unexpected EOF from spell checker" #~ msgstr "Unerwartetes EOF vom Rechtschreibprüfungsprogramm" #~ 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 "Unlock Index" #~ msgstr "Bereitstellung freigeben" #~ 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 "Unrecognized spell checker" #~ msgstr "Unbekanntes Rechtschreibprüfungsprogramm" #~ msgid "Unstage Hunk From Commit" #~ msgstr "Kontext aus Bereitstellung herausnehmen" #~ msgid "Unsupported spell checker" #~ msgstr "Rechtschreibprüfungsprogramm nicht unterstützt" #~ 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 "Updating working directory to '%s'..." #~ msgstr "Arbeitskopie umstellen auf »%s«..." #~ msgid "Updating..." #~ msgstr "Aktualisiere..." #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Kompaktes Datenformat benutzen (für langsame Netzverbindungen)" #~ msgid "Verify Database" #~ msgstr "Datenbank überprüfen" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "Die Objektdatenbank durch »fsck-objects« überprüfen lassen" #~ msgid "Visualize %s's History" #~ msgstr "Historie von »%s« darstellen" #~ msgid "Working... please wait..." #~ msgstr "Verarbeitung. Bitte warten..." #~ 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 "" #~ "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 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 "You must correct the above errors before committing." #~ msgstr "Sie müssen die obigen Fehler zuerst beheben, bevor Sie eintragen können." #~ msgid "[Up To Parent]" #~ msgstr "[Nach oben]" #~ msgid "buckets" #~ msgstr "Buckets" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree fehlgeschlagen:" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "Fehler: »%s« kann nicht als Zweig oder Version erkannt werden" #~ 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" #~ msgid "files" #~ msgstr "Dateien" #~ msgid "files checked out" #~ msgstr "Dateien aktualisiert" #~ msgid "files reset" #~ msgstr "Dateien zurückgesetzt" #~ msgid "git clone returned exit code %s" #~ msgstr "git clone wurde mit dem Fehlercode %s beendet" #~ msgid "git tag returned exit code %s" #~ msgstr "git tag wurde mit dem Fehlercode %s beendet" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - eine grafische Oberfläche für Git." #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: Programmfehler" #~ msgid "inotify enabled." #~ msgstr "inotify aktiviert" #~ 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" #~ msgid "lines annotated" #~ msgstr "Zeilen annotiert" #~ msgid "objects" #~ msgstr "Objekte" #~ msgid "pt." #~ msgstr "pt." #~ msgid "push %s" #~ msgstr "»%s« versenden..." #~ msgid "remote prune %s" #~ msgstr "Aufräumen von »%s«" #~ msgid "unknown" #~ msgstr "unbekannt" #~ msgid "update-ref failed:" #~ msgstr "update-ref fehlgeschlagen:" #~ msgid "warning" #~ msgstr "Warnung" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "Warning: Tcl/Tk unterstützt die Zeichencodierung »%s« nicht." #~ msgid "write-tree failed:" #~ msgstr "write-tree fehlgeschlagen:" git-cola-4.6.1/cola/i18n/es.po000066400000000000000000003322421457126473700157130ustar00rootroot00000000000000# Translation of git-cola to Spanish. # Copyright (C) 2014 Pilar Molina Lopez # Copyright (C) 2014-2024 David Aguilar # This file is distributed under the same license as the git-cola package. # # # Pilar Molina Lopez , 2014. # victorhck , 2018, 2022. msgid "" msgstr "" "Project-Id-Version: git-cola VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-17 01:06-0700\n" "PO-Revision-Date: 2022-07-01 18:58+0200\n" "Last-Translator: victorhck \n" "Language-Team: Spanish <>\n" "Language: es_ES\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" "X-Generator: Lokalize 22.04.2\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " Arrastre y suelte o use el botón Añadir para añadir\n" " parches a la lista\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" "\n" "
\n" " Git Cola ha sido traducida a diferentes idiomas gracias\n" " a la ayuda de diferentes personas que se enumeran a continuación.\n" "\n" "
\n" "

\n" " La traducción es aproximada. Si encuentra un error,\n" " por favor avísenos para abrir una incidencia en Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " Le invitamos a participar en la traducción añadiendo o actualizando\n" " una traducción y abriendo un \"pull request\".\n" "

\n" "\n" "
\n" "\n" " " #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" "\n" "
\n" " Git Cola versión %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" "\n" "
\n" " Por favor utilice %(bug_link)s para informar de un problema.\n" "
\n" " " #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" "\n" " Formato de Variables de String\n" " -----------------------\n" " %(path)s = ruta de archivo relativa\n" " %(abspath)s = ruta del archivo absoluta\n" " %(dirname)s = ruta de la carpeta relativa\n" " %(absdirname)s = ruta de la carpeta absoluta\n" " %(filename)s = nombre base del archivo\n" " %(basename)s = nombre base del archivo sin extensión\n" " %(ext)s = extensión del archivo\n" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" "\n" "Atajos de teclado\n" "------------------\n" "J, Down = Desplazar hacia abajo\n" "K, Up = Desplazar hacia arriba\n" "Enter = Editar los archivos seleccionados\n" "Spacebar = Abrir un archivo utilizando la aplicación predeterminada\n" "Ctrl + L = Llevar el foco al campo para introducir texto\n" "? = Mostrar ayuda\n" "\n" "Las flechas hacia arriba y hacia abajo cambian el foco entre los campos para introducir texto\n" "y los resultados.\n" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr " - DAG" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr "commits atrás" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "\"%(branch)s\" ha sido eliminado de \"%(remote)s\"." #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "\"%(command)s\" devolvieron este estado de salida \"%(status)d\"" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "\"%(command)s\" devolvieron este estado de salida %(status)d" #: cola/guicmds.py:156 #, python-format msgid "\"%s\" already exists" msgstr "\"%s\" ya existe" #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "\"%s\" ya existe, cola creará una nueva carpeta" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "\"%s\" requiere que seleccione un archivo." #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "#" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s: %(branch)s - Navegar" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "%(project)s: %(ref)s - DAG" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "Hace %d días" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "Hace %d horas" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "Hace %d minutos" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "%d parche(s) aplicado(s)." #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d omitido" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" "%s parece contener conflictor al hacer merge.\n" "\n" "Quizás debería omitir este archivo.\n" "¿Incluirlo en \"Stage\" de todas formas?" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "%s no es un repositorio Git." #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "%s será eliminado de sus marcadores." #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "%s será eliminado de tus repositorios recientes." #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: el archivo o carpeta no existe." #: cola/widgets/main.py:748 msgid "&Edit" msgstr "&Editar" #: cola/widgets/main.py:690 msgid "&File" msgstr "&Archivo" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(Corrigiendo)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "*** Punto de la rama ***" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** Sandbox ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "100%" #: cola/widgets/diff.py:817 msgid "200%" msgstr "200%" #: cola/widgets/diff.py:814 msgid "25%" msgstr "25%" #: cola/widgets/diff.py:818 msgid "400%" msgstr "400%" #: cola/widgets/diff.py:815 msgid "50%" msgstr "50%" #: cola/widgets/diff.py:819 msgid "800%" msgstr "800%" #: cola/widgets/finder.py:118 msgid " ..." msgstr " ..." #: cola/cmds.py:1685 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 "" "No se ha configurado una plantilla de commit.\n" "Utilice \"git config\" y modifique \"commit.template\"\n" "para que apunte a una plantilla." #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "Un hook debe ser configurado en \"%s\"" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "Cancelar" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "Cancelar acción" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "Cancelar Merge" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Cancelar Merge..." #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "¿Desea cancelar la acción?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Cancelar el \"merge\" actual causará que *TODOS* los cambios que no se haya hecho un commit se perderán.\n" "No es posible recuperar los cambios en los que no se haya hecho un commit." #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "¿Cancelar el merge actual?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "Acerca de" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "Acerca de git-cola" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "Aceptar" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "Aceptar cambios y rebase\n" "Atajo de teclado: Ctrl+Enter" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "Nombre de acción" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "Acciones" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "Acciones..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "Añadir" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "Añadir favorito" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "Añadir repositorio remoto" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "Añadir separador" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "Añandir submódulo" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "Añadir submódulo..." #: cola/widgets/editremotes.py:60 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 "" "Añadir y eliminar repositorios remotos usando los \n" "botones Añadir(+) y Eliminar(-) a la izquierda.\n" "\n" "Puede cambiar el nombre de los repositorios remotos \n" "seleccionando uno en la lista \n" "y presionando \"enter\", o haciendo doble clic." #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "Añadir nuevo repositorio remoto de git" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "Añadir parches (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "Añadir repositorio remoto" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "¿Añadir este submódulo?" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "Añadir a .gitignore" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "Añadir a Git Annex" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "Añadir a Git LFS" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "Añadir a exclusiones" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "Añadir a local .git/info/exclude" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "Adiciones" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "Avanzado" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "Edad" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "Todos los repositorios" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" "Todos los submódulos serán actualizados usando\n" "\"%s\"" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "Permitir actualizaciones \"non-fast-forward\". Utilizar \"force\" puede causar que el repositorio remoto pierda los commits, utilizar con cuidado" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "Siempre utilizar un \"merge commit\" cuando este habilitado, incluso cuando el \"merge\" es una actualización \"fast-forward\"" #: cola/cmds.py:220 msgid "Amend" msgstr "Corregir" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "Corregir commit" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Corregir el último commit" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "¿Corregir el commit publicado?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "Corrigiendo" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "Una acción está siendo ejecutada.\n" "Cancelarla podría causar pérdida de información." #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "Una etiqueta sin firmar, de poca entidad será creada.\n" "¿Crear una etiqueta sin firmar?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "Apariencia" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "Aplicar" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "Aplicar parches" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "Aplicar parches..." #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "Aplicar y eliminar el stash seleccionado (git stash pop)" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "Aplicar el stash seleccionado" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "Argumentos" #: cola/qtutils.py:886 msgid "Attach" msgstr "Adjuntar" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "Autor" #: cola/widgets/about.py:90 msgid "Authors" msgstr "Autores" #: cola/hidpi.py:41 msgid "Auto" msgstr "Auto" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "Salto de línea automático" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "Autocompletar rutas" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "Cargar automáticamente la plantilla de mensajes de commit" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "Regexp básico" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "Visor de responsables" #: cola/widgets/browse.py:206 msgid "Blame selected paths" msgstr "Responsables de las rutas seleccionadas" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "Responsable..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "Fuente en negrita con fondo negro en vez de cabeceras en cursiva" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Rama" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "La rama \"%(branch)s\" no existe en \"%(remote)s\".\n" "Se publicará una nueva rama remota." #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "La rama \"%s\" ya existe." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "Visor de diferencias en ramas." #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "Rama existe" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Nombre de la rama" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "Nombre de la rama" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "Rama: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "Ramas" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "Ramas..." #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "Traducción al Brasileño" #: cola/guicmds.py:52 msgid "Browse" msgstr "Navegar" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "Navegar por los commits..." #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "Navegar por la rama actual..." #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "Navegar por otra rama..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "Navegar..." #: cola/widgets/main.py:87 msgid "Browser" msgstr "Navegador" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "Navegando por %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "Evitar Commit Hooks" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "Cancelar" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "Cancelar rebase\n" "Atajo de teclado: Ctrl+Q" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "No se puede corregir" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "No se puede ejecutar \"%s\": por favor configure un visor de responsable" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "No se pudo ejecutar \"%s\": por favor, configure un navegador de historial" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "No se pudo ejecutar \"%s\": por favor, configure su editor" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "Cambiado aguas arriba (upstream)" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "Comprobar commits publicados al modificar" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "Comprobar ortografía" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "Comprobar ortografía" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "Comprobar si se ha publicado un commit al modificar" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Checkout" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "Checkout después de crear" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Checkout rama" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "Checkout HEAD separado" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "Checkout como nueva rama" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Checkout..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "Cherry Pick" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "Cherry-Pick Commit" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "Cherry-Pick..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "Escoger rutas" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "Escoger el modo de expresión regular \"git grep\"" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "Limpiar el repositorio predeterminado" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "Limpiar el mensaje de commit" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "¿Limpiar el mensaje de commit?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "Limpiar..." #: cola/widgets/clone.py:124 msgid "Clone" msgstr "Clonar" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "Clonar repositorio" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Clonar..." #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "Clonando repositorio en %s" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Cerrar" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "Cerrar..." #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "Colapsar todo" #: cola/sequenceeditor.py:371 msgid "Command" msgstr "Comando" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "Commit" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "Commit fallido" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "Hacer un commit de los cambios en \"stage\"" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "Hacer un commit de los cambios en \"stage\"\n" "Atajo de teclado: Ctrl+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "Sumario de commit" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "Hacer un commit del merge sin no hay conflictos. Desmarcar para dejar el merge sin commit" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "Commit@@verb" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "Comparar" #: cola/difftool.py:102 msgid "Compare All" msgstr "Comparar todo" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "Configurar barra de herramientas" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "Configurar la rama remota como la nueva \"upstream\"" #: cola/widgets/main.py:169 msgid "Console" msgstr "Terminal" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Continuar" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Copiar" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "Copiar el nombre base al portapapeles" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "Copiar la ruta principal al portapapeles" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "Copiar la ruta al portapapeles" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "Copiar la ruta relativa al portapapeles" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "Copiar SHA-1" #: cola/widgets/status.py:738 msgid "Copy..." msgstr "Copiar..." #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "No se pudo abrir %s." #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "No fue posible procesar la Git URL: \"%s\"" #: cola/app.py:499 msgid "Create" msgstr "Crear" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Crear rama" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "Crear parche" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "Crear rama remota" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "Crear commit firmado" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "Crear etiqueta" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "Crear etiqueta..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "Crear etiqueta sin firmar" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "Crear un \"merge commit\" incluso cuando el \"merge\" se resuelva como un \"fast-forward\"" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "¿Crear una nueva rama remota?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "¿Crear un nuevo repositorio en esa ubicación?" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "Cree un clon superficial con el historial truncado al número especificado de revisiones. 0 realiza una clonación completa." #: cola/widgets/main.py:565 msgid "Create..." msgstr "Crear..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "Se creó una nueva etiqueta con nombre \"%s\"" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "Repositorio actual" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "Acciones de copiado personalizadas" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "Personalizar..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "Cortar" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "Traducción al Checo" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "DAG..." #: cola/icons.py:54 msgid "Dark Theme" msgstr "Tema oscuro" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "Fecha, hora" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "Predeterminado" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Eliminar" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "¿Desea eliminar %d archivo(s)?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "Eliminar marcadores" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "¿Eliminar marcadores?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Eliminar rama" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "Eliminar archivos" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "Eliminar archivos..." #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "¿Eliminar archivos?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "Eliminar repositorio remoto" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "Eliminar rama remota" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "Eliminar rama remota..." #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "Eliminar barra de herramientas" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "¿Eliminar rama \"%s\"?" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "Eliminar repositorio remoto" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "Eliminar repositorio remoto \"%s\"" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "¿Desea eliminar el repositorio remoto?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Eliminar..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "Fallo intentando eliminar \"%s\"" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "Eliminaciones" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "Profundidad" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "Separar" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "Detectar Conflict Markers" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "Detectar conflicto en marcadores en archivos en los que no se haya hecho merge" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "Desarrollador" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "Diferencia" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "Diferencia respecto del predecesor..." #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "Opciones al mostrar las diferencias" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "Herramienta de diferencias (Diff)" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "Diferencia seleccionada -> esta" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "Comprobar diferencias en esta -> seleccionada" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "Mostrar diferencias (Diffstat)" #: cola/difftool.py:324 msgid "Difftool" msgstr "Herramienta Diff" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "La carpeta ya existe" #: cola/hidpi.py:42 msgid "Disable" msgstr "Deshabilitar" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "Mostrar ficheros sin seguimiento" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "Documentación" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "Abandonar" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "Abandonar Stash" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "¿Abandonar Stash?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "¿Abandonar el Stash \"%s\"?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "Abandonar el Stash seleccionado" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 msgid "Edit" msgstr "Editar" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "Editar Rebase" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "Editar repositorios remotos" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "Editar repositorios remotos..." #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "Editar repositorios remotos seleccionándolos de la lista" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "Editar rutas seleccionadas" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "Editar..." #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "Editor" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "Dirección de correo electrónico" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "Dirección de correo electrónico del colaborador" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "Habilitar autocompletado de ruta en herramientas" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "Habilitar el ajuste de palabras" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "Habilitado" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "Introducir el nombre de la nueva rama" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "Introducir el nombre para el nuevo repositorio remoto básico" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "Introducir el nombre para el Stash" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "Error" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "Error al clonar" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "Error al crear rama" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "Error al crear repositorio" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "Error al eliminar rama remota" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "Error al editar el archivo" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "Error al arrancar el visor de responsables" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "Error al arrancar el navegador del historial" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "Error al abrir el repositorio" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "Error al crear el repositorio remoto \"%s\"" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "Error al crear Stash" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "Error al borrar la rama \"%s\"" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Error al eliminar el repositorio remoto \"%s\"" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "Error al renombrar \"%(name)s\" a \"%(new_name)s\"" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "Error al ejecutar el hook prepare-commitmsg" #: cola/cmds.py:2987 cola/cmds.py:3033 #, python-format msgid "Error updating submodule %s" msgstr "Error al actualizar el submódulo %s" #: cola/cmds.py:3069 msgid "Error updating submodules" msgstr "Error actualizando submódulos" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "Error: No se pudo encontrar la plantilla para el commit" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "Error: Plantilla para el commit no configurada" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Error: no se pudo clonar \"%s\"" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "Error: no se pudo crear la etiqueta \"%s\"" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "Ejecutando la acción %s" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "Expandir todo" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "Exportar parches" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "Exportar parches..." #: cola/widgets/main.py:547 msgid "Expression..." msgstr "Expresión..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "Extender Regexp" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "Descripción extendida..." #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Sólo Fast Forward" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "Sólo Fast-forward" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "Repositorios favoritos" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "Favoritos" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "Extraer (Fetch)" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "Extraer (Fetch) la rama en seguimiento" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "Extraer (Fetch)..." #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "Navegador de archivos..." #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "Diferencias de archivos" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "Archivo guardado" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "Archivo guardado en \"%s\"" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "Supervisión del cambio del sistema de archivo: está desactivada porque \"cola.inotify\" es falso\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "Supervisión del cambio del sistema de archivo: está desactivada porque libc no es compatible con el sistema de llamadas de inotify.\n" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "Supervisión del cambio del sistema de archivo: está desactivada porque pywin32 no está instalada.\n" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" "Supervisión del cambio del sistema de archivo: está desactivada porque el límite del número total de los seguimientos que hace inotify se ha alcanzado. Debería incrementar el número del límite de seguimientos que se pueden ejecutar:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "Supervisión del cambio del sistema de archivo: activada.\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "Nombre de archivo" #: cola/widgets/dag.py:821 msgid "Files" msgstr "Archivos" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "Filtrar ramas..." #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "Filtrar rutas..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "Encontrar archivos" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "Cadena fijada" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "Fijar ancho de fuente" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "Arreglar" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "Arreglar un Commit previo" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "Azul oscuro plano" #: cola/themes.py:705 msgid "Flat dark green" msgstr "Verde oscuro plano" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "Gris oscuro plano" #: cola/themes.py:691 msgid "Flat dark red" msgstr "Rojo oscuro plano" #: cola/themes.py:656 msgid "Flat light blue" msgstr "Azul claro plano" #: cola/themes.py:677 msgid "Flat light green" msgstr "Verde claro plano" #: cola/themes.py:670 msgid "Flat light grey" msgstr "Gris claro plano" #: cola/themes.py:663 msgid "Flat light red" msgstr "Rojo claro plano" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "Carpeta" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "Seguir el estilo del sistema" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Tamaño de fuente" #: cola/widgets/remote.py:197 msgid "Force" msgstr "Forzar" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "Forzar extracción (Fetch)" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "¿Forzar extracción (Fetch)?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "Forzar Push" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "¿Forzar Push?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "¿Forzar extracción desde %s?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "¿Forzar Push a %s?" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "Formato de cadena" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "Traducción al Francés" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "Firmar mediante GPG el Merge Commit" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "Tema de la interfaz" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "Reuniendo información para \"%s\"..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "Traducción al Alemán" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "Aplicar plantilla de mensaje de Commit" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "Bajar" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "Subir" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "Tomar archivo..." #: cola/widgets/dag.py:848 msgid "Graph" msgstr "Gráfico" #: cola/widgets/main.py:354 msgid "Grep" msgstr "Grep" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "¿Ha realizado un rebase/pull recientemente?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Ayuda" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "Ayuda - Acciones de copiado personalizadas" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "Ayuda - Encontrar archivos" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "Ayuda - git-cola-sequence-editor" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "DPI alto" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "Navegador de historial" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "Traducción al Húngaro" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "Solo iconos" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "Tema de iconos" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "Ignorar todos los espacios en blanco" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "Ignorar cambios en la cantidad de espacios en blanco" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "Ignorar cambios de espacios en blanco en EOL" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "Ignorar patrón personalizado" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "Ignorar el nombre de archivo exacto" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "Ignorar nombre de archivo o patrón" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "Ignorar..." #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "Incluir etiquetas " #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "Rutas de estado de sangría" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "Traducción al Indonesio" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "Inicializar Git Annex" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "Inicializar Git LFS" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "Inicializar submódulos" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "Insertar espacios en vez de tabulaciones" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "Rebase interactivo" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "Revisión inválida" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "Traducción al Japonés" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "Conservar Merge Backups *.orig" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "Mantener Index" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "Atajos de teclado" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "Ejecutar la herramienta de comparación" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "Ejecutar la herramienta de comparación de carpetas" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "Abrir Editor" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "Abrir Terminal" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" "Abrir una herramienta de diferencias externa\n" "Atajo de teclado: Ctrl+D" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "Ejecutar git-cola" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "Ejecutar git-difftool en versiones previas" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "Ejecutar git-difftool en la ruta actual" #: cola/icons.py:55 msgid "Light Theme" msgstr "Tema claro" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "Lista" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "Cargar el mensaje del Commit" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "Cargar el mensaje del Commit..." #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "Cargar un mensaje del Commit previo" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "Cargando..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "Local" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Rama local" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "Rama local" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "Bloquear diseño" #: cola/widgets/dag.py:816 msgid "Log" msgstr "Registro" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "Responsable (desde 2007) y desarrollador" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Merge" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "Merge \"%(revision)s\" con \"%(branch)s\"" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "Herramienta Merge" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Mostrar mensajes de salida de Merge" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "Falló Merge. Se necesita resolver los conflictos." #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "Merge en \"%s\"" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "Merge en la rama actual" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "Merge..." #: cola/widgets/main.py:1177 msgid "Merging" msgstr "Uniendo" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "Mensaje" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "Mensaje de commit ausente" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "Datos ausentes" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "Nombre ausente" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "Revisión ausente" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "Mensaje de etiqueta ausente" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "Modificado" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "Más..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "Bajar" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "Subir" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "Mover los archivos a la papelera" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "Nombre" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "Nombre para el nuevo repositorio remoto" #: cola/guicmds.py:147 cola/widgets/main.py:281 msgid "New Bare Repository..." msgstr "Nuevo repositorio vacío..." #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "Nuevo repositorio..." #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "Nueva barra de herramientas" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Nuevo..." #: cola/actions.py:56 msgid "Next File" msgstr "Archivo siguiente" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "No" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "No se ha especificado una revisión" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Sin cambios para hacer commit.\n" "\n" "Debe realizar al menos un cambio antes de poder hacer un commit." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "No existen commits en esta rama." #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "Sin \"fast forward\"" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "Sin \"fast-forward\"" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Ningún repositorio ha sido seleccionado." #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "¡Ningún \"fast-forward\" sobreescribe el historial local!" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "¡Ningún \"fast-forward\" sobreescribe el historial publicado!\n" "(¿Ha ejecutado \"pull\" primero?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "Nada para hace commit" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "Nada que hacer" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Numero de lineas de contexto Diff" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Abrir" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Abrir repositorio git" #: cola/widgets/submodules.py:48 msgid "Open Parent" msgstr "Abrir padre" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "Abrir carpeta padre" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "Abrir recientes" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "Abrir utilizando la aplicación predeterminada" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "Abrir en una ventana nueva" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "Abrir en una ventana nueva..." #: cola/widgets/main.py:410 msgid "Open..." msgstr "Abrir..." #: cola/widgets/branch.py:354 msgid "Other branches" msgstr "Otras ramas" #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "Sobrescribir" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "¿Desea sobrescribir \"%s\"?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "¿Desea sobrescribir el archivo?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "Analizar los argumentos utilizando la línea de comandos.\n" "Las consultas con espacios requerirán \"comillas dobles\". " #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "En \"Stage\" parcialmente" #: cola/widgets/main.py:758 msgid "Paste" msgstr "Pegar" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "Parche(s) aplicado(s)" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "Ruta" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "Ruta o URL a clonar (Env. $VARS okay)" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "Escoger" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "Pixel XOR" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "Por favor proporcione tanto el nombre de la rama como la expresión de la revisión." #: cola/cmds.py:2297 msgid "Please select a file" msgstr "Por favor, seleccione un archivo" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "Por favor, especifique un nombre para la nueva etiqueta." #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "Por favor, especifique una revisión para etiquetar." #: cola/widgets/commitmsg.py:417 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 "" "Por favor, proporciones un mensaje para el commit.\n" "\n" "Un buen mensaje de commit tiene el siguiente formato:\n" "\n" "- Primera línea: Describa en una línea lo que ha realizado.\n" "- Segunda línea: En blanco.\n" "- Las líneas restantes: Describa porque este cambio es apropiado.\n" #: cola/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "¿Apuntar la el comienzo de la rama actual a un nuevo commit?" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "Traducción al Polaco" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "Pop" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Preferencias" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "Prefijo" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "Cargar mensaje de commit" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "Evitar el \"Stage\" de todos los archivos cuando nada es seleccionado" #: cola/actions.py:65 msgid "Previous File" msgstr "Archivo anterior" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "Solicitud de creación" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "Solicitar que al hacer \"push\" cree nuevas ramas en el repositorio remoto" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "Eliminar (Prune)" #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "Eliminar entradas faltantes" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "Pull" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "Pull..." #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Push" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Push..." #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Salir" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Rebase" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "Rebase en %s" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "Rebase detenido" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "Hacer \"rebase\" de la rama actual en vez de unirlas (merge)" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "Rebasing" #: cola/widgets/main.py:118 msgid "Recent" msgstr "Reciente" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "Repositorios recientes" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "Enumerar los repositorios recientes" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "Archivos modificados recientemente" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "Archivos modificados recientemente..." #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "No es posible recuperar un \"stash\" eliminado." #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Recuperar \"commits\" perdidos puede que no sea sencillo." #: cola/widgets/main.py:751 msgid "Redo" msgstr "Rehacer" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "Reducir el historial de \"commit\" al mínimo" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "Repositorio de referencia" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "URL de referencia" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "Repositorio de referencia para usar al clonar (opcional)" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Refrescar" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "Evite realizar un \"merge\" a menos que el HEAD actual ya esté actualizado o el \"merge\" se puede resolver como un \"fast-forward\"" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Repositorio Remoto" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "Rama remota" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "Rama remota eliminada" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "Repositorios de git remotos - doble clic para renombrar" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "Eliminar" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "¿Eliminar %s de la lista de recientes?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "Eliminar elemento" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "Eliminar el seguimiento de ramas remotas que ya no existen en el repositorio remoto" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "Eliminar seleccionados (Delete)" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "Eliminar entradas obsoletas para repositorios que ya no existen" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Renombrar" #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "Renombrar \"%s\"" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "Renombrar rama" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "Renombrar rama..." #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "Renombrar una rama existente" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "Renombrar repositorio remoto" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "Renombrar repositorio" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "Renombrar rama" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "¿Desea renombrar el repositorio remoto \"%(current)s\" como \"%(new)s\"?" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "Renombrar las rutas seleccionadas" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "Repositorio no encontrado" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "Repositorio: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Reiniciar" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "¿Reiniciar \"%(branch)s\" a \"%(revision)s\"?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "Restablecer todo (mantener los cambios que no están en \"stage\")" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "Reiniciar rama" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "Reiniciar rama (Soft)" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "Reiniciar rama y Stage (Mixed)" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "¿Reiniciar rama?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "Reiniciar diseño" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "¿Reiniciar rama de trabajo y reiniciar todo?" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "Reiniciar y restaurar" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "¿Reiniciar rama?" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "Reiniciar \"%(branch)s\" a \"%(revision)s\" hará que se pierdan los \"commits\"." #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "Cambiar el tamaño de las columnas del explorador de archivos" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "Reinicie la aplicación después de cambiar la configuración de apariencia." #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "Restaurar árbol de trabajo" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "Restaurar árbol de trabajo y reiniciar todo (Hard)" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "Restaurar árbol de trabajo y reiniciar todo (Mantener cambios que no estén en Stage)" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "Restaurar árbol de trabajo y reiniciar todo (Mantener las ediciones que no estén en Stage)" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "Restaurar árbol de trabajo y reiniciar todo (Merge)" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "¿Restaurar árbol de trabajo y reiniciar todo?" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "¿Restaurar árbol de trabajo a %s?" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "¿Restaurar árbol de trabajo, reset y mantener las ediciones que no estén en Stage?" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "Revertir" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "Revertir Diff Hunk" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "Revertir Diff Hunk..." #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "¿Revertir Diff Hunk?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "Revertir las líneas seleccionadas" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "Revertir las líneas seleccionadas..." #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "¿Revertir las líneas seleccionadas?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "Revertir los cambios en los que no se haya hecho \"commit\"" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "¿Revertir los cambios en los que no se haya hecho \"commit\"?" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "Revertir las ediciones en las que no se haya hecho \"commit\"..." #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "Revertir cambios que no estén en \"stage\"" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "¿Revertir cambios que no estén en \"stage\"?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "Revertir cambios que no estén en \"stage\"..." #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "¿Revertir los cambios en los que no se haya hecho commit?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "¿Revertir cambios que no estén en \"stage\"?" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "Revertir los cambios en los que no se haya hecho \"commit\" a las rutas seleccionadas" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "Revertir cambios que no estén en \"stage\" a las rutas seleccionadas" #: cola/guicmds.py:320 msgid "Review" msgstr "Revisar" #: cola/widgets/main.py:597 msgid "Review..." msgstr "Revisar..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Revisión" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Expresión de revisión:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Revisión a unir (merge)" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "Redactar de otra forma" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "¿Reescribir el commit publicado?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "Ejecutar" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "¿Desea ejecutar \"%s\"?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "¿Desea ejecutar %s?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "¿Desea ejecutar el comando \"%s\"?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "Ejecutando comando: %s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "Traducción al Ruso" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "SHA-1" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "Modo seguro" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Guardar" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "Guardar archivo" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "Guardar como Tarball/Zip..." #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "Guardar ajustes de la interfaz de usuario" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "Guardar Stash" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "Guardar el estado modificado a un nuevo \"stash\"" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "Se guardó \"%(filename)s\" de \"%(ref)s\" en \"%(destination)s\"" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "Buscar" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "Buscar autores" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "Buscar mensajes de commit" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "Buscar a quien ha realizado commits" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "Buscar en un rango de fechas" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "Buscar Diffs" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "Buscar por expresión" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "Buscar por ruta" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "Buscar por una cadena fija" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "Buscar utilizando expresión regular básica POSIX " #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "Buscar utilizando expresión regular extendida POSIX " #: cola/widgets/main.py:507 msgid "Search..." msgstr "Buscar..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "Buscar:" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Seleccionar" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Seleccionar todo" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "Seleccionar rama para revisar" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "Seleccionar hijo" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "Seleccionar commit" #: cola/guicmds.py:136 msgid "Select Directory..." msgstr "Seleccionar carpeta..." #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "Seleccionar un nuevo repositorio aguas arriba (upstream)" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "Seleccionar hijo más reciente" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "Seleccionar padre más antiguo" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "Seleccionar padre" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "Seleccionar una versión previa" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "Seleccione un directorio padre para el nuevo clonado" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "Seleccionar un directorio de salida" #: cola/widgets/selectcommits.py:182 msgid "Select output directory" msgstr "Seleccionar carpeta de salida" #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "Seleccionar archivo(s) de parche..." #: cola/widgets/editremotes.py:434 msgid "Select repository" msgstr "Seleccionar repositorio..." #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "Establecer el repositorio como predeterminado" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "Establecer rama aguas arriba (upstream)" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" "Establezca el orden de clasificación para ramas y etiquetas.\n" "Alterne entre clasificación basada en la fecha y basada en el nombre de la versión." #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "Establecer aguas arriba (upstream)" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "Ajustes" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "Argumentos línea de comandos" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "Desplazar hacia abajo" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "Desplazar hacia arriba" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "Atajos" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Mostrar \"Diffstat\" tras hacer \"merge\"" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "Mostrar las rutas completas en el título de la ventana" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "Mostrar ayuda" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "Mostrar historial" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "Mostrar recuentos de archivos en títulos de estado" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "Mostrar ayuda\n" "Atajo de teclado: ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "Mostrar números de línea" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "Mostrar todo lo que rodea las funciones de cambios" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "Mostrando cambios desde" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "Lado al lado" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Cerrar sesión" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "Firmar etiqueta" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "Cerrar sesión en este \"commit\"" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "Traducción al Chino simplificado" #: cola/cmds.py:2527 msgid "Skip" msgstr "Omitir" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "Omitir el parche actual" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "Ordenar los marcadores alfabéticamente" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "Traducción al Español" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "Especifica la firma SHA-1 a la etiqueta" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "Especifica el mensaje de la etiqueta" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "Especifica el nombre de la etiqueta" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "Sugerencias de ortografía" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "Concentrar (squash)" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "Concentrar los commits unidos (merged) en un único commit" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "Realizar Stage" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "Realizar Stage / Unstage" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "Realizar Stage / Unstage todo" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "Realizar Stage Diff Hunk" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Stage modificado" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "Stage modificado y sin seguimiento" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "Stage seleccionado" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "Líneas de Stage seleccionado" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "Stage sin hacer merge" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "Stage sin seguimiento" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "Stage y commit" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "¿Stage y commit?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "Realizar Stage a conflictos" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "¿Realizar Stage a conflictos?" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "Stage/unstage rutas seleccionadas para confirmar" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "Staged" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "Realizando Stage: %s" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "Comenzar rebase interactivo..." #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "Comenzando revisión" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "Stash" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "Stash índice" #: cola/widgets/stash.py:79 msgid "Stash staged changes only" msgstr "Realizar Stash solo a los cambios que se ha realizado Stage" #: cola/widgets/stash.py:75 msgid "Stash unstaged changes only, keeping staged changes" msgstr "Realizar Stash solo a los cambios que no se ha realizado Stage, manteniendo los cambios que se realizó Stage" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "Stash..." #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "Estado" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "Dejar de seguir las rutas" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "URL del submódulo (puede ser relativa, por ejemplo: ../repo.git)" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "Rama de submódulo para seguir (opcional)" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "Ruta de submódulo dentro del repositorio actual (opcional)" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "Submódulos" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "Sumario de Merge Commits" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "Resumen" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Ancho de tabulación" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Etiqueta" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "Etiqueta Creada" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Mensaje de etiqueta..." #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "Se necesitó una firma de la etiqueta pero el mensaje de la etiqueta está vacío." #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "Etiquetas" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "Texto junto al icono" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "Solo texto" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "Texto bajo el icono" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "Ancho del texto" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "La rama no volverá a estar disponible." #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "La rama será reiniciada utilizando \"git reset --mixed %s\"" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "La rama será reiniciada utilizando \"git reset --soft %s\"" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "El mensaje del commit será borrado." #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "El archivo \"%s\" ya existe y será sobrescrito." #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "Los siguientes archivos serán eliminados:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "El repositorio se restablecerá usando \"git reset --hard %s\"" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "El repositorio se restablecerá usando \"git reset --keep %s\"" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "El repositorio se restablecerá usando \"git reset --merge %s\"" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "La expresión de revisión no puede estar vacía." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" "El submódulo será añadido utilizando\n" "\"%s\"" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" "El submódulo será actualizado utilizando\n" "\"%s\"" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "El árbol de trabajo se restaurará usando \"git read-tree --reset -u %s\"" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "Esto no se puede deshacer. ¿Borrar mensaje de commit?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "Este commit ya ha sido publicado.\n" "Esta operación reescribirá el historial publicado.\n" "Probablemente no quiere hacer esto." #: cola/widgets/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "Esta operación eliminará los cambios en los que no se haya hecho commit.\n" "Estos cambios no pueden ser recuperados." #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Esta operación eliminará las ediciones en las que no se haya hecho commit de los archivos seleccionados.\n" "Estos cambios no pueden ser recuperados." #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Esta operación elimina ediciones que no estén en \"stage\" de los archivos seleccionados.\n" "Estos cambios no pueden ser recuperados." #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "Este repositorio está actualmente siendo rebasado.\n" "Resolver los conflictos, hacer commit con los cambios, y ejecutar:\n" " Rebase > Continue" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "Este repositorio está en el medio de un \"merge\".\n" "Resolver los conflictos y hacer commit con los cambios." #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "Alternar habilitado" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "Alternar imagen de diferencia" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "Alternar el filtro de las ramas" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "Alternar el filtro de las rutas" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "Estilo de barra de herramientas:" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Rama en seguimiento" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "Rama en seguimiento" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "Traducción al Chino (Taiwan) tradicional" #: cola/widgets/about.py:421 msgid "Translation" msgstr "Traducción" #: cola/widgets/about.py:91 msgid "Translators" msgstr "Traductores" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "Traducción al Turco" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "URL: %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "Traducción al Ucraniano" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "Incapaz de hacer rebase" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "Imposible especificar la URL para \"%(name)s\" a \"%(url)s\"" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "Deshacer" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "Deshacer último commit" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "¿Deshacer último commit?" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "¿Deshacer el commit publicado?" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "No fusionado (unmerged)" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "Unstage" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "Unstage a todo" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "Unstage Diff Hunk" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "Unstage seleccionado" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "Líneas de Stage seleccionado" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "Sin hacer Stage: %s" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "Sin seguimiento (untrack) seleccionado" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "Sin seguimiento" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "Sin seguimiento: %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "Actualizar todos los submódulo..." #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Actualizar rama existente:" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "Actualizar submódulo" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "Actualizar submódulo..." #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "Actualizar submódulos" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "¿Actualizar todos los submódulos?" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "Actualizar submódulos..." #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "Actualizar este submódulo" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "¿Actualizar este submódulo?" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "Actualizando" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Nombre de Usuario" #: cola/widgets/about.py:89 msgid "Version" msgstr "Versión" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "Ver" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "Ver historial..." #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "Ver historial para las rutas seleccionadas" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "Visualizar" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "Visualizar todas las ramas..." #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "Visualizar la rama actual..." #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "Ya sea para firmar la etiqueta (git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "¿Le gustaría hacer stage y commit de todos los archivos modificados?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "XOR" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "Sí" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "Está en medio de un merge.\n" "No se puede modificar mientras se ejecuta el merge." #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "No puede realizar rebase con cambios en los que no se ha hecho commit." #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "Debe especificar una revisión para hacer merge." #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "Debe especificar una revisión para hacer ver." #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "Acercar" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "Alejar" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "Ajustar el zoom" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "argumentos de la línea de comandos" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "error: imposible ejecutar git" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "código de salida %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "fatal: \"%s\" no es una carpeta. Por favor especifique un correcto --repo ." #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "versión de git cola %s" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "git-cola diff" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "git://git.example.com/repo.git" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "resultados de grep..." #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "hotkeys.html" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "ruta/a/submódulo" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "vX.Y.Z" #: cola/hidpi.py:43 msgid "x 1" msgstr "x 1" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "x 1.5" #: cola/hidpi.py:46 msgid "x 2" msgstr "x 2" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "aaaa-MM-dd" #~ msgid "" #~ "\n" #~ "Commands\n" #~ "--------\n" #~ "pick = use commit\n" #~ "reword = use commit, but edit the commit message\n" #~ "edit = use commit, but stop for amending\n" #~ "squash = use commit, but meld into previous commit\n" #~ "fixup = like \"squash\", but discard this commit's log message\n" #~ "exec = run command (the rest of the line) using shell\n" #~ "\n" #~ "These lines can be re-ordered; they are executed from top to bottom.\n" #~ "\n" #~ "If you disable a line here THAT COMMIT WILL BE LOST.\n" #~ "\n" #~ "However, if you disable everything, the rebase will be aborted.\n" #~ "\n" #~ "Keyboard Shortcuts\n" #~ "------------------\n" #~ "? = show help\n" #~ "j = move down\n" #~ "k = move up\n" #~ "J = shift row down\n" #~ "K = shift row up\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "spacebar = toggle enabled\n" #~ "\n" #~ "ctrl+enter = accept changes and rebase\n" #~ "ctrl+q = cancel and abort the rebase\n" #~ "ctrl+d = launch difftool\n" #~ msgstr "" #~ "\n" #~ "Comandos\n" #~ "--------\n" #~ "pick = usar commit\n" #~ "reword = usar commit, pero editando el mensaje del commit\n" #~ "edit = usar commit, pero parar al modificar\n" #~ "squash = usar el commit, pero unirlo a un commit previo\n" #~ "fixup = como \"squash\", pero descartando el mensaje de registro del commit\n" #~ "exec = ejecutar un comando (el resto de la línea) utilizando la línea de comandos\n" #~ "\n" #~ "Estas líneas pueden ser re-ordenadas; son ejecutadas de arriba abajo.\n" #~ "\n" #~ "Si inhabilita una línea aquí ESE COMMIT SE PERDERÁ.\n" #~ "\n" #~ "Sin embargo, si inhabilita todo, el \"rebase\" será cancelado.\n" #~ "\n" #~ "Atajos de teclado\n" #~ "------------------\n" #~ "? = mostrar ayuda\n" #~ "j = mover hacia abajo\n" #~ "k = mover hacia arriba\n" #~ "J = desplazar una fila hacia abajo\n" #~ "K = desplazar una fila hacia arriba\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "spacebar = cambiador habilitado\n" #~ "\n" #~ "ctrl+enter = aceptar cambios y realizar un rebase\n" #~ "ctrl+q = cancelar y abortar el rebase\n" #~ "ctrl+d = arrancar la herramienta difftool\n" #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Un \"stash\" llamado \"%s\" ya existe" #~ msgid "Delete selected branch?" #~ msgstr "¿Desea eliminar la rama seleccionada?" #~ msgid "Error: Stash exists" #~ msgstr "Error: ya existe el Stash" #~ msgid "Hide Details.." #~ msgstr "Ocultar detalles..." #~ msgid "Reset Branch Head" #~ msgstr "Reiniciar inicio (head) de rama" #~ msgid "Reset Hard" #~ msgstr "Reinicio duro (hard)" #~ msgid "Reset Merge" #~ msgstr "Reiniciar \"merge\"" #~ msgid "Reset Soft" #~ msgstr "Reinicio suave (soft)" #~ msgid "Reset Worktree" #~ msgstr "Reiniciar el árbol de trabajo" #~ msgid "Reset hard?" #~ msgstr "¿Reinicio duro (hard)?" #~ msgid "Reset merge?" #~ msgstr "¿Reiniciar \"merge\"?" #~ msgid "Reset soft?" #~ msgstr "¿Reinicio suave (soft)?" #~ msgid "Reset worktree?" #~ msgstr "¿Reiniciar el árbol de trabajo de trabajo?" #~ msgid "Select Repository..." #~ msgstr "Seleccionar repositorio..." #~ msgid "Select manually..." #~ msgstr "Seleccionar manualmente..." #~ msgid "Show Details..." #~ msgstr "Mostrar detalles..." #~ msgid "Show icon? (if available)" #~ msgstr "¿Mostrar icono? (si está disponible)" #~ msgid "The branch will be reset using \"git reset --hard %s\"" #~ msgstr "La rama será reiniciada utilizando \"git reset --hard %s\"" #~ msgid "The branch will be reset using \"git reset --merge %s\"" #~ msgstr "La rama será reiniciada utilizando \"git reset --merge %s\"" #~ msgid "The worktree will be reset using \"git reset --keep %s\"" #~ msgstr "El árbol de trabajo será reiniciado utilizando \"git reset --keep %s\"" #~ msgid "title" #~ msgstr "título" #~ msgid "unknown" #~ msgstr "desconocido" git-cola-4.6.1/cola/i18n/fr.po000066400000000000000000003334401457126473700157140ustar00rootroot00000000000000# Copyright (C) 2008, 2011 Shawn Pearce, et al. # This file is distributed under the same license as the git-cola package. # # Christian Couder , 2008 # David Aguilar , 2011 # Mickael Albertus , 2017 # Maxime Leroy , 2021 # msgid "" msgstr "" "Project-Id-Version: git-cola VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-01 00:00+0100\n" "PO-Revision-Date: 2021-12-18 02:25+0200\n" "Last-Translator: Maxime Leroy \n" "Language-Team: français <>\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.0\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Poedit-Bookmarks: -1,537,-1,-1,-1,-1,-1,-1,-1,-1\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " Effectuez un glisser-déposer ou appuyez sur le bouton Ajouter pour ajouter\n" " les patchs à la liste\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" "\n" "
\n" " Git Cola a été traduit dans différentes langues grâce\n" " à l'aide des personnes listées en dessous.\n" "\n" "
\n" "

\n" " Le plus grand soin a été apporté à ces traductions. Mais si vous trouvez\n" " des erreurs, n'hésitez pas à ouvrir un ticket sur Github :\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " Nous vous invitons à participer aux traductions en en ajoutant\n" " ou en modifiant puis à faire une pull request.\n" "

\n" "\n" "
\n" "\n" " " #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" "\n" "
\n" " Git Cola en version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" "\n" "
\n" " Veuillez utiliser %(bug_link)s pour signaler des problèmes.\n" "
\n" " " #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" "\n" " Format des Variables\n" " -----------------------\n" " %(path)s = chemin de fichier relatif\n" " %(abspath)s = chemin de fichier absolu\n" " %(dirname)s = chemin de répertoire relatif\n" " %(absdirname)s = chemin de répertoire absolu\n" " %(filename)s = nom de fichier\n" " %(basename)s = nom de fichier sans l'extension\n" " %(ext)s = extension du fichier\n" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" "\n" "Raccourcis clavier\n" "------------------\n" "J, Bas = Descendre\n" "K, Haut = Monter\n" "Entrée = Modifier les fichiers sélectionnés\n" "Barre d'espace = Ouvre le fichier avec l'application par défaut\n" "Ctrl + L = Mettre le curseur dans le champ d'entrée\n" "? = Afficher l'aide\n" "\n" "Les flèches du haut et du bas font naviguer le curseur entre les champs d'entrée et les résultats.\n" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr " - DAG" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr " commits avant" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "La branche « %(branch)s » a été supprimée de « %(remote)s »." #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "La commande « %(command)s » a retourné le statut de sortie  %(status)d »" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "La commande « %(command)s » a retourné le statut de sortie %(status)d" #: cola/guicmds.py:156 #, python-format msgid "\"%s\" already exists" msgstr "« %s » existe déjà" #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "« %s » existe déjà, git-cola va créer un nouveau répertoire" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "« %s » nécessite de sélectionner un fichier." #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "#" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s : %(branch)s - Naviguer" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "%(project)s : %(ref)s - DAG" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "il y a %d jours" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "il y a %d heures" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "il y a %d minutes" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "%d patch(s) appliqué(s)." #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d passé(s)" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" "%s semble contenir des conflits de fusion.\n" "\n" "Vous devriez ignorer ce fichier.\n" "Le commiter malgré tout ?" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "%s n'a pu être ouvert. Le retirer des marque-pages ?" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "%s n'est pas un dépôt Git." #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "%s sera supprimé de vos marque-pages." #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "%s sera supprimé de vos dépôts récents." #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s : fichier ou répertoire inexistant." #: cola/widgets/main.py:748 msgid "&Edit" msgstr "&Éditer" #: cola/widgets/main.py:690 msgid "&File" msgstr "&Fichier" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(Correction)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "*** Point de branchement ***" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** Bac à sable ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "100 %" #: cola/widgets/diff.py:817 msgid "200%" msgstr "200 %" #: cola/widgets/diff.py:814 msgid "25%" msgstr "25 %" #: cola/widgets/diff.py:818 msgid "400%" msgstr "400 %" #: cola/widgets/diff.py:815 msgid "50%" msgstr "50 %" #: cola/widgets/diff.py:819 msgid "800%" msgstr "800 %" #: cola/widgets/finder.py:118 msgid " ..." msgstr "..." #: cola/cmds.py:1685 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 "" "Un modèle de commit n'a pas été configuré.\n" "Utilisez « git config » pour définir « commit.template »\n" "de sorte qu'il pointe vers un modèle de commit." #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "Un crochet doit être spécifié à « %s »" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "Abandonner" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "Abandonner l'action" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "Abandonner la fusion" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Abandonner la fusion..." #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "Abandonner l'action ?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Abandonner la fusion courante entraînera la perte de *TOUTES* les modifications non commitées.\n" "La récupération des modifications non commitées ne sera pas possible." #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "Abandonner la fusion actuelle ?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "A propos" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "À propos de git-cola" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "Accepter" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "Accepter les modifications et rétablir\n" "Raccourcis : Ctrl+Entrée" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "Nom de l'action" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "Actions" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "Actions..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "Ajouter" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "Ajouter comme marque-page" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "Ajouter un élément distant" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "Ajouter un séparateur" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "Ajouter un sous-module" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "Ajouter un sous-module..." #: cola/widgets/editremotes.py:60 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 "" "Ajouter et supprimer des dépôts distants en utilisant les\n" "boutons ajouter (+) et supprimer (-) sur le côté gauche.\n" "\n" "Les éléments distants peuvent être renommés en les sélectionnant dans la liste\n" "et en appuyant sur « Entrée », ou en double-cliquant." #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "Ajouter un nouveau dépôt Git distant" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "Ajouter les patchs (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "Ajouter un élément distant" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "Ajouter ce sous-module ?" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "Ajouter à .gitignore" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "Ajouter à Git Annex" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "Ajouter à Git LFS" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "Marquer à exclure" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "Ajouter au fichier local .git/info/exclude" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "Ajouts" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "Avancé" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "Âge" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "Tous les dépôts" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" "Tous les sous-modules seront mis à jour avec\n" "« %s »" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "Autoriser les mises à jour non rapides. Utiliser « force » peut provoquer des pertes de commit au niveau du dépôt distant : utilisez-le avec précaution" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "Toujours créer un commit fusionné quand cela est possible, même si la fusion est une mise à jour rapide" #: cola/cmds.py:220 msgid "Amend" msgstr "Correction" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "Corriger le commit" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Corriger le dernier commit" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "Corriger le commit publié ?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "Correction" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "Une action est toujours en cours.\n" "L'interrompre pourrait entraîner une perte de données." #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "Un marqueur non signé et léger sera créé à la place.\n" "Créer un tag non signé ?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "Apparence" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "Appliquer" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "Appliquer les patchs" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "Appliquer les patchs..." #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "Appliquer et supprimer le remisage sélectionné (git stash pop)" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "Appliquer la remise actuelle" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "Arguments" #: cola/qtutils.py:886 msgid "Attach" msgstr "Attacher" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "Auteur" #: cola/widgets/about.py:90 msgid "Authors" msgstr "Auteurs" #: cola/hidpi.py:41 msgid "Auto" msgstr "Auto" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "Retour à la ligne automatique" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "Auto-compléter les chemins" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "Charger automatiquement le modèle de message de commit" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "Regexp basique" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "Visionneur de fichier" #: cola/widgets/browse.py:206 msgid "Blame selected paths" msgstr "Visionner les chemins sélectionnés" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "Visionner..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "Police en gras avec fond sombre pour les en-têtes plutôt que l'italique" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Branche" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "La branche « %(branch)s » n'existe pas dans « %(remote)s ».\n" "Une nouvelle branche distante sera publiée." #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "La branche « %s » existe déjà." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "Visionneur de différence de branches" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "La branche existe" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Nom de branche" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "Nom de branche" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "Branche : %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "Branches" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "Branches..." #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "Traduction brésilienne" #: cola/guicmds.py:52 msgid "Browse" msgstr "Parcourir" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "Parcourir les commits..." #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "Parcourir la branche courante..." #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "Parcourir les autres branches..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "Parcourir..." #: cola/widgets/main.py:87 msgid "Browser" msgstr "Parcourir" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "Parcours de %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "Contourner le crochet de commit" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "Annuler" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "Annuler le rétablissement\n" "Raccourcis : Ctrl+Q" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "Impossible de corriger" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "Impossible d'exécuter « %s » : veuillez configurer un visionneur de fichier" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "Impossible d'exécuter « %s » : veuillez configurer un navigateur d'historique" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "Impossible d'exécuter « %s » : veuillez configurer votre éditeur" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "Source modifiée" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "Vérifier la publication d'un commit lors de sa correction" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "Vérifier l'orthographe" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "Vérifier l'orthographe" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "Vérifier si un commit a été publié avant qu'il soit corriger" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Emprunter" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "Emprunt après création" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Emprunter la branche" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "Emprunter le HEAD détaché" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "Emprunter comme nouvelle branche" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Emprunter..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "Copier" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "Copier commit" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "Copier..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "Choisir les chemins" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "Choisissez le mode d'expression régulière pour « git grep »" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "Effacer le dépôt par défaut" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "Effacer le message de commit" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "Effacer le message de commit ?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "Effacer..." #: cola/widgets/clone.py:124 msgid "Clone" msgstr "Cloner" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "Cloner le dépôt" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Cloner..." #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "Cloner le dépôt à %s" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Fermer" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "Fermer..." #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "Tout réduire" #: cola/sequenceeditor.py:371 msgid "Command" msgstr "Commande" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "Commit" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "Le commit a échoué" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "Commiter les modifications pré-commitées" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "Commit des modifications\n" "Raccourci : Ctrl+Entrée" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "Résumé du commit" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "Commiter la fusion s'il n'y a pas de conflits. Décocher pour laisser la fusion non commitée" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "Commiter" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "Comparer" #: cola/difftool.py:102 msgid "Compare All" msgstr "Tout comparer" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "Configurer la barre d'outils" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "Configurer la branche distante comme la nouvelle source" #: cola/widgets/main.py:169 msgid "Console" msgstr "Terminal" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Continuer" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Copier" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "Copier le nom de base dans le presse-papiers" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "Copier le chemin principal dans le presse-papiers" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "Copier le chemin dans le presse-papiers" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "Copier le chemin relatif dans le presse-papiers" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "Copier SHA-1" #: cola/widgets/status.py:738 msgid "Copy..." msgstr "Copier..." #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "Ne peut pas ouvrir %s." #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "Impossible d'interpréter l'URL Git : « %s »" #: cola/app.py:499 msgid "Create" msgstr "Créer" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Créer branche" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "Créer patch" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "Créer une branche distante" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "Créer un commit signé" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "Créer marque" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "Créer une marque..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "Créer un marqueur non signé" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "Créer un commit fusionné même quand la fusion se résout rapidement" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "Créer une nouvelle branche distante ?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "Créer un nouveau dépôt à cet emplacement ?" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "Créer un clonage de surface avec l'historique limité au nombre de révision spécifiée. 0 pour un clonage en entier." #: cola/widgets/main.py:565 msgid "Create..." msgstr "Créer..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "Créer un nouveau marqueur appelé « %s »" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "Dépôt actuel" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "Actions de copie personnalisées" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "Personnaliser..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "Couper" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "Traduction tchèque" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "DAG..." #: cola/icons.py:54 msgid "Dark Theme" msgstr "Thème sombre" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "Date, heure" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "Défaut" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Supprimer" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "Supprimer %d fichier(s) ?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "Supprimer marque-page" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "Supprimer le marque-page ?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Supprimer la branche" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "Supprimer les fichiers" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "Supprimer les fichiers..." #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "Supprimer les fichiers ?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "Supprimer le dépôt distant" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "Supprimer la branche distante" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "Supprimer la branche distante..." #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "Supprimer la barre d'outils" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "Supprimer la branche « %s » ?" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "Supprimer élément distant" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "Supprimer la branche distante « %s »" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "Supprimer la branche distante ?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Supprimer..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "Suppression de « %s » a échoué" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "Suppressions" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "Profondeur" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "Détacher" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "Détecter les marqueurs de conflit" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "Détecter des marqueurs de conflits dans les fichiers non fusionnés" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "Développeur" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "Différence" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "Différence par rapport au prédécesseur..." #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "Options des différences" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "Outil de différence" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "Différence sélection -> ceci" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "Différence ceci -> sélection" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "Diffstat" #: cola/difftool.py:324 msgid "Difftool" msgstr "Difftool" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "Le répertoire existe" #: cola/hidpi.py:42 msgid "Disable" msgstr "Désactiver" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "Afficher les fichiers non suivis" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "Documentation" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "Supprimer" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "Supprimer le remisage" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "Supprimer le remisage ?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "Supprimer le remisage « %s » ?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "Supprimer la remise sélectionnée" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 msgid "Edit" msgstr "Editer" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "Éditer rétablissement" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "Éditer les éléments distants" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "Éditer les éléments distants..." #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "Modifier les éléments distants en les sélectionnant depuis la liste" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "Éditer les chemins sélectionnés" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "Editer..." #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "Éditeur" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "Adresse email" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "Email des contributeurs" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "Activer l’auto-complétion des chemins dans les outils" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "Activé" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "Entrez le nouveau nom de la branche" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "Entrez un nom pour le nouveau dépôt vide" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "Entrer un nom pour le remisage" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "Erreur" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "Erreur lors du clonage" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "Erreur lors de la création de la branche" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "Erreur lors de la création du dépôt" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "Erreur lors de la suppression de la branche distante" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "Erreur en modifiant le fichier" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "Erreur lors de l'ouverture du visionneur de fichier" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "Erreur lors de l'ouverture de l'historique" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "Erreur lors de l'ouverture du dépôt" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "Erreur lors de la création de l'élément distant « %s »" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "Erreur lors de la création du stash" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "Erreur lors de la suppression de la branche « %s »" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Erreur lors de la suppression de la branche distante « %s »" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "Erreur lors du renommage de « %(name)s » en « %(new_name)s »" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "Erreur lors du lancement de « prepare-commitmsg hook »" #: cola/cmds.py:2987 cola/cmds.py:3033 #, python-format msgid "Error updating submodule %s" msgstr "Erreur lors de la mise à jour du sous-module « %s »" #: cola/cmds.py:3069 msgid "Error updating submodules" msgstr "Erreur lors de la mise à jour des sous-modules" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "Erreur : impossible de trouver un modèle de commit" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "Erreur : modèle de commit non configuré" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Erreur : impossible de cloner « %s »" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "Erreur : impossible de créer le tag « %s »" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "Exécution de l'action %s" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "Tout développer" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "Exporter les patchs" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "Exporter les patchs..." #: cola/widgets/main.py:547 msgid "Expression..." msgstr "Expression..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "Regexp approfondi" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "Détailler la description..." #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Avance rapide seulement" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "Avance rapide seulement" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "Dépôts favoris" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "Favoris" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "Récupération" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "Récupérer la branche suivie" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "Récupérer..." #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "Navigateur de fichier..." #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "Différences des fichiers" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "Fichier enregistré" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "Fichier enregistré sous « %s »" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "Surveillance du changement de système de fichiers : désactivé car « cola.inotify » vaut « false ».\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "Surveillance du système de fichiers : désactivé car libc ne supporte pas le système d'appels de inotify.\n" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "Surveillance du changement de système de fichiers : désactivé car pywin32 n'est pas installé.\n" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" "Surveillance du changement de système de fichiers : désactivé car la limite sur le nombre total d'aperçu inotify a été atteint. Vous devriez être capable d'augmenter la limite d'aperçu en exécutant :\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "Surveillance des changements dans le système de fichiers : activé.\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "Nom de fichier" #: cola/widgets/dag.py:821 msgid "Files" msgstr "Fichiers" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "Filtrer les branches..." #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "Filtrer les chemins..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "Trouver des fichiers" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "Chaîne fixe" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "Police à largeur fixe" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "Réparer" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "Réparer le commit précédent" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "Simple bleu foncé" #: cola/themes.py:705 msgid "Flat dark green" msgstr "Simple vert foncé" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "Simple gris foncé" #: cola/themes.py:691 msgid "Flat dark red" msgstr "Simple rouge foncé" #: cola/themes.py:656 msgid "Flat light blue" msgstr "Simple bleu clair" #: cola/themes.py:677 msgid "Flat light green" msgstr "Simple vert clair" #: cola/themes.py:670 msgid "Flat light grey" msgstr "Simple gris clair" #: cola/themes.py:663 msgid "Flat light red" msgstr "Simple rouge clair" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "Répertoire" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Taille de police" #: cola/widgets/remote.py:197 msgid "Force" msgstr "Forcer" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "Forcer la récupération" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "Forcer la récupération ?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "Forcer la poussée" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "Forcer la poussée ?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "Forcer la récupération depuis %s ?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "Forcer la poussée vers %s ?" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "Le texte du format" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "Traduction française" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "GPG-signer le commit fusionné" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "Thème de l'interface" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "Récupération des informations de %s..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "Traduction allemande" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "Obtenir un modèle de message de commit" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "Descendre" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "Monter" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "Maintenir le fichier..." #: cola/widgets/dag.py:848 msgid "Graph" msgstr "Graphe" #: cola/widgets/main.py:354 msgid "Grep" msgstr "Grep" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "Avez-vous restauré/tiré récemment ?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Aide" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "Aide - Actions de copie personnalisées" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "Aide - Trouver des fichiers" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "Aide - git-cola-sequence-editor" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "Haut DPI" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "Navigateur de l'historique" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "Traduction hongroise" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "Thème des icônes" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "Ignorer tous les espaces blancs" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "Ignorer les changements de quantités d'espaces" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "Ignorer les changements d'espaces à la fin des lignes" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "Ignorer les motifs personnalisés" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "Ignorer les noms de fichier exacts" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "Ignorer un nom de fichier ou un motif" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "Ignorer..." #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "Inclure les marques " #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "Indenter le chemin des statuts" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "Traduction indonésienne" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "Initialiser Git Annex" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "Initialiser Git LFS" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "Initialiser les sous-modules" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "Insérer des espaces au lieu de tabulations" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "Rétablissement interactif" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "Révision invalide" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "Traduction japonaise" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "Conserver les sauvegardes de fusion *.orig" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "Conserver l'index" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "Raccourcis clavier" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "Lancer l'outil de différence" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "Lancer l'outil de différence de répertoire" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "Lancer l'éditeur" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "Lancer le terminal" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" "Lancer un outil de diff externe\n" "Raccourcis : Ctrl+D" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "Lancer git-cola" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "Lancer git-difftool par rapport aux versions précédentes" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "Lancer git-difftool sur le chemin actuel" #: cola/icons.py:55 msgid "Light Theme" msgstr "Thème clair" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "Liste" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "Charger le message de commit" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "Charger le message de commit..." #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "Charger le message du précédent commit" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "Chargement..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "Local" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Branche locale" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "Branche locale" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "Verrouiller la disposition" #: cola/widgets/dag.py:816 msgid "Log" msgstr "Journal" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "Mainteneur (depuis 2007) et développeur" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Fusionner" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "Fusionner « %(revision)s » vers « %(branch)s »" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "Outil de fusion" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Fusion détaillée" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "La fusion a échouée. Il est nécessaire de résoudre les conflits." #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "Fusionner dans « %s »" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "Fusionner dans la branche actuelle" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "Fusionner..." #: cola/widgets/main.py:1177 msgid "Merging" msgstr "Fusion" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "Message" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "Message de commit manquant" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "Données manquantes" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "Nom manquant" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "Révision manquante" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "Message du marqueur manquant" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "Modifié" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "Plus..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "Déplacer vers le bas" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "Déplacer vers le haut" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "Mettre les fichiers à la corbeille" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "Nom" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "Nom pour le nouvel élément distant" #: cola/guicmds.py:147 cola/widgets/main.py:281 msgid "New Bare Repository..." msgstr "Nouveau dépôt vide..." #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "Nouveau dépôt..." #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "Nouvelle barre d'outils" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Nouveau..." #: cola/actions.py:56 msgid "Next File" msgstr "Fichier suivant" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "Non" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "Pas de révision sélectionnée" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 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." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "Aucun commit n'existe dans cette branche." #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "Pas d'avance rapide" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "Pas d'avance rapide" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Aucun dépôt n'est sélectionné." #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "La récupération non rapide écrase l'historique local !" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "La poussée non rapide écrase l'historique publié !\n" "(Voulez-vous tirer en premier ?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "Rien à commiter" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "Il n'y a rien à faire" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Nombre de lignes de contexte dans les diffs" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Ouvrir" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Ouvrir un dépôt Git" #: cola/widgets/submodules.py:48 msgid "Open Parent" msgstr "Ouvrir le parent" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "Ouvrir le répertoire parent" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "Ouvrir récent" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "Ouvrir en utilisant l'application par défaut" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "Ouvrir dans une nouvelle fenêtre" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "Ouvrir dans une nouvelle fenêtre..." #: cola/widgets/main.py:410 msgid "Open..." msgstr "Ouvrir..." #: cola/widgets/branch.py:354 msgid "Other branches" msgstr "Autres branches" #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "Écraser" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "Écraser « %s » ?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "Écraser le fichier ?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "Interpréter les arguments en utilisant un shell.\n" "Les requêtes comportant des espaces nécessiteront \"des guillemets doubles\"." #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "Partiellement pré-commité" #: cola/widgets/main.py:758 msgid "Paste" msgstr "Coller" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "Patch(s) appliqué(s)" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "Chemin" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "Chemin ou URL à cloner (Env. $VARS ok)" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "Choisir" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "Ou-exclusif des pixels" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "Veuillez donner un nom de branche et une expression de révision." #: cola/cmds.py:2297 msgid "Please select a file" msgstr "Veuillez choisir un fichier" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "Veuillez spécifier un nom pour le nouveau marqueur." #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "Veuillez spécifier une révision à marquer." #: cola/widgets/commitmsg.py:417 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 : Vide.\n" "- Lignes suivantes : Expliquer l'intérêt de vos modifications.\n" #: cola/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "Pointer la tête de branche actuelle vers un nouveau commit ?" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "Traduction polonaise" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "Supprimer" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Préférences" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "Préfixe" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "Préparer le message de commit" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "Empêcher \"Pré-commiter\" de tout pré-commiter si aucun fichier n'est sélectionné" #: cola/actions.py:65 msgid "Previous File" msgstr "Fichier précédent" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "Confirmation à la création" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "Confirmation lorsque la poussée créée des nouvelles branches distantes" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "Réviser " #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "Réviser les entrées manquantes" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "Tirer" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "Tirer..." #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Pousser" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Pousser..." #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Quitter" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Rétablir" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "Rétablir sur %s" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "Rétablissement arrêté" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "Rétablir la branche courante au lieu de la fusionner" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "Rétablir" #: cola/widgets/main.py:118 msgid "Recent" msgstr "Récent" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "Dépôts récents" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "Nombre de dépôts récents" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "Fichiers récemment modifiés" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "Fichiers récemment modifiés..." #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "Restaurer un remisage supprimé n'est pas possible." #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Récupérer les commits perdus n'est pas toujours évident." #: cola/widgets/main.py:751 msgid "Redo" msgstr "Refaire" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "Réduire l'historique des commits au minimum" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "Dépôt de référence" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "URL de référence" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "Le dépôt de référence à utiliser lors du clonage (facultatif)" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Rafraichir" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "Refuser de fusionner sauf si l'en-tête actuelle est déjà mis à jour ou bien que la fusion peut être résolue rapidement" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Élément distant" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "Branche distante" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "Branche distante supprimée" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "Dépôts Git distants - double-cliquez pour renommer" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "Supprimer" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "Supprimer %s de la liste des dépôts récents ?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "Supprimer l'élément" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "Retirer les branches distantes suivies qui n'existent plus dans l'élément distant" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "Supprimer la sélection" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "Retirer les entrées obsolètes du dépôt qui n'existent plus" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Renommer" #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "Renommer « %s »" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "Renommer branche" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "Renommer branche..." #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "Renommer la branche existante" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "Renommer l'élément distant" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "Renommer le dépôt" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "Renommer branche" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "Renommage de l'élément distant « %(current)s » en « %(new)s » ?" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "Renommer les chemins sélectionnés" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "Dépôt non trouvé" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "Dépôt : %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Réinitialiser" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "Réinitialiser « %(branch)s » vers « %(revision)s » ?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "Tout réinitialiser (Garder les modifications non pré-commitées)" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "Réinitialiser la branche" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "Réinitialiser la banche (Soft)" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "Réinitialiser la branche et pré-commiter (Mixed)" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "Réinitialiser la branche ?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "Réinitialiser la mise en page" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "Réinitialiser l'arbre de travail et tout rétablir ?" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "Réinitialiser et rétablir" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "Réinitialiser la branche ?" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "Réinitialiser « %(branch)s » à « %(revision)s » perdra les commits." #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "Redémarrez l'application pour appliquer les modifications de l'apparence." #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "Rétablir l'arbre de travail" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "Réinitialiser l'arbre de travail et tout rétablir (Hard)" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "Réinitialiser l'arbre de travail et tout rétablir (Garder les modifications non pré-commitées)" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "Réinitialiser l'arbre de travail et tout rétablir (Garder les modifications non pré-commitées)" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "Réinitialiser l'arbre de travail et tout rétablir (Fusionner)" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "Réinitialiser l'arbre de travail et tout rétablir ?" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "Rétablir l'arbre de travail à %s ?" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "Réinitialiser l'arbre de travail, rétablir, et garder les modifications non pré-commitées ?" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "Rétablir" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "Rétablir la section de différences" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "Rétablir la section de différences..." #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "Rétablir la section de différences ?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "Inverser les lignes sélectionnées" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "Inverser les lignes sélectionnées..." #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "Inverser les lignes sélectionnées ?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "Rétablir les modifications non commitées" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "Rétablir les modifications non commitées ?" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "Rétablir modifications non commitées..." #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "Rétablir les modifications non pré-commitées" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "Rétablir les modifications non pré-commitées ?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "Rétablir les modifications non pré-commitées..." #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "Rétablir les modifications non commitées ?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "Rétablir les modifications non pré-commités ?" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "Rétablir les changements non commités dans les chemins sélectionnés" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "Rétablir les changements non pré-commités dans les chemins sélectionnés" #: cola/guicmds.py:320 msgid "Review" msgstr "Examiner" #: cola/widgets/main.py:597 msgid "Review..." msgstr "Examiner..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Révision" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Expression de révision :" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Révision à fusionner" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "Renommer" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "Réécrire les commits publiés ?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "Exécuter" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "Exécuter « %s » ?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "Exécuter %s ?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "Exécuter la commande « %s » ?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "Exécution de la commande : %s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "Traduction russe" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "SHA-1" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "Mode sûr" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Enregistrer" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "Enregistrer l'archive" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "Enregistrer comme Tarball/Zip..." #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "Sauvegarder les paramètres de l'interface" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "Enregistrer la remise" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "Enregistrer l'état modifié dans une nouvelle remise" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "Fichier(s) « %(filename)s » enregistré(s) à partir de « %(ref)s » dans « %(destination)s »" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "Rechercher" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "Rechercher les auteurs" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "Rechercher par messages de commit" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "Rechercher les commiteurs" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "Rechercher une période ciblée" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "Rechercher les différences" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "Rechercher par expression" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "Rechercher par chemin" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "Rechercher pour une chaîne donnée" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "Rechercher en utilisant une expression régulière basique POSIX" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "Rechercher en utilisant une expression régulière approfondie POSIX" #: cola/widgets/main.py:507 msgid "Search..." msgstr "Rechercher..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Sélectionner" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Tout sélectionner" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "Sélectionner une branche à examiner" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "Sélectionner un enfant" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "Sélectionner commit" #: cola/guicmds.py:136 msgid "Select Directory..." msgstr "Sélectionnez un répertoire..." #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "Sélectionner une nouvelle source" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "Sélectionner l'enfant le plus récent" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "Sélectionner le parent le plus ancien" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "Sélectionner le parent" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "Sélectionner la version précédente" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "Sélectionner un répertoire parent pour le nouveau clonage" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "Sélectionner dossier de sortie" #: cola/widgets/selectcommits.py:182 msgid "Select output directory" msgstr "Sélectionnez le répertoire de sortie" #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "Sélectionnez le(s) fichier(s) de patch..." #: cola/widgets/editremotes.py:434 msgid "Select repository" msgstr "Sélectionner le dépôt" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "Définirr le dépôt par défaut" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "Définir la branche à jour" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" "Définir l'ordre des branches et des marqueurs.\n" "Changer l'ordre entre basé sur la date ou sur le nom de la version." #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "Modifier la source" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "Préférences" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "Arguments Shell" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "Vers le bas" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "Vers le haut" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "Raccourcis" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Montrer le Diffstat après la fusion" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "Afficher le chemin complet dans le titre de la fenêtre" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "Afficher l'aide" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "Afficher l'historique" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "Afficher le nombre de fichiers dans le titre du statut" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "Afficher l'aide\n" "Raccourci : ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "Afficher le numéro des lignes" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "Afficher toutes les fonctions environnantes pour les changements" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "Afficher les modifications depuis" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "Côte-à-côte" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Signer" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "Signer le marqueur" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "Signer ce commit" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "Traductions en chinois simplifié" #: cola/cmds.py:2527 msgid "Skip" msgstr "Ignorer" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "Sauter le patch actuel" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "Trier les marque-pages par ordre alphabétique" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "Traduction espagnole" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "Spécifie le SHA-1 au marqueur" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "Définie le message du marqueur" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "Spécifie le nom du marqueur" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "Suggestions d'orthographe" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "Écraser" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "Écraser les commits fusionnés en un seul commit" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "Pré-commiter" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "Pré-commiter/non pré-commiter" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "Pré-commiter/non pré-commiter tous" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "Pré-commiter cette section" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Pré-commit modifiés" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "Pré-commiter les modifiés ou non suivis" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "Pré-commiter la sélection" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "Pré-commiter lignes sélectionnées" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "Pré-commit défusionné" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "Pré-commit démarqué" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "Pré-commiter et commiter" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "Pré-commiter et commiter ?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "Conflits de commit" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "Conflits de commit ?" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "Non/Pré-commiter les chemins sélectionnés" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "Pré-commité" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "Pré-commit : %s" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "Commencer le rétablissement interactif..." #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "Début de révision" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "Remiser" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "Remiser l'index" #: cola/widgets/stash.py:79 msgid "Stash staged changes only" msgstr "Ne remiser que les modifications pré-commitées" #: cola/widgets/stash.py:75 msgid "Stash unstaged changes only, keeping staged changes" msgstr "Ne remiser que les modifications non pré-commitées, et garder celles pré-commitées" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "Cacher..." #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "Statut" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "Stopper le suivi des chemins" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "L'URL du sous-module (peut être relatif, par ex. ../repo.git)" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "La branche du sous-module à suivre (facultatif)" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "Le chemin du sous-module dans le dépôt actuel (facultatif)" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "Sous-modules" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "Résumer les commits de fusion" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "Résumé" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Largeur de la tabulation" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Marquer" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "Marqueur créé" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Message du marqueur..." #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "La signature du marqueur a été demandée mais le message du marqueur est vide." #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "Marqueurs" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "Largeur du texte" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "Cette branche ne sera plus disponible." #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "La branche sera réinitialisée en utilisant « git reset --mixed %s »" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "La branche sera réinitialisée en utilisant « git reset --soft %s »" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "Le message de commit sera effacé." #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "Le fichier « %s » existe et sera écrasé." #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "Les fichiers suivants seront effacés :" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "Le dépôt va être réinitialisé avec « git reset --hard %s »" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "Le dépôt va être réinitialisé avec « git reset --keep %s »" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "Le dépôt va être réinitialisé avec « git reset --merge %s »" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "L'expression de révision est vide." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" "Le sous-module va être ajouté avec\n" "« %s »" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "L'arbre de travail sera restauré avec \"git read-tree --reset -u %s\"" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "Cela ne peut pas être annulé. Effacer le message du commit ?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "Ce commit a déjà été publié.\n" "Cette opération réécrira l'historique publié.\n" "Vous ne voulez probablement pas effectuer cela." #: cola/widgets/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "Cette opération supprime les modifications non commitées.\n" "Ces modifications ne pourront pas être récupérées." #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Cette opération supprime les modifications non commitées.\n" "Ces modifications ne pourront pas être récupérées." #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Cette opération supprime les modifications pré-commitées.\n" "Ces modifications ne pourront pas être récupérées." #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "Ce dépôt est en cours de rétablissement.\n" "Résolvez les conflits, commitez les changements et exécutez :\n" " Rétablir > Continuer" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "Ce dépôt est en cours de fusion.\n" "Résolvez les conflits et commitez les changements." #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "Dés/activer actif" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "Dés/activer le différence des images" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "Dés/activer le filtre des branches" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "Dés/activer le filtre des chemins" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Suivi de branche" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "Suivi de branche" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "Traduction chinois traditionnel (Taïwan)" #: cola/widgets/about.py:421 msgid "Translation" msgstr "Traduction" #: cola/widgets/about.py:91 msgid "Translators" msgstr "Traducteurs" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "Traduction turque" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "URL : %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "Traduction ukrainienne" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "Impossible de rétablir" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "Impossible de mettre l'URL de « %(name)s » pour « %(url)s »" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "Annuler" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "Annuler le dernier commit" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "Annuler le dernier commit ?" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "Annuler le commit publié ?" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "Non fusionné" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "Retirer du pré-commit" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "Tout retirer du pré-commit" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "Retirer ce diff du pré-commit" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "Retirer sélection du pré-commit" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "Retirer les lignes sélectionnées du pré-commit" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "Retirer du pré-commit : %s" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "Ne plus suivre la sélection" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "Non suivi" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "Non-suivi : %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "Mettre à jour tous les sous-modules..." #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Mettre à jour branche existante :" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "Mettre à jour le sous-module" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "Mettre à jour le sous-module..." #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "Mettre à jour les sous-modules" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "Mettre à jour tous les sous-modules ?" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "Mettre à jour les sous-modules..." #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "Mettre à jour ce sous-module" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "Mettre à jour ce sous-module ?" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "Mise à jour" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Nom d'utilisateur" #: cola/widgets/about.py:89 msgid "Version" msgstr "Version" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "Affichage" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "Afficher l'historique..." #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "Afficher l'historique pour les chemins sélectionnés" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "Visualiser" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "Visualiser toutes les branches..." #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "Visualiser la branche courante..." #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "Si vous voulez signer le marqueur (git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "Voulez-vous pré-commiter puis commiter tous les fichiers modifiés ?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "Ou-exclusif" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "Oui" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "Vous êtes au milieu d'une fusion.\n" "Impossible de corriger durant cette fusion." #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "Vous ne pouvez pas rétablir avec des modifications non commitées." #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "Vous devez spécifier une révision à fusionner." #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "Vous devez spécifier une révision à afficher." #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "Zoom avant" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "Zoom arrière" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "Ajuster à la largeur" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "arguments en ligne de commande" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "erreur : impossible d'exécuter git" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "code de sortie %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "erreur fatale : « %s » n'est pas un répertoire. Veuillez sélectionner un --repo valide." #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "Version de git cola %s" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "git-cola diff" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "git://git.example.com/repo.git" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "Résultat de grep..." #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "hotkeys.html" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "path/to/submodule" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "vX.Y.Z" #: cola/hidpi.py:43 msgid "x 1" msgstr "1x" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "1.5x" #: cola/hidpi.py:46 msgid "x 2" msgstr "2x" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "dd/MM/yyyy" #~ msgid "" #~ "\n" #~ "Commands\n" #~ "--------\n" #~ "pick = use commit\n" #~ "reword = use commit, but edit the commit message\n" #~ "edit = use commit, but stop for amending\n" #~ "squash = use commit, but meld into previous commit\n" #~ "fixup = like \"squash\", but discard this commit's log message\n" #~ "exec = run command (the rest of the line) using shell\n" #~ "\n" #~ "These lines can be re-ordered; they are executed from top to bottom.\n" #~ "\n" #~ "If you disable a line here THAT COMMIT WILL BE LOST.\n" #~ "\n" #~ "However, if you disable everything, the rebase will be aborted.\n" #~ "\n" #~ "Keyboard Shortcuts\n" #~ "------------------\n" #~ "? = show help\n" #~ "j = move down\n" #~ "k = move up\n" #~ "J = shift row down\n" #~ "K = shift row up\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "spacebar = toggle enabled\n" #~ "\n" #~ "ctrl+enter = accept changes and rebase\n" #~ "ctrl+q = cancel and abort the rebase\n" #~ "ctrl+d = launch difftool\n" #~ msgstr "" #~ "\n" #~ "Commandes\n" #~ "--------\n" #~ "pick = utiliser le commit\n" #~ "reword = utiliser le commit, mais modifier le message du commit\n" #~ "edit = utiliser le commit, mais arrêter pour la correction\n" #~ "squash = utiliser le commit, mais fusionner avec le commit précédent\n" #~ "fixup = comme \"squash\", mais effacer le message de journal de ce commit\n" #~ "exec = lancer une commande (la suite de la ligne) via le shell\n" #~ "\n" #~ "L'ordre de ces lignes peut être changé ; elles sont exécutées de haut en bas.\n" #~ "\n" #~ "Si vous désactivez une ligne ici CE COMMIT SERA PERDU.\n" #~ "\n" #~ "Mais si vous désactivez tout, ce rétablissement sera annulé.\n" #~ "\n" #~ "Raccourcis clavier\n" #~ "------------------\n" #~ "? = afficher l'aide\n" #~ "j = se déplacer vers le bas\n" #~ "k = se déplacer vers le haut\n" #~ "J = déplacer la ligne vers le bas\n" #~ "K = déplacer la ligne vers le haut\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "espace = changer l'activation\n" #~ "\n" #~ "ctrl+entrée = accepter les modifications et rétablir\n" #~ "ctrl+q = tout annuler dont le rétablissement\n" #~ "ctrl+d = lancer difftool\n" #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Un stash nommé « %s » existe déjà" #~ msgid "Error: Stash exists" #~ msgstr "Erreur : le stash existe" #~ msgid "Reset Branch Head" #~ msgstr "Supprimer la branche principale" #~ msgid "Reset Worktree" #~ msgstr "Réinitialiser l'arbre de travail" #~ msgid "Reset worktree?" #~ msgstr "Réinitialiser l'arbre de travail ?" #~ msgid "Select Repository..." #~ msgstr "Sélectionner le dépôt..." #~ msgid "Select manually..." #~ msgstr "Sélectionner manuellement..." #~ msgid "Show icon? (if available)" #~ msgstr "Afficher l'icône ? (si disponible)" #~ msgid "The branch will be reset using \"git reset --hard %s\"" #~ msgstr "La branche sera réinitialisée en utilisant « git reset --hard %s »" #~ msgid "The branch will be reset using \"git reset --merge %s\"" #~ msgstr "La branche sera réinitialisée en utilisant « git reset --merge %s »" #~ msgid "The worktree will be reset using \"git reset --keep %s\"" #~ msgstr "Cet arbre de travail sera réinitialisé en utilisant « git reset --keep %s »" #~ msgid "title" #~ msgstr "titre" #~ msgid "unknown" #~ msgstr "inconnu" git-cola-4.6.1/cola/i18n/git-cola.pot000066400000000000000000002375041457126473700171740ustar00rootroot00000000000000#: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr "" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr "" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "" #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "" #: cola/guicmds.py:156 #, python-format msgid "\"%s\" already exists" msgstr "" #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "" #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "" #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "" #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "" #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "" #: cola/widgets/main.py:748 msgid "&Edit" msgstr "" #: cola/widgets/main.py:690 msgid "&File" msgstr "" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/diff.py:816 msgid "100%" msgstr "" #: cola/widgets/diff.py:817 msgid "200%" msgstr "" #: cola/widgets/diff.py:814 msgid "25%" msgstr "" #: cola/widgets/diff.py:818 msgid "400%" msgstr "" #: cola/widgets/diff.py:815 msgid "50%" msgstr "" #: cola/widgets/diff.py:819 msgid "800%" msgstr "" #: cola/widgets/finder.py:118 msgid " ..." msgstr "" #: cola/cmds.py:1685 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:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "" #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "" #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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:78 msgid "Add new remote git repository" msgstr "" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "" #: cola/cmds.py:220 msgid "Amend" msgstr "" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "" #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "" #: cola/qtutils.py:886 msgid "Attach" msgstr "" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "" #: cola/widgets/about.py:90 msgid "Authors" msgstr "" #: cola/hidpi.py:41 msgid "Auto" msgstr "" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "" #: cola/widgets/browse.py:206 msgid "Blame selected paths" msgstr "" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "" #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "" #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "" #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "" #: cola/guicmds.py:52 msgid "Browse" msgstr "" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "" #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "" #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "" #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "" #: cola/widgets/main.py:87 msgid "Browser" msgstr "" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "" #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "" #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "" #: cola/widgets/clone.py:124 msgid "Clone" msgstr "" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "" #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "" #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "" #: cola/sequenceeditor.py:371 msgid "Command" msgstr "" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "" #: cola/difftool.py:102 msgid "Compare All" msgstr "" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "" #: cola/widgets/main.py:169 msgid "Console" msgstr "" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "" #: cola/widgets/status.py:738 msgid "Copy..." msgstr "" #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "" #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "" #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "" #: cola/widgets/main.py:754 msgid "Cut" msgstr "" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "" #: cola/icons.py:54 msgid "Dark Theme" msgstr "" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "" #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "" #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "" #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "" #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "" #: cola/difftool.py:324 msgid "Difftool" msgstr "" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 msgid "Edit" msgstr "" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "" #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "" #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "" #: cola/cmds.py:2987 cola/cmds.py:3033 #, python-format msgid "Error updating submodule %s" msgstr "" #: cola/cmds.py:3069 msgid "Error updating submodules" msgstr "" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "" #: cola/widgets/main.py:547 msgid "Expression..." msgstr "" #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "" #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "" #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "" #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "" #: cola/widgets/dag.py:821 msgid "Files" msgstr "" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "" #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "" #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "" #: cola/themes.py:705 msgid "Flat dark green" msgstr "" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "" #: cola/themes.py:691 msgid "Flat dark red" msgstr "" #: cola/themes.py:656 msgid "Flat light blue" msgstr "" #: cola/themes.py:677 msgid "Flat light green" msgstr "" #: cola/themes.py:670 msgid "Flat light grey" msgstr "" #: cola/themes.py:663 msgid "Flat light red" msgstr "" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "" #: cola/widgets/remote.py:197 msgid "Force" msgstr "" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "" #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "" #: cola/widgets/dag.py:848 msgid "Graph" msgstr "" #: cola/widgets/main.py:354 msgid "Grep" msgstr "" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "" #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "" #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "" #: cola/icons.py:55 msgid "Light Theme" msgstr "" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "" #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "" #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "" #: cola/widgets/dag.py:816 msgid "Log" msgstr "" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "" #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "" #: cola/widgets/main.py:1177 msgid "Merging" msgstr "" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "" #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "" #: cola/guicmds.py:147 cola/widgets/main.py:281 msgid "New Bare Repository..." msgstr "" #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "" #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "" #: cola/widgets/startup.py:52 msgid "New..." msgstr "" #: cola/actions.py:56 msgid "Next File" msgstr "" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "" #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "" #: cola/widgets/submodules.py:48 msgid "Open Parent" msgstr "" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "" #: cola/widgets/main.py:410 msgid "Open..." msgstr "" #: cola/widgets/branch.py:354 msgid "Other branches" msgstr "" #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "" #: cola/widgets/main.py:758 msgid "Paste" msgstr "" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/cmds.py:2297 msgid "Please select a file" msgstr "" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "" #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "" #: cola/widgets/commitmsg.py:417 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/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "" #: cola/actions.py:65 msgid "Previous File" msgstr "" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "" #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "" #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "" #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "" #: cola/widgets/main.py:118 msgid "Recent" msgstr "" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "" #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "" #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "" #: cola/widgets/main.py:751 msgid "Redo" msgstr "" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "" #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "" #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "" #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "" #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "" #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "" #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "" #: cola/guicmds.py:320 msgid "Review" msgstr "" #: cola/widgets/main.py:597 msgid "Review..." msgstr "" #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "" #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "" #: cola/widgets/main.py:507 msgid "Search..." msgstr "" #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "" #: cola/widgets/main.py:764 msgid "Select All" msgstr "" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "" #: cola/guicmds.py:136 msgid "Select Directory..." msgstr "" #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "" #: cola/widgets/selectcommits.py:182 msgid "Select output directory" msgstr "" #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "" #: cola/widgets/editremotes.py:434 msgid "Select repository" msgstr "" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "" #: cola/cmds.py:2527 msgid "Skip" msgstr "" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "" #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "" #: cola/widgets/stash.py:79 msgid "Stash staged changes only" msgstr "" #: cola/widgets/stash.py:75 msgid "Stash unstaged changes only, keeping staged changes" msgstr "" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "" #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "" #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "" #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "" #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "" #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 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/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "" #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "" #: cola/widgets/about.py:89 msgid "Version" msgstr "" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "" #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "" #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "" #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "" #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "" #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "" #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "" #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "" #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "" #: cola/hidpi.py:43 msgid "x 1" msgstr "" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "" #: cola/hidpi.py:46 msgid "x 2" msgstr "" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "" git-cola-4.6.1/cola/i18n/glossary/000077500000000000000000000000001457126473700166015ustar00rootroot00000000000000git-cola-4.6.1/cola/i18n/glossary/de.po000066400000000000000000000130211457126473700175260ustar00rootroot00000000000000# Translation of git-cola glossary to German # Copyright (C) 2007 Shawn Pearce, et al. # This file is distributed under the same license as the git-cola package. # Christian Stimming , 2007 # msgid "" msgstr "" "Project-Id-Version: git-cola 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-4.6.1/cola/i18n/glossary/it.po000066400000000000000000000131271457126473700175610ustar00rootroot00000000000000# Translation of git-cola glossary to Italian # Copyright (C) 2007 Shawn Pearce, et al. # This file is distributed under the same license as the git-cola package. # Christian Stimming , 2007 # msgid "" msgstr "" "Project-Id-Version: git-cola 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-4.6.1/cola/i18n/glossary/zh_cn.po000066400000000000000000000122401457126473700202410ustar00rootroot00000000000000# Translation of git-cola glossary to Simplified Chinese # Copyright (C) 2007 Shawn Pearce, et al. # This file is distributed under the same license as the git-cola package. # Xudong Guan and the zh-kernel.org mailing list, 2007 # ZH , 2015 # msgid "" msgstr "" "Project-Id-Version: git-cola glossary\n" "PO-Revision-Date: 2007-07-23 22:07+0200\n" "Last-Translator: ZH \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-4.6.1/cola/i18n/glossary/zh_tw.po000066400000000000000000000157611457126473700203060ustar00rootroot00000000000000# Translation of git-cola glossary to Traditional Chinese(Taiwan) # Copyright (C) 2007 Shawn Pearce, et al. # This file is distributed under the same license as the git-cola package. # V字龍(Vdragon) , 2014, 2018. msgid "" msgstr "" "Project-Id-Version: git-cola glossary\n" "PO-Revision-Date: 2018-06-27 23:50+0800\n" "Last-Translator: V字龍(Vdragon) \n" "Language-Team: Chinese l10n \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_TW\n" "Plural-Forms: nplurals=2; plural=n != 1;\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]: 標註,或者乾脆用原意:註解,或註釋 #, fuzzy 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 "推送至遠端版控庫" # 相對於「復原(undo)」 #. "" 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?)" #. In revision control systems, a repository[1] is an on-disk data structure which stores metadata for a set of files and/or directory structure.(摘錄自 [Repository (version control) - Wikipedia](https://en.wikipedia.org/wiki/Repository_(version_control))) #. V字龍:過去所採用的「版本倉庫」翻譯之理解為「存放版本的倉庫」並不符合 VCS Repo 除了版本之外保存其他版本控制需要的詮釋資料的實際情況,所以被棄用) #. V字龍:「版控庫」為「因版本控制目的而建立的倉庫(至於倉庫內存了什麼哪些東西不是一般使用者該關心的細節)」的簡寫 msgid "repository" msgstr "版控庫" #. "" msgid "reset" msgstr "重設" #. "" msgid "revert" msgstr "撤銷" #. "A particular state of files and directories which was stored in the object database." #. V字龍:修訂版(revision)指得是版本控制系統控管內容修改的最小單位,與「版本(version)」的差異為「修訂版」微不足道到作者沒必要給它指定一個有意義的識別名稱(Vx.y.z)而是使用版本控制系統隨機產生的識別名稱(如 a3dfe84...)或是編號(如 Build 12345) msgid "revision" msgstr "修訂版" #. "" msgid "sign off" msgstr "簽名" # 意思應該是 commit 的準備區域的樣子 #. "" #. 似乎是git-gui裡面顯示的本次提交的文件清單區域 msgid "staging area" msgstr "新修訂版準備區域" # 意思應該是 commit 的準備區域的樣子 #. "" #. 似乎是git-gui裡面顯示的本次提交的文件清單區域 msgid "stage" 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 "復原" # 注意和fetch的區分 #. "" msgid "update" msgstr "更新" #. "" msgid "verify" msgstr "驗證" #. "The tree of actual checked out files." #. "工作副本?工作區域?工作目錄" #. [LI Yang]: 當前副本, 當前源碼樹? msgid "working copy, working tree" msgstr "當前工作目錄" #. "" msgid "rebase" msgstr "變更基底" #. "" msgid "patch(noun)" msgstr "修正" #. "" msgid "patch(verb)" msgstr "套用修正" #. "" msgid "clone" msgstr "克隆" #. "" msgid "(merge) conflict" msgstr "合併衝突" #. "" msgid "stash" msgstr "珍藏項目" #. "Cherry-picking, moving only some revisions from one branch to another in version control" msgid "cherry-pick" msgstr "揀選" git-cola-4.6.1/cola/i18n/hu.po000066400000000000000000003361301457126473700157200ustar00rootroot00000000000000# Hungarian translations for git-cola package. # Copyright (C) 2007 THE git-cola'S Miklos Vajna at el. # This file is distributed under the same license as the git-cola package. # Miklos Vajna , 2007 # Meskó Balázs , 2019. # Gyuris Gellért , 2019-2021. # msgid "" msgstr "" "Project-Id-Version: git-cola 3.4\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-17 01:06-0700\n" "PO-Revision-Date: 2021-04-30 00:36+0200\n" "Last-Translator: Gyuris Gellért \n" "Language-Team: Hungarian \n" "Language: hu\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" "X-Generator: Gtranslator 3.38.0\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " A foltok listához való hozzáadása fogd és vidd módszerrel,\n" " vagy a Hozzáadás gombbal végezhető el\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" "\n" "
\n" " A Git Cola az alábbi személyeknek köszönhetően lett több nyelvre lefordítva.\n" "\n" "
\n" "

\n" " A fordítás megközelítő. Hiba felfedezése esetén, kérjük vegyen fel egy hibajegyet a GitHubon.\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " Kérjük, vegyen részt a fordításban egy új fordítás hozzáadásával vagy egy \n" " meglévő frissítésével, valamint egy beolvasztási kérés nyitásával.\n" "

\n" "\n" "
\n" "\n" " " #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" "\n" "
\n" " Git Cola %(cola_version)s verzió\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" "\n" "
\n" " Kérjük, itt jelentse a hibákat: %(bug_link)s.\n" "
\n" " " #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" "\n" " Formázó karakterlánc változók\n" " -----------------------------\n" " %(path)s = relatív fájlútvonal\n" " %(abspath)s = abszolút fájlútvonal\n" " %(dirname)s = mappa relatív útvonala\n" " %(absdirname)s = mappa abszolút útvonala\n" " %(filename)s = fájl alapnév\n" " %(basename)s = fájl alapnév, kiterjesztés nélkül\n" " %(ext)s = fájl kiterjesztése\n" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" "\n" "Gyorsbillentyűk\n" "------------------\n" "J, Lefelé = Mozgatás lefelé\n" "K, Felfelé = Mozgatás felfelé\n" "Enter = Kijelölt fájlok szerkesztése\n" "Szóköz = Fájl megnyitása az alapértelmezett alkalmazással\n" "Ctrl + L = Szövegelemmező fókuszba helyezése\n" "? = Súgó megjelenítése\n" "\n" "A felfelé és lefelé billentyűk módosítják a szövegelem-mezők közti\n" "fókuszt, valamint az eredményeket.\n" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr " - DAG" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr " véglegesítéssel ezelőtt" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "A(z) „%(branch)s” ág törölve lett erről: „%(remote)s”" #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "A(z) „%(command)s” ezzel a kilépési állapottal tért vissza: „%(status)d”" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "A(z) „%(command)s” ezzel a kilépési állapottal tért vissza: %(status)d" #: cola/guicmds.py:156 #, python-format msgid "\"%s\" already exists" msgstr "A(z) „%s” már létezik" #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "A(z) „%s” már létezik, ezért a cola új mappát hoz létre" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "A(z) „%s” kijelölt fájlt igényel." #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "#" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s: %(branch)s – tallózás" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "%(project)s: %(ref)s - DAG" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "%d napja" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "%d órája" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "%d perce" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "%d folt alkalmazva." #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d kihagyva" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" "Úgy tűnik, hogy a(z) %s beolvasztási ütközéseket tartalmaz.\n" "\n" "Valószínűleg ki kellene hagyni ezt a fájlt.\n" "Biztosan kiszemelésre kerüljön?" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "%s-t nem lehet megnyitni. Eltávolítja a könyvjelzők közül?" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "A(z) %s nem git tároló." #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "A(z) %s el lesz távolítva a könyvjelzők közül." #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "A(z) %s el lesz távolítva a legutóbbi tárolókból." #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: Nincs ilyen fájl vagy könyvtár." #: cola/widgets/main.py:748 msgid "&Edit" msgstr "Sz&erkesztés" #: cola/widgets/main.py:690 msgid "&File" msgstr "&Fájl" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(Javítás)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "*** Elágazás ***" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** Homokozó ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "100%" #: cola/widgets/diff.py:817 msgid "200%" msgstr "200%" #: cola/widgets/diff.py:814 msgid "25%" msgstr "25%" #: cola/widgets/diff.py:818 msgid "400%" msgstr "400%" #: cola/widgets/diff.py:815 msgid "50%" msgstr "50%" #: cola/widgets/diff.py:819 msgid "800%" msgstr "800%" #: cola/widgets/finder.py:118 msgid " ..." msgstr " …" #: cola/cmds.py:1685 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 "" "A véglegesítési sablon nem lett még beállítva.\n" "A „git config” használatával hozható létre a „commit.template”,\n" "hogy az egy véglegesítési sablonra mutasson." #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "Egy hurkot kell létrehozni itt: „%s”" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "Megszakítás" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "Művelet megszakítása" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "Beolvasztás megszakítása" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Beolvasztás megszakítása…" #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "Megszakítja a műveletet?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "A jelenlegi beolvasztás megszakítása *MINDEN* nem véglegesített módosítás elvesztését jelenti.\n" "A nem véglegesített módosítások helyreállítása nem lehetséges." #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "Megszakítja a jelenlegi beolvasztást?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "Névjegy" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "A git-cola névjegye" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "Elfogadás" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "Változások elfogadása és újraalapozás\n" "Gyorsbillentyű: Ctrl+Enter" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "Művelet neve" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "Műveletek" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "Műveletek…" #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "Hozzáadás" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "Kedvenc hozzáadása" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "Távoli hozzáadása" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "Elválasztó hozzáadása" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "Részmodul hozzáadása" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "Részmodul hozzáadása…" #: cola/widgets/editremotes.py:60 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 "" "A bal oldali hozzáadás(+) és törlés(-) gombokkal lehet\n" "hozzáadni és törölni távoli tárolókat.\n" "\n" "A távoli tárolók átnevezhetők a listából való kijelöléssel\n" "majd az Enter lenyomásával vagy dupla kattintással." #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "Új távoli git tároló hozzáadása" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "Foltok hozzáadása (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "Távoli hozzáadása" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "Hozzáadja ezt a részmodult?" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "Hozzáadás a .gitignore-hoz" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "Hozzáadás a Git Annexhez" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "Hozzáadás a Git LFS-hez" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "Hozzáadás a kizárásokhoz" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "Hozzáadás a helyi .git/info/exclude-hoz" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "Kiegészítések" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "Speciális" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "Kor" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "Minden tároló" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" "Az összes almodul frissítve lesz ezzel:\n" "„%s”" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "Nem előrepörgetett frissítések engedélyezése. A kényszerítés a távoli tárolón a véglegesítések elvesztéséhez vezethet. Óvatosan érdemes használni." #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "Engedélyezve mindig beolvasztással történik a véglegesítés, akkor is, ha a beolvasztás előrepörgetett frissítés" #: cola/cmds.py:220 msgid "Amend" msgstr "Javítás" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "Véglegesítés javítása" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Utolsó véglegesítés javítása" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "Javítja a közzétett véglegesítést?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "Javítás" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "Egy művelet épp fut.\n" "A megszakítása adatvesztéshez vezethet." #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "Ehelyett csak egy aláíratlan, könnyűsúlyú címke lesz csak létrehozva.\n" "Készüljön egy aláíratlan címke?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "Megjelenés" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "Alkalmaz" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "Foltok alkalmazása" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "Foltok alkalmazása…" #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "Kijelölt félretett változat alkalmazása és eldobása (git stash pop)" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "Kijelölt félretett változat alkalmazása" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "Argumentumok" #: cola/qtutils.py:886 msgid "Attach" msgstr "Csatolás" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "Szerző" #: cola/widgets/about.py:90 msgid "Authors" msgstr "Szerzők" #: cola/hidpi.py:41 msgid "Auto" msgstr "Automatikus" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "Sorok automatikus tördelése" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "Útvonalak automatikus kiegészítése" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "Véglegesítő üzenetsablon automatikus betöltése" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "Egyszerű regexp" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "Hibáztatás megjelenítő" #: cola/widgets/browse.py:206 msgid "Blame selected paths" msgstr "Kijelölt útvonalak hibáztatása" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "Hibáztatás…" #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "Félkövéren szedett és sötét fejlécek a dőlt helyett" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Elágazás" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "A(z) „%(branch)s” nem létezik itt: „%(remote)s”.\n" "Új távoli ág lesz közzétéve." #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "A(z) „%s” ág már létezik." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "Ág-összehasonlító megjelenítő" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "Létező ág" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Ág neve" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "Ág neve" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "Ág: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "Ágak" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "Ágak…" #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "Brazil fordítás" #: cola/guicmds.py:52 msgid "Browse" msgstr "Tallózás" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "Véglegesítések tallózása…" #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "Jelenlegi ág tallózása…" #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "Egyéb ágak tallózása…" #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "Tallózás…" #: cola/widgets/main.py:87 msgid "Browser" msgstr "Böngésző" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "%s tallózása" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "Véglegesítési hurkok kikerülése" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "Mégse" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "Újraalapozás megszakítása\n" "Gyorsbillentyű: Ctrl+Q" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "A javítás nem lehetséges" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "A(z) „%s” nem futtatható: állítson be egy hibáztatás megjelenítőt" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "A(z) „%s” nem futtatható: állítson be egy történetböngészőt" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "A(z) „%s” nem futtatható: állítsa be a szerkesztőjét" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "Módosítva a távoli tárolóban" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "Közzétett véglegesítések ellenőrzése javítás alatt" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "Helyesírás-ellenőrzés" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "Helyesírás-ellenőrzés" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "Javítás közben ellenőrizze, hogy a véglegesítések közzé lettek-e téve" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Átváltás" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "Átváltás a létrehozás után" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Ág átváltása" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "Átváltás a leválasztott FEJ-re" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "Átváltás új ágként" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Átváltás…" #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "Mazsolázás" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "Mazsolázó véglegesítés" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "Mazsolázás…" #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "Válasszon útvonalakat" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "Válassza ki a „git grep” reguláris kifejezés módját" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "Alapértelmezett tároló tisztítása" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "Véglegesítő üzenet tisztítása" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "Tisztítja a véglegesítő üzenetet?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "Tisztítás…" #: cola/widgets/clone.py:124 msgid "Clone" msgstr "Klónozás" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "Tároló klónozása" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Klónozás…" #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "Tároló klónozása ide: %s" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Bezárás" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "Bezárás…" #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "Összes összecsukása" #: cola/sequenceeditor.py:371 msgid "Command" msgstr "Parancs" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "Véglegesítés" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "Véglegesítés sikertelen" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "Kiszemelt módosítások véglegesítése" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "Kiszemelt módosítások véglegesítése\n" "Gyorsbillentyű: Ctrl+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "Véglegesítés összegzése" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "Beolvasztás véglegesítése, ha nincsenek ütközések. Bejelöletlenül hagyva a beolvasztás nem lesz véglegesítve" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "Véglegesítés" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "Összehasonlítás" #: cola/difftool.py:102 msgid "Compare All" msgstr "Mind összehasonlítása" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "Eszköztár beállítása" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "A távoli ág beállítása új távoli tárolóként" #: cola/widgets/main.py:169 msgid "Console" msgstr "Konzol" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Folytatás" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Másolás" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "Alapnév másolása a vágólapra" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "Kezdő útvonal másolása a vágólapra" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "Útvonal másolása a vágólapra" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "Relatív útvonal másolása a vágólapra" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "SHA-1 másolása" #: cola/widgets/status.py:738 msgid "Copy..." msgstr "Másolás…" #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "Nem lehet megnyitni: %s." #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "Nem lehet feldolgozni a git URL-t: „%s”" #: cola/app.py:499 msgid "Create" msgstr "Létrehozás" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Ág létrehozása" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "Folt létrehozása" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "Távoli ág létrehozása" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "Aláírt véglegesítés létrehozása" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "Címke létrehozása" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "Címke (tag) létrehozása…" #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "Aláíratlan címke létrehozása" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "Beolvasztásos véglegesítést hoz létre akkor is, ha a beolvasztás előrepörgetett lenne" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "Létrehozza az új távoli ágat?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "Létrehozza a tárolót ezen a helyen?" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "Felszínes klón létrehozása a történet megadott számú revízióra csonkolásával. A 0 teljes klónt hoz létre." #: cola/widgets/main.py:565 msgid "Create..." msgstr "Létrehozás…" #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "„%s” nevű címke létrehozva" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "Jelenlegi tároló" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "Egyéni másolási műveletek" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "Testreszabás…" #: cola/widgets/main.py:754 msgid "Cut" msgstr "Kivágás" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "Cseh fordítás" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "DAG…" #: cola/icons.py:54 msgid "Dark Theme" msgstr "Sötét téma" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "Dátum és idő" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "Alapértelmezett" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Törlés" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "Törli a(z) %d fájlt?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "Könyvjelző törlése" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "Törli a könyvjelzőt?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Ág törlése" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "Fájlok törlése" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "Fájlok törlése…" #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "Törli a fájlokat?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "Távoli törlése" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "Távoli ág törlése" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "Távoli ág törlése…" #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "Eszköztár törlése" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "Törli az ágat: „%s”?" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "Távoli törlése" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "„%s” távoli törlése" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "Törli a távolit?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Törlés…" #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "„%s” törlése sikertelen" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "Törlések" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "Mélység" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "Leválasztás" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "Ütközésjelölők észlelése" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "Ütközésjelölők észlelése a nem beolvasztott fájlokban" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "Fejlesztő" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "Összehasonlítás" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "Összehasonlítás az előddel…" #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "Összehasonlítási lehetőségek" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "Összehasonlító eszköz" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "Kijelölt összehasonlítása → ezzel" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "Ez összehasonlítása → a kijelölttel" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "Összehasonlítási statisztika" #: cola/difftool.py:324 msgid "Difftool" msgstr "Összehasonlító eszköz" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "Könyvtár létezik" #: cola/hidpi.py:42 msgid "Disable" msgstr "Letiltás" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "Nem követett fájlok megjelenítése" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "Dokumentáció" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "Eldobás" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "Félretett változat eldobása" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "Eldobja a félrerakott változatot?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "Eldobja a(z) „%s” félretett változatot?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "Kijelölt félretett változat eldobása" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 msgid "Edit" msgstr "Szerkesztés" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "Újraalapozás szerkesztése" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "Távolik szerkesztése" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "Távolik szerkesztése…" #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "Távoli szerkesztése a listából való kijelöléssel" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "Kijelölt útvonalak szerkesztése" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "Szerkesztés…" #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "Szerkesztő" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "E-mail cím" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "E-mail közreműködő" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "Útvonalak automatikus kiegészítésének engedélyezése az eszközökben" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "Engedélyezett" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "Adja meg az új ág nevét" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "Adja meg az új csupasz tároló nevét" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "Adjon meg egy nevet a félrerakáshoz" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "Hiba" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "Hiba a klónozáskor" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "Hiba az ág létrehozásakor" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "Hiba a tároló létrehozásakor" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "Hiba a távoli ág törlésekor" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "Hiba a fájl szerkesztésekor" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "Hiba a gyanúsító megjelenítő indítása közben" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "Hiba a történetböngésző indításakor" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "Hiba a tároló megnyitásakor" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "Hiba a(z) „%s” távoli létrehozásakor" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "Hiba a félretett változat létrehozásakor" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "Hiba az ág törlésekor: „%s”" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Hiba a(z) „%s” távoli törlésekor" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "Hiba az átnevezéskor: „%(name)s” → „%(new_name)s”" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "Hiba a prepare-commitmsg hurok futtatásakor" #: cola/cmds.py:2987 cola/cmds.py:3033 #, python-format msgid "Error updating submodule %s" msgstr "Hiba a(z) %s almodul frissítésekor" #: cola/cmds.py:3069 msgid "Error updating submodules" msgstr "Hiba az almodulok frissítésekor" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "Hiba: Nem található véglegesítési üzenetsablon" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "Hiba: Nincs beállítva véglegesítési sablon" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Hiba: A(z) „%s” nem klónozható" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "Hiba: A(z) „%s” címke nem hozható létre" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "Művelet végrehajtása: %s" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "Összes kibontása" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "Foltok exportálása" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "Foltok exportálása…" #: cola/widgets/main.py:547 msgid "Expression..." msgstr "Kifejezés…" #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "Bővített regexp" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "Bővített leírás…" #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Csak előrepörgetés" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "Csak előrepörgetés" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "Kedvenc tárolók" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "Kedvencek" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "Letöltés" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "Követett ág letöltése" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "Letöltés…" #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "Fájlböngésző…" #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "Fájlok különbségei" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "Fájl mentve" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "Fájl mentve: „%s”" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "A fájlrendszer változásainak figyelése: letiltva, mivel a „cola.inotify” hamis.\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "A fájlrendszer változásainak figyelése: letiltva, mivel a libc nem támogatja az inotify rendszerhívásait.\n" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "A fájlrendszer változásainak figyelése: letiltva, mivel a pywin32 nincs telepítve.\n" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" "A fájlrendszer változásainak figyelése: letiltva, mivel az inotify megfigyelő elérte a teljes létszám korlátját. Ezt a korlátot meg lehet növelni az alábbi futtatásával:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "A fájlrendszer változásainak figyelése: engedélyezve\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "Fájlnév" #: cola/widgets/dag.py:821 msgid "Files" msgstr "Fájlok" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "Ágak szűrése…" #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "Útvonalak szűrése…" #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "Fájlok keresése" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "Rögzített szöveg" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "Rögzített szélességű betűkészlet" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "Gyorsjavítás" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "Előző véglegesítés gyorsjavítása" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "Lapos sötétkék" #: cola/themes.py:705 msgid "Flat dark green" msgstr "Lapos sötétzöld" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "Lapos sötétszürke" #: cola/themes.py:691 msgid "Flat dark red" msgstr "Lapos sötétvörös" #: cola/themes.py:656 msgid "Flat light blue" msgstr "Lapos világoskék" #: cola/themes.py:677 msgid "Flat light green" msgstr "Lapos világoszöld" #: cola/themes.py:670 msgid "Flat light grey" msgstr "Lapos világosszürke" #: cola/themes.py:663 msgid "Flat light red" msgstr "Lapos világos vörös" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "Mappa" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Betűméret" #: cola/widgets/remote.py:197 msgid "Force" msgstr "Kényszerítés" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "Letöltés kényszerítése" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "Kényszeríti a letöltést?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "Felküldés kényszerítése" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "Kényszeríti a felküldést?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "Kényszeríti a letöltést innen: %s?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "Kényszeríti a felküldést ide: %s?" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "Formázó karakterlánc" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "Francia fordítás" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "A beolvasztási véglegesítés GPG-aláírása" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "Felhasználói felület témája" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "Információk gyűjtése erről: „%s”…" #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "Német fordítás" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "Véglegesítő üzenetsablon lekérdezése" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "Lefelé" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "Felfelé" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "Fájl megfogása…" #: cola/widgets/dag.py:848 msgid "Graph" msgstr "Grafikon" #: cola/widgets/main.py:354 msgid "Grep" msgstr "Grep" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "Újraalapozott vagy lekért nemrégiben?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Súgó" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "Súgó – Egyéni másolási műveletek" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "Súgó – Fájlok keresése" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "Súgó – git-cola-sequence-editor" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "Magas DPI" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "Történetböngésző" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "Magyar fordítás" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "Ikontéma" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "Üres helyek mellőzése" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "Üres helyek mennyiségváltozásának mellőzése" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "Sorvégi üres helyek változásának mellőzése" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "Egyéni minta mellőzése" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "Pontos fájlnév mellőzése" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "Fájlnév vagy minta mellőzése" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "Mellőz…" #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "Címkéket is" #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "Státuszútvonalak behúzása" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "Indonéz fordítás" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "Git Annex előkészítése" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "Git LFS előkészítése" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "Almodulok előkészítése" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "Szóközök a tabulátorok helyett" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "Interaktív újraalapozás" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "Érvénytelen revízió" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "Japán fordítás" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "Beolvasztási *.orig biztonsági tartalék megtartása" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "Jegyzék megtartása" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "Gyorsbillentyűk" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "Összehasonlító eszköz indítása" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "Könyvtár-összehasonlító eszköz indítása" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "Szerkesztő indítása" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "Terminál indítása" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" "Külső összehasonlító eszköz indítása\n" "Gyorsbillentyű: Ctrl+D" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "git-cola indítása" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "git-difftool indítása az előző verzión" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "git-difftool indítása a jelenlegi útvonalon" #: cola/icons.py:55 msgid "Light Theme" msgstr "Világos téma" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "Lista" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "Véglegesítő üzenet betöltése" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "Véglegesítő üzenet betöltése…" #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "Előző véglegesítő üzenet betöltése" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "Betöltés…" #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "Helyi" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Helyi ág" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "Helyi ág" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "Elrendezés zárolása" #: cola/widgets/dag.py:816 msgid "Log" msgstr "Napló" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "Karbantartó (2007 óta) és fejlesztő" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Beolvasztás" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "„%(revision)s” beolvasztása az ágba: „%(branch)s”" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "Beolvasztó eszköz" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Beolvasztás beszédessége" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "A beolvasztás sikertelen. Fel kell oldani az ütközéseket." #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "Beolvasztás a következőbe: „%s”" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "Beolvasztás a jelenlegi ágba" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "Beolvasztás…" #: cola/widgets/main.py:1177 msgid "Merging" msgstr "Beolvasztás" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "Üzenet" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "Hiányzó véglegesítési üzenet" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "Hiányzó adat" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "Hiányzó név" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "Hiányzó revízió" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "Hiányzó címkeüzenet" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "Módosított" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "További…" #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "Mozgatás lefelé" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "Mozgatás felfelé" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "Fájlok kukába dobása" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "Név" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "Az új távoli neve" #: cola/guicmds.py:147 cola/widgets/main.py:281 msgid "New Bare Repository..." msgstr "Új csupasz tároló…" #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "Új tároló…" #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "Eszköztár hozzáadása" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Új…" #: cola/actions.py:56 msgid "Next File" msgstr "Következő fájl" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "Nem" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "Nincs revízió megadva" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Nincs véglegesíthető változtatás.\n" "\n" "Legalább egy fájl ki kell szemelni, hogy véglegesíteni lehessen." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "Nincsenek véglegesítések ebben az ágban." #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "Nincs előrepörgetés" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "Nincs előrepörgetés" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Nincs tároló kiválasztva." #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "A nem előrepörgetett letöltés felülírja a helyi történetet!" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "A nem előrepörgetett felküldés felülírja a közzétett történetet!\n" "(Csinált előtte lekérést?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "Nincs véglegesíthető változás" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "Nincs teendő" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "A diff környezeti sorok száma" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Megnyitás" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Git tároló megnyitása" #: cola/widgets/submodules.py:48 msgid "Open Parent" msgstr "Szülő megnyitása" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "Szülő könyvtár megnyitása" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "Legutóbbiak megnyitása" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "Megnyitás az alapértelmezett alkalmazással" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "Megnyitás új ablakban" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "Megnyitás új ablakban…" #: cola/widgets/main.py:410 msgid "Open..." msgstr "Megnyitás…" #: cola/widgets/branch.py:354 msgid "Other branches" msgstr "Egyéb ágak" #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "Felülírás" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "Felülírja: „%s”?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "Felülírja a fájlt?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "Argumentumok feldolgozása parancsértelmezővel.\n" "A szóközökkel rendelkező lekérdezéseket \"dupla idézőjelekkel\" kell levédeni." #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "Részlegesen kiszemelve" #: cola/widgets/main.py:758 msgid "Paste" msgstr "Beillesztés" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "Alkalmazott folt(ok)" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "Útvonal" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "Klónozandó útvonal vagy URL ($VARS környezeti változó rendben)" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "Kiválasztás" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "Pixel alapú logikai kizáró vagy" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "Adjon meg ágnevet és revíziókifejezést is." #: cola/cmds.py:2297 msgid "Please select a file" msgstr "Jelöljön ki egy fájlt" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "Adjon meg egy nevet az új címke számára." #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "Jelöljön ki egy megcímkézendő revíziót." #: cola/widgets/commitmsg.py:417 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 "" "Adjon meg egy véglegesítési üzenetet.\n" "\n" "Egy jó véglegesítő üzenet formátuma:\n" "\n" "- Első sor: Egy mondat arról, hogy mit csinált.\n" "- Második sor: Üres\n" "- A többi sor: Leírás arról, hogy miért jó ez a változtatás.\n" #: cola/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "A jelenlegi ág fejét az új véglegesítésre állítja?" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "Lengyel fordítás" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "Alkalmazás és eldobás" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Beállítások" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "Előtag" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "Véglegesítési üzenet előkészítése" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "Az összes fájl kiszemelésének megakadályozása a „kiszemelés” számára, ha semmi sincs kijelölve" #: cola/actions.py:65 msgid "Previous File" msgstr "Előző fájl" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "Kérdés létrehozáskor" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "Kérdés, ha a felküldés új távoli ágat hozna létre" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "Tisztogatás" #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "Hiányzó bejegyzések tisztogatása" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "Lekérés" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "Lekérés…" #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Felküldés" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Felküldés…" #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Kilépés" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Újraalapozás" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "Újraalapozás erre: %s" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "Újraalapozás leállítva" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "Újraalapozás – beolvasztás helyett – a jelenlegi ágra" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "Újraalapozás" #: cola/widgets/main.py:118 msgid "Recent" msgstr "Legutóbbiak" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "Legutóbbi tárolók" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "Legutóbbi tárolók száma" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "Legutóbb módosított fájlok" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "Legutóbb módosított fájlok…" #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "Az eldobott félretett változatok helyreállítása nem lehetséges." #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Az elveszett véglegesítések helyreállítása nem biztos, hogy egyszerű." #: cola/widgets/main.py:751 msgid "Redo" msgstr "Mégis" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "Véglegesítési üzenetek történetének minimalizálása" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "Hivatkozó tároló" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "Hivatkozás URL" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "Klónozáskor alkalmazott hivatkozó tároló (választható)" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Frissítés" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "A beolvasztás visszautasítása, kivéve, ha a jelenlegi FEJ már friss, vagy a beolvasztást előrepörgetéssel lehet végezni" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Távoli" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "Távoli ág" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "Távoli ág törölve" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "Távoli git tárolók – dupla kattintás az átnevezéshez" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "Eltávolítás" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "Eltávolítja a legutóbbiak listájáról: %s?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "Elem eltávolítása" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "Távoli követett ágak eltávolítása, melyek már nem léteznek a távolin" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "Kijelöltek eltávolítása (Törlés)" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "Már nem létező elavult bejegyzések eltávolítása a tárolóból" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Átnevezés" #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "„%s” átnevezése" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "Ág átnevezése" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "Ág átnevezése…" #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "Létező ág átnevezése" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "Távoli átnevezése" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "Tároló átnevezése" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "Ág átnevezése" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "Átnevezi a(z) „%(current)s” távolit erre: „%(new)s”?" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "Kijelölt útvonalak átnevezése" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "Tároló nem található" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "Tároló: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Visszaállítás" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "Visszaállítja a(z) „%(branch)s” ágat erre: „%(revision)s”?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "Minden visszaállítása (elengedett módosítások megtartása)" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "Ág visszaállítása" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "Ág visszaállítása (nyugodt)" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "Ág visszaállítása és kiszemelés (kevert)" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "Visszaállítja az ágat?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "Elrendezés visszaállítása" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "Visszaállítja a munkafát és mindent visszaállít?" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "Visszaállítás és helyreállítás" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "Visszaállítja az ágat?" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "A(z) „%(branch)s” visszaállítása a(z) „%(revision)s” revízióra a véglegesítések elvesztéséhez vezet." #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "A megjelenési beállítások módosítása után indítsa újra az alkalmazást." #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "Munkafa helyreállítása" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "Munkafa helyreállítása és minden visszaállítása (teljes)" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "Munkafa helyreállítása és minden visszaállítása (elengedett módosítások megtartása)" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "Munkafa helyreállítása és minden visszaállítása (elengedett szerkesztések megtartása)" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "Munkafa helyreállítása és minden visszaállítása (beolvasztás)" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "Helyreállítja a munkát és mindent visszaállít?" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "Helyreállítja a munkafát erre: %s?" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "Helyreállítja a munkafát, visszaállít és megőrzi az elengedett szerkesztéseket?" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "Visszavonás" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "Összehasonlítási egység visszavonása" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "Összehasonlítási egység visszavonása…" #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "Visszavonja az összehasonlítási egységeket?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "Kijelölt sorok visszavonása" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "Kijelölt sorok visszavonása…" #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "Visszavonja a kijelölt sorokat?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "Nem véglegesített módosítások visszavonása" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "Visszavonja a nem véglegesített módosításokat?" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "Nem véglegesített szerkesztések visszavonása…" #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "Elengedett módosítások visszavonása" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "Visszavonja az elengedett módosításokat?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "Elengedett szerkesztések visszavonása…" #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "Visszavonja a nem véglegesített módosításokat?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "Visszavonja az elengedett módosításokat?" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "Nem véglegesített módosítások visszavonása a kijelölt útvonalakon" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "Elengedett módosítások visszavonása a kijelölt útvonalakon" #: cola/guicmds.py:320 msgid "Review" msgstr "Áttekintés" #: cola/widgets/main.py:597 msgid "Review..." msgstr "Áttekintés…" #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Revízió" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Revízió kifejezés:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Beolvasztani kívánt revízió" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "Átfogalmazás" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "Újraírja a közzétett véglegesítést?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "Futtatás" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "Futtatja ezt: „%s”?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "Futtatja ezt: %s?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "Futtatja a(z) „%s” parancsot?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "Parancs futtatása: %s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "Orosz fordítás" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "SHA-1" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "Biztonságos mód" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Mentés" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "Mentés archívumként" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "Mentés tar-archívumként/zipként…" #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "Felhasználói felület beállításainak mentése" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "Félretett változat mentése" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "A módosított állapot mentése új félretett változatként" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "A(z) „%(ref)s” a(z) „%(filename)s” helyről ide lett mentve: „%(destination)s”" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "Keresés" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "Szerzők keresése" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "Véglegesítési üzenetek keresése" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "Véglegesítők keresése" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "Dátumintervallum keresése" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "Összehasonlítások keresése" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "Keresés kifejezésre" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "Keresés útvonal alapján" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "Keresés rögzített szövegre" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "Keresés POSIX alapszintű reguláris kifejezéssel" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "Keresés POSIX bővített reguláris kifejezéssel" #: cola/widgets/main.py:507 msgid "Search..." msgstr "Keresés…" #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Kijelölés" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Összes kijelölése" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "Ág kijelölése áttekintéshez" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "Gyermek kijelölése" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "Véglegesítés kijelölése" #: cola/guicmds.py:136 msgid "Select Directory..." msgstr "Könyvtár kijelölése…" #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "Új távoli tároló kijelölése" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "Legújabb gyermek kijelölése" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "Legöregebb szülő kijelölése" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "Szülő kijelölése" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "Előző verzió kijelölése" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "Válasszon szülő mappát az új klón számára" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "Kimeneti könyvtár kijelölése" #: cola/widgets/selectcommits.py:182 msgid "Select output directory" msgstr "Kimeneti könyvtár kijelölése" #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "Foltfájl(ok) kijelölése…" #: cola/widgets/editremotes.py:434 msgid "Select repository" msgstr "Tároló kijelölése" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "Alapértelmezett tároló beállítása" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "Távoli tároló ág beállítása" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" "Az ágak és címkék rendezési sorrendjének beállítása.\n" "Váltás a dátum alapú és a verziónév alapú rendezési sorrend között." #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "Beállítás távoli tárolóként" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "Beállítások" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "Parancsértelmező argumentumai" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "Mozgatás lefelé" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "Mozgatás felfelé" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "Gyorsbillentyűk" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Diffstat megjelenítése a beolvasztás után" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "Teljes útvonal megjelenítése az ablakok címsorában" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "Súgó megjelenítse" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "Történet megjelenítése" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "Fájlok számának megjelentése az állapotcímekben" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "Súgó megjelenítése\n" "Gyorsbillentyű: ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "Sorok számának megjelenítése" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "A módosításokat érintő funkciók teljes környezetének megjelenítése" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "Változások megjelenítése ekkortól:" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "Egymás mellett" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Aláírás" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "Címke aláírása" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "A véglegesítés aláírása" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "Egyszerűsített kínai fordítás" #: cola/cmds.py:2527 msgid "Skip" msgstr "Kihagyás" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "Jelenlegi folt kihagyása" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "Könyvjelzők rendezése ábécésorrendben" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "Spanyol fordítás" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "Megadja a címke SHA-1 értékét" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "Megadja a címkeüzenetet" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "Megadja a címke nevét" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "Helyesírási javaslatok" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "Összevonás" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "Az beolvasztott véglegesítések összevonása egyetlen véglegesítésbe" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "Kiszemelés" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "Kiszemelés/elengedés" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "Összes kiszemelése/elengedése" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "Összehasonlítási egység kiszemelése" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Módosítottak kiszemelése" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "Módosítottak és nem követettek kiszemelése" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "Kijelöltek kiszemelése" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "Kijelölt sorok kiszemelése" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "Nem beolvasztottak kiszemelése" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "Nem követett változások kiszemelése" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "Kiszemelés és véglegesítés" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "Kiszemeli és véglegesíti?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "Ütközések kiszemelése" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "Kiszemeli az ütközéseket?" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "A kijelölt útvonalak kijelölése/elengedése véglegesítésre" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "Kiszemelve" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "Kiszemelés: %s" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "Interaktív újraalapozás indítása…" #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "A következő revíziótól" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "Félrerakás" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "Félrerakási jegyzék" #: cola/widgets/stash.py:79 msgid "Stash staged changes only" msgstr "Csak a kiszemelt módosítások félrerakása" #: cola/widgets/stash.py:75 msgid "Stash unstaged changes only, keeping staged changes" msgstr "Csak az elengedett módosítások félrerakása, a kiszemelt módosítások megtartása" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "Félrerakás…" #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "Állapot" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "Útvonalak követésének leállítása" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "Részmodul URL (lehet relatív is, pl.: ../tároló.git)" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "Követett részmodul ág (választható)" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "Részmodul útvonala a jelenlegi tárolóban (választható)" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "Almodulok" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "A beolvasztási véglegesítések összegzése" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "Összegzés" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Tabulátorszélesség" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Címke" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "Címke létrehozva" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Címkeüzenet…" #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "Címkealáírás lett kérve, de a címkeüzenet üres." #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "Címkék" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "Szövegszélesség" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "Az ág nem lesz többé elérhető." #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "Az ág visszaállítása ezzel a paranccsal: „git reset --mixed %s”" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "Az ág visszaállítása ezzel a paranccsal: „git reset --soft %s”" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "A véglegesítési üzenet meg lett tisztítva." #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "A(z) „%s” fájl létezik és felül lesz írva." #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "A következő fájlok törölve lesznek:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "A tároló vissza lesz állítva ezzel a paranccsal: „git reset --hard %s”" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "A tároló vissza lesz állítva ezzel a paranccsal: „git reset --keep %s”" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "A tároló vissza lesz állítva ezzel a paranccsal: „git reset --merge %s”" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "A revíziókifejezés nem lehet üres." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" "A részmodul így lesz hozzáadva:\n" "„%s”" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" "Az almodul frissítve lesz ezzel:\n" "„%s”" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "A munkafa helyre lesz állítva ezzel a paranccsal: „git read-tree --reset -u %s”" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "Ez nem vonható vissza. Megtisztítja a véglegesítési üzenetet?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "A véglegesítés már közzé lett téve.\n" "Ez a művelet felülírja a közzétett történetet.\n" "Valószínűleg nem ezt akarja tenni." #: cola/widgets/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "Ez a művelet kidobja a nem véglegesített módosításokat.\n" "Ezek a módosítások nem állíthatók vissza." #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Ez a művelet eltávolítja a nem véglegesített szerkesztések a kijelölt fájlokban.\n" "Ezek a módosítások nem állíthatók vissza." #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Ez a művelet eltávolítja az elengedett szerkesztéseket a kijelölt fájlokon.\n" "Ezek a módosítások nem állíthatók vissza." #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "A tároló épp újraalapozás alatt áll.\n" "Oldja fel az ütközéseket, véglegesítse a módosításokat és futtassa:\n" " Újralapozás > Folytatás" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "A tároló épp egy beolvasztás alatt áll.\n" "Oldja fel az ütközéseket és véglegesítse a változásokat." #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "Engedélyezés átváltása" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "Képösszehasonlítás átváltása" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "Elágazásszűrő átváltása" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "Útvonalszűrő átváltása" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Követett ág" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "Követett ágak" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "Tradicionális kínai (Tajvan) fordítás" #: cola/widgets/about.py:421 msgid "Translation" msgstr "Fordítás" #: cola/widgets/about.py:91 msgid "Translators" msgstr "Fordítók" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "Török fordítás" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "URL: %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "Ukrán fordítás" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "Nem lehet újraalapozni" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "Nem állítható be URL a(z) „%(name)s” számára: „%(url)s”" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "Visszavonás" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "Utolsó véglegesítés visszavonása" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "Visszavonja az utolsó véglegesítést?" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "Visszavonja a már közzétett véglegesítést?" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "Nem beolvasztottak" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "Elengedés" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "Összes elengedése" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "Összehasonlítási egység elengedése" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "Kijelöltek elengedése" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "Kijelölt sorok elengedése" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "Elengedés: %s" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "Kijelöltek követésének törlése" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "Nem követett" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "Követés törlése: %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "Összes almodul frissítése…" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Létező ág frissítése:" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "Almodul frissítése" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "Almodul frissítése…" #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "Almodulok frissítése" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "Frissíti az összes almodult?" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "Almodulok frissítése…" #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "Ezen almodul frissítése" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "Frissíti ezt az almodult?" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "Frissítés" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Felhasználónév" #: cola/widgets/about.py:89 msgid "Version" msgstr "Verzió" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "Nézet" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "Történet megjelenítése…" #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "A kijelölt útvonal történetének megjelenítése" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "Vizualizálás" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "Összes ág vizualizálása…" #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "Jelenlegi ág vizualizálása…" #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "Aláírásra kerüljön-e a címke (git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "Valóban kiszemeli és véglegesíti az összes módosított fájlt?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "Logikai kizáró vagy" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "Igen" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "Egy beolvasztás közepén van.\n" "Nem lehet javítani beolvasztás közben." #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "Nem lehet újraalapozni nem véglegesített módosításokkal." #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "Meg kell adni egy revíziót a beolvasztáshoz." #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "Meg kell adni egy revíziót a megjelenítéshez." #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "Nagyítás" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "Kicsinyítés" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "Nagyítás, hogy elférjen" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "parancssori argumentumok" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "hiba: a git nem hajtható végre" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "%s kilépési kód" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "végzetes: „%s” nem könyvtár. Adjon meg egy helyes útvonalat: --repo ." #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "git cola %s verzió" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "git-cola diff" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "git://git.példa.com/tároló.git" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "grep eredmény…" #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "hotkeys.html" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "útvonal/a/részmodulhoz" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "vX.Y.Z" #: cola/hidpi.py:43 msgid "x 1" msgstr "×1" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "×1,5" #: cola/hidpi.py:46 msgid "x 2" msgstr "×2" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "yyyy-MM-dd" #~ msgid "" #~ "\n" #~ "Commands\n" #~ "--------\n" #~ "pick = use commit\n" #~ "reword = use commit, but edit the commit message\n" #~ "edit = use commit, but stop for amending\n" #~ "squash = use commit, but meld into previous commit\n" #~ "fixup = like \"squash\", but discard this commit's log message\n" #~ "exec = run command (the rest of the line) using shell\n" #~ "\n" #~ "These lines can be re-ordered; they are executed from top to bottom.\n" #~ "\n" #~ "If you disable a line here THAT COMMIT WILL BE LOST.\n" #~ "\n" #~ "However, if you disable everything, the rebase will be aborted.\n" #~ "\n" #~ "Keyboard Shortcuts\n" #~ "------------------\n" #~ "? = show help\n" #~ "j = move down\n" #~ "k = move up\n" #~ "J = shift row down\n" #~ "K = shift row up\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "spacebar = toggle enabled\n" #~ "\n" #~ "ctrl+enter = accept changes and rebase\n" #~ "ctrl+q = cancel and abort the rebase\n" #~ "ctrl+d = launch difftool\n" #~ msgstr "" #~ "\n" #~ "Parancsok\n" #~ "---------\n" #~ "pick = véglegesítés felhasználása\n" #~ "reword = véglegesítés felhasználása, de a véglegesítési üzenet szerkesztésével\n" #~ "edit = véglegesítés felhasználása, de a javítás leállítása\n" #~ "squash = véglegesítés felhasználása, és beolvasztás az előző véglegesítésbe\n" #~ "fixup = mint a „squash”, de a véglegesítési naplóüzenet elvetése\n" #~ "exec = parancs (a sor hátralévő része) futtatása parancsértelmezőben\n" #~ "\n" #~ "A sorok újrarendezhetők; fentről lefelé lesznek végrehajtva.\n" #~ "\n" #~ "Egy sor letiltása itt a VÉGLEGESÍTÉS ELVESZTÉSÉT jelenti.\n" #~ "\n" #~ "Azonban, az összes letiltása az újraalapozás megszakításához vezet.\n" #~ "\n" #~ "Gyorsbillentyűk\n" #~ "------------------\n" #~ "? = súgó megjelenítése\n" #~ "j = mozgatás lefelé\n" #~ "k = mozgatás felfelé\n" #~ "J = sor lefelé mozgatása\n" #~ "K = sor felfelé mozgatása\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "szóköz = átváltás engedélyezése\n" #~ "\n" #~ "ctrl+enter = módosítások elfogadása és újraalapozás\n" #~ "ctrl+q = mégse és az újraalapozás megszakítása\n" #~ "ctrl+d = összehasonlító eszköz indítása\n" #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Már létezik egy ilyen nevű félretett változat: „%s”" #~ msgid "Delete selected branch?" #~ msgstr "Törli a kijelölt ágat?" #~ msgid "Error: Stash exists" #~ msgstr "Hiba: A félretett változat már létezik" #~ msgid "Hide Details.." #~ msgstr "Részletek elrejtése…" #~ msgid "Reset Branch Head" #~ msgstr "Ág fejének visszaállítása" #~ msgid "Reset Hard" #~ msgstr "Teljes visszaállítás" #~ msgid "Reset Merge" #~ msgstr "Beolvasztás visszaállítása" #~ msgid "Reset Soft" #~ msgstr "Nyugodt visszaállítás" #~ msgid "Reset Worktree" #~ msgstr "Munkafa visszaállítása" #~ msgid "Reset hard?" #~ msgstr "Elindítja a teljes visszaállítást?" #~ msgid "Reset merge?" #~ msgstr "Elindítja a beolvasztás visszaállítását?" #~ msgid "Reset soft?" #~ msgstr "Elindítja a nyugodt visszaállítást?" #~ msgid "Reset worktree?" #~ msgstr "Elindítja a munkafa visszaállítását?" #~ msgid "Select Repository..." #~ msgstr "Tároló kijelölése…" #~ msgid "Select manually..." #~ msgstr "Kézi kijelölés…" #~ msgid "Show Details..." #~ msgstr "Részletek megjelenítése…" #~ msgid "Show icon? (if available)" #~ msgstr "Megjeleníti az ikonokat (ha vannak)?" #~ msgid "The branch will be reset using \"git reset --hard %s\"" #~ msgstr "Az ág visszaállítása ezzel a paranccsal: „git reset --hard %s”" #~ msgid "The branch will be reset using \"git reset --merge %s\"" #~ msgstr "Az ág visszaállítása ezzel a paranccsal: „git reset --merge %s”" #~ msgid "The worktree will be reset using \"git reset --keep %s\"" #~ msgstr "A munkafa visszaáll ezzel a paranccsal: „git reset --keep %s”" #~ msgid "title" #~ msgstr "cím" #~ msgid "unknown" #~ msgstr "ismeretlen" git-cola-4.6.1/cola/i18n/id_ID.po000066400000000000000000003020661457126473700162550ustar00rootroot00000000000000# Indonesian translations for PACKAGE package. # Copyright (C) 2014 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Samsul Ma'arif , 2014. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-17 01:06-0700\n" "PO-Revision-Date: 2014-06-30 14:21+0700\n" "Last-Translator: Samsul Ma'arif \n" "Language-Team: Indonesian\n" "Language: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ASCII\n" "Content-Transfer-Encoding: 8bit\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " Drag dan drop atau gunakan tombol Tambah untuk menambah\n" " patch ke daftar\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr " - DAG" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr " commit yang lalu" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "\"%(branch)s\" telah dihapus dari \"%(remote)s\"." #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "\"%(command)s\" menghasilkan exit status \"%(status)d\"" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "\"%(command)s\" keluar dengan status %(status)d" #: cola/guicmds.py:156 #, fuzzy, python-format msgid "\"%s\" already exists" msgstr "Cabang \"%s\" sudah ada." #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "\"%s\" sudah ada, cola akan membuat direktori baru" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "\"%s\" berkas terpilih diperlukan." #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s: %(branch)s - Jelajah" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "%d hari lalu" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "%d jam lalu" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "%d menit lalu" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "%d patch diterapkan." #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d dilewati" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, fuzzy, python-format msgid "%s is not a Git repository." msgstr "Masukkan Repositori Git" #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "" #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "" #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: Berkas atau direktori tidak ada." #: cola/widgets/main.py:748 msgid "&Edit" msgstr "Sunting" #: cola/widgets/main.py:690 msgid "&File" msgstr "Berkas" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(Mengubah)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "*** Poin Cabang ***" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** Bak Pasir ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "" #: cola/widgets/diff.py:817 msgid "200%" msgstr "" #: cola/widgets/diff.py:814 msgid "25%" msgstr "" #: cola/widgets/diff.py:818 msgid "400%" msgstr "" #: cola/widgets/diff.py:815 msgid "50%" msgstr "" #: cola/widgets/diff.py:819 msgid "800%" msgstr "" #: cola/widgets/finder.py:118 msgid " ..." msgstr "" #: cola/cmds.py:1685 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 "" "Templat commit belum dikonfigurasi.\n" "Gunakan \"git config\" untuk menentukan \"commit.template\"\n" "agar mengarah ke templat commit." #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "Batal" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "Batalkan Aksi" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "Batalkan Merge" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Batalkan Penggabungan..." #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "Batalkan aksi?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Membatalkan merge saat ini akan menghilangkan *SEMUA* perubahan commit.\n" "Mengembalikan perubahan yang belum dicommit tidak dimungkinkan." #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "Batalkan merge saat ini?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "Tentang" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "Tentang git-cola" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "" #: cola/sequenceeditor.py:164 #, fuzzy msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "Commit perubahan stage\n" "Pintasan: Ctrl+Enter" #: cola/widgets/status.py:1376 #, fuzzy msgid "Action Name" msgstr "Aksi" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "Aksi" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "Aksi..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "Tambah" #: cola/widgets/bookmarks.py:469 #, fuzzy msgid "Add Favorite" msgstr "Tambahkan Hulu" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "Tambahkan Hulu" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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 "" "Tambah dan hapus repositori hulu menggunakan tombol \n" "Tambah(+) dan Hapus(-) pada sisi sebelah kiri.\n" "Hulu dapat diganti nama dengan memilih salah satu dari \n" "daftar dan tekan \"enter\", atau dobel-klik." #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "Tambahkan repositori git hulu" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "Tambahkan patch (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "Tambahkan hulu" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "Tambahkan ke .gitignore" #: cola/widgets/status.py:287 #, fuzzy msgid "Add to Git Annex" msgstr "Tambahkan ke .gitignore" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "Penambahan" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "Mahir" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "Usia" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "Semua Repositori" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "" #: cola/cmds.py:220 msgid "Amend" msgstr "Ubah" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "Ubah Commit" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Ubah Commit Terakhir" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "Ubah penerbitan commit?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "Mengubah" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "Aksi ini masih berjalan.\n" "Mengakhiri ini dapat menghilangkan data." #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "Tak bertanda, tag ringan akan dibuat.\n" "Buat tag tak bertanda?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "Terapkan" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "Terapkan Patch" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "Terapkan Patch..." #: cola/widgets/stash.py:66 #, fuzzy msgid "Apply and drop the selected stash (git stash pop)" msgstr "Terapkan stash terpilih" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "Terapkan stash terpilih" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "Argumen" #: cola/qtutils.py:886 msgid "Attach" msgstr "Lampirkan" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "Penulis" #: cola/widgets/about.py:90 #, fuzzy msgid "Authors" msgstr "Penulis" #: cola/hidpi.py:41 msgid "Auto" msgstr "" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "Auto-Wrap Baris" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "Regexp Dasar" #: cola/widgets/prefs.py:276 #, fuzzy msgid "Blame Viewer" msgstr "Penampil Diff Cabang" #: cola/widgets/browse.py:206 #, fuzzy msgid "Blame selected paths" msgstr "Sunting lokasi terpilih" #: cola/cmds.py:545 cola/widgets/status.py:283 #, fuzzy msgid "Blame..." msgstr "Tutup..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Cabang" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "Cabang \"%(branch)s\" tidak ada di \"%(remote)s\".\n" "Cabang hulu baru akan di publikasikan." #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "Cabang \"%s\" sudah ada." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "Penampil Diff Cabang" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "Cabang Sudah Ada" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Nama Cabang" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "Cabang: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 #, fuzzy msgid "Branches" msgstr "Cabang" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "Cabang..." #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "" #: cola/guicmds.py:52 msgid "Browse" msgstr "Ramban" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "Ramban Commit..." #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "Jelajah Cabang Saat ini..." #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "Jelajah Cabang Lain..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "Jelajah..." #: cola/widgets/main.py:87 msgid "Browser" msgstr "Jelajah" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "Ramban %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "Batalkan" #: cola/sequenceeditor.py:181 #, fuzzy msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "Commit perubahan stage\n" "Pintasan: Ctrl+Enter" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "Tidak dapat diubah" #: cola/cmds.py:560 #, fuzzy, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "Tidak dapat mengeksekusi \"%s\": silahkan konfigurasi editor Anda" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "Tidak dapat menjalankan \"%s\": silahkan konfigurasi peramban histori" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "Tidak dapat mengeksekusi \"%s\": silahkan konfigurasi editor Anda" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "Ubah Upstream" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "Periksa Ejaan" #: cola/widgets/prefs.py:286 #, fuzzy msgid "Check spelling" msgstr "Periksa Ejaan" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Checkout" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "Checkout Setelah Dibuat" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Checkout Cabang" #: cola/widgets/dag.py:413 #, fuzzy msgid "Checkout Detached HEAD" msgstr "Checkout Cabang" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 #, fuzzy msgid "Checkout as new branch" msgstr "Checkout Cabang" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Checkout..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "Cherry Pick" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "Commit Cherry-Pick" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "Cherry-Pick..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "Pilih Lokasi" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "Pilih mode ekspresi reguler \"git grep\"" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 #, fuzzy msgid "Clear Default Repository" msgstr "Repositori Saat Ini" #: cola/widgets/commitmsg.py:312 #, fuzzy msgid "Clear commit message" msgstr "Cari Pesan Commit" #: cola/widgets/commitmsg.py:309 #, fuzzy msgid "Clear commit message?" msgstr "Cari Pesan Commit" #: cola/widgets/commitmsg.py:63 #, fuzzy msgid "Clear..." msgstr "Tutup..." #: cola/widgets/clone.py:124 #, fuzzy msgid "Clone" msgstr "Clon...." #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 #, fuzzy msgid "Clone Repository" msgstr "Repositori Saat Ini" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Clon...." #: cola/widgets/clone.py:61 #, fuzzy, python-format msgid "Cloning repository at %s" msgstr "Repositori: %s" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Tutup" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "Tutup..." #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "Gulung semua" #: cola/sequenceeditor.py:371 #, fuzzy msgid "Command" msgstr "Commit" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "Commit" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "Commit gagal" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "Commit perubahan stage" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "Commit perubahan stage\n" "Pintasan: Ctrl+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "Ringkasan commit" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "Commit@@verb" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "Bandingkan" #: cola/difftool.py:102 #, fuzzy msgid "Compare All" msgstr "Bandingkan" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "" #: cola/widgets/main.py:169 msgid "Console" msgstr "Konsol" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Lanjutkan" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Salin" #: cola/widgets/status.py:269 #, fuzzy msgid "Copy Basename to Clipboard" msgstr "Salin Lokasi ke Papan klip" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 #, fuzzy msgid "Copy Leading Path to Clipboard" msgstr "Salin Lokasi ke Papan klip" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "Salin Lokasi ke Papan klip" #: cola/widgets/status.py:260 #, fuzzy msgid "Copy Relative Path to Clipboard" msgstr "Salin Lokasi ke Papan klip" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "Salin SHA-1" #: cola/widgets/status.py:738 #, fuzzy msgid "Copy..." msgstr "Salin" #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "Tidak dapat mengurai URL Git: \"%s\"" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Buat Cabang" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "Buat Patch" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "Buat Cabang Hulu" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 #, fuzzy msgid "Create Signed Commit" msgstr "Buat commit: %s" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "Buat Tag" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "Buat Tag..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "Buat Tag tak Bertanda" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "Buat cabang baru di hulu?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "Buat..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "Buat tag baru bernama \"%s\"" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "Repositori Saat Ini" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "" #: cola/widgets/status.py:274 #, fuzzy msgid "Customize..." msgstr "Tutup..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "DAG..." #: cola/icons.py:54 msgid "Dark Theme" msgstr "" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "Tanggal, Waktu" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Hapus" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "Hapus %d berkas?" #: cola/cmds.py:1016 #, fuzzy msgid "Delete Bookmark" msgstr "Markah" #: cola/cmds.py:1014 #, fuzzy msgid "Delete Bookmark?" msgstr "Markah" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Hapus Cabang" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "Hapus Berkas" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "Hapus Berkas...?" #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "Hapus Berkas?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "Hapus Hulu" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "Hapus Cabang Hulu" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "Hapus Cabang Hulu..." #: cola/widgets/toolbar.py:276 #, fuzzy msgid "Delete Toolbar" msgstr "Markah" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "Hapus hulu" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "Hapus hulu \"%s\"" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "Hapus hulu?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Hapus..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "Gagal menghapus \"%s\"" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "Penghapusan" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "Lepaskan" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "Diff" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "Diff Pada Predessor..." #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "Pilihan Diff" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "Alat Diff" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "Diff terpilih -> ini" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "Diff ini -> terpilih" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "Diffstat" #: cola/difftool.py:324 #, fuzzy msgid "Difftool" msgstr "Alat Diff" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "Direktori Sudah Ada" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "Tampilkan Berkas Tak Terlacak" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "Dokumentasi" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "Buang" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "Buang Stash" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "Buang Stash?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "Buang stash \"%s\"?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "Buang stash terpilih" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 #, fuzzy msgid "Edit" msgstr "Sunting" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "Sunting Rebase" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "Sunting Hulu" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "Sunting Hulu..." #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "Sunting lokasi terpilih" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "Sunting..." #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "Penyunting" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "Alamat Email" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "" #: cola/guicmds.py:332 cola/widgets/branch.py:478 #, fuzzy msgid "Enter New Branch Name" msgstr "Nama Cabang" #: cola/guicmds.py:146 #, fuzzy msgid "Enter a name for the new bare repo" msgstr "Masukkan nama untuk stash" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "Masukkan nama untuk stash" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "Error" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "Error Kloning" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "Erroe Membuat Cabang" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "Error Membuat Repositori" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "Error menghapus Cabang Hulu" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "Error Menyunting Berkas" #: cola/cmds.py:559 #, fuzzy msgid "Error Launching Blame Viewer" msgstr "Errot Menjalankan Peramban Histori" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "Errot Menjalankan Peramban Histori" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "Error membuat hulu \"%s\"" #: cola/models/stash.py:233 #, fuzzy msgid "Error creating stash" msgstr "Erroe Membuat Cabang" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Error menghapus hulu \"%s\"" #: cola/cmds.py:954 #, fuzzy, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "Menandai \"%(revision)s\" sebagai \"%(name)s\"" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "" #: cola/cmds.py:2987 cola/cmds.py:3033 #, fuzzy, python-format msgid "Error updating submodule %s" msgstr "Error membuat hulu \"%s\"" #: cola/cmds.py:3069 #, fuzzy msgid "Error updating submodules" msgstr "Error Menyunting Berkas" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "Error: Tidak dapat melakukan commit templat" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "Error: Commit templat belum dikonfigurasi" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Error: tidak bisa kloning \"%s\"" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "Error: tidak dapat membuat tag \"%s\"" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "Bentangkan semua" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "Ekspor Patch" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "Ekspor Patch..." #: cola/widgets/main.py:547 msgid "Expression..." msgstr "Ekspresi..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "Regexp Perluasan" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "Perluaskan penjelasan..." #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Hanya Fast Forward" #: cola/widgets/remote.py:181 #, fuzzy msgid "Fast-forward only" msgstr "Hanya Fast Forward" #: cola/widgets/bookmarks.py:90 #, fuzzy msgid "Favorite repositories" msgstr "Semua Repositori" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "" #: cola/widgets/remote.py:735 #, fuzzy msgid "Fetch" msgstr "Ambil..." #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "Fetch Cabang Terlacak" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "Ambil..." #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "Jelajah Berkas..." #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "Perbedaan Berkas" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "Berkas Tersimpan" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "Berkas disimpan di \"%s\"" #: cola/fsmonitor.py:530 #, fuzzy msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "inotify dinonaktifkan karena \"cola.inotify\" ialah false\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" #: cola/fsmonitor.py:145 #, fuzzy msgid "File system change monitoring: enabled.\n" msgstr "Pemberitahuan berkas diaktifkan.\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "Namaberkas" #: cola/widgets/dag.py:821 msgid "Files" msgstr "Berkas" #: cola/widgets/branch.py:837 #, fuzzy msgid "Filter branches..." msgstr "Ambil..." #: cola/widgets/status.py:1333 #, fuzzy msgid "Filter paths..." msgstr "Ambil..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 #, fuzzy msgid "Find Files" msgstr "Berkas" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "String Tetap" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "Lebar-Tetap Font" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "Perbaiki Commit Sebelumnya" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "" #: cola/themes.py:705 msgid "Flat dark green" msgstr "" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "" #: cola/themes.py:691 msgid "Flat dark red" msgstr "" #: cola/themes.py:656 msgid "Flat light blue" msgstr "" #: cola/themes.py:677 msgid "Flat light green" msgstr "" #: cola/themes.py:670 msgid "Flat light grey" msgstr "" #: cola/themes.py:663 msgid "Flat light red" msgstr "" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Ukuran Font" #: cola/widgets/remote.py:197 #, fuzzy msgid "Force" msgstr "Paksa Push" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "Paksa Fetch" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "Paksa Fetch?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "Paksa Push" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "Paksa Push?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "Paksa fetch dari %s?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "Paksa push ke %s?" #: cola/widgets/status.py:1376 #, fuzzy msgid "Format String" msgstr "String Tetap" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "Mengumpulkan info untuk \"%s\"..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "Ambil Templat Pesan Commit" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "Ke Bawah" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "Ke Atas" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "Ambil Berkas..." #: cola/widgets/dag.py:848 msgid "Graph" msgstr "Grafik" #: cola/widgets/main.py:354 msgid "Grep" msgstr "Grep" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "Sudahkan Anda rebase/tarik baru-baru ini?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Bantuan" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "Penjelajah Histori" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "Abaikan semua spasi" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "Abaikan perubahan jumlah spasi" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "Abaikan perubahan spasi pada EOL" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "" #: cola/widgets/gitignore.py:43 #, fuzzy msgid "Ignore exact filename" msgstr "Abaikan semua spasi" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "" #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "Sertakan tag " #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "rebase Interaktif" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "Revisi Salah" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "Biarkan *.orig Merge Backup" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "Pertahankan Index" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "Pintasan Papan Tik" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "Jalankan Alat Diff" #: cola/widgets/dag.py:401 #, fuzzy msgid "Launch Directory Diff Tool" msgstr "Jalankan Alat Diff" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "Jalankan Penyunting" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "Jalankan Terminal" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "Jalankan git-cola" #: cola/widgets/browse.py:173 #, fuzzy msgid "Launch git-difftool against previous versions" msgstr "Jalankan git-difftool pada versi sebelumnya." #: cola/widgets/browse.py:165 #, fuzzy msgid "Launch git-difftool on the current path" msgstr "Jalankan git-difftool pada lokasi saat ini." #: cola/icons.py:55 msgid "Light Theme" msgstr "" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "Muat Pesan Commit" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "Muat Pesan Commit..." #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "Muat Pesan Commit Sebelumnya" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "Memuat..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "Lokal" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Cabang Lokal" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "Cabang Lokal" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "Kunci Tata Letak" #: cola/widgets/dag.py:816 msgid "Log" msgstr "Log" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Merge" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "Merge \"%(revision)s\" ke \"%(branch)s\"" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "Alat Merger" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Verbositas Merge" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "" #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "Merge ke \"%s\"" #: cola/widgets/branch.py:242 #, fuzzy msgid "Merge into current branch" msgstr "Jelajah Cabang Saat ini..." #: cola/widgets/main.py:359 msgid "Merge..." msgstr "Gabung..." #: cola/widgets/main.py:1177 msgid "Merging" msgstr "Menggabungkan" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "Pesan" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "Pesan Commit Tidak Ada" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "Data Hilang" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "Nama Tidak Ditemukan" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "Revisi Tidak Ditemukan" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "Pesan Tag Tidak Ditemukan" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "Berubah" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "Lanjut..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "Pindah Ke Bawah" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "Pindah Ke Atas" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "Nama" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "Nama untuk hulu baru" #: cola/guicmds.py:147 cola/widgets/main.py:281 #, fuzzy msgid "New Bare Repository..." msgstr "Repositori Baru..." #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "Repositori Baru..." #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Baru..." #: cola/actions.py:56 #, fuzzy msgid "Next File" msgstr "Pilih Berkas" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "Tidak" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "Revisi tidak Ditentukan" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Tidak ada perubahan untuk dicommit.\n" "\n" "Anda harus menstag setidaknya 1 berkas sebelum Anda commit." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "Tidak ada commit di cabang ini." #: cola/widgets/merge.py:63 #, fuzzy msgid "No fast forward" msgstr "Hanya Fast Forward" #: cola/widgets/remote.py:190 #, fuzzy msgid "No fast-forward" msgstr "Hanya Fast Forward" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Tidak ada repositori terpilih" #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "Nonfast-forward fetch menimpa histori lokal!" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "Non-fast-forward push menimpa histori terpublikasi!\n" "(Apakah sudah ditarik sebelumnya?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "Tidak ada yang dicommit" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "Tak ada yang perlu dilakukan" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Jumlah Baris Context Diff" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Buka" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Bukan Repositori Git" #: cola/widgets/submodules.py:48 #, fuzzy msgid "Open Parent" msgstr "Buka yang Terkini" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "Bukan Direktori di Atasnya" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "Buka yang Terkini" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "Buka dengan Aplikasi Bawaan" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "Bukan di Jendela Baru" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "Buka di Jendela Baru..." #: cola/widgets/main.py:410 msgid "Open..." msgstr "Buka..." #: cola/widgets/branch.py:354 #, fuzzy msgid "Other branches" msgstr "Ambil..." #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "Timpa" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "Timpa \"%s\"" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "Timpa Berkas?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "Uraikan argumen menggunakan sebuah shell.\n" "Queri dengan spasi memerlukan \"tanda kutip dua\"." #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "Sebagian Stagged" #: cola/widgets/main.py:758 msgid "Paste" msgstr "" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "Patch Diterapkan" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "Lokasi atau URL untuk kloning (Env. $VARS oke)" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "Silahkan tentukan nama cabang dan ekspresi revisi." #: cola/cmds.py:2297 msgid "Please select a file" msgstr "Silahkan pilih berkas" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "Silahkan tentukan nama untuk tag baru." #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "Tentukan revisi untuk di-tag" #: cola/widgets/commitmsg.py:417 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 "" "Silahkan lengkapi pesan commit.\n" "\n" "Pesan commit yang baik memiliki format berikut:\n" "\n" "- Baris pertama: Jelaskan dalam satu kalimat apa yang telah Anda lakukan.\n" "- Baris kedua: Kosong\n" "- Baris selanjutnya : Jelaskan mengapa perubahan ini bagus.\n" #: cola/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Preferensi" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "Awalan" #: cola/widgets/main.py:341 #, fuzzy msgid "Prepare Commit Message" msgstr "Cari Pesan Commit" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "" #: cola/actions.py:65 msgid "Previous File" msgstr "" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "" #: cola/widgets/remote.py:170 #, fuzzy msgid "Prompt when pushing creates new remote branches" msgstr "Buat cabang baru di hulu?" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "" #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 #, fuzzy msgid "Pull" msgstr "Tarik..." #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "Tarik..." #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Push" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Tekan..." #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Tutup" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Rebase" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "Rebase ke %s" #: cola/cmds.py:2105 #, fuzzy msgid "Rebase stopped" msgstr "Rebase" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "Me-rebase" #: cola/widgets/main.py:118 #, fuzzy msgid "Recent" msgstr "Reset" #: cola/widgets/bookmarks.py:92 #, fuzzy msgid "Recent repositories" msgstr "Semua Repositori" #: cola/widgets/prefs.py:279 #, fuzzy msgid "Recent repository count" msgstr "Semua Repositori" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "Berkas yang Baru Dimodifikasi" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "Berkas Baru Dimodifikasi..." #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "Tidak mungkin mengembalikan stash yang dibuang." #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Mengembalikan commit yang hilang tidak akan mudah." #: cola/widgets/main.py:751 msgid "Redo" msgstr "" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Segarkan" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Hulu" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "Cabang Hulu" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "Cabang Hulu Dihapus" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "Repositori hulu git - dobel-klik untuk mengganti nama" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "Hapus" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "" #: cola/widgets/toolbar.py:321 #, fuzzy msgid "Remove Element" msgstr "Hapus" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "Hapus yang terpilih (Hapus)" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Ganti nama" #: cola/cmds.py:1153 #, fuzzy, python-format msgid "Rename \"%s\"" msgstr "Ganti nama" #: cola/widgets/branch.py:268 #, fuzzy msgid "Rename Branch" msgstr "Cabang Hulu" #: cola/widgets/main.py:584 #, fuzzy msgid "Rename Branch..." msgstr "Cabang Hulu" #: cola/guicmds.py:329 #, fuzzy msgid "Rename Existing Branch" msgstr "Perbarui Cabang yang Ada:" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "Ganti Nama Hulu" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 #, fuzzy msgid "Rename Repository" msgstr "Repositori Saat Ini" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 #, fuzzy msgid "Rename branch" msgstr "Cabang Hulu" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "Ganti nama hulu \"%(current)s\" ke \"%(new)s\"?" #: cola/widgets/browse.py:159 #, fuzzy msgid "Rename selected paths" msgstr "Sunting lokasi terpilih" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "Repositori: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Reset" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "Atur Ulang \"%(branch)s\" ke \"%(revision)s\"?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "Atur Ulang Cabang" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "Atur Ulang Cabang?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "Mengatur ulang \"%(branch)s\" ke \"%(revision)s\" akan menghilangkan commit." #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "Kembalikan Area Diff" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "Kembalikan Area Diff..." #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "Kembalikan Area Diff?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "Kembalikan Baris Terpilih" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "Kembalikan Baris Terpilih..." #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "Kembalikan Baris Terpilih?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "Kembalikan Perubahan Tak Tercommit" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "Kembalikan Perubahan Tak Tercommit?" #: cola/cmds.py:2247 #, fuzzy msgid "Revert Uncommitted Edits..." msgstr "Kembalikan Suntingan Belum dicommmit..." #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "Kembalikan Perubahan Belum Distag" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "Kembalikan Perubahan Belum Distag?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "Kembalikan Suntingan tak distag..." #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "Kembalikan perubahan tak tercommit?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "Kembalikan perubahan belum distag?" #: cola/widgets/browse.py:190 #, fuzzy msgid "Revert uncommitted changes to selected paths" msgstr "Kembalikan perubahan ke lokasi terpilih." #: cola/widgets/browse.py:181 #, fuzzy msgid "Revert unstaged changes to selected paths" msgstr "Kembalikan perubahan ke lokasi terpilih." #: cola/guicmds.py:320 msgid "Review" msgstr "Tinjau" #: cola/widgets/main.py:597 msgid "Review..." msgstr "Pratampil..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Revisi" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Ekspresi Revisi:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Revisi untuk Dimerge" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "Tulis Ulang Penerbit Commit?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "Jalankan" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "Jalankan \"%s\"?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "Jalankan %s?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "Jalankan perintah \"%s\"?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "Menjalankan perintah: %s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "" #: cola/sequenceeditor.py:372 #, fuzzy msgid "SHA-1" msgstr "Salin SHA-1" #: cola/widgets/prefs.py:205 #, fuzzy msgid "Safe Mode" msgstr "Stage Berubah" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Simpan" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "Simpan Arsip" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "Simpan Sebagai Tarball/Zip.." #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "Simpan Pengaturan GUI" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "Simpan Stash" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "Simpan perubahan ke stash baru" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "Simpan \"%(filename)s\" dari \"%(ref)s\" ke \"%(destination)s\"" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "Cari" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "Cari Penulis" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "Cari Pesan Commit" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "Cari Commiter" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "Cari Rentang Tanggal" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "Cari Diff" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "Cari berdasarkan Ekspresi" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "Cari berdasarkan Lokasi" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "Cari teks tetap" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "Cari menggunakan ekspresi reguler POSIX dasar" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "Cari menggunakan ekspresi reguler POSIX perluasan" #: cola/widgets/main.py:507 msgid "Search..." msgstr "Cari..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Pilih" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Pilih Semua" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "Pilih Cabang untuk Ditinjau" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "Pilih Anakan" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "Pilih Commit" #: cola/guicmds.py:136 #, fuzzy msgid "Select Directory..." msgstr "Pilih Repository..." #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "Pilih Upstream Baru" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "Pilih Anakan Terbaru" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "Pilih Indukan Tertua" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "Pilih Indukan" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "Pilih Versi Sebelumnya" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "Pilih direktori di atasnya untuk klon baru" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 #, fuzzy msgid "Select output dir" msgstr "Pilih Commit" #: cola/widgets/selectcommits.py:182 #, fuzzy msgid "Select output directory" msgstr "Pilih Repository..." #: cola/widgets/diff.py:1770 #, fuzzy msgid "Select patch file(s)..." msgstr "Pilih berkas patch..." #: cola/widgets/editremotes.py:434 #, fuzzy msgid "Select repository" msgstr "Pilih Repository..." #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 #, fuzzy msgid "Set Default Repository" msgstr "Pilih Repository..." #: cola/widgets/branch.py:291 #, fuzzy msgid "Set Upstream Branch" msgstr "Pilih Upstream Baru" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 #, fuzzy msgid "Set upstream" msgstr "Pilih Upstream Baru" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "Pengaturan" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "Argumen shell" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "Pintasan" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Tampilkan Diffstat setelah Merge" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 #, fuzzy msgid "Show Help" msgstr "Bantuan" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "Tunjukan sejarah" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "Tampilkan seluruh sekitar fungsi perubahan" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "Menampilkan perubahan sejak" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Sign Off" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "Tandai Tag" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "Tanda tangani commit ini" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "" #: cola/cmds.py:2527 msgid "Skip" msgstr "" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "Lewati Cabang Saat Ini" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "Tentukan SHA-1 untuk di-tag" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "Tentukan pesan tag" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "Tentukan nama tag" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "Saran Ejaan" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "Squash" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "Stage" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "Stage / Unstage" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "Stage Area Diff" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Stage Berubah" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "Stage Terpilih" #: cola/widgets/diff.py:1050 #, fuzzy msgid "Stage Selected Lines" msgstr "Stage Batis &Terpilih" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "Stage Tak Termerge" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "Stage Tak Terlacak" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "Stage dan Commit" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "Stage dan commit?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 #, fuzzy msgid "Stage conflicts" msgstr "Stage dan commit?" #: cola/cmds.py:2517 #, fuzzy msgid "Stage conflicts?" msgstr "Stage dan commit?" #: cola/widgets/browse.py:146 #, fuzzy msgid "Stage/unstage selected paths for commit" msgstr "Stage lokasi terpilih untuk commit" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "Stagged" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "Staging: %s" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "Mulai Rebase Interaktif..." #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "Memulai Revisi" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "Stash" #: cola/widgets/stash.py:79 #, fuzzy msgid "Stash Index" msgstr "Stash" #: cola/widgets/stash.py:79 #, fuzzy msgid "Stash staged changes only" msgstr "Commit perubahan stage" #: cola/widgets/stash.py:75 #, fuzzy msgid "Stash unstaged changes only, keeping staged changes" msgstr "Kembalikan perubahan ke lokasi terpilih." #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "Stash..." #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "Status" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "Hentikan melacak lokasi" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "Ringkasan Merge Commit" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "Ringkasan" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Lebar Tab" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Tag" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "Tag Telah Dibuat" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Pesan tag..." #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "Penandaan tag diperlukan tetapi pesan tag kosong." #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "Lebar Teks" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "" #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "" #: cola/widgets/commitmsg.py:310 #, fuzzy msgid "The commit message will be cleared." msgstr "Berkas berikut akan dihapus:" #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "Berkas \"%s\" sudah ada dan akan ditimpa." #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "Berkas berikut akan dihapus:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "Ekspresi revisi tidak boleh kosong." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "Commit ini telah diterbitkan.\n" "Operasi ini akan menulis ulang sejarah publikasi.\n" "Mungkin Anda tidak ingin melakukan ini." #: cola/widgets/diff.py:1232 #, fuzzy msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "Operasi ini akan menghilangkan perubahan tak tercommit.\n" "Perubahan ini tidak dapat direkoveri." #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Operasi ini akan menghilangkan perubahan tak tercommit.\n" "Perubahan ini tidak dapat direkoveri." #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Operasi ini membuang perubahan belum distag.\n" "Perubahan ini tidak dapat dikembalikan" #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "Repositori ini sedang direbase.\n" "Perbaiki konflik, commitkan perubahan, dan jalankan:\n" " Rebase > Lanjutkan" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "Repositori ini sedang dimerge.\n" "Perbaiki konflik dan commitkan perubahan." #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Melacak Cabang" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "Melacak cabang" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "URL: %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "Tak termerjer" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "Unstage" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "Unstage Semua" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "Unstage Area Diff" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "Unstage Terpilih" #: cola/widgets/diff.py:1015 #, fuzzy msgid "Unstage Selected Lines" msgstr "Unstage Baris &Terpilih" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "Unstaging: %s" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "Jangan Lacak Terpilih" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "Tak Terlacak" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "Untracking: %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Perbarui Cabang yang Ada:" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "" #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "Sedang memperbarui" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Nama Pengguna" #: cola/widgets/about.py:89 #, fuzzy msgid "Version" msgstr "Revisi" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "Tampil" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "Tampilkan Histori..." #: cola/widgets/browse.py:138 #, fuzzy msgid "View history for selected paths" msgstr "Tampilkan histori untuk lokasi terpilih" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "Visualisasikan" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "Visualisasikan Semua Cabang..." #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "Visualisasikan Cabang Saat ini..." #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "Kalau menandai tag (git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "Apakah Anda ingin menstage dan commit semua berkas yang berubah?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "Anda sedang melakukan merjer.\n" "Tidak dapat mengubah ketika merjer" #: cola/cmds.py:2072 #, fuzzy msgid "You cannot rebase with uncommitted changes." msgstr "Kembalikan perubahan tak tercommit?" #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "Anda harus tentukan revisi untuk dimerge." #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "Anda harus tentukan revisi untuk ditampilkan." #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "Perbesar" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "Perkecil" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "Zoom agar Sesuai" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "argumen baris-perintah" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "kode keluar %s" #: cola/app.py:300 #, fuzzy, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "fatal: \"%s\" bukan direktori. Silahkan tentukan --repo ." #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "git cola versi %s" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "git-cola diff" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "hasil grep..." #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "hotkeys.html" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "vX.Y.Z" #: cola/hidpi.py:43 msgid "x 1" msgstr "" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "" #: cola/hidpi.py:46 msgid "x 2" msgstr "" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "dd-MM-yyyy" #, fuzzy #~ msgid "\"%s\" returned exit status %d" #~ msgstr "\"%(command)s\" keluar dengan status %(status)d" #~ msgid "\"git commit\" returned exit code %s" #~ msgstr "\"git commit\" returned exit code %s" #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Stash dengan nama \"%s\" sudah ada" #~ msgid "Already up-to-date." #~ msgstr "Sudah up-to-date." #~ msgid "Apply Diff Selection to Work Tree" #~ msgstr "Terapkan Diff Terpilih ke Work Tree" #~ msgid "Bookmarks" #~ msgstr "Markah" #~ msgid "Bookmarks..." #~ msgstr "Markah..." #~ msgid "Commit failed: %s" #~ msgstr "Commit gagal: %s" #~ msgid "Created commit: %s" #~ msgstr "Buat commit: %s" #, fuzzy #~ msgid "Delete selected branch?" #~ msgstr "Hapus Cabang Hulu" #~ msgid "Enter Git Repository" #~ msgstr "Masukkan Repositori Git" #, fuzzy #~ msgid "Error %s" #~ msgstr "Error: %s" #~ msgid "Error: Stash exists" #~ msgstr "Error: Stash sudah ada" #~ msgid "Errors: %s" #~ msgstr "Error: %s" #~ msgid "Exit code: %s" #~ msgstr "Kode exit: %s" #~ msgid "Fast Forward Only " #~ msgstr "Hanya Fast Forward" #~ msgid "Filter" #~ msgstr "Saring" #~ msgid "GPG-signed" #~ msgstr "tandatangan-GPG" #, fuzzy #~ msgid "Local Branches" #~ msgstr "Cabang Lokal" #~ msgid "No files selected for checkout from HEAD." #~ msgstr "Tidak ada berkas terpilih untuk checkout dari HEAD." #, fuzzy #~ msgid "On Debian-based systems try: sudo apt-get install python-pyinotify" #~ msgstr "Pada sistem Debian: sudo apt-get install python-pyinotify" #~ msgid "Options" #~ msgstr "Pilihan" #~ msgid "" #~ "Output:\n" #~ "%s" #~ msgstr "" #~ "Keluaran:\n" #~ "%s" #~ msgid "Output: %s" #~ msgstr "Keluaran: %s" #~ msgid "PATCH %(current)d/%(count)d" #~ msgstr "PATCH %(current)d/%(count)d" #~ msgid "Path to git repository" #~ msgstr "Lokasi repositori git" #~ msgid "Process Diff Hunk" #~ msgstr "Proses Area Diff" #~ msgid "Process Selection" #~ msgstr "Proses Pilihan" #, fuzzy #~ msgid "Remote Branches" #~ msgstr "Cabang Hulu" #~ msgid "Remove selected paths from the staging area" #~ msgstr "Buang lokasi terpilih dari staging area" #~ msgid "Rename remote?" #~ msgstr "Ganti nama hulu?" #, fuzzy #~ msgid "Reset Branch Head" #~ msgstr "Atur Ulang Cabang" #, fuzzy #~ msgid "Reset Hard" #~ msgstr "Atur Ulang Cabang" #, fuzzy #~ msgid "Reset Merge" #~ msgstr "Revisi untuk Dimerge" #, fuzzy #~ msgid "Reset Soft" #~ msgstr "Reset" #, fuzzy #~ msgid "Reset hard?" #~ msgstr "Atur Ulang Cabang?" #, fuzzy #~ msgid "Reset merge?" #~ msgstr "Atur Ulang Cabang?" #, fuzzy #~ msgid "Reset soft?" #~ msgstr "Reset" #~ msgid "Revert Uncommitted Changes..." #~ msgstr "Kembalikan Perubahan Tak Tercommit..." #~ msgid "Select File" #~ msgstr "Pilih Berkas" #~ msgid "Select Repository..." #~ msgstr "Pilih Repository..." #~ msgid "Select file from \"%s\"" #~ msgstr "Pilih berkas dari \"%s\"" #~ msgid "Select manually..." #~ msgstr "Pilih secara manual..." #, fuzzy #~ msgid "Show Details..." #~ msgstr "Hapus Berkas...?" #~ msgid "Staging Area" #~ msgstr "Area Stagnan" #~ msgid "Summary:" #~ msgstr "Ringkasan:" #~ msgid "" #~ "This PyQt4 does not include QtWebKit.\n" #~ "The keyboard shortcuts feature is unavailable." #~ msgstr "" #~ "PyQt4 ini tidak menyertakan QtWebKit.\n" #~ "Fitur pintasan papan tik tak tersedia." #~ msgid "Updating..." #~ msgstr "Memperbarui..." #~ msgid "" #~ "file notification: disabled\n" #~ "Note: install pywin32 to enable.\n" #~ msgstr "" #~ "berkas pemberitahuan: dinonaktifkan\n" #~ "Catatan: install pywin32 untuk mengaktifkan.\n" #~ msgid "git clone returned exit code %s" #~ msgstr "git clone keluar kode %s" #~ msgid "git tag returned exit code %s" #~ msgstr "git tag menghasilkan kode exit %s" #~ msgid "inotify enabled." #~ msgstr "inotify diaktifkan." #~ msgid "" #~ "inotify: disabled\n" #~ "Note: install python-pyinotify to enable inotify.\n" #~ msgstr "" #~ "inotify: dinonaktifkan\n" #~ "Catatan: install python-pyinotify untuk mengaktifkan inotify.\n" #~ msgid "unknown" #~ msgstr "tidak diketahui" git-cola-4.6.1/cola/i18n/it.po000066400000000000000000003527711457126473700157310ustar00rootroot00000000000000# Translation of git-cola to Italian # Copyright (C) 2007 Shawn Pearce at el. # This file is distributed under the same license as the git-cola package. # Paolo Ciarrocchi , 2007 # Michele Ballabio , 2007. # msgid "" msgstr "" "Project-Id-Version: git-cola VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-17 01:06-0700\n" "PO-Revision-Date: 2008-03-12 22:12+0100\n" "Last-Translator: David Aguilar \n" "Language-Team: Italian\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr "" #: cola/widgets/recent.py:52 #, fuzzy msgid " commits ago" msgstr "Messaggio di fusione:" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "" #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "" #: cola/guicmds.py:156 #, fuzzy, python-format msgid "\"%s\" already exists" msgstr "Il ramo '%s' esiste già." #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "" #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, fuzzy, python-format msgid "%s is not a Git repository." msgstr "Archivio Git" #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "" #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "" #: cola/cmds.py:1662 #, 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/widgets/main.py:748 msgid "&Edit" msgstr "Modifica" #: cola/widgets/main.py:690 #, fuzzy msgid "&File" msgstr "&File" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/diff.py:816 msgid "100%" msgstr "" #: cola/widgets/diff.py:817 msgid "200%" msgstr "" #: cola/widgets/diff.py:814 msgid "25%" msgstr "" #: cola/widgets/diff.py:818 msgid "400%" msgstr "" #: cola/widgets/diff.py:815 msgid "50%" msgstr "" #: cola/widgets/diff.py:819 msgid "800%" msgstr "" #: cola/widgets/finder.py:118 msgid " ..." msgstr "" #: cola/cmds.py:1685 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:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 #, fuzzy msgid "Abort" msgstr "Interruzione" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 #, fuzzy msgid "Abort Action" msgstr "Interruzione" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 #, fuzzy msgid "Abort Merge" msgstr "Interrompi fusione..." #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Interrompi fusione..." #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 #, 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/cmds.py:186 msgid "Aborting the current merge?" msgstr "" #: cola/widgets/about.py:88 cola/widgets/main.py:531 #, fuzzy msgid "About" msgstr "Informazioni su %s" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/status.py:1376 #, fuzzy msgid "Action Name" msgstr "Opzioni" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 #, fuzzy msgid "Actions" msgstr "Opzioni" #: cola/widgets/commitmsg.py:107 #, fuzzy msgid "Actions..." msgstr "Opzioni..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "" #: cola/widgets/bookmarks.py:469 #, fuzzy msgid "Add Favorite" msgstr "Remoto" #: cola/widgets/editremotes.py:371 #, fuzzy msgid "Add Remote" msgstr "Remoto" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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:78 #, fuzzy msgid "Add new remote git repository" msgstr "%s non è un archivio Git." #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "" #: cola/widgets/editremotes.py:430 #, fuzzy msgid "Add remote" msgstr "Remoto" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 #, fuzzy msgid "Additions" msgstr "Opzioni" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "" #: cola/widgets/prefs.py:441 #, fuzzy msgid "All Repositories" msgstr "Tutti gli archivi" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "" #: cola/cmds.py:220 msgid "Amend" msgstr "" #: cola/widgets/commitmsg.py:470 #, fuzzy msgid "Amend Commit" msgstr "Correggi l'ultima revisione" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Correggi l'ultima revisione" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 #, fuzzy msgid "Apply" msgstr "Apple" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "" #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "" #: cola/qtutils.py:886 msgid "Attach" msgstr "" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 #, fuzzy msgid "Author" msgstr "Autore:" #: cola/widgets/about.py:90 #, fuzzy msgid "Authors" msgstr "Autore:" #: cola/hidpi.py:41 msgid "Auto" msgstr "" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "" #: cola/widgets/prefs.py:276 #, fuzzy msgid "Blame Viewer" msgstr "Mostra file" #: cola/widgets/browse.py:206 #, fuzzy msgid "Blame selected paths" msgstr "Rinomina ramo" #: cola/cmds.py:545 cola/widgets/status.py:283 #, fuzzy msgid "Blame..." msgstr "Rinomina" #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Ramo" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/createbranch.py:256 #, fuzzy, python-format msgid "Branch \"%s\" already exists." msgstr "Il ramo '%s' esiste già." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 #, fuzzy msgid "Branch Exists" msgstr "Rami" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Nome del ramo" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, fuzzy, python-format msgid "Branch: %s" msgstr "Ramo:" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 #, fuzzy msgid "Branches" msgstr "Ramo" #: cola/widgets/main.py:552 #, fuzzy msgid "Branches..." msgstr "Rami" #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "" #: cola/guicmds.py:52 #, fuzzy msgid "Browse" msgstr "Esplora" #: cola/guicmds.py:52 #, fuzzy msgid "Browse Commits..." msgstr "Esplora" #: cola/widgets/main.py:513 #, fuzzy msgid "Browse Current Branch..." msgstr "Esplora i file del ramo attuale" #: cola/widgets/main.py:519 #, fuzzy msgid "Browse Other Branch..." msgstr "Esplora i file del ramo..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 #, fuzzy msgid "Browse..." msgstr "Esplora" #: cola/widgets/main.py:87 #, fuzzy msgid "Browser" msgstr "Esplora" #: cola/widgets/browse.py:590 #, fuzzy, python-format msgid "Browsing %s" msgstr "Aggiunta di %s in corso" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "Annulla" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" #: cola/cmds.py:253 #, fuzzy msgid "Cannot Amend" msgstr "Impossibile scrivere icona:" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Attiva" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "Attiva dopo la creazione" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Attiva ramo" #: cola/widgets/dag.py:413 #, fuzzy msgid "Checkout Detached HEAD" msgstr "Attiva ramo" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 #, fuzzy msgid "Checkout as new branch" msgstr "Attiva ramo" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Attiva..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/guicmds.py:72 #, fuzzy msgid "Cherry-Pick Commit" msgstr "Copia revisione" #: cola/widgets/main.py:324 #, fuzzy msgid "Cherry-Pick..." msgstr "Attiva..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 #, fuzzy msgid "Choose Paths" msgstr "Scegli %s" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 #, fuzzy msgid "Clear Default Repository" msgstr "Crea nuovo archivio" #: cola/widgets/commitmsg.py:312 #, fuzzy msgid "Clear commit message" msgstr "Messaggio di fusione:" #: cola/widgets/commitmsg.py:309 #, fuzzy msgid "Clear commit message?" msgstr "Messaggio di fusione:" #: cola/widgets/commitmsg.py:63 #, fuzzy msgid "Clear..." msgstr "Clona..." #: cola/widgets/clone.py:124 msgid "Clone" msgstr "Clona" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 #, fuzzy msgid "Clone Repository" msgstr "Clona archivio esistente" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Clona..." #: cola/widgets/clone.py:61 #, fuzzy, python-format msgid "Cloning repository at %s" msgstr "Clona archivio esistente" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Chiudi" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 #, fuzzy msgid "Close..." msgstr "Clona..." #: cola/widgets/recent.py:69 #, fuzzy msgid "Collapse all" msgstr "Chiudi" #: cola/sequenceeditor.py:371 #, fuzzy msgid "Command" msgstr "Revisione:" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 #, fuzzy msgid "Commit" msgstr "Revisione:" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 #, fuzzy msgid "Commit failed" msgstr "Impossibile creare una nuova revisione." #: cola/widgets/commitmsg.py:62 #, fuzzy msgid "Commit staged changes" msgstr "Archiviazione modifiche..." #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:586 #, fuzzy msgid "Commit summary" msgstr "Messaggio di revisione:" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "Nuova revisione" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "" #: cola/difftool.py:102 msgid "Compare All" msgstr "" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "" #: cola/widgets/main.py:169 #, fuzzy msgid "Console" msgstr "Chiudi" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Continua" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Copia" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 #, fuzzy msgid "Copy SHA-1" msgstr "Copia tutto" #: cola/widgets/status.py:738 #, fuzzy msgid "Copy..." msgstr "Copia" #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Crea ramo" #: cola/widgets/dag.py:372 #, fuzzy msgid "Create Patch" msgstr "Crea ramo" #: cola/widgets/remote.py:640 #, fuzzy msgid "Create Remote Branch" msgstr "Cancella ramo remoto" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 #, fuzzy msgid "Create Signed Commit" msgstr "Creata revisione %s: %s" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 #, fuzzy msgid "Create Tag" msgstr "Crea" #: cola/widgets/main.py:558 #, fuzzy msgid "Create Tag..." msgstr "Crea..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "" #: cola/widgets/remote.py:639 #, fuzzy msgid "Create a new remote branch?" msgstr "Crea nuovo ramo" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "Crea..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 #, fuzzy msgid "Current Repository" msgstr "Crea nuovo archivio" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "" #: cola/widgets/status.py:274 #, fuzzy msgid "Customize..." msgstr "Clona..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "Taglia" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "" #: cola/icons.py:54 msgid "Dark Theme" msgstr "" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "" #: cola/icons.py:53 cola/themes.py:643 #, fuzzy msgid "Default" msgstr "Ripristina valori predefiniti" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Elimina" #: cola/cmds.py:1088 #, fuzzy, python-format msgid "Delete %d file(s)?" msgstr "Elimina" #: cola/cmds.py:1016 #, fuzzy msgid "Delete Bookmark" msgstr "Elimina ramo" #: cola/cmds.py:1014 #, fuzzy msgid "Delete Bookmark?" msgstr "Elimina ramo" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Elimina ramo" #: cola/cmds.py:1089 #, fuzzy msgid "Delete Files" msgstr "Elimina" #: cola/widgets/status.py:312 #, fuzzy msgid "Delete Files..." msgstr "Elimina..." #: cola/cmds.py:1085 #, fuzzy msgid "Delete Files?" msgstr "Elimina" #: cola/cmds.py:919 #, fuzzy msgid "Delete Remote" msgstr "Cancella ramo remoto" #: cola/guicmds.py:34 cola/widgets/branch.py:279 #, fuzzy msgid "Delete Remote Branch" msgstr "Cancella ramo remoto" #: cola/widgets/main.py:578 #, fuzzy msgid "Delete Remote Branch..." msgstr "Cancella ramo remoto" #: cola/widgets/toolbar.py:276 #, fuzzy msgid "Delete Toolbar" msgstr "Elimina ramo" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "" #: cola/widgets/editremotes.py:85 #, fuzzy msgid "Delete remote" msgstr "Cancella ramo remoto" #: cola/cmds.py:921 #, fuzzy, python-format msgid "Delete remote \"%s\"" msgstr "Cancella ramo remoto" #: cola/cmds.py:920 #, fuzzy msgid "Delete remote?" msgstr "Cancella ramo remoto" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Elimina..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "" #: cola/widgets/filelist.py:25 #, fuzzy msgid "Deletions" msgstr "Elimina" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 #, fuzzy msgid "Detach" msgstr "Elimina ramo" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "" #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 #, fuzzy msgid "Diff Options" msgstr "Opzioni" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "" #: cola/difftool.py:324 #, fuzzy msgid "Difftool" msgstr "Opzioni" #: cola/widgets/clone.py:205 #, fuzzy msgid "Directory Exists" msgstr "Directory:" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 #, fuzzy msgid "Documentation" msgstr "Documentazione sul web" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 #, fuzzy msgid "Edit" msgstr "Modifica" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 #, fuzzy msgid "Edit Rebase" msgstr "Ripristina" #: cola/widgets/editremotes.py:34 #, fuzzy msgid "Edit Remotes" msgstr "Remoto" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "" #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 #, fuzzy msgid "Edit..." msgstr "Modifica" #: cola/widgets/prefs.py:274 #, fuzzy msgid "Editor" msgstr "Modifica" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "Indirizzo Email" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "" #: cola/guicmds.py:332 cola/widgets/branch.py:478 #, fuzzy msgid "Enter New Branch Name" msgstr "Nome del ramo" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 #, fuzzy msgid "Error" msgstr "errore" #: cola/widgets/clone.py:189 #, fuzzy msgid "Error Cloning" msgstr "Errore nel caricamento del file:" #: cola/widgets/createbranch.py:312 #, fuzzy msgid "Error Creating Branch" msgstr "Crea ramo" #: cola/app.py:501 cola/guicmds.py:100 #, fuzzy msgid "Error Creating Repository" msgstr "Crea nuovo archivio" #: cola/cmds.py:1205 #, fuzzy msgid "Error Deleting Remote Branch" msgstr "Crea ramo" #: cola/cmds.py:1572 #, fuzzy msgid "Error Editing File" msgstr "Errore nel caricamento delle differenze:" #: cola/cmds.py:559 #, fuzzy msgid "Error Launching Blame Viewer" msgstr "File browser" #: cola/cmds.py:3089 #, fuzzy msgid "Error Launching History Browser" msgstr "File browser" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "" #: cola/models/stash.py:233 #, fuzzy msgid "Error creating stash" msgstr "Crea ramo" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "" #: cola/cmds.py:1721 #, fuzzy msgid "Error running prepare-commitmsg hook" msgstr "Avvio pre-commit hook..." #: cola/cmds.py:2987 cola/cmds.py:3033 #, fuzzy, python-format msgid "Error updating submodule %s" msgstr "Errore nel caricamento delle differenze:" #: cola/cmds.py:3069 #, fuzzy msgid "Error updating submodules" msgstr "Errore nel caricamento delle differenze:" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "" #: cola/widgets/branch.py:433 #, fuzzy, python-format msgid "Executing action %s" msgstr "Il dizionario è stato reimpostato su %s." #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "" #: cola/widgets/main.py:547 #, fuzzy msgid "Expression..." msgstr "Opzioni..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "" #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Solo fast forward" #: cola/widgets/remote.py:181 #, fuzzy msgid "Fast-forward only" msgstr "Solo fast forward" #: cola/widgets/bookmarks.py:90 #, fuzzy msgid "Favorite repositories" msgstr "Archivi recenti" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "" #: cola/widgets/remote.py:735 #, fuzzy msgid "Fetch" msgstr "Ripristina..." #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "Recupera duplicato locale di ramo remoto" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 #, fuzzy msgid "Fetch..." msgstr "Ripristina..." #: cola/widgets/main.py:602 #, fuzzy msgid "File Browser..." msgstr "Esplora" #: cola/widgets/compare.py:74 #, fuzzy msgid "File Differences" msgstr "Preferenze" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" #: cola/fsmonitor.py:145 #, fuzzy msgid "File system change monitoring: enabled.\n" msgstr "Fidati delle date di modifica dei file\n" #: cola/widgets/filelist.py:25 #, fuzzy msgid "Filename" msgstr "Rinomina" #: cola/widgets/dag.py:821 #, fuzzy msgid "Files" msgstr "File:" #: cola/widgets/branch.py:837 #, fuzzy msgid "Filter branches..." msgstr "Ripristina..." #: cola/widgets/status.py:1333 #, fuzzy msgid "Filter paths..." msgstr "Ripristina..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 #, fuzzy msgid "Find Files" msgstr "File:" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "" #: cola/widgets/commitmsg.py:154 #, fuzzy msgid "Fixup Previous Commit" msgstr "Messaggio di fusione:" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "" #: cola/themes.py:705 msgid "Flat dark green" msgstr "" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "" #: cola/themes.py:691 msgid "Flat dark red" msgstr "" #: cola/themes.py:656 msgid "Flat light blue" msgstr "" #: cola/themes.py:677 msgid "Flat light green" msgstr "" #: cola/themes.py:670 msgid "Flat light grey" msgstr "" #: cola/themes.py:663 msgid "Flat light red" msgstr "" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Dimensione caratteri" #: cola/widgets/remote.py:197 msgid "Force" msgstr "" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:650 #, fuzzy, python-format msgid "Force fetching from %s?" msgstr "Recupero %s da %s" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "" #: cola/widgets/editremotes.py:315 #, fuzzy, python-format msgid "Gathering info for \"%s\"..." msgstr "Caricamento delle differenze di %s..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "" #: cola/widgets/main.py:525 #, fuzzy msgid "Get Commit Message Template" msgstr "Larghezza del messaggio di revisione" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "" #: cola/widgets/dag.py:848 msgid "Graph" msgstr "" #: cola/widgets/main.py:354 msgid "Grep" msgstr "" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Aiuto" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 #, fuzzy msgid "History Browser" msgstr "File browser" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "" #: cola/widgets/remote.py:207 #, fuzzy msgid "Include tags " msgstr "Includi etichette" #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "" #: cola/widgets/main.py:657 #, fuzzy msgid "Initialize Git Annex" msgstr "Inizializzazione..." #: cola/widgets/main.py:661 #, fuzzy msgid "Initialize Git LFS" msgstr "Inizializzazione..." #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "" #: cola/cmds.py:2313 #, fuzzy msgid "Invalid Revision" msgstr "Revisione non valida: %s" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "" #: cola/icons.py:55 msgid "Light Theme" msgstr "" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 #, fuzzy msgid "Load Commit Message" msgstr "Messaggio di revisione:" #: cola/widgets/main.py:335 #, fuzzy msgid "Load Commit Message..." msgstr "Messaggio di revisione:" #: cola/widgets/commitmsg.py:150 #, fuzzy msgid "Load Previous Commit Message" msgstr "Messaggio di fusione:" #: cola/widgets/diff.py:264 #, fuzzy msgid "Loading..." msgstr "Caricamento %s..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Ramo locale" #: cola/widgets/createbranch.py:112 #, fuzzy msgid "Local branch" msgstr "Ramo locale" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "" #: cola/widgets/dag.py:816 msgid "Log" msgstr "" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Fusione (Merge)" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/widgets/prefs.py:278 #, fuzzy msgid "Merge Tool" msgstr "Fusione (Merge)" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Prolissità della fusione" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "Fusione non riuscita. Bisogna risolvere i conflitti." #: cola/widgets/merge.py:165 #, fuzzy, python-format msgid "Merge into \"%s\"" msgstr "Fusione in %s" #: cola/widgets/branch.py:242 #, fuzzy msgid "Merge into current branch" msgstr "Esplora i file del ramo attuale" #: cola/widgets/main.py:359 #, fuzzy msgid "Merge..." msgstr "Fusione (Merge)" #: cola/widgets/main.py:1177 #, fuzzy msgid "Merging" msgstr "Fusione (Merge)" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 #, fuzzy msgid "Message" msgstr "Fusione (Merge)" #: cola/widgets/commitmsg.py:424 #, fuzzy msgid "Missing Commit Message" msgstr "Messaggio di fusione:" #: cola/widgets/createbranch.py:250 #, fuzzy msgid "Missing Data" msgstr "Mancante" #: cola/cmds.py:2741 #, fuzzy msgid "Missing Name" msgstr "Mancante" #: cola/cmds.py:2735 #, fuzzy msgid "Missing Revision" msgstr "Revisione iniziale" #: cola/cmds.py:2745 #, fuzzy msgid "Missing Tag Message" msgstr "Revisione da fondere" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 #, fuzzy msgid "Modified" msgstr "Non modificato" #: cola/widgets/commitmsg.py:528 #, fuzzy msgid "More..." msgstr "Clona..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 #, fuzzy msgid "Name" msgstr "Nome:" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "" #: cola/guicmds.py:147 cola/widgets/main.py:281 #, fuzzy msgid "New Bare Repository..." msgstr "Archivio Git" #: cola/guicmds.py:86 cola/widgets/main.py:276 #, fuzzy msgid "New Repository..." msgstr "Archivio Git" #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Nuovo..." #: cola/actions.py:56 #, fuzzy msgid "Next File" msgstr "Seleziona tutto" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "No" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 #, fuzzy msgid "No Revision Specified" msgstr "Nessuna revisione selezionata." #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 #, 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." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/merge.py:63 #, fuzzy msgid "No fast forward" msgstr "Solo fast forward" #: cola/widgets/remote.py:190 #, fuzzy msgid "No fast-forward" msgstr "Solo fast forward" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Nessun archivio selezionato." #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/commitmsg.py:451 #, fuzzy msgid "Nothing to commit" msgstr "Nessuna modifica per la nuova revisione." #: cola/gitcmds.py:626 #, fuzzy msgid "Nothing to do" msgstr "Niente da clonare da %s." #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Numero di linee di contesto nelle differenze" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Apri" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 #, fuzzy msgid "Open Git Repository" msgstr "Apri archivio esistente" #: cola/widgets/submodules.py:48 #, fuzzy msgid "Open Parent" msgstr "Apri archivio recente:" #: cola/cmds.py:1827 #, fuzzy msgid "Open Parent Directory" msgstr "Apri archivio recente:" #: cola/widgets/main.py:693 #, fuzzy msgid "Open Recent" msgstr "Apri archivio recente:" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "" #: cola/widgets/main.py:416 #, fuzzy msgid "Open in New Window..." msgstr "Apri archivio esistente" #: cola/widgets/main.py:410 msgid "Open..." msgstr "Apri..." #: cola/widgets/branch.py:354 #, fuzzy msgid "Other branches" msgstr "Ripristina..." #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "" #: cola/widgets/main.py:758 msgid "Paste" msgstr "Incolla" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/cmds.py:2297 #, fuzzy msgid "Please select a file" msgstr "Scegliere un duplicato locale di ramo remoto" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "" #: cola/cmds.py:2735 #, fuzzy msgid "Please specify a revision to tag." msgstr "Scegliere un ramo da rinominare." #: cola/widgets/commitmsg.py:417 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/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Preferenze" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "" #: cola/widgets/main.py:341 #, fuzzy msgid "Prepare Commit Message" msgstr "Messaggio di fusione:" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "" #: cola/actions.py:65 msgid "Previous File" msgstr "" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "" #: cola/widgets/remote.py:170 #, fuzzy msgid "Prompt when pushing creates new remote branches" msgstr "Crea nuovo ramo" #: cola/widgets/remote.py:212 #, fuzzy msgid "Prune " msgstr "Effettua potatura da" #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 #, fuzzy msgid "Pull" msgstr "Propaga..." #: cola/widgets/action.py:73 cola/widgets/main.py:402 #, fuzzy msgid "Pull..." msgstr "Propaga..." #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Propaga (Push)" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Propaga..." #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Esci" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 #, fuzzy msgid "Rebase" msgstr "Ripristina" #: cola/cmds.py:2092 #, fuzzy, python-format msgid "Rebase onto %s" msgstr "Ripristina" #: cola/cmds.py:2105 #, fuzzy msgid "Rebase stopped" msgstr "Ripristina" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 #, fuzzy msgid "Rebasing" msgstr "Ripristina" #: cola/widgets/main.py:118 #, fuzzy msgid "Recent" msgstr "Ripristina" #: cola/widgets/bookmarks.py:92 #, fuzzy msgid "Recent repositories" msgstr "Archivi recenti" #: cola/widgets/prefs.py:279 #, fuzzy msgid "Recent repository count" msgstr "Archivi recenti" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "" #: cola/widgets/main.py:316 #, fuzzy msgid "Recently Modified Files..." msgstr "Ricerca di file modificati in corso..." #: cola/widgets/stash.py:274 #, fuzzy msgid "Recovering a dropped stash is not possible." msgstr "Ricomporre le revisioni perdute potrebbe non essere semplice." #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Ricomporre le revisioni perdute potrebbe non essere semplice." #: cola/widgets/main.py:751 msgid "Redo" msgstr "Ripeti" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Rinfresca" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Remoto" #: cola/widgets/remote.py:160 #, fuzzy msgid "Remote Branch" msgstr "Rinomina ramo" #: cola/cmds.py:1196 #, fuzzy msgid "Remote Branch Deleted" msgstr "Rinomina ramo" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 #, fuzzy msgid "Remove" msgstr "Remoto" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "" #: cola/widgets/toolbar.py:321 #, fuzzy msgid "Remove Element" msgstr "Remoto" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "" #: cola/widgets/diff.py:1704 #, fuzzy msgid "Remove selected (Delete)" msgstr "Rinomina ramo" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Rinomina" #: cola/cmds.py:1153 #, fuzzy, python-format msgid "Rename \"%s\"" msgstr "Rinomina" #: cola/widgets/branch.py:268 #, fuzzy msgid "Rename Branch" msgstr "Rinomina ramo" #: cola/widgets/main.py:584 #, fuzzy msgid "Rename Branch..." msgstr "Rinomina ramo" #: cola/guicmds.py:329 #, fuzzy msgid "Rename Existing Branch" msgstr "Aggiorna ramo esistente:" #: cola/cmds.py:941 #, fuzzy msgid "Rename Remote" msgstr "Remoto" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 #, fuzzy msgid "Rename Repository" msgstr "Clona archivio esistente" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 #, fuzzy msgid "Rename branch" msgstr "Rinomina ramo" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/browse.py:159 #, fuzzy msgid "Rename selected paths" msgstr "Rinomina ramo" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, fuzzy, python-format msgid "Repository: %s" msgstr "Archivio:" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Ripristina" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 #, fuzzy msgid "Reset Branch" msgstr "Elimina ramo" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 #, fuzzy msgid "Reset Branch?" msgstr "Elimina ramo" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, 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/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "" #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:1223 #, fuzzy msgid "Revert Selected Lines?" msgstr "Annullare le modifiche nel file %s?" #: cola/cmds.py:2260 #, fuzzy msgid "Revert Uncommitted Changes" msgstr "Annulla modifiche" #: cola/cmds.py:2254 #, fuzzy msgid "Revert Uncommitted Changes?" msgstr "Annulla modifiche" #: cola/cmds.py:2247 #, fuzzy msgid "Revert Uncommitted Edits..." msgstr "Annulla modifiche" #: cola/cmds.py:2238 #, fuzzy msgid "Revert Unstaged Changes" msgstr "Modifiche non preparate" #: cola/cmds.py:2232 #, fuzzy msgid "Revert Unstaged Changes?" msgstr "Modifiche non preparate" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "" #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "" #: cola/cmds.py:2237 #, fuzzy msgid "Revert the unstaged changes?" msgstr "Modifiche non preparate" #: cola/widgets/browse.py:190 #, fuzzy msgid "Revert uncommitted changes to selected paths" msgstr "Annullare le modifiche nel file %s?" #: cola/widgets/browse.py:181 #, fuzzy msgid "Revert unstaged changes to selected paths" msgstr "Annullare le modifiche nel file %s?" #: cola/guicmds.py:320 msgid "Review" msgstr "" #: cola/widgets/main.py:597 #, fuzzy msgid "Review..." msgstr "Ripristina..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Revisione" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Espressione di revisione:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Revisione da fondere" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "" #: cola/sequenceeditor.py:372 #, fuzzy msgid "SHA-1" msgstr "Copia tutto" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Salva" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "" #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "" #: cola/widgets/search.py:223 #, fuzzy msgid "Search Commit Messages" msgstr "Messaggio di fusione:" #: cola/widgets/search.py:226 #, fuzzy msgid "Search Committers" msgstr "Revisione creata da:" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:221 #, fuzzy msgid "Search by Expression" msgstr "Espressione di revisione:" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "" #: cola/widgets/main.py:507 #, fuzzy msgid "Search..." msgstr "Avvio in corso..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Seleziona" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Seleziona tutto" #: cola/guicmds.py:320 #, fuzzy msgid "Select Branch to Review" msgstr "Elimina ramo" #: cola/widgets/dag.py:1667 #, fuzzy msgid "Select Child" msgstr "Seleziona tutto" #: cola/widgets/commitmsg.py:534 #, fuzzy msgid "Select Commit" msgstr "Messaggio di fusione:" #: cola/guicmds.py:136 #, fuzzy msgid "Select Directory..." msgstr "Archivio Git" #: cola/cmds.py:2078 #, fuzzy msgid "Select New Upstream" msgstr "Seleziona" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "" #: cola/widgets/dag.py:1656 #, fuzzy msgid "Select Parent" msgstr "Seleziona" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 #, fuzzy msgid "Select output dir" msgstr "Messaggio di fusione:" #: cola/widgets/selectcommits.py:182 #, fuzzy msgid "Select output directory" msgstr "Archivio Git" #: cola/widgets/diff.py:1770 #, fuzzy msgid "Select patch file(s)..." msgstr "Elimina..." #: cola/widgets/editremotes.py:434 #, fuzzy msgid "Select repository" msgstr "Archivio Git" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 #, fuzzy msgid "Set Default Repository" msgstr "Archivio Git" #: cola/widgets/branch.py:291 #, fuzzy msgid "Set Upstream Branch" msgstr "Seleziona" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 #, fuzzy msgid "Set upstream" msgstr "Seleziona" #: cola/widgets/prefs.py:443 #, fuzzy msgid "Settings" msgstr "Avvio in corso..." #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Mostra statistiche delle differenze dopo la fusione" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 #, fuzzy msgid "Show Help" msgstr "Aiuto" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/widgets/recent.py:56 #, fuzzy msgid "Showing changes since" msgstr "Propagazione modifiche a %s" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Sign Off" #: cola/widgets/createtag.py:69 #, fuzzy msgid "Sign Tag" msgstr "Sign Off" #: cola/widgets/commitmsg.py:56 #, fuzzy msgid "Sign off on this commit" msgstr "Preparato per una nuova revisione" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "" #: cola/cmds.py:2527 msgid "Skip" msgstr "" #: cola/widgets/main.py:261 cola/widgets/main.py:631 #, fuzzy msgid "Skip Current Patch" msgstr "Crea ramo" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "" #: cola/widgets/spellcheck.py:45 #, fuzzy msgid "Spelling Suggestions" msgstr "Nessun suggerimento" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 #, fuzzy msgid "Squash" msgstr "Propaga (Push)" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 #, fuzzy msgid "Stage" msgstr "Salva" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Prepara modificati" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 #, fuzzy msgid "Stage Selected" msgstr "Seleziona" #: cola/widgets/diff.py:1050 #, fuzzy msgid "Stage Selected Lines" msgstr "Modifiche non preparate" #: cola/cmds.py:2642 #, fuzzy msgid "Stage Unmerged" msgstr "Prepara non merged" #: cola/cmds.py:2653 #, fuzzy msgid "Stage Untracked" msgstr "Prepara non tracked" #: cola/widgets/commitmsg.py:445 #, fuzzy msgid "Stage and Commit" msgstr "Prepara per una nuova revisione" #: cola/widgets/commitmsg.py:442 #, fuzzy msgid "Stage and commit?" msgstr "Preparato per una nuova revisione" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 #, fuzzy msgid "Stage conflicts" msgstr "Preparato per una nuova revisione" #: cola/cmds.py:2517 #, fuzzy msgid "Stage conflicts?" msgstr "Preparato per una nuova revisione" #: cola/widgets/browse.py:146 #, fuzzy msgid "Stage/unstage selected paths for commit" msgstr "Preparato per una nuova revisione" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "" #: cola/cmds.py:2545 #, fuzzy, python-format msgid "Staging: %s" msgstr "Analisi in corso %s..." #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "" #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "Revisione iniziale" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "" #: cola/widgets/stash.py:79 #, fuzzy msgid "Stash Index" msgstr "Errore nell'indice" #: cola/widgets/stash.py:79 #, fuzzy msgid "Stash staged changes only" msgstr "Archiviazione modifiche..." #: cola/widgets/stash.py:75 #, fuzzy msgid "Stash unstaged changes only, keeping staged changes" msgstr "Annullare le modifiche nel file %s?" #: cola/widgets/action.py:76 cola/widgets/main.py:423 #, fuzzy msgid "Stash..." msgstr "Propaga..." #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "Riepilogo nelle revisioni di fusione" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Etichetta" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "" #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "" #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "" #: cola/widgets/commitmsg.py:310 #, fuzzy msgid "The commit message will be cleared." msgstr "Larghezza del messaggio di revisione" #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 #, fuzzy msgid "The revision expression cannot be empty." msgstr "L'espressione di revisione è vuota." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 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/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Duplicato locale di ramo remoto" #: cola/widgets/createbranch.py:113 #, fuzzy msgid "Tracking branch" msgstr "Duplicato locale di ramo remoto" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "URL" #: cola/widgets/remote.py:496 #, fuzzy, python-format msgid "URL: %s" msgstr "URL:" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "" #: cola/cmds.py:2071 #, fuzzy msgid "Unable to rebase" msgstr "Impossibile ripulire %s" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "Annulla" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 #, fuzzy msgid "Unmerged" msgstr "Fusione (Merge)" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 #, fuzzy msgid "Unstage" msgstr "Modifiche non preparate" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "" #: cola/widgets/diff.py:1015 #, fuzzy msgid "Unstage Selected Lines" msgstr "Modifiche non preparate" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, fuzzy, python-format msgid "Unstaging: %s" msgstr "%s non farà parte della prossima revisione" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "" #: cola/widgets/status.py:159 cola/widgets/status.py:647 #, fuzzy msgid "Untracked" msgstr "Non tracciato, non preparato per una nuova revisione" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Aggiorna ramo esistente:" #: cola/cmds.py:3019 #, fuzzy msgid "Update Submodule" msgstr "Aggiornato" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "" #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 #, fuzzy msgid "Updating" msgstr "Avvio in corso..." #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Nome utente" #: cola/widgets/about.py:89 #, fuzzy msgid "Version" msgstr "Revisione" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "" #: cola/widgets/browse.py:138 #, fuzzy msgid "View history for selected paths" msgstr "Annullare le modifiche nel file %s?" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "Visualizza" #: cola/widgets/main.py:502 #, fuzzy msgid "Visualize All Branches..." msgstr "Visualizza la cronologia di tutti i rami" #: cola/widgets/main.py:496 #, fuzzy msgid "Visualize Current Branch..." msgstr "Visualizza la cronologia del ramo attuale" #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" #: cola/cmds.py:2072 #, fuzzy msgid "You cannot rebase with uncommitted changes." msgstr "Annulla modifiche" #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "" #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "" #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "" #: cola/widgets/log.py:52 #, fuzzy, python-format msgid "exit code %s" msgstr "recupera da %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "" #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "" #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "" #: cola/hidpi.py:43 msgid "x 1" msgstr "" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "" #: cola/hidpi.py:46 msgid "x 2" msgstr "" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "" #~ 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 "" #~ "\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 "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%1$s ... %6$s: %2$*i di %4$*i (%7$3i%%)" #~ msgid "%s Repository" #~ msgstr "Archivio di %s" #~ msgid "%s of %s" #~ msgstr "%s di %s" #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "'%s' non è utilizzabile come nome di ramo." #~ msgid "* Binary file (not showing content)." #~ msgstr "* File binario (il contenuto non sarà mostrato)." #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "Si richiede un ramo per 'Fuso in'." #, fuzzy, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Il file %s esiste già." #~ msgid "Abort completed. Ready." #~ msgstr "Interruzione completata. Pronto." #~ msgid "Abort failed." #~ msgstr "Interruzione non riuscita." #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "Attivazione di '%s' fallita (richiesta una fusione a livello file)." #~ msgid "Always (Do not perform merge checks)" #~ msgstr "Sempre (non verificare le fusioni)" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "Sempre (Non effettuare verifiche di fusione)." #~ 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 "Annotation complete." #~ msgstr "Annotazione completata." #~ 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 "Apply/Reverse Hunk" #~ msgstr "Applica/Inverti sezione" #~ msgid "Arbitrary URL:" #~ msgstr "URL specifico:" #~ 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 "Branch '%s' does not exist." #~ msgstr "Il ramo '%s' non esiste." #, fuzzy #~ msgid "Branch created" #~ msgstr "Nome del ramo" #~ msgid "Browse %s's Files" #~ msgstr "Esplora i file di %s" #~ msgid "Browse Branch Files" #~ msgstr "Esplora i file del ramo" #, fuzzy #~ msgid "Browse Revision..." #~ msgstr "Revisione" #~ msgid "Calling commit-msg hook..." #~ msgstr "Avvio commit-msg hook..." #~ 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 "" #~ "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 "Cannot determine HEAD. See console output for details." #~ msgstr "Impossibile determinare HEAD. Controllare i dettagli forniti dalla console." #~ 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 find git in PATH." #~ msgstr "Impossibile trovare git nel PATH" #~ 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 "Cannot move to top of working directory:" #~ msgstr "Impossibile spostarsi sulla directory principale del progetto:" #~ msgid "Cannot parse Git version string:" #~ msgstr "Impossibile determinare la versione di Git:" #~ msgid "Cannot resolve %s as a commit." #~ msgstr "Impossibile risolvere %s come una revisione." #~ msgid "Cannot use funny .git directory:" #~ msgstr "Impossibile usare una .git directory strana:" #~ msgid "Cannot write shortcut:" #~ msgstr "Impossibile scrivere shortcut:" #~ msgid "Change Font" #~ msgstr "Cambia caratteri" #~ msgid "Checked out '%s'." #~ msgstr "Attivazione di '%s' completata." #~ msgid "Clone Type:" #~ msgstr "Tipo di clone:" #~ msgid "Clone failed." #~ msgstr "Clonazione non riuscita." #~ msgid "Cloning from %s" #~ msgstr "Clonazione da %s" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "La revisione %s sembra essere danneggiata" #~ msgid "Commit declined by commit-msg hook." #~ msgstr "Revisione rifiutata dal commit-msg hook." #~ msgid "Commit declined by pre-commit hook." #~ msgstr "Revisione rifiutata dal pre-commit hook." #, fuzzy #~ msgid "Commit failed: %s" #~ msgstr "Impossibile creare una nuova revisione." #~ msgid "Commit@@noun" #~ msgstr "Revisione" #~ msgid "Compress Database" #~ msgstr "Comprimi l'archivio" #~ msgid "Compressing the object database" #~ msgstr "Compressione dell'archivio in corso" #~ msgid "Copied Or Moved Here By:" #~ msgstr "Copiato o spostato qui da:" #~ msgid "Copying objects" #~ msgstr "Copia degli oggetti" #~ msgid "Counting objects" #~ msgstr "Calcolo oggetti" #~ msgid "Create Desktop Icon" #~ msgstr "Crea icona desktop" #, fuzzy #~ msgid "Created commit: %s" #~ msgstr "Creata revisione %s: %s" #~ msgid "Creating working directory" #~ msgstr "Creazione directory di lavoro" #~ msgid "Current Branch:" #~ msgstr "Ramo attuale:" #~ msgid "Database Statistics" #~ msgstr "Statistiche dell'archivio" #~ msgid "Decrease Font Size" #~ msgstr "Diminuisci dimensione caratteri" #~ msgid "Delete Local Branch" #~ msgstr "Elimina ramo locale" #~ msgid "Delete Only If" #~ msgstr "Elimina solo se" #~ msgid "Delete Only If Merged Into" #~ msgstr "Cancella solo se fuso con un altro ramo" #, fuzzy #~ msgid "Delete selected branch?" #~ msgstr "Cancella ramo remoto" #~ msgid "Destination Repository" #~ msgstr "Archivio di destinazione" #~ msgid "Detach From Local Branch" #~ msgstr "Stacca da ramo locale" #~ msgid "Diff/Console Font" #~ msgstr "Caratteri per confronti e terminale" #~ msgid "Directory %s already exists." #~ msgstr "La directory %s esiste già." #~ msgid "Disk space used by loose objects" #~ msgstr "Spazio su disco utilizzato da oggetti slegati" #~ msgid "Disk space used by packed objects" #~ msgstr "Spazio su disco utilizzato da oggetti impacchettati" #~ msgid "Do Nothing" #~ msgstr "Non fare niente" #, fuzzy #~ msgid "Enter Git Repository" #~ msgstr "Archivio Git" #, fuzzy #~ msgid "Error %s" #~ msgstr "errore" #~ msgid "Error loading commit data for amend:" #~ msgstr "Errore durante il caricamento dei dati della revisione da correggere:" #~ msgid "Error: Command Failed" #~ msgstr "Errore: comando non riuscito" #~ msgid "Failed to completely save options:" #~ msgstr "Impossibile salvare completamente le opzioni:" #~ msgid "Failed to configure origin" #~ msgstr "Impossibile configurare origin" #~ msgid "Failed to create repository %s:" #~ msgstr "Impossibile creare l'archivio %s:" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "Impossibile cancellare i rami:\n" #~ "%s" #~ msgid "Failed to open repository %s:" #~ msgstr "Impossibile accedere all'archivio %s:" #~ msgid "Failed to rename '%s'." #~ msgstr "Impossibile rinominare '%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 "Failed to stage selected hunk." #~ msgstr "Impossibile preparare la sezione scelta per una nuova revisione." #~ msgid "Failed to unstage selected hunk." #~ msgstr "Impossibile rimuovere la sezione scelta dalla nuova revisione." #~ msgid "Failed to update '%s'." #~ msgstr "Impossibile aggiornare '%s'." #, fuzzy #~ msgid "Fast Forward Only " #~ msgstr "Solo fast forward" #~ msgid "Fetch from" #~ msgstr "Recupera da" #~ msgid "Fetching new changes from %s" #~ msgstr "Recupero nuove modifiche da %s" #~ msgid "File level merge required." #~ msgstr "E' richiesta una fusione a livello file." #~ msgid "Font Example" #~ msgstr "Esempio caratteri" #~ msgid "Font Family" #~ msgstr "Famiglia di caratteri" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "Sovrascrivi ramo esistente (alcune modifiche potrebbero essere perse)" #~ msgid "From Repository" #~ msgstr "Da archivio" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "Copia completa (più lento, backup ridondante)" #~ msgid "Garbage files" #~ msgstr "File inutili" #~ msgid "Git Gui" #~ msgstr "Git Gui" #~ msgid "Git Repository (subproject)" #~ msgstr "Archivio Git (sottoprogetto)" #~ msgid "Git directory not found:" #~ msgstr "Non trovo la directory 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 "Hardlinks are unavailable. Falling back to copying." #~ msgstr "Impossibile utilizzare gli hardlink. Si ricorrerà alla copia." #~ msgid "In File:" #~ msgstr "Nel file:" #~ msgid "Increase Font Size" #~ msgstr "Aumenta dimensione caratteri" #~ msgid "Initial Commit Message:" #~ msgstr "Messaggio di revisione iniziale:" #~ msgid "Initial file checkout failed." #~ msgstr "Attivazione iniziale non riuscita." #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "GIT_COMMITTER_IDENT non valida:" #~ msgid "Invalid date from Git: %s" #~ msgstr "Git ha restituito una data non valida: %s" #~ msgid "Invalid font specified in %s:" #~ msgstr "Caratteri non validi specificati in %s:" #~ msgid "Invalid spell checking configuration" #~ msgstr "La configurazione del correttore ortografico non è valida" #~ msgid "KiB" #~ msgstr "KiB" #~ 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 "" #~ "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 "" #~ "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 "Linking objects" #~ msgstr "Collegamento oggetti" #~ msgid "Loading annotation..." #~ msgstr "Caricamento annotazioni..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "Caricamento annotazioni per copie/spostamenti..." #~ msgid "Loading original location annotations..." #~ msgstr "Caricamento annotazioni per posizione originaria..." #~ msgid "Local Branches" #~ msgstr "Rami locali" #~ msgid "Local Merge..." #~ msgstr "Fusione locale..." #~ msgid "Location %s already exists." #~ msgstr "Il file/directory %s esiste già." #~ msgid "Main Font" #~ msgstr "Caratteri principali" #~ msgid "Match Tracking Branch Name" #~ msgstr "Appaia nome del duplicato locale di ramo remoto" #~ msgid "Match Tracking Branches" #~ msgstr "Appaia duplicati locali di rami remoti" #~ msgid "Merge completed successfully." #~ msgstr "Fusione completata con successo." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "La strategia di fusione '%s' non è supportata." #~ msgid "Merged Into:" #~ msgstr "Fuso in:" #~ msgid "Merging %s and %s..." #~ msgstr "Fusione di %s e %s in corso..." #~ msgid "Modified, not staged" #~ msgstr "Modificato, non preparato per una nuova revisione" #~ msgid "New Branch Name Template" #~ msgstr "Modello per il nome di un nuovo ramo" #~ msgid "New Commit" #~ msgstr "Nuova revisione" #~ msgid "New Name:" #~ msgstr "Nuovo Nome:" #~ 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 "No default branch obtained." #~ msgstr "Non è stato trovato un ramo predefinito." #~ 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 "No working directory" #~ msgstr "Nessuna directory di lavoro" #~ msgid "Number of loose objects" #~ msgstr "Numero di oggetti slegati" #~ msgid "Number of packed objects" #~ msgstr "Numero di oggetti impacchettati" #~ msgid "Number of packs" #~ msgstr "Numero di pacchetti" #~ 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 "Options" #~ msgstr "Opzioni" #~ msgid "Original File:" #~ msgstr "File originario:" #~ msgid "Originally By:" #~ msgstr "In origine da:" #~ msgid "Packed objects waiting for pruning" #~ msgstr "Oggetti impacchettati che attendono la potatura" #, fuzzy #~ msgid "Path to git repository" #~ msgstr "%s non è un archivio Git." #~ msgid "Please select one or more branches to delete." #~ msgstr "Scegliere uno o più rami da cancellare." #~ msgid "Please supply a branch name." #~ msgstr "Inserire un nome per il ramo." #~ msgid "Portions staged for commit" #~ msgstr "Parti preparate per una nuova revisione" #~ 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 "Preferences..." #~ msgstr "Preferenze..." #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "Effettua potatura dei duplicati locali di rami remoti durante il recupero" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "Effettua potatura dei duplicati locali di rami remoti cancellati da %s" #~ msgid "Push Branches" #~ msgstr "Propaga rami" #~ msgid "Push to" #~ msgstr "Propaga verso" #~ msgid "Pushing %s %s to %s" #~ msgstr "Propagazione %s %s a %s" #~ msgid "Reading %s..." #~ msgstr "Lettura di %s..." #~ msgid "Ready to commit." #~ msgstr "Pronto per creare una nuova revisione." #~ msgid "Ready." #~ msgstr "Pronto." #, fuzzy #~ msgid "Rebase Branch" #~ msgstr "Rinomina ramo" #, fuzzy #~ msgid "Rebase..." #~ msgstr "Ripristina..." #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "Ricomporre rami cancellati è difficile.\n" #~ "\n" #~ "Cancellare i rami selezionati?" #~ 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 "Refreshing file status..." #~ msgstr "Controllo dello stato dei file in corso..." #, fuzzy #~ msgid "Remote Branches" #~ msgstr "Rinomina ramo" #~ msgid "Remote:" #~ msgstr "Remoto:" #, fuzzy #~ msgid "Rename remote?" #~ msgstr "Remoto" #~ msgid "Repository" #~ msgstr "Archivio" #~ msgid "Requires merge resolution" #~ msgstr "Richiede risoluzione dei conflitti" #~ msgid "Rescan" #~ msgstr "Analizza nuovamente" #, fuzzy #~ msgid "Reset Branch Head" #~ msgstr "Elimina ramo" #, fuzzy #~ msgid "Reset Hard" #~ msgstr "Elimina ramo" #, fuzzy #~ msgid "Reset Merge" #~ msgstr "Revisione da fondere" #, fuzzy #~ msgid "Reset Soft" #~ msgstr "Ripristina" #~ 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?" #, fuzzy #~ msgid "Reset hard?" #~ msgstr "Elimina ramo" #, fuzzy #~ msgid "Reset merge?" #~ msgstr "Elimina ramo" #, fuzzy #~ msgid "Reset soft?" #~ msgstr "Ripristinare '%s'?" #~ msgid "Revert changes in these %i files?" #~ msgstr "Annullare le modifiche in questi %i file?" #, fuzzy #~ msgid "Select File" #~ msgstr "Seleziona tutto" #, fuzzy #~ msgid "Select Repository..." #~ msgstr "Archivio Git" #, fuzzy #~ msgid "Select file from \"%s\"" #~ msgstr "Cancellazione rami da %s" #, fuzzy #~ msgid "Select manually..." #~ msgstr "Seleziona tutto" #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "Shared (il più veloce, non raccomandato, nessun backup)" #~ msgid "Shared only available for local repository." #~ msgstr "Shared è disponibile solo per archivi locali." #, fuzzy #~ msgid "Show Details..." #~ msgstr "Elimina..." #~ msgid "Show Less Context" #~ msgstr "Mostra meno contesto" #~ msgid "Show More Context" #~ msgstr "Mostra più contesto" #~ msgid "Source Branches" #~ msgstr "Rami di origine" #~ msgid "Spell Checker Failed" #~ msgstr "Errore nel correttore ortografico" #~ msgid "Spell checker silently failed on startup" #~ msgstr "Il correttore ortografico ha riportato un errore all'avvio" #~ msgid "Spell checking is unavailable" #~ msgstr "Correzione ortografica indisponibile" #~ msgid "Spelling Dictionary:" #~ msgstr "Lingua dizionario:" #~ msgid "Stage Hunk For Commit" #~ msgstr "Prepara sezione per una nuova revisione" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "Modifiche preparate (saranno nella 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" #, fuzzy #~ msgid "Staging Area" #~ msgstr "Analisi in corso %s..." #~ msgid "Staging area (index) is already locked." #~ msgstr "L'area di preparazione per una nuova revisione (indice) è già bloccata." #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "Standard (veloce, semi-ridondante, con hardlink)" #~ msgid "Standard only available for local repository." #~ msgstr "Standard è disponibile solo per archivi locali." #~ msgid "Starting gitk... please wait..." #~ msgstr "Avvio di gitk... attendere..." #~ msgid "Staying on branch '%s'." #~ msgstr "Si rimarrà sul ramo '%s'." #~ msgid "Success" #~ msgstr "Successo" #~ msgid "The 'main' branch has not been initialized." #~ msgstr "Il ramo 'main' non è stato inizializzato." #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "I rami seguenti non sono stati fusi completamente in %s:" #~ 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 "" #~ "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 "This Detached Checkout" #~ msgstr "Questa revisione attiva staccata" #~ 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 "" #~ "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 "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 "Transfer Options" #~ msgstr "Opzioni di trasferimento" #~ msgid "Unable to copy object: %s" #~ msgstr "Impossibile copiare oggetto: %s" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "Impossibile copiare oggetti/info/alternate: %s" #~ msgid "Unable to display %s" #~ msgstr "Impossibile visualizzare %s" #~ msgid "Unable to hardlink object: %s" #~ msgstr "Hardlink impossibile sull'oggetto: %s" #~ msgid "Unable to obtain your identity:" #~ msgstr "Impossibile ottenere la tua identità:" #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "Impossibile avviare gitk:\n" #~ "\n" #~ "%s non esiste" #~ msgid "Unable to unlock the index." #~ msgstr "Impossibile sbloccare l'accesso all'indice" #~ msgid "Unexpected EOF from spell checker" #~ msgstr "Il correttore ortografico ha mandato un EOF inaspettato" #~ 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 "Unlock Index" #~ msgstr "Sblocca l'accesso all'indice" #~ 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 "Unrecognized spell checker" #~ msgstr "Correttore ortografico sconosciuto" #~ msgid "Unstage Hunk From Commit" #~ msgstr "Sezione non preparata per una nuova revisione" #~ msgid "Unsupported spell checker" #~ msgstr "Correttore ortografico non supportato" #~ 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 "Updating working directory to '%s'..." #~ msgstr "Aggiornamento della directory di lavoro a '%s' in corso..." #, fuzzy #~ msgid "Updating..." #~ msgstr "Avvio in corso..." #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Utilizza 'thin pack' (per connessioni lente)" #~ msgid "Verify Database" #~ msgstr "Verifica l'archivio" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "Verifica dell'archivio con fsck-objects in corso" #~ msgid "Visualize %s's History" #~ msgstr "Visualizza la cronologia di %s" #~ msgid "Working... please wait..." #~ msgstr "Elaborazione in corso... attendere..." #~ 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 "" #~ "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 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 "You must correct the above errors before committing." #~ msgstr "Bisogna correggere gli errori suddetti prima di creare una nuova revisione." #~ msgid "[Up To Parent]" #~ msgstr "[Directory superiore]" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree non riuscito:" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "errore grave: impossibile risolvere %s" #~ msgid "files" #~ msgstr "file" #~ msgid "files checked out" #~ msgstr "file presenti nella directory di lavoro" #~ msgid "files reset" #~ msgstr "ripristino file" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - un'interfaccia grafica per Git." #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: errore grave" #~ msgid "lines annotated" #~ msgstr "linee annotate" #~ msgid "objects" #~ msgstr "oggetti" #~ msgid "pt." #~ msgstr "pt." #~ msgid "push %s" #~ msgstr "propaga verso %s" #~ msgid "remote prune %s" #~ msgstr "potatura remota di %s" #~ msgid "update-ref failed:" #~ msgstr "update-ref non riuscito:" #~ msgid "warning" #~ msgstr "attenzione" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "attenzione: Tcl non supporta la codifica '%s'." #~ msgid "write-tree failed:" #~ msgstr "write-tree non riuscito:" git-cola-4.6.1/cola/i18n/ja.po000066400000000000000000004346721457126473700157100ustar00rootroot00000000000000# Translation of git-cola to Japanese # Copyright (C) 2007 Shawn Pearce at el. # This file is distributed under the same license as the git-cola package. # しらいし ななこ , 2007. # fu7mu4 , 2020. # Shun Sakai , 2019. # msgid "" msgstr "" "Project-Id-Version: git-cola VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-17 01:06-0700\n" "PO-Revision-Date: 2022-07-30 19:33+0900\n" "Last-Translator: Kisaragi Hiu \n" "Language-Team: Japanese\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " ドラッグ&ドロップまたは追加ボタンを押して追加します。\n" " リストにパッチを適用する\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" "\n" "
\n" " Git Cola は様々な言語に翻訳されてきました。\n" " 以下のリストの皆さまに感謝します。\n" "\n" "
\n" "

\n" " 翻訳はおおよそです。もし間違いがあった場合、\n" " Githubに課題を作成して知らせてください。:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " 私たちはあなたに翻訳を追加したり翻訳を更新したりしていただきたいです。\n" " そしてプルリクエストを送っていただきたいです。\n" "

\n" "\n" "
\n" "\n" " " #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" "\n" "
\n" " Git Cola のバージョンは %(cola_version)s、の\n" "
    \n" "
  • %(platform_version)sです。\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" "\n" "
\n" " %(bug_link)s を使って課題を報告してください。\n" "
\n" " " #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" "\n" " フォーマットストリング変数\n" " -----------------------\n" " %(path)s = ファイルへの相対パス\n" " %(abspath)s = ファイルへの絶対パス\n" " %(dirname)s = ディレクトリへの相対パス\n" " %(absdirname)s = ディレクトリへの絶対パス\n" " %(filename)s = ファイルのベース名\n" " %(basename)s = ファイルのベース名(拡張子なし)\n" " %(ext)s = ファイルの拡張子\n" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" "\n" "キーボードショートカット\n" "------------------\n" "J, Down = 下に移動\n" "K, Up = 上に移動\n" "Enter = 選択ファイルの編集\n" "Spacebar = デフォルトのアプリケーションでファイルを開く\n" "Ctrl + L = テキスト項目にフォーカスを移動する\n" "?= ヘルプを表示する\n" "\n" "カーソルの上下でテキスト項目と結果の間でフォーカスを変更する。\n" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr " - DAG" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr " 前にコミット" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "\"%(branch)s\" は \"%(remote)s\" から削除されています。" #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "\"%(command)s\" は終了ステータスとして \"%(status)d\" を返しました。" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "\"%(command)s\" は終了ステータスとして %(status)d を返しました。" #: cola/guicmds.py:156 #, python-format msgid "\"%s\" already exists" msgstr "\"%s\" ブランチは既に存在します。" #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "\"%s\" は既に存在しています。git colaは新しいディレクトリを作成してします。" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "\"%s\" は選択したファイルを要求します。" #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "#" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s: %(branch)s - ブラウズ" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "%(project)s: %(ref)s - DAG" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "%d 日前" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "%d 時間前" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "%d 分前" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "%d パッチを適用しました。" #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d スキップしました。" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" "%s マージに衝突があることがわかりました。\n" "\n" "このファイルはおそらくスキップすべきです。\n" "これをステージングしますか?" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "%s を開けませんでした。ブックマークから削除しますか?" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "%s は Gitのリポジトリではありません。" #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "%s をあなたのブックマークから削除します。" #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "%s をあなたの最近のリポジトリリストから削除します。" #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: そのようなファイルやディレクトリはありません。" #: cola/widgets/main.py:748 msgid "&Edit" msgstr "編集(&E)" #: cola/widgets/main.py:690 msgid "&File" msgstr "ファイル(&F)" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(訂正)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "*** ブランチポイント ***" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** サンドボックス ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "100%" #: cola/widgets/diff.py:817 msgid "200%" msgstr "200%" #: cola/widgets/diff.py:814 msgid "25%" msgstr "25%" #: cola/widgets/diff.py:818 msgid "400%" msgstr "400%" #: cola/widgets/diff.py:815 msgid "50%" msgstr "50%" #: cola/widgets/diff.py:819 msgid "800%" msgstr "800%" #: cola/widgets/finder.py:118 msgid " ..." msgstr "<パス> ..." #: cola/cmds.py:1685 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 "" "コミットテンプレートは変更できません。\n" "\"git config\" を使って、\"commit.template\"を定義してください。\n" "これはコミットテンプレートを指定します。" #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "フックが\"%s\"で提供されなければなりません。" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "中止" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "アクションを中止" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "マージを中止" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "マージを中止…" #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "このアクションを中止しますか?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "現在のマージを中止すると、コミットしていない *全て* の変更を失います。\n" "コミットしていない変更を戻すことはできません。" #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "現在のマージを中止しますか?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "About" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "git-colaについて" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "受け入れ" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "変更を受け入れてrebaseします。\n" "ショートカット: Ctrl+Enter" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "アクション名" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "アクション" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "アクション..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "追加" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "お気に入りの追加" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "リモートの追加" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "セパレータの追加" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "サブモジュールの追加" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "サブモジュールの追加..." #: cola/widgets/editremotes.py:60 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 "" "リモートリポジトリの追加や削除するには\n" "左側のAdd(+) または Delete(-) ボタンを使用します。\n" "\n" "リモートリポジトリの名前を変更するには、リストから選択して\n" "\"enter\"を入力する、またはダブルクリックします。" #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "新しいgitのリモートリポジトリを追加します。" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "パッチを追加 (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "リモートを追加" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "このサブモジュールを追加しますか?" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr ".gitignoreに追加" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "Git Annexに追加" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "Git LFSに追加" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "exclusionsに追加" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "ローカルの .git/info/exclude に追加" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "追加" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "拡張" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "年齢" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "全てのリポジトリ" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "ファストフォワードではない更新を許可します。\"force\" はリモートリポジトリでコミットを失う可能性があります。使用には注意してください。" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "可能な場合には常にマージコミットを作成するする、たとえそのマージがファーストフォワードアップデートだった場合でもでも作成する。" #: cola/cmds.py:220 msgid "Amend" msgstr "訂正" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "コミットの訂正" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "最新コミットを訂正" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "発行済のコミットを訂正しますか?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "訂正中" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "アクション継続中です。\n" "中断は結果としてデータを失うことがありえます。" #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "署名のない、軽量のタグを代わりにに作成します。\n" "署名なしタグを作成しますか?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "外観" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "適用" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "パッチの適用" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "パッチの適用..." #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "選択したスタッシュを適用する(git stash pop)" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "選択したスタッシュを適用する" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "引数" #: cola/qtutils.py:886 msgid "Attach" msgstr "アタッチ" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "著者" #: cola/widgets/about.py:90 msgid "Authors" msgstr "著者" #: cola/hidpi.py:41 msgid "Auto" msgstr "自動" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "自動行折り返し" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "自動補完パス" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "自動的にコミットメッセージテンプレート読み込み" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "基本正規表現" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "責任者ビューアー" #: cola/widgets/browse.py:206 #, fuzzy msgid "Blame selected paths" msgstr "選択したパスの名前を変更" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "責任者..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "イタリックフォントからボールドフォントとダークヘッダに" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "ブランチ" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "\"%(branch)s\" は \"%(remote)s\" に存在していません。\n" "新しいリモートブランチを作成し、公開します。" #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "\"%s\" ブランチは既に存在します。" #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "ブランチ差分ビューアー" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "ブランチの存在" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "ブランチ名" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "ブランチ名" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "ブランチ: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "ブランチ" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "ブランチ..." #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "ブラジル語翻訳" #: cola/guicmds.py:52 msgid "Browse" msgstr "ブラウズ" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "コミットのブラウズ..." #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "現在ブランチのブラウズ..." #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "その他のブランチのブラウズ..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "ブラウズ..." #: cola/widgets/main.py:87 msgid "Browser" msgstr "ブラウザー" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "%s のブラウズ" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "コミットフックの回避" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "中止" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "rebaseの中止\n" "ショートカット: Ctrl+Q: Ctrl+Q" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "訂正不可" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "\"%s\"を実行できません。責任者ビューアーを設定してください。" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "\"%s\"を実行できません。履歴ビューアーを設定してください。" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "\"%s\"を実行できません。エディタを設定してください。" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "変更したアップストリーム" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "アメンド時の発行したコミットを確認" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "スペルチェック" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "スペルチェック" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "アメンド時にコミットを発行したかどうかを確認" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "チェックアウト" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "作成してすぐチェックアウト" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "ブランチをチェックアウト" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "デタッチしたHEADをチェックアウト" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "新しいブランチとしてチェックアウト" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "チェックアウト..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "チェリーピック" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "チェリーピックコミット" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "チェリーピック..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "パスの選択" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "\"git grep\" 正規表現モードを選択する" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "デフォルトリポジトリをクリアする" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "コミットメッセージをクリアする" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "コミットメッセージをクリアしますか?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "クリア..." #: cola/widgets/clone.py:124 msgid "Clone" msgstr "Clone" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "リポジトリのClone" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Clone…" #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "リポジトリのClone中: %s" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "閉じる" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "閉じ作業中..." #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "全てCollapse" #: cola/sequenceeditor.py:371 msgid "Command" msgstr "コマンド" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "コミット" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "コミット失敗" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "ステージした変更をコミット" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "ステージした変更をコミット\n" "ショートカット: Ctrl+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "コミットサマリー" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "衝突のない場合のみこのマージをコミットチェックなしで、コミットされていないマージを残す。" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "コミット" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "比較" #: cola/difftool.py:102 msgid "Compare All" msgstr "全て比較" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "ツールバーの設定" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "新しいアップストリームとしてリモートブランチを設定する" #: cola/widgets/main.py:169 msgid "Console" msgstr "コンソール" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "続行" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "コピー" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "ベースネームをクリップボードにコピー" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "リーディングパスをクリップボードにコピー" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "パスをクリップボードにコピー" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "相対パスをクリップボードにコピー" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "SHA-1をコピー" #: cola/widgets/status.py:738 msgid "Copy..." msgstr "コピー中..." #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "%s を開けませんでした。" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "Git URL \"%s\"がパースできません。" #: cola/app.py:499 msgid "Create" msgstr "作成" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "ブランチを作成" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "パッチを作成" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "リモートブランチを作成" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "署名されたコミットの作成" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "タグの作成" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "タグの作成中..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "書名のないタグの作成" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "マージコミットを作成するそれがファーストフォワードとしてマージされる可能性がある" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "リモートブランチを作成しますか?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "この場所に新しいリポジトリを作成しますか?" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "指定した数まで履歴を切り詰めた浅いクローンを作成します。0 は完全なクローンになります。" #: cola/widgets/main.py:565 msgid "Create..." msgstr "作成…" #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "新しく作成したタグ \"%s\" " #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "現在のリポジトリ" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "コピーアクションをカスタム" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "カスタマイズ中..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "切り取り" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "チェコ語翻訳" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "DAG中..." #: cola/icons.py:54 msgid "Dark Theme" msgstr "ダークテーマ" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "日時" #: cola/icons.py:53 cola/themes.py:643 #, fuzzy msgid "Default" msgstr "既定値に戻す" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "削除" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "%d のfileを削除しますか?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "ブックマークの削除" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "ブックマークを削除しますか?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "ブランチ削除" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "ファイルの削除" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "ファイルを削除中..." #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "ファイルを削除しますか?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "リモートの削除" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "リモートブランチの削除" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "リモートブランチの削除中..." #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "ツールバーの削除" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "ブランチ \"%s\" を削除しますか?" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "リモートの削除" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "リモート \"%s\"の削除" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "リモートを削除しますか?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "削除中…" #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "\"%s\"の削除に失敗しました。" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "削除" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "デタッチ" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "衝突マーカーをデタッチ" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "マージされていない衝突マーカーの検出" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "開発者" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "差分" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "前任者との差分..." #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "diffツールオプション" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "差分ツール" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "Diff 選択 -> this" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "Diff this -> 選択" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "差分状態" #: cola/difftool.py:324 msgid "Difftool" msgstr "差分ツール" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "ディレクトリが存在" #: cola/hidpi.py:42 msgid "Disable" msgstr "無効" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "未追跡ファイルの表示" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "ドキュメント" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "ドロップ" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "スタッシュのドロップ" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "ドロップをスタッシュしますか?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "\"%s\" スタッシュをドロップしますか?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "選択したスタッシュをドロップします。" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 msgid "Edit" msgstr "編集" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "リベースを編集" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "リモートを編集" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "リモートを編集中..." #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "リストから選択してリモートを編集する" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "選択したパスを編集する" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "編集中..." #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "エディタ" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "メールアドレス" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "メールコントリビュータ" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "ツールのパス自動補完を有効にする" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "有効" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "新しいブランチ名を入力する" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "新しいbaraリポジトリの名前を入力する" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "スタッシュの名前を入力する" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "エラー" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "クローン中のエラー" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "ブランチ作成エラー" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "リポジトリ作成エラー" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "リモートブランチ削除エラー" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "ファイル編集エラー" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "責任者ビューア起動エラー" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "履歴ブラウザ起動エラー" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "履歴オープン時のエラー" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "リモート \"%s\"作成エラー" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "スタッシュ作成エラー" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "ブランチ削除エラー \"%s\"" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "リモート \"%s\" 削除エラー" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "\"%(name)s\" から \"%(new_name)s\" の名前変更エラー" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "コミットメッセージ前フック実行エラー" #: cola/cmds.py:2987 cola/cmds.py:3033 #, fuzzy, python-format msgid "Error updating submodule %s" msgstr "リモート \"%s\"作成エラー" #: cola/cmds.py:3069 #, fuzzy msgid "Error updating submodules" msgstr "ファイル編集エラー" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "エラー:コミットテンプレートが見つかりません。" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "エラー:コミットテンプレートが設定されていない" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "エラー: \"%s\" が cloneできない" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "エラー: tag \"%s\" が作成できない" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "アクション %s の実行中" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "全て展開" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "パッチのエクスポート" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "パッチのエクスポート中..." #: cola/widgets/main.py:547 msgid "Expression..." msgstr "表現..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "拡張正規表現" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "拡張記述..." #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "ファーストフードのみ" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "ファーストフードのみ" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "よく使うリポジトリ" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "よく使う" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "取得" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "トラッキング・ブランチを取得" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "取得中..." #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "ファイルブラウザ..." #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "ファイル差分" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "保存したファイル" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "ファイルを \"%s\" へ保存" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "ファイルシステム変更監視: \"cola.inotify\"がfalseであるため、無効です。\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "ファイルシステム変更監視: libcがinotifyシステムコールをサポートしていないため、無効です。\n" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "ファイルシステム変更監視: pywin32がインストールされていないため、無効です。\n" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" "ファイルシステム変更監視: inotify 監視の総数が上限に到達したため無効です。inotifyの監視の総数の上限を増加させるには以下のように実行します。:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "ファイルシステム変更監視: 有効です。\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "ファイル名" #: cola/widgets/dag.py:821 msgid "Files" msgstr "ファイル" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "ブランチのフィルタ..." #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "パスのフィルタ..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "ファイルの検索" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "固定文字列" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "固定幅フォント" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "修正" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "以前のコミットを修正" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "フラットダークブルー" #: cola/themes.py:705 msgid "Flat dark green" msgstr "フラットダークグリーン" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "フラットダークグレー" #: cola/themes.py:691 msgid "Flat dark red" msgstr "フラットダークレッド" #: cola/themes.py:656 msgid "Flat light blue" msgstr "フラットライトブルー" #: cola/themes.py:677 msgid "Flat light green" msgstr "フラットライトグリーン" #: cola/themes.py:670 msgid "Flat light grey" msgstr "フラットライトグレー" #: cola/themes.py:663 msgid "Flat light red" msgstr "フラットライトレッド" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "フォルダ" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "フォントサイズ" #: cola/widgets/remote.py:197 msgid "Force" msgstr "強制" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "強制フェッチ" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "強制フェッチしますか?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "強制プッシュ" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "強制プッシュしますか?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "%sから強制フェッチしますか?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "%sへ強制プッシュしますか?" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "フォーマットストリング" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "フランス語翻訳" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "マージコミットのGPG署名" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "GUIテーマ" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "\"%s\"の情報を収集..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "ドイツ語翻訳" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "コミットメッセージのテンプレートを取得" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "下に移動" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "上に移動" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "ファイルのGrab..." #: cola/widgets/dag.py:848 msgid "Graph" msgstr "グラフ" #: cola/widgets/main.py:354 msgid "Grep" msgstr "Grep" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "最近rebaseまたはpullを実行しましたか?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "ヘルプ" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "ヘルプ - カスタムコピーアクション" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "ヘルプ - ファイルの捜索" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "ヘルプ - git-cola-sequence-editor" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "高DPI" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "履歴ブラウザ" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "ハンガリー語翻訳" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "アイコンテーマ" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "全ての空白文字を無視する" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "変更の空白文字を無視する" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "変更の、改行などの行末空白文字を無視する" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "カスタムパターンで無視を指定する" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "厳密に指定したファイル名で無視を指定する" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "ファイル名またはパターンで無視を指定する" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "無視..." #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "タグを含める " #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "インドネシア語翻訳" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "Git Annexを初期化する" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "Git LFSを初期化する" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "サブモジュールを初期化する" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "タブではなく空白スペースを挿入する" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "インタラクティブリベース" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "無効なリビジョン" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "日本語翻訳" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "*.orig マージバックアップを保持" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "インデックスを保持" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "キーボードショートカット" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "差分ツールを起動" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "ディレクトリ差分ツールを起動" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "エディタを起動" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "ターミナルを起動" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" "外部差分ツールを起動\n" "ショートカット: Ctrl+D" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "git-colaを起動" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "git差分ツールを以前のバージョンに対して起動" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "git差分ツールを現在のパスに対して起動" #: cola/icons.py:55 msgid "Light Theme" msgstr "ライトテーマ" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "リスト" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "コミットメッセージをロード" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "コミットメッセージをロード中" #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "以前のコミットメッセージをロード" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "ロード中..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "ローカル" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "ローカルブランチ" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "ローカルブランチ" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "レイアウトのロック" #: cola/widgets/dag.py:816 msgid "Log" msgstr "ログ" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "2007年からのメンテナーと開発者" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "マージ" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "\"%(revision)s\" を \"%(branch)s\" にマージ" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "マージツール" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "マージの冗長度" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "マージ失敗衝突の解明が必要です。" #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "\"%s\"へのマージ" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "現在のブランチへマージ" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "マージ中..." #: cola/widgets/main.py:1177 msgid "Merging" msgstr "マージ中" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "メッセージ" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "コミットメッセージの喪失" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "データの喪失" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "名前の喪失" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "リビジョンの喪失" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "タグメッセージの喪失" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "修正" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "以上..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "下に移動" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "上に移動" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "ファイルをゴミ箱に移動" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "名前" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "新しいリモートの名前" #: cola/guicmds.py:147 cola/widgets/main.py:281 msgid "New Bare Repository..." msgstr "新しい Bare リポジトリ..." #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "新しいリポジトリ..." #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "ツールバーの追加" #: cola/widgets/startup.py:52 msgid "New..." msgstr "新規…" #: cola/actions.py:56 msgid "Next File" msgstr "次のファイル" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "いいえ" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "指定リビジョンがありません" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "コミットする変更がありません\n" "\n" "コミットする前に少なくとも1ファイルをステージしなければなりません。" #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "このブランチにコミットはありません。" #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "ファーストフォワードがありません" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "ファーストフォワードがありません" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "リポジトリが選択されていません。" #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "ファーストフォワードではないフェッチはローカルの履歴を上書きします!" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "ファーストフォワードではないフェッチは発行した履歴を上書きします!\n" "(pullを先に行いますか?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "コミットするものはありません。" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "すべきことはありません" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "diff の文脈行数" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "開く" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Git リポジトリを開く" #: cola/widgets/submodules.py:48 #, fuzzy msgid "Open Parent" msgstr "最近のものを開く" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "親ディレクトリを開く" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "最近のものを開く" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "デフォルトのアプリケーションで開く" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "新しいウィンドウで開く" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "新しいウィンドウで開いています..." #: cola/widgets/main.py:410 msgid "Open..." msgstr "開く…" #: cola/widgets/branch.py:354 msgid "Other branches" msgstr "その他のブランチ" #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "上書き" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "\"%s\"を上書きしますか?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "ファイルを上書きしますか?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "シェルで引数をパースします。\n" "空白文字のあるクエリは二重引用符で囲む必要があります。" #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "部分ステージ" #: cola/widgets/main.py:758 msgid "Paste" msgstr "貼り付け" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "パッチの適用" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "パス" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "CloneのパスやURL(環境変数は解釈できる)" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "ピック" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "Pixel XOR" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "ブランチ名とリビジョン表現を両方を提供してください。" #: cola/cmds.py:2297 msgid "Please select a file" msgstr "ファイルを選択してください" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "新しいタグの名前を指定してください。" #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "タグをつけるためのリビジョンを指定してください。" #: cola/widgets/commitmsg.py:417 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" "- 3行目以降: あなたがした変更の理由を説明します。\n" #: cola/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "現在のブランチのheadを新しいコミットに指定しますか?" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "ポーランド語翻訳" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "Pop" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "設定" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "prefix" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "コミットメッセージの準備" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "何も選択されていないとき、全てのファイルをステージングしないようにする" #: cola/actions.py:65 msgid "Previous File" msgstr "以前のファイル" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "生成時のプロンプト" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "新規のリモートブランチを作成するプッシュ時のプロンプト" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "Prune " #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "プル" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "プル..." #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "プッシュ" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "プッシュ…" #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "終了" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Rebase" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "%s にrebase" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "停止したrebase" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "マージの代わりに現在ブランチをrebase" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "rebase中" #: cola/widgets/main.py:118 msgid "Recent" msgstr "最近" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "最近のリポジトリ" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "最近のリポジトリ数" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "最近の修正ファイル" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "最近の修正ファイル..." #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "ドロップしたスタッシュの回復をはできません。" #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "失なわれたコミットを回復するのは簡単ではありません。" #: cola/widgets/main.py:751 msgid "Redo" msgstr "やり直し" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "コミット履歴を最小に減らす" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "参照リポジトリ" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "参照URL" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "clone時に使用する参照リポジトリ(任意)" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "再読み込み" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "現在のHEADが既に最新ではないまたはマージがファーストフォワードとして解決されない限りマージを拒否する。" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "リモート" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "リモートブランチ" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "リモートブランチ削除" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "リモートgitリポジトリ - ダブルクリックして名前の変更" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "削除" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "最近のリストから %s を削除しますか?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "要素の削除" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "リモートリポジトリ上に今は存在するしないブランチのリモートトラッキングを削除する" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "選択したものを削除 (Delete)" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "名前変更" #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "\"%s\" の名前を変更" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "ブランチの名前変更" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "ブランチの名前変更中..." #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "存在するブランチの名前変更" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "リモートの名前変更" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "リポジトリの名前変更" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "ブランチの名前変更" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "リモートの\"%(current)s\" を \"%(new)s\" と名前を変更しますか?" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "選択したパスの名前を変更" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "リポジトリが見付かりません" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "リポジトリ: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "リセット" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "ブランチの \"%(branch)s\" を \"%(revision)s\" リビジョンにリセットしますか?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "ブランチのリセット" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "ブランチをリセットしますか?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "レイアウトのリセット" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "\"%(branch)s\" ブランチを \"%(revision)s\" リビジョンにリセットするとコミットが失われます。" #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "外観の設定を変更後にこのアプリケーションを再起動します。" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "リバート" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "差分のリバート" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "差分のリバート…" #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "差分をリバートしますか?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "選択行のリバート" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "選択行のリバート…" #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "選択行をリバートしますか?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "コミットしていない変更のリバート" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "コミットしていない変更をリバートしますか?" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "コミットしていない編集のリバート…" #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "ステージングしていない変更のリバート" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "ステージングしていない変更をリバートしますか?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "ステージングしていない編集のリバート…" #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "コミットしていない変更をリバートしますか?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "ステージングしていない変更をリバートしますか?" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "コミットしていない変更を選択パスへリバート" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "ステージングしていない変更を選択パスへリバート" #: cola/guicmds.py:320 msgid "Review" msgstr "レビュー" #: cola/widgets/main.py:597 msgid "Review..." msgstr "レビュー..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "リビジョン" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "リビジョン表現:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "マージするリビジョン" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "書き直し" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "発行済コミットを書き直しますか?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "実行" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "\"%s\"を実行しますか?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "%sを実行しますか?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "\"%s\"コマンドを実行しますか?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "コマンド %s を実行中..." #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "ロシア語翻訳" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "SHA-1" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "セーフモード" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "保存" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "アーカイブ保存" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "Tarball/Zip形式で保存する" #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "GUI設定を保存する" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "スタッシュを保存する" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "修正した状態を新しいスタッシュで保存する" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "\"%(ref)s\" から \"%(destination)s\" に \"%(filename)s\" を保存する" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "検索" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "著者を検索" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "コミットメッセージを検索" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "コミッターを検索" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "検索日時の範囲" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "差分検索" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "表現による検索" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "パスによる検索" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "固定文字列検索" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "POSIX基本正規表現検索" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "POSIX拡張正規表現検索" #: cola/widgets/main.py:507 msgid "Search..." msgstr "検索中..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "選択" #: cola/widgets/main.py:764 msgid "Select All" msgstr "全て選択" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "レビュー対象のブランチを選択" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "子を選択" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "コミットを選択" #: cola/guicmds.py:136 msgid "Select Directory..." msgstr "ディレクトリを選択..." #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "新しいアップストリームを選択" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "最新の子を選択" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "最古の親を選択" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "親を選択" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "以前のバージョンを選択" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "新しいクローン用に親ディレクトリを選択" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "出力ディレクトリを選択" #: cola/widgets/selectcommits.py:182 msgid "Select output directory" msgstr "出力ディレクトリを選択" #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "パッチファイルを選択..." #: cola/widgets/editremotes.py:434 msgid "Select repository" msgstr "リポジトリを選択" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "デフォルトリポジトリを設定" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "アップストリームブランチを設定" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" "ブランチやタグのソート順番を設定します。\n" "ソートを日付順とバージョン名順を切り替えます。" #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "アップストリームを設定" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "設定" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "シェル引数" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "シフトダウン" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "シフトアップ" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "ショートカット" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "マージ後に diffstat を表示" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "ウィンドウタイトルにフルパスを表示" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "ヘルプの表示" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "履歴の表示" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "ステータスタイトリにファイル数を表示" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "ヘルプの表示\n" "ショートカット: ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "行数の表示" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "変更を含む関数全体を表示" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "期日以降の変更の表示 :" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "サイドバイサイド表示" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "署名" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "署名されたタグ" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "このコミットの署名をOFFにする" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "簡体字中国語翻訳" #: cola/cmds.py:2527 msgid "Skip" msgstr "スキップ" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "現在のパスをスキップ" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "ブックマークをアルファベット順にソート" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "スペイン語翻訳" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "タグにSHA-1を指定する" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "タグメッセージを指定する" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "タグ名を指定する" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "スペルの提案" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "スカッシュ" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "複数のマージコミットを一つのコミットにまとめる(スカッシュ)" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "ステージ" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "ステージ / ステージ解除" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "一括ステージ / 一括ステージ解除" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "差分のステージング" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "修正のステージング" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "修正と未追跡のステージング" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "選択分のステージング" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "選択行のステージング" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "非マージ分のステージング" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "未追跡のステージング" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "ステージングとコミット" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "ステージングとコミットをしますか?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "コンフリクトのステージング" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "コンフリクトのステージングしますか?" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "選択したパスのステージングまたは登録解除" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "ステージ済" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "%s をステージしています…" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "インタラクティブリベースを開始する..." #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "初期リビジョン" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "スタッシュ" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "インデックスのスタッシュ" #: cola/widgets/stash.py:79 msgid "Stash staged changes only" msgstr "ステージされた変更のみをスタッシュ" #: cola/widgets/stash.py:75 msgid "Stash unstaged changes only, keeping staged changes" msgstr "ステージされていない変更のみをスタッシュ、ステージされた変更を維持" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "スタッシュ中..." #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "ステータス" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "パスのトラッキングを中止する" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "サブモジュールのURL(取得可能なもの、例: ../repo.git)" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "追跡するサブモジュールのブランチ(任意)" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "現在のリポジトリ内のサブモジュールのパス (任意)" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "サブモジュール" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "マージコミットの要約" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "要約" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "タグ幅" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "タグ" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "作成されたタグ" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "タグメッセージ..." #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "タグの署名が要求されていますが、タグメッセージが空です。" #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "タグ" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "テキスト幅" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "このブランチはもう利用できません。" #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "このブランチは\"git reset --mixed %s\"でリセットする。" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "このブランチは\"git reset --soft %s\"でリセットする。" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "このコミットメッセージはクリアされました。" #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "このファイル \"%s\"は存在します。そんため上書きされます。" #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "以下のファイルは削除されます。:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "このリビジョン表記を空にできません。" #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" "\"%s\"を使ってサブモジュールを\n" "追加します" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" "\"%s\"を使ってサブモジュールを\n" "更新" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "これは元に戻せません。コミットメッセージをクリアしますか?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "このコミットは既に発行済みです。\n" "この操作は、発行済履歴を上書きします。\n" "この操作は、あなたが望んだ操作ではない可能性が高いです。" #: cola/widgets/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "この操作は、コミットしていない変更を破棄します。\n" "これらの変更は回復できません。" #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "この操作は、選択されたファイルのコミットされていない編集を削除します。\n" "これらの変更は回復できません。" #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "この操作は、選択されたファイルのステージされていない編集を削除します。\n" "これらの変更は回復できません。" #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "このリポジトリは現在リベースされています。\n" "衝突を解決し、変更をコミットして実行します。:\n" " Rebase > Continue" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "このリポジトリはマージの中間です。\n" "衝突を解決し、変更をコミットします。:" #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "有効に切り替えます。" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "イメージ差分を切り替えます" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "ブランチフィルタを切り替えます" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "パスフィルタを切り替えます" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "トラッキングブランチ" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "トラッキングブランチ" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "繁体字中国語(台湾)翻訳" #: cola/widgets/about.py:421 msgid "Translation" msgstr "翻訳" #: cola/widgets/about.py:91 msgid "Translators" msgstr "翻訳者" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "トルコ語翻訳" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "URL: %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "ウクライナ語翻訳" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "リベースできません" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "URLの\"%(name)s\" を \"%(url)s\" に設定できません。" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "元に戻す" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "マージされていない" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "ステージされていない" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "全てのステージを解除" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "差分のステージ解除" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "選択をステージ解除" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "選択行をステージ解除する" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "ステージ解除: %s" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "選択を未追跡にする" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "未追跡" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "未追跡にしています: %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "全てのサブモジュールを更新..." #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "既存のブランチを更新:" #: cola/cmds.py:3019 #, fuzzy msgid "Update Submodule" msgstr "更新しました" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 #, fuzzy msgid "Update Submodules" msgstr "サブモジュールを初期化する" #: cola/cmds.py:3053 #, fuzzy msgid "Update all submodules?" msgstr "サブモジュールを初期化しますか?" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 #, fuzzy msgid "Update submodules..." msgstr "サブモジュールを初期化する..." #: cola/widgets/status.py:953 #, fuzzy msgid "Update this submodule" msgstr "サブモジュールを初期化する" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "このサブモジュールを更新しますか?" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "更新" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "ユーザ名" #: cola/widgets/about.py:89 msgid "Version" msgstr "バージョン" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "ビュー" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "ビュー履歴..." #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "選択パスのビュー履歴" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "可視化" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "全てのブランチを可視化" #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "現在ブランチを可視化" #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "タグで署名した場所 (git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "全ての修正したファイルを、ステージしてコミットしますか?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "XOR" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "はい" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "マージ中です。\n" "マージ中は訂正できません。" #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "コミットされていない変更をリベースできません。" #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "マージするリビジョンを指定してください。" #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "表示するリビジョンを指定してください。" #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "ズームイン" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "ズームアウト" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "表示幅に合わせてズーム" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "コマンドライン引数" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "エラー: gitを実行できません。" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "終了コード %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "致命的: \"%s\" はディレクトリではありません。正しいパスを--repo で指定してください。" #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "git cola バージョン %s" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "git-cola diff" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "git://git.example.com/repo.git" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "grep 結果..." #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "hotkeys.html" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "path/to/submodule" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "vX.Y.Z" #: cola/hidpi.py:43 msgid "x 1" msgstr "" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "" #: cola/hidpi.py:46 msgid "x 2" msgstr "" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "yyyy-MM-dd" #~ 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 "" #~ "\n" #~ "Commands\n" #~ "--------\n" #~ "pick = use commit\n" #~ "reword = use commit, but edit the commit message\n" #~ "edit = use commit, but stop for amending\n" #~ "squash = use commit, but meld into previous commit\n" #~ "fixup = like \"squash\", but discard this commit's log message\n" #~ "exec = run command (the rest of the line) using shell\n" #~ "\n" #~ "These lines can be re-ordered; they are executed from top to bottom.\n" #~ "\n" #~ "If you disable a line here THAT COMMIT WILL BE LOST.\n" #~ "\n" #~ "However, if you disable everything, the rebase will be aborted.\n" #~ "\n" #~ "Keyboard Shortcuts\n" #~ "------------------\n" #~ "? = show help\n" #~ "j = move down\n" #~ "k = move up\n" #~ "J = shift row down\n" #~ "K = shift row up\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "spacebar = toggle enabled\n" #~ "\n" #~ "ctrl+enter = accept changes and rebase\n" #~ "ctrl+q = cancel and abort the rebase\n" #~ "ctrl+d = launch difftool\n" #~ msgstr "" #~ "\n" #~ "コマンド\n" #~ "--------\n" #~ "pick = コミットを使う。\n" #~ "reword = コミットを使う、がしかしコミットメッセージを編集する。\n" #~ "edit = コミットを使う、が修正のために停止する。\n" #~ "squash = コミットを使う、が以前のコミットと混ぜ合わせる。\n" #~ "fixup = \"squash\"に似ているが、コミットログのメッセージを破棄する。\n" #~ "exec = シェルを使って、(行の残り部分の)コマンドを実行する。\n" #~ "\n" #~ "これらの行は並べ直すことができます。これは上から下に実行します。\n" #~ "\n" #~ "もし1行を無効にした場合、そのコミットはなくなります。\n" #~ "\n" #~ "しかし、もし全てを無効にした場合、そのrebaseは中止になります。\n" #~ "\n" #~ "キーボードショートカット\n" #~ "------------------\n" #~ "?= ヘルプの表示\n" #~ "j = 下に移動\n" #~ "k = 上に移動\n" #~ "J = shift row down\n" #~ "K = shift row up\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "spacebar = 有効化の切り替え\n" #~ "\n" #~ "ctrl+enter = 変更を受け入れて、rebaseする\n" #~ "ctrl+q = rebaseをキャンセルして、rebaseを中止する。\n" #~ "ctrl+d = diffツールの起動\n" #~ msgid "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "これは Cygwin で配布されている Tcl バイナリに\n" #~ "関しての既知の問題によります" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%1$s ... %4$*i %6$s 中の %2$*i (%7$3i%%)" #~ msgid "%s Repository" #~ msgstr "%s リポジトリ" #~ msgid "%s of %s" #~ msgstr "%s の %s ブランチ" #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "'%s' はブランチ名に使えません。" #~ msgid "* Binary file (not showing content)." #~ msgstr "* バイナリファイル(内容は表示しません)" #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "'マージ先' にはブランチが必要です。" #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "\"%s\" という名前のstashは既に存在します。" #~ msgid "Abort completed. Ready." #~ msgstr "中断完了。" #~ msgid "Abort failed." #~ msgstr "中断に失敗しました。" #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "'%s' のチェックアウトを中止しました(ファイル毎のマージが必要です)。" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "無条件(マージ検査をしない)" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "無条件(マージテストしない)" #~ msgid "Amended Commit Message:" #~ msgstr "訂正したコミットメッセージ:" #~ msgid "Amended Initial Commit Message:" #~ msgstr "訂正した最初のコミットメッセージ:" #~ msgid "Amended Merge Commit Message:" #~ msgstr "訂正したマージコミットメッセージ:" #~ msgid "Annotation complete." #~ msgstr "注釈完了しました" #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "変更を元に戻すとコミット予定していない変更は全て失われます。" #~ msgid "Apply/Reverse Hunk" #~ msgstr "パッチを適用/取り消す" #~ msgid "Arbitrary URL:" #~ msgstr "任意の URL:" #~ 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 "Branch '%s' does not exist." #~ msgstr "ブランチ'%s'は存在しません。" #~ msgid "Branch created" #~ msgstr "ブランチ名" #~ msgid "Browse %s's Files" #~ msgstr "ブランチ %s のファイルを見る" #~ msgid "Browse Branch Files" #~ msgstr "現在のブランチのファイルを見る" #~ msgid "Browse Revision..." #~ msgstr "リビジョン" #~ msgid "Calling commit-msg hook..." #~ msgstr "コミット・メッセージ・フックを実行中・・・" #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\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 "Cannot determine HEAD. See console output for details." #~ msgstr "HEAD を確定できません。コンソール出力を見て下さい" #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "ブランチやオブジェクトを取得できません。コンソール出力を見て下さい" #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "タグを取得できません。コンソール出力を見て下さい" #~ msgid "Cannot find git in PATH." #~ msgstr "PATH 中に git が見つかりません" #~ 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 "Cannot move to top of working directory:" #~ msgstr "作業ディレクトリの最上位に移動できません" #~ msgid "Cannot parse Git version string:" #~ msgstr "Git バージョン名が理解できません:" #~ msgid "Cannot resolve %s as a commit." #~ msgstr "%s をコミットとして解釈できません" #~ msgid "Cannot use funny .git directory:" #~ msgstr "変な .git ディレクトリは使えません" #~ msgid "Cannot write shortcut:" #~ msgstr "ショートカットが書けません:" #~ msgid "Change Font" #~ msgstr "フォントを変更" #~ msgid "Checked out '%s'." #~ msgstr "'%s' をチェックアウトしました" #~ msgid "Clone Type:" #~ msgstr "複製方式:" #~ msgid "Clone failed." #~ msgstr "複写に失敗しました。" #~ msgid "Cloning from %s" #~ msgstr "%s から複製しています" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "コミット %s は壊れています" #~ msgid "Commit declined by commit-msg hook." #~ msgstr "コミット・メッセージ・フックがコミットを拒否しました" #~ msgid "Commit declined by pre-commit hook." #~ msgstr "コミット前フックがコミットを拒否しました" #~ msgid "Commit failed: %s" #~ msgstr "コミットに失敗しました。" #~ msgid "Commit@@noun" #~ msgstr "コミット" #~ msgid "Compress Database" #~ msgstr "データベース圧縮" #~ msgid "Compressing the object database" #~ msgstr "データベース圧縮" #~ msgid "Copied Or Moved Here By:" #~ msgstr "複写・移動者:" #~ msgid "Copying objects" #~ msgstr "オブジェクトを複写しています" #~ msgid "Counting objects" #~ msgstr "オブジェクトを数えています" #~ msgid "Create Desktop Icon" #~ msgstr "デスクトップ・アイコンを作る" #~ msgid "Created commit: %s" #~ msgstr "コミット %s を作成しました: %s" #~ msgid "Creating working directory" #~ msgstr "作業ディレクトリを作成しています" #~ msgid "Current Branch:" #~ msgstr "現在のブランチ" #~ msgid "Database Statistics" #~ msgstr "データベース統計" #~ msgid "Decrease Font Size" #~ msgstr "フォントを小さく" #~ msgid "Delete Local Branch" #~ msgstr "ローカル・ブランチを削除" #~ msgid "Delete Only If" #~ msgstr "条件付で削除" #~ msgid "Delete Only If Merged Into" #~ msgstr "マージ済みの時のみ削除" #~ msgid "Delete selected branch?" #~ msgstr "選択したブランチを削除しますか?" #~ msgid "Destination Repository" #~ msgstr "送り先リポジトリ" #~ msgid "Detach From Local Branch" #~ msgstr "ローカル・ブランチから削除" #~ msgid "Diff/Console Font" #~ msgstr "diff/コンソール・フォント" #~ msgid "Directory %s already exists." #~ msgstr "ディレクトリ '%s' は既に存在します。" #~ msgid "Disk space used by loose objects" #~ msgstr "ばらばらなオブジェクトの使用するディスク量" #~ msgid "Disk space used by packed objects" #~ msgstr "パックされたオブジェクトの使用するディスク量" #~ msgid "Do Nothing" #~ msgstr "何もしない" #~ msgid "Enter Git Repository" #~ msgstr "GIT リポジトリ" #~ msgid "Error %s" #~ msgstr "エラー" #~ msgid "Error loading commit data for amend:" #~ msgstr "訂正するコミットのデータを読めません:" #~ msgid "Error: Command Failed" #~ msgstr "エラー: コマンドが失敗しました" #~ msgid "Error: Stash exists" #~ msgstr "エラー:スタッシュの存在" #~ msgid "Failed to completely save options:" #~ msgstr "完全にオプションを保存できません:" #~ msgid "Failed to configure origin" #~ msgstr "origin を設定できませんでした" #~ msgid "Failed to create repository %s:" #~ msgstr "リポジトリ %s を作製できません:" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "以下のブランチを削除できません:\n" #~ "%s" #~ msgid "Failed to open repository %s:" #~ msgstr "リポジトリ %s を開けません:" #~ msgid "Failed to rename '%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 "Failed to stage selected hunk." #~ msgstr "選択されたパッチをコミット予定に加えられません。" #~ msgid "Failed to unstage selected hunk." #~ msgstr "選択されたパッチをコミット予定から外せません。" #~ msgid "Failed to update '%s'." #~ msgstr "'%s' の更新に失敗しました。" #~ msgid "Fast Forward Only " #~ msgstr "早送りのみ" #~ msgid "Fetch from" #~ msgstr "取得元" #~ msgid "Fetching new changes from %s" #~ msgstr "%s から新しい変更をフェッチしています" #~ msgid "File level merge required." #~ msgstr "ファイル毎のマージが必要です。" #~ msgid "Font Example" #~ msgstr "フォント・サンプル" #~ msgid "Font Family" #~ msgstr "フォント・ファミリー" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "既存ブランチを上書き(変更を破棄する可能性があります)" #~ msgid "From Repository" #~ msgstr "元のリポジトリ" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "全複写(低速・冗長バックアップ)" #~ msgid "Garbage files" #~ msgstr "ゴミファイル" #~ msgid "Git Gui" #~ msgstr "Git GUI" #~ msgid "Git Repository (subproject)" #~ msgstr "Git リポジトリ(サブプロジェクト)" #~ msgid "Git directory not found:" #~ 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 "Hardlinks are unavailable. Falling back to copying." #~ msgstr "ハードリンクが作れないので、コピーします" #~ msgid "Hide Details.." #~ msgstr "詳細を隠す。" #~ msgid "In File:" #~ msgstr "ファイル:" #~ msgid "Increase Font Size" #~ msgstr "フォントを大きく" #~ msgid "Initial Commit Message:" #~ msgstr "最初のコミットメッセージ:" #~ msgid "Initial file checkout failed." #~ msgstr "初期チェックアウトに失敗しました" #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "GIT_COMMITTER_IDENT が無効です:" #~ msgid "Invalid date from Git: %s" #~ msgstr "Git から出た無効な日付: %s" #~ msgid "Invalid font specified in %s:" #~ msgstr "%s に無効なフォントが指定されています:" #~ msgid "Invalid spell checking configuration" #~ msgstr "スペルチェックの設定が不正です" #~ msgid "KiB" #~ msgstr "KiB" #~ 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 "" #~ "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 "" #~ "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 "Linking objects" #~ msgstr "オブジェクトを連結しています" #~ msgid "Loading annotation..." #~ msgstr "注釈を読み込んでいます…" #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "コピー・移動追跡データを読んでいます…" #~ msgid "Loading original location annotations..." #~ msgstr "元位置行の注釈データを読んでいます…" #~ msgid "Local Branches" #~ msgstr "ローカル・ブランチ" #~ msgid "Local Merge..." #~ msgstr "ローカル・マージ…" #~ msgid "Location %s already exists." #~ msgstr "'%s' は既に存在します。" #~ msgid "Main Font" #~ msgstr "主フォント" #~ msgid "Match Tracking Branch Name" #~ msgstr "トラッキング・ブランチ名を合わせる" #~ msgid "Match Tracking Branches" #~ msgstr "トラッキングブランチを合わせる" #~ msgid "Merge completed successfully." #~ msgstr "マージが完了しました" #~ msgid "Merge strategy '%s' not supported." #~ msgstr "'%s' マージ戦略はサポートされていません。" #~ msgid "Merged Into:" #~ msgstr "マージ先:" #~ msgid "Merging %s and %s..." #~ msgstr "%s と %s をマージ中・・・" #~ msgid "Modified, not staged" #~ msgstr "変更あり、コミット未予定" #~ msgid "New Branch Name Template" #~ msgstr "新しいブランチ名のテンプレート" #~ msgid "New Commit" #~ msgstr "新規コミット" #~ msgid "New Name:" #~ msgstr "新しい名前:" #~ 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 "No default branch obtained." #~ msgstr "デフォールト・ブランチが取得されませんでした" #~ 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 "No working directory" #~ msgstr "作業ディレクトリがありません" #~ msgid "Not connected to aspell" #~ msgstr "aspell に接続していません" #~ msgid "Number of loose objects" #~ msgstr "ばらばらなオブジェクトの数" #~ msgid "Number of packed objects" #~ msgstr "パックされたオブジェクトの数" #~ msgid "Number of packs" #~ msgstr "パックの数" #~ 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 "Options" #~ msgstr "オプション" #~ msgid "Original File:" #~ msgstr "元ファイル" #~ msgid "Originally By:" #~ msgstr "原作者:" #~ msgid "PATCH %(current)d/%(count)d" #~ msgstr "PATCH %(current)d/%(count)d" #~ msgid "Packed objects waiting for pruning" #~ msgstr "パックに存在するので捨てて良いオブジェクトの数" #~ msgid "Path to git repository" #~ msgstr "Git リポジトリではありません: %s" #~ msgid "Please select one or more branches to delete." #~ msgstr "削除するブランチを選択して下さい。" #~ msgid "Please supply a branch name." #~ msgstr "ブランチ名を指定して下さい。" #~ msgid "Portions staged for commit" #~ 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 "Preferences..." #~ msgstr "設定…" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "フェッチ中にトラッキングブランチを刈る" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "%s から削除されたトラッキング・ブランチを刈っています" #~ msgid "Push Branches" #~ msgstr "ブランチをプッシュ" #~ msgid "Push to" #~ msgstr "プッシュ先" #~ msgid "Pushing %s %s to %s" #~ msgstr "%3$s へ %1$s %2$s をプッシュしています" #~ msgid "Reading %s..." #~ msgstr "%s を読んでいます…" #~ msgid "Ready to commit." #~ msgstr "コミット準備完了" #~ msgid "Ready." #~ msgstr "準備完了" #~ msgid "Rebase Branch" #~ msgstr "ブランチの名前変更" #~ msgid "Rebase..." #~ msgstr "リセット…" #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "削除したブランチを回復するのは困難です。\n" #~ "\n" #~ "選択したブランチを削除して良いですか?" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "ブランチを削除すると元に戻すのは困難です。 \n" #~ "\n" #~ " 選択したブランチを削除しますか?" #~ msgid "Refreshing file status..." #~ msgstr "ファイル状態を更新しています…" #~ msgid "Remote Branches" #~ msgstr "ブランチの名前変更" #~ msgid "Remote:" #~ msgstr "リモート:" #~ msgid "Rename remote?" #~ msgstr "リモート" #~ msgid "Repository" #~ msgstr "リポジトリ" #~ msgid "Requires merge resolution" #~ msgstr "要マージ解決" #~ msgid "Rescan" #~ msgstr "再スキャン" #~ msgid "Reset Branch Head" #~ msgstr "ブランチをHeadにリセット" #~ msgid "Reset Hard" #~ msgstr "ハードリセット" #~ msgid "Reset Merge" #~ msgstr "マージリセット" #~ msgid "Reset Soft" #~ msgstr "ソフトリセット" #~ msgid "Reset Worktree" #~ msgstr "ワークツリーをリセット" #~ 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 "Reset hard?" #~ msgstr "ハードリセットをしますか?" #~ msgid "Reset merge?" #~ msgstr " マージリセットをしますか?" #~ msgid "Reset soft?" #~ msgstr "ソフトリセットをしますか?" #~ msgid "Reset worktree?" #~ msgstr "ワークツリーをリセットしますか?" #~ msgid "Revert changes in these %i files?" #~ msgstr "これら %i 個のファイルにした変更を元に戻しますか?" #~ msgid "Select File" #~ msgstr "全て選択" #~ msgid "Select Repository..." #~ msgstr "リポジトリを選択..." #~ msgid "Select file from \"%s\"" #~ msgstr "%s からブランチを削除しています。" #~ msgid "Select manually..." #~ msgstr "マニュアルで選択..." #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "共有(最高速・非推奨・バックアップ無し)" #~ msgid "Shared only available for local repository." #~ msgstr "共有方式は同一計算機上のリポジトリにのみ使えます。" #~ msgid "Show Details..." #~ msgstr "詳細の表示..." #~ msgid "Show Less Context" #~ msgstr "文脈を少なく" #~ msgid "Show More Context" #~ msgstr "文脈を多く" #~ msgid "Show icon? (if available)" #~ msgstr "アイコンを表示しますか?(可能な場合)" #~ msgid "Source Branches" #~ msgstr "元のブランチ" #~ msgid "Spell Checker Failed" #~ msgstr "スペルチェック失敗" #~ msgid "Spell checker silently failed on startup" #~ msgstr "スペルチェッカーの起動に失敗しました" #~ msgid "Spell checking is unavailable" #~ msgstr "スペルチェック機能は使えません" #~ msgid "Spelling Dictionary:" #~ msgstr "スペルチェック辞書" #~ msgid "Stage Hunk For Commit" #~ msgstr "パッチをコミット予定に加える" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "ステージングされた(コミット予定済の)変更" #~ msgid "Staged for commit, missing" #~ msgstr "コミット予定済、ファイル無し" #~ msgid "Staged for removal" #~ msgstr "削除予定済" #~ msgid "Staged for removal, still present" #~ msgstr "削除予定済、ファイル未削除" #~ msgid "Staging Area" #~ msgstr "%s をスキャンしています…" #~ msgid "Staging area (index) is already locked." #~ msgstr "インデックスは既にロックされています。" #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "標準(高速・中冗長度・ハードリンク)" #~ msgid "Standard only available for local repository." #~ msgstr "標準方式は同一計算機上のリポジトリにのみ使えます。" #~ msgid "Starting gitk... please wait..." #~ msgstr "gitk を起動中…お待ち下さい…" #~ msgid "Staying on branch '%s'." #~ msgstr "ブランチ '%s' に滞まります。" #~ msgid "Success" #~ msgstr "成功" #~ msgid "Summary:" #~ msgstr "要約:" #~ msgid "The 'main' branch has not been initialized." #~ msgstr "'main' ブランチが初期化されていません" #~ msgid "The branch will be reset using \"git reset --hard %s\"" #~ msgstr "このブランチは\"git reset --hard %s\"でリセットする。" #~ msgid "The branch will be reset using \"git reset --merge %s\"" #~ msgstr "このブランチは\"git reset --merge %s\"でリセットする。" #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "以下のブランチは %s に完全にマージされていません:" #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "以下のブランチは %s に完全にマージされていません:\n" #~ "\n" #~ " - %s" #~ msgid "The worktree will be reset using \"git reset --keep %s\"" #~ msgstr "このワークツリーは\"git reset --keep %s\"でリセットする。" #~ 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 "This Detached Checkout" #~ msgstr "分離されたチェックアウト" #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "これはサンプル文です。\n" #~ "このフォントが気に入ればお使いになれます。" #~ 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 "Tracking branch %s is not a branch in the remote repository." #~ msgstr "トラッキング・ブランチ %s は遠隔リポジトリのブランチではありません。" #~ msgid "Transfer Options" #~ msgstr "通信オプション" #~ msgid "Unable to copy object: %s" #~ msgstr "オブジェクトを複写できません: %s" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "objects/info/alternates を複写できません: %s" #~ msgid "Unable to display %s" #~ msgstr "%s を表示できません" #~ msgid "Unable to hardlink object: %s" #~ msgstr "オブジェクトをハードリンクできません: %s" #~ msgid "Unable to obtain your identity:" #~ msgstr "ユーザの正体を確認できません:" #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "gitk を起動できません:\n" #~ "\n" #~ "%s がありません" #~ msgid "Unable to unlock the index." #~ msgstr "インデックスをロックできません" #~ msgid "Unexpected EOF from spell checker" #~ msgstr "スペルチェッカーが予想外の EOF を返しました" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "不明なファイル状態 %s です。\n" #~ "\n" #~ "ファイル %s は本プログラムではコミットできません。\n" #~ msgid "Unlock Index" #~ msgstr "インデックスのロック解除" #~ 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 "Unrecognized spell checker" #~ msgstr "スペルチェッカーが判別できません" #~ msgid "Unstage Hunk From Commit" #~ msgstr "パッチをコミット予定から外す" #~ msgid "Unsupported spell checker" #~ msgstr "サポートされていないスペルチェッカーです" #~ msgid "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui." #~ msgstr "GIT インデックスの更新が失敗しました。git-gui と同期をとるために再スキャンします。" #~ msgid "Updating working directory to '%s'..." #~ msgstr "作業ディレクトリを '%s' に更新しています…" #~ msgid "Updating..." #~ msgstr "起動中…" #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Thin Pack を使う(遅いネットワーク接続)" #~ msgid "Verify Database" #~ msgstr "データベース検証" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "fsck-objects でオブジェクト・データベースを検証しています" #~ msgid "Visualize %s's History" #~ msgstr "ブランチ %s の履歴を見る" #~ msgid "Working... please wait..." #~ msgstr "実行中…お待ち下さい…" #~ 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 "" #~ "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 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 "You must correct the above errors before committing." #~ msgstr "コミットする前に、以上のエラーを修正して下さい" #~ msgid "[Up To Parent]" #~ msgstr "[上位フォルダへ]" #~ msgid "buckets" #~ msgstr "バケツ" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree が失敗しました:" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "致命的エラー: %s を解決できません" #~ msgid "files" #~ msgstr "ファイル" #~ msgid "files checked out" #~ msgstr "チェックアウトされたファイル" #~ msgid "files reset" #~ msgstr "リセットしたファイル" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "Git のグラフィカルUI git-gui" #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: 致命的なエラー" #~ msgid "lines annotated" #~ msgstr "行を注釈しました" #~ msgid "objects" #~ msgstr "オブジェクト" #~ msgid "pt." #~ msgstr "ポイント" #~ msgid "push %s" #~ msgstr "%s をプッシュ" #~ msgid "remote prune %s" #~ msgstr "遠隔刈込 %s" #~ msgid "title" #~ msgstr "タイトル" #~ msgid "unknown" #~ msgstr "不明" #~ msgid "update-ref failed:" #~ msgstr "update-ref が失敗しました:" #~ msgid "warning" #~ msgstr "警告" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "警告: Tcl はエンコーディング '%s' をサポートしていません" #~ msgid "write-tree failed:" #~ msgstr "write-tree が失敗しました:" git-cola-4.6.1/cola/i18n/pl.po000066400000000000000000003466561457126473700157350ustar00rootroot00000000000000# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # SPDX-FileCopyrightText: 2016, 2020, 2021, 2023 Łukasz Wojniłowicz msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-17 01:06-0700\n" "PO-Revision-Date: 2023-12-28 21:50+0100\n" "Last-Translator: Łukasz Wojniłowicz \n" "Language-Team: Polish \n" "Language: pl_PL\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Generator: Lokalize 23.08.3\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " Przeciągnij i upuść lub naciśnij Dodaj, aby dodać\n" " łaty do listy\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" "\n" "
\n" " Git Cola została przetłumaczona na wiele języków dzięki\n" " pomocy osób wymienionych poniżej.\n" "\n" "
\n" "

\n" " Tłumaczenie jest przybliżone. Jeśli znajdziesz błąd,\n" " daj nam znać, zakładając błąd na Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " Zachęcamy do udziału w tłumaczeniu, poprzez dodawanie lub\n" " uaktualnianie tłumaczenia, a następnie utworzeniu prośby o wciągnięcie.\n" "

\n" "\n" "
\n" "\n" " " #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" "\n" "
\n" " Git Cola w wersji %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" "\n" "
\n" " Użyj %(bug_link)s do zgłaszania błędów.\n" "
\n" " " #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" "\n" " Zmienne do formatowania ciągu znaków\n" " -----------------------\n" " %(path)s = względna ścieżka do pliku\n" " %(abspath)s = bezwzględna ścieżka do pliku\n" " %(dirname)s = względna ścieżka do katalogu\n" " %(absdirname)s = bezwzględna ścieżka do katalogu\n" " %(filename)s = nazwa pliku\n" " %(basename)s = nazwa pliku bez jego rozszerzenia\n" " %(ext)s = rozszerzenie pliku\n" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" "\n" "Polecenia\n" "--------\n" "pick = użyj zmiany\n" "reword = użyj zmiany, lecz zmień jej nazwę i opis\n" "edit = użyj zmiany, lecz zatrzymaj się, aby coś do niej dodać\n" "squash = użyj zmiany, lecz scal z poprzednią\n" "fixup = jak \"squash\", lecz porzuć ten opis\n" "exec = wykonaj polecenie (reszta wiersza) w powłoce\n" "update-ref = uaktualnij gałęzie, które wskazują na zmiany\n" "\n" "Kolejność tych wierszy można zamieniać; zostaną wykonane od góry do dołu.\n" "\n" "Jeśli wyłączysz tutaj wiersz, to UTRACISZ TĘ ZMIANĘ.\n" "\n" "Jednakże, gdy wyłączysz wszystko, to przerwiesz zmienianie podstawy.\n" "\n" "Skróty klawiszowe\n" "------------------\n" "? = pokaż pomoc\n" "j = przejdź w dół\n" "k = przejdź w górę\n" "J = przesuń wiersz w dół\n" "K = przesuń wiersz w górę\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = przestaw na włączony\n" "\n" "ctrl+enter = przyjmij zmiany i zmień podstawę\n" "ctrl+q = anuluj i porzuć zmienianie podstawy\n" "ctrl+d = uruchom narzędzie różnicy\n" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" "\n" "Skróty klawiszowe\n" "------------------\n" "J, Strzałka w dół = Przejdź w dół\n" "K, Strzałka w górę = Przejdź w górę\n" "Enter = Zmień wybrany plik\n" "Spacja = Otwórz plik przy użyciu domyślnej aplikacji\n" "Ctrl + L = Uaktywnij pole wprowadzania tekstu\n" "? = Pokaż pomoc\n" "\n" "Strzałki w górę i dół zmieniają uaktywnienie pomiędzy polem tekstowym\n" "i wynikami.\n" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr " - DAG" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr " zmian temu" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "\"%(branch)s\" została usunięta z \"%(remote)s\"." #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "\"%(command)s\" zwróciło kod wyjścia \"%(status)d\"" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "\"%(command)s\" zwróciło kod wyjścia %(status)d" #: cola/guicmds.py:156 #, python-format msgid "\"%s\" already exists" msgstr "\"%s\" już istnieje" #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "\"%s\" już istnieje, cola utworzy nowy katalog" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "\"%s\" wymaga wybrania pliku." #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" "\"git rebase --update-refs\" sam siłowo uaktualnia wszystkie\n" "gałęzie, które wskazują na zmiany, który podstawa ulegnie zmianie.\n" "\n" "Wszystkie gałęzie, które zostały pobrane w drzewie pracy nie zostaną uaktualnione.\n" "\n" "Używanie tego jest pomocne przy pracy z \"nałożonymi\" gałęziami." #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "#" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s: %(branch)s - Przeglądaj" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "%(project)s: %(ref)s - DAG" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "%d dni temu" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "%d godzin temu" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "%d minut temu" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "Zastosowano %d łat" #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "Pominięto %d" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" "Wygląda na to, że %s zawiera sprzeczności po scaleniu.\n" "\n" "Powinieneś pominąć ten plik.\n" "Czy dobrać go mimo tego?" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "Nie można otworzyć %s. Czy usunąć z zakładek?" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "%s nie jest repozytorium Git." #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "%s zostanie usunięta z twoich zakładek." #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "%s zostanie usunięte z listy ostatnich repozytoriów." #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: Nie ma takiego pliku lub katalogu." #: cola/widgets/main.py:748 msgid "&Edit" msgstr "&Edycja" #: cola/widgets/main.py:690 msgid "&File" msgstr "Plik" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(Uzupełnianie)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "*** Punkt gałęzi ***" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** Piaskownica ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "100%" #: cola/widgets/diff.py:817 msgid "200%" msgstr "200%" #: cola/widgets/diff.py:814 msgid "25%" msgstr "25%" #: cola/widgets/diff.py:818 msgid "400%" msgstr "400%" #: cola/widgets/diff.py:815 msgid "50%" msgstr "50%" #: cola/widgets/diff.py:819 msgid "800%" msgstr "800%" #: cola/widgets/finder.py:118 msgid " ..." msgstr "<ścieżka> ..." #: cola/cmds.py:1685 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 "" "Wzorzec zmiany nie został ustawiony.\n" "Wykonaj \"git config\", aby ustawić \"commit.template\"\n" "tak, aby wskazywał na plik wzorca zmiany." #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "Należy podać haczyk w \"%s\"" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "Przerwij" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "Przerwij działanie" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "Przerwij stosowanie łaty" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "Przerwij stosowanie łaty..." #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "Przerwij stosowanie łat..." #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "Przerwij wybiórcze zaciąganie" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "Przerwij wybiórcze zaciąganie..." #: cola/cmds.py:192 msgid "Abort Merge" msgstr "Przerwij scalanie" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Przerwij scalanie..." #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "Przerwać działanie?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "Przerwij bieżące posiedzenie łatania \"git am\"" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Przerwanie zaciągnięcia wybiórczego może spowodować utratę niezatwierdzonych zmian.\n" "Przywrócenie ich będzie niemożliwe." #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Przerwanie nakładania łaty może spowodować utratę niezatwierdzonych zmian.\n" "Przywrócenie ich będzie niemożliwe." #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "Przerwać stosowanie bieżącej łaty?" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "Przerwać bieżące zaciągnięcie wybiórcze?" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Przerwanie obecnego scalania spowoduje utratę *WSZYSTKICH* niezatwierdzonych zmian.\n" "Przywrócenie niezatwierdzonych zmian będzie niemożliwe." #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "Przerwać bieżące scalanie?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "O programie" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "O git-cola" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "Przyjmij" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "Przyjmij zmiany i zmień podstawę\n" "Skrót: Ctrl+Enter" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "Nazwa działania" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "Działania" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "Działania..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "Dodaj" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "Dodaj ulubione" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "Dodaj zdalne repozytorium" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "Dodaj oddzielacz" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "Dodaj podmoduł" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "Dodaj podmoduł..." #: cola/widgets/editremotes.py:60 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 "" "Dodaj lub usuń zdalne repozytorium przy użyciu \n" "przycisku Dodaj(+) lub Usuń(-) po lewej stronie.\n" "\n" "Nazwy repozytoriów zdalnych można zmienić zaznaczając je na wykazie\n" "i naciskając \"enter\" lub klikając dwukrotnie." #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "Dodaj nowe zdalne repozytorium git" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "Dodaj łaty (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "Dodaj zdalne repozytorium" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "Czy dodać ten podmoduł?" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "Dodaj do .gitignore" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "Dodaj do Git Annex" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "Dodaj do Git LFS" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "Dodaj do wykluczonych" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "Dodaj do lokalnego .git/info/exclude" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "Dodano" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "Zaawansowane" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "Względem zmiany... (tryb różnicy)" #: cola/models/browse.py:32 msgid "Age" msgstr "Wiek" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "Wszystkie repozytoria" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" "Wszystkie podmoduły zostaną uaktualnione przy użyciu\n" "\"%s\"" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "Zezwól na uaktualnienia nie będące przewinięciem do przodu. Użycie \"wymuś\" może spowodować, że zdalne repozytoria zgubią zmiany; używaj z rozwagą" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "Zawsze twórz zmianę scalenia, gdy włączone, nawet gdy scalanie polega na przewinięciu do przodu" #: cola/cmds.py:220 msgid "Amend" msgstr "Uzupełnij" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "Uzupełnij zmianę" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Uzupełnij ostatnią zmianę" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "Uzupełnić opublikowaną zmianę?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "Uzupełnianie" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "Działanie nadal jest wykonywane.\n" "Jego zakończenie może skutkować utratą danych." #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "Zamiast tego zostanie utworzony niepodpisany, lekki znacznik.\n" "Czy utworzyć niepodpisany znacznik?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "Wygląd" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "Dołącz łatę" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "Dołącz łatę..." #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "Zastosuj" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "Stosowanie łat" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "Zastosuj łaty..." #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "Zastosuj i porzuć wybraną przechowalnię (git stash pop)" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "Zastosuj wybraną przechowalnię" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "Nakładanie łaty" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "Argumenty" #: cola/qtutils.py:886 msgid "Attach" msgstr "Dołącz" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "Autor" #: cola/widgets/about.py:90 msgid "Authors" msgstr "Autorzy" #: cola/hidpi.py:41 msgid "Auto" msgstr "Auto" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "Zawijaj wiersze" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "Uzupełniaj ścieżki" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "Sam wczytaj wzorzec opisu zmiany" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "Podstawowe wyrażenie regularne" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "Przeglądarka autorów" #: cola/widgets/browse.py:206 msgid "Blame selected paths" msgstr "Obwiń wybrane ścieżki" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "Przejrzyj autorów..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "Wytłuść czcionkę zamiast ją pochylać na ciemnych nagłówkach" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Gałąź" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "Gałąź \"%(branch)s\" nie istnieje w \"%(remote)s\".\n" "Zostanie opublikowana nowa zdalna gałąź." #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "Gałąź \"%s\" już istnieje." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "Przeglądarka różnic na gałęziach" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "Gałąź istnieje" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Nazwa gałęzi" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "Nazwa gałęzi" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "Gałąź: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "Gałęzie" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "Pomiędzy gałęziami..." #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "Tłumaczenie na brazylijski" #: cola/guicmds.py:52 msgid "Browse" msgstr "Przeglądaj" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "Przejrzyj zmiany..." #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "Przejrzyj bieżącą gałąź..." #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "Przejrzyj inną gałąź..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "Przeglądaj..." #: cola/widgets/main.py:87 msgid "Browser" msgstr "Przeglądarka" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "Przeglądanie %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "Pomiń wykonywanie haczyków" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "Zaniechaj" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "Zaniechaj zmieniania podstawy\n" "Skrót: Ctrl+Enter" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "Nie można uzupełnić" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "Nie można wykonać \"%s\": najpierw ustaw przeglądarkę autorów" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "Nie można wykonać \"%s\": najpierw ustaw przeglądarkę historii" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "Nie można wykonać \"%s\": ustaw swój edytor" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "Zmienione w źródle odgórnym" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "Uzupełniając zmianę, sprawdź jej opublikowanie" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "Sprawdź pisownię" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "Sprawdź pisownię" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "Sprawdź, czy zmiana została już opublikowana, przed jej uzupełnieniem" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Przełącz" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "Przełącz po utworzeniu" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Przełącz na gałąź" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "Przełącz na odłączony HEAD" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "Pobierz pliki" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "Przełącz jako nowa gałąź" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "Pobierz pliki z naszej gałęzi (HEAD)" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "Pobrać pliki z naszej gałęzi?" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "Pobierz pliki z ich gałęzi (MERGE_HEAD)" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "Pobrać pliki z ich gałęzi?" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Przełącz..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "Zaciągnij wybiórczo" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "Wybiórczo zaciągnij zmianę" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "Zaciągnij wybiórczo..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "Nie udało się zaciągnąć wybiórczo" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "Zaciąganie wybiórcze" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "Wybierz łatę..." #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "Wybierz ścieżkę/ścieżki" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "Wybierz tryb wyrażenia regularnego \"git grep\"" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "Wyczyść domyślne repozytorium" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "Wyczyść opis zmiany" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "Wyczyścić opis zmiany?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "Wyczyść..." #: cola/widgets/clone.py:124 msgid "Clone" msgstr "Pobierz" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "Pobieranie repozytorium" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Pobierz..." #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "Pobieranie repozytorium o adresie %s" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Zamknij" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "Zamknij pasek wyszukiwania" #: cola/qtutils.py:650 msgid "Close..." msgstr "Zamknij..." #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "Zwiń wszystko" #: cola/sequenceeditor.py:371 msgid "Command" msgstr "Polecenie" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "Zmiana" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "Nie udało się zatwierdzić" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "Zatwierdź dobrane zmiany" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "Zatwierdź zebrane zmiany\n" "Skrót: Ctrl+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "Nazwa zmiany" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "Zatwierdź bieżący stan i kontynuuj stosowanie pozostałych łat" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "Zatwierdź scalenie, jeśli brak sprzeczności. Odznacz pole, aby pozostawić scalenie niezatwierdzonym" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "Zatwierdź@@verb" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "Porównaj" #: cola/difftool.py:102 msgid "Compare All" msgstr "Porównaj wszystkie" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "Ustawienia paska narzędzi" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "Ustaw zdalną gałąź jako nową gałąź odgórną" #: cola/widgets/main.py:169 msgid "Console" msgstr "Konsola" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Dalej" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "Kontynuuj stosowanie łat" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Skopiuj " #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "Skopiuj nazwę pliku do schowka" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "Skopiuj różnicę" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "Skopiuj ścieżkę katalogu do schowka" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "Skopiuj ścieżkę do schowka" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "Skopiuj względną ścieżkę do schowka" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "Skopiuj SHA-1" #: cola/widgets/status.py:738 msgid "Copy..." msgstr "Skopiuj..." #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "Nie można otworzyć %s." #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "Nie można przetworzyć adresu URL Gita: \"%s\"" #: cola/app.py:499 msgid "Create" msgstr "Utwórz" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Utwórz gałąź" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "Utwórz łatę" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "Utwórz zdalną gałąź" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "Podpisz zmianę" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "Utwórz znacznik" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "Utwórz znacznik..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "Utwórz niepodpisany znacznik" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "Utwórz zmianę scalenia, nawet gdy scalanie będzie polegać na przewinięciu do przodu" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "Czy utworzyć nową zdalną gałąź?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "Czy utworzyć nowe repozytorium w tym miejscu?" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "Pobierz płytko z historią przyciętą do danej liczby wydań. 0 wykonuje pobiera z całą historią." #: cola/widgets/main.py:565 msgid "Create..." msgstr "Utwórz..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "Utworzono nowy znacznik o nazwie \"%s\"" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "Ctrl+rolka myszy, aby powiększać" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "Bieżące repozytorium" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "Własne działania kopiowania" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "Dostosuj..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "Wytnij" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "Tłumaczenie na czeski" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "DAG..." #: cola/icons.py:54 msgid "Dark Theme" msgstr "Ciemne" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "Data, czas" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "Domyślne" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" "Domyślny katalog do eksportowania łat.\n" "Odniesieniem dla ścieżek względnych będzie bieżące repozytorium.\n" "Ścieżki bezwzględne będą używane tak jak podano." #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Usuń" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "Usunąć %d plik(ów)?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "Usuń zakładkę" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "Usunąć zakładkę?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Usuń gałąź" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "Usuń pliki" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "Usuń plik(i)..." #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "Usunąć pliki?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "Usuń zdalną gałąź" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "Usuń zdalną gałąź" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "Usuń zdalną gałąź..." #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "Usuń pasek narzędzi" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "Usuń gałąź \"%s\"?" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "Usuń zdalne repozytorium" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "Usuń zdalne repozytorium \"%s\"" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "Usunąć zdalne repozytorium?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Usuń..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "Nie udało się usunąć \"%s\"" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "Usunięto" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "Głębokość" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "Odczep" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "Wykryj znaczniki sprzeczności" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "Wykryj znaczniki sprzeczności w niescalonych plikach" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "Programista" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "Różnica" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "Różnica względem zmiany" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "Różnica wzgl. poprzednika..." #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "Tryb różnicy" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "Opcje różnicy" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "Narzędzie różnicy" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "Różnica zaznaczenia wzgl. tego" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "Różnica tego wzgl. zaznaczenia" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "Statystyka różnicy" #: cola/difftool.py:324 msgid "Difftool" msgstr "Narzędzie różnicy" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "Katalog istnieje" #: cola/hidpi.py:42 msgid "Disable" msgstr "Wyłącz" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "Wyświetl niezarządzane pliki" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "Nie uaktualniaj nałożonych gałęzi" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "Dokumentacja" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "Porzuć" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "Porzuć przechowalnię" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "Porzucić przechowalnię?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "Porzucić przechowalnię \"%s\"?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "Porzuć wybraną przechowalnię" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 msgid "Edit" msgstr "Zmień" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "Edytuj kawałek różnicy przed jego wycofaniem..." #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "Edytuj kawałek różnicy przed jego dobraniem..." #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "Edytuj kawałek różnicy przed jego odłożeniem..." #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "Ustawienia zmiany podstawy" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "Zmień zdalne repozytoria" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "Zmień zdalne repozytoria..." #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "Edytuj zaznaczone wiersze przed ich wycofaniem..." #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "Edytuj zaznaczone wiersze przed ich dobraniem..." #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "Edytuj zaznaczone wiersze przed ich odłożeniem..." #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "Zmień repozytoria zdalne poprzez wybranie ich z wykazu" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "Zmień wybraną ścieżkę/ścieżki" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "Edytuj następującą łatę, która następnie zostanie nałożona w obszarze dobierania do dobierania zmian:" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "Edytuj następującą łatę, która następnie zostanie nałożona w obszarze dobierania do odłożenia zmian:" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "Edytuj następującą łatę, która następnie zostanie nałożona na drzewo pracy do wycofania zmian:" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "Ustawienia..." #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "Edytor" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "Edytor zwrócił %s jako kod wyjścia. Nie nałożono łaty." #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "Adres email" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "Napisz do współtwórcy" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "Włącz ikony z Gravatar" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "Włącz uzupełnianie ścieżki w narzędziach" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "Włącz zawijanie słów" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "Uwzględnione" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "Podaj nazwę nowej gałęzi" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "Wpisz nazwę do założenia nowego repozytorium" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "Podaj nazwę dla przechowalni" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "Błąd" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "Błąd pobierania" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "Błąd tworzenia gałęzi" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "Błąd tworzenia repozytorium" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "Błąd usuwania zdalnej gałęzi" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "Błąd edytowania pliku" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "Nie można uruchomić przeglądarki autorów" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "Nie można uruchomić przeglądarki historii" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "Błąd otwierania repozytorium" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "Błąd podczas zapisu pliku" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "Błąd podczas tworzenia zdalnego repozytorium \"%s\"" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "Błąd tworzenia przechowalni" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "Błąd usuwania gałęzi \"%s\"" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Błąd usuwania zdalnego repozytorium \"%s\"" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "Nie udało się przemianować \"%(name)s\" na \"%(new_name)s\"" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "Nie udało się wykonać haczyka prepare-commitmsg" #: cola/cmds.py:2987 cola/cmds.py:3033 #, python-format msgid "Error updating submodule %s" msgstr "Nie udało się uaktualnić podmodułu\"%s\"" #: cola/cmds.py:3069 msgid "Error updating submodules" msgstr "Nie udało się uaktualnić podmodułów" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "Błąd zapisywania łaty" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "Błąd: Nie można znaleźć wzorca opisu zmiany" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "Błąd: Nie ustawiono wzorca opisu zmiany" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Błąd: nie można pobrać \"%s\"" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "Błąd: nie można utworzyć znacznika \"%s\"" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "Wykonywanie działania %s" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "Wyjdź z trybu \"różnicy\"" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "Wyjdź z trybu różnicy" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "Wyjdź z trybu różnicy" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "Wyjdź z trybu różnicy" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "Rozwiń wszystko" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "Wyeksportuj łatę" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "Eksportowanie łat" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "Wyeksportuj łaty..." #: cola/widgets/main.py:547 msgid "Expression..." msgstr "Pomiędzy wyrażeniami zmian..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "Rozszerzone wyrażenie regularne" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "Rozbudowany opis zmiany..." #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "Nie udało się zatwierdzić i kontynuować stosowanie pozostałych łat" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "Nie udało się nałożenie łat po pominięciu bieżącej łaty" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Wyłącznie przewijając do przodu" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "Wyłącznie przewinięcie do przodu" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "Ulubione repozytoria" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "Ulubione" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "Pobierz" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "Pobierz odgórną gałąź" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "Pobierz..." #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "Przeglądarka plików..." #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "Różniące się pliki" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "Zapisano plik" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "Plik zapisano w \"%s\"" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "Monitorowanie zmiany systemu plików: wyłączone, bo \"cola.inotify\" jest false.\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "Monitorowanie zmiany systemu plików: wyłączone, bo libc nie obsługuje wywołań systemowych inotify.\n" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "Monitorowanie zmiany systemu plików: wyłączone, bo nie wgrano pywin32.\n" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" "Monitorowanie zmiany systemu plików: wyłączone, bo osiągnięto górną granicę całkowitej liczby obserwowanych inotify. Możesz zwiększyć tę granicę wykonując:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "Monitorowanie zmiany systemu plików: włączone.\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "Nazwa pliku" #: cola/widgets/dag.py:821 msgid "Files" msgstr "Pliki" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "Odfiltruj gałęzie..." #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "Odfiltruj ścieżki..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "Poszukaj plików" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "Poszukaj w różnicy" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "Poszukaj następnej rzeczy" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "Poszukaj poprzedniej rzeczy" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "Poszukaj następnego wystąpienia wyrażenia" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "Poszukaj poprzedniego wystąpienia wyrażenia" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "Stały ciąg znaków" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "Czcionka o stałej szerokości" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "Popraw" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "Popraw wcześniejszą zmianę" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "Płaski, ciemny, niebieski" #: cola/themes.py:705 msgid "Flat dark green" msgstr "Płaski, ciemny, zielony" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "Płaski, ciemny, szary" #: cola/themes.py:691 msgid "Flat dark red" msgstr "Płaski, ciemny, czerwony" #: cola/themes.py:656 msgid "Flat light blue" msgstr "Płaski, jasny, niebieski" #: cola/themes.py:677 msgid "Flat light green" msgstr "Płaski, jasny, zielony" #: cola/themes.py:670 msgid "Flat light grey" msgstr "Płaski, jasny, szary" #: cola/themes.py:663 msgid "Flat light red" msgstr "Płaski, jasny, czerwony" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "Katalog" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "Zgodnie z wyglądem systemu" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Rozmiar czcionki" #: cola/widgets/remote.py:197 msgid "Force" msgstr "Wymuś" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "Wymuś pobranie" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "Wymusić pobranie?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "Wymuś wypchnięcie" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "Wymusić wypchnięcie?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "Wymusić pobranie z %s?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "Wymusić wypchnięcie do %s?" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "Sformatowany ciąg znaków" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "Tłumaczenie na francuski" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "Podpisz-GPG zmianę scalenia" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "Ogólny wygląd" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "Zbieranie informacji dla \"%s\"..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "Tłumaczenie na niemiecki" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "Pobierz wzorzec opisu zmiany" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "Przejdź w dół" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "Przejdź w górę" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "Pobierz plik..." #: cola/widgets/dag.py:848 msgid "Graph" msgstr "Graf" #: cola/widgets/main.py:354 msgid "Grep" msgstr "Wyszukaj (grep)" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "Czy ostatnio zmieniłeś podstawę/zaciągnąłeś?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Pomoc" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "Pomoc - Własne działania kopiowania" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "Pomoc - poszukaj plików" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "Pomoc - git-cola-sequence-editor" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "Wysokie DPI" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "Wskazówka: Menu \"Działania > Przerwij zaciąganie wybiórcze\" można wykorzystać do anulowania bieżącego zaciągania wybiórczego." #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "Przeglądarka historii" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "Tłumaczenie na węgierski" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "Tylko ikona" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "Zestaw ikon" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "Pomiń wszystkie białe znaki" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "Pomiń zmiany w liczbie białych znaków" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "Pomiń zmiany w białych znakach na końcu wiersza" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "Pomiń własny wzorzec" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "Pomiń dokładne nazwy plików" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "Pomiń nazwy plików lub wzorce" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "Pomiń..." #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "Ze znacznikami " #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "Wetnij ścieżki w oknie stanu" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "Tłumaczenie na indonezyjski" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "Przygotuj Git Annex" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "Przygotuj Git LFS" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "Przygotuj podmoduły" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "Wstaw odstępy zamiast tabulatorów" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "Zmień podstawę interaktywnie" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "Nieprawidłowe wydanie" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "Nie jest konieczne uaktualnienie wierszy nagłówków kawałka, bo zostaną one napisane samoczynnie." #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "Japońskie tłumaczenie" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "Zachowaj kopie zapasowe *.orig po scaleniu" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "Pozostaw indeks" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "Skróty klawiszowe" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "Wywołaj narzędzie różnicy" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "Wywołaj narzędzie różnicy na katalogu" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "Otwórz w edytorze" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "Otwórz terminal" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" "Wywołaj zewnętrzne narzędzie różnicy\n" "Skrót: Ctrl+D" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "Uruchom git-cola" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "Uruchom git-difftool względem poprzednich wersji" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "Uruchom git-difftool dla bieżącej ścieżki" #: cola/icons.py:55 msgid "Light Theme" msgstr "Jasne" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "Wiersze zaczynające na '%s' będą pomijane." #: cola/widgets/startup.py:73 msgid "List" msgstr "Lista" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "Wczytaj opis zmiany" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "Wczytaj opis zmiany..." #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "Wczytaj opis wcześniejszej zmiany" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "Wczytywanie..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "Lokalne repozytoria" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Lokalna gałąź" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "Lokalna gałąź" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "Zablokuj układ" #: cola/widgets/dag.py:816 msgid "Log" msgstr "Dziennik" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "Zapis daty w dzienniku" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "Opiekun (od 2007) i programista" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "Rozróżniaj wielkość liter" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Scal" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "Scal \"%(revision)s\" z \"%(branch)s\"" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "Narzędzie scalania" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Szczegółowość przy scalaniu" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "Nie udało się scalić. Wymagane jest rozwiązanie sprzeczności." #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "Scal z \"%s\"" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "Scal z bieżącą gałęzią" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "Scal..." #: cola/widgets/main.py:1177 msgid "Merging" msgstr "Scalanie" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "Opis" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "Brak opisu zmiany" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "Brakuje danych" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "Brak nazwy" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "Brak wydania" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "Brak opisu znacznika" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "Zmienione" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "Więcej..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "Przesuń w dół" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "Przesuń w górę" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "Przenieś plik(i) do kosza" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "Nazwa" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "Nazwa nowego zdalnego repozytorium" #: cola/guicmds.py:147 cola/widgets/main.py:281 msgid "New Bare Repository..." msgstr "Nowe repozytorium bez drzewa pracy..." #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "Nowe repozytorium..." #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "Dodaj pasek narzędzi" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Nowe..." #: cola/actions.py:56 msgid "Next File" msgstr "Następny plik" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "Nie" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "Nie podano wydania" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Nie ma żadnych zmian do zatwierdzenia.\n" "\n" "Aby cokolwiek zatwierdzić, należy dobrać co najmniej 1 plik." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "Brak zmian w tej gałęzi." #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "Nie przewijaj do przodu" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "Nie przewijaj do przodu" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Nie wybrano repozytorium." #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "Pobranie bez przewinięcia do przodu zastępuje lokalną historię!" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "Wypchnięcie bez przewinięcia do przodu zastępuje opublikowaną historię!" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "Nie ma nic do zatwierdzenia" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "Nie ma nic do zrobienia" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Liczba wierszy otaczających różnicę" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Otwórz" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "Otwórz \"%s\"" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "Otwórz katalog" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Otwórz repozytorium Git" #: cola/widgets/submodules.py:48 msgid "Open Parent" msgstr "Otwórz nadrzędny" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "Otwórz katalog nadrzędny" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "Otwórz z ostatnich" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "Otwórz w domyślnej aplikacji" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "Otwórz drzewo pracy" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "Otwórz w nowym oknie" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "Otwórz w nowym oknie..." #: cola/widgets/main.py:410 msgid "Open..." msgstr "Otwórz..." #: cola/widgets/branch.py:354 msgid "Other branches" msgstr "Inne gałęzie" #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "Zastąp" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "Zastąpić \"%s\"?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "Zastąpić plik?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "Przetwórz argumenty przy użyciu powłoki.\n" "Zapytania z odstępami będą wymagać cudzysłowów." #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "Częściowo dobrany" #: cola/widgets/main.py:758 msgid "Paste" msgstr "Wklej" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "Nie udało się nałożyć łaty" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "Zastosowano łatę/łaty" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "Łaty" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "Katalog łat" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "Ścieżka" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "Ścieżka lub adres URL do pobrania (Zm. środowiskowe $VARS są OK)" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "Użyj" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "Pixel XOR" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "Podaj zarówno nazwę gałęzi jak i wyrażenie wydania." #: cola/cmds.py:2297 msgid "Please select a file" msgstr "Wybierz plik" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "Podać nazwę dla nowego znacznika." #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "Podaj wydanie do oznaczenia." #: cola/widgets/commitmsg.py:417 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 "" "Stwórz opis zmiany.\n" "\n" "Dobry opis zmiany ma następującą postać:\n" "\n" "- Pierwszy wiersz: Opisz w jednym zdaniu co zrobiłeś.\n" "- Drugi wiersz: Pusty\n" "- Pozostałe wiersze: Opisz dlaczego ta zmiana jest dobra.\n" #: cola/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "Ustawić HEAD bieżącej gałęzi na nowej zmianie?" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "Tłumaczenie na polski" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "Pobierz" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Ustawienia" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "Przedrostek" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "Przygotuj opis zmiany" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "Uniemożliw dobranie wszystkich plików, gdy nie jest zaznaczony żaden plik" #: cola/actions.py:65 msgid "Previous File" msgstr "Poprzedni plik" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "Zapytaj przed stworzeniem" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "Zapytaj, gdy wypchnięcie miałoby utworzyć nową zdalną gałąź" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "Oczyść " #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "Oczyść brakujące wpisy" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "Zaciągnij" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "Zaciągnij..." #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Wypchnij" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Wypchnij..." #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "Szybkie otwieranie repozytoriów" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "Szybkie otwarcie..." #: cola/widgets/main.py:351 msgid "Quit" msgstr "Wyjdź" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Zmień podstawę" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "Zmień podstawę na %s" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "Zatrzymano zmianę podstawy" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "Zmień podstawę bieżącej gałęzi zamiast scalić" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "Zmień podstawę na tę zmianę" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "Zmiana podstawy" #: cola/widgets/main.py:118 msgid "Recent" msgstr "Ostatnie" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "Ostatnie repozytoria" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "Liczba ostatnich repozytoriów" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "Ostatnio zmienone pliki" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "Ostatnio zmienone pliki..." #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "Odzyskanie porzuconej przechowalni będzie niemożliwe." #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Przywrócenie utraconych zmian może nie być łatwe." #: cola/widgets/main.py:751 msgid "Redo" msgstr "Przywróć" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "Ogranicz historię zmian do minimum" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "Repozytorium odniesienia" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "Adres URL odniesienia" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "Repozytorium odniesienia, używane podczas pobierania (niewymagane)" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Odśwież" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "Odmów scalenia do chwili uaktualnienia bieżącego HEAD lub rozwiązania scalenia poprzez przewinięcie do przodu." #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Zdalne repozytoria" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "Zdalna gałąź" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "Usunięto zdalną gałąź" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "Zdalne repozytoria git - kliknij dwukrotnie, aby przemianować" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "Usuń" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "Usunąć %s z listy ostatnich?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "Usuń element" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "Usuń gałęzie zdalne, które już nie istnieją w repozytorium zdalnym" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "Usuń wybrane (Usuń)" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "Usuń zawisłe wpisy dla repozytoriów, które już nie istnieją" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Przemianuj " #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "Przemianuj \"%s\"" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "Przemianuj gałąź" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "Przemianuj gałąź..." #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "Przemianuj istniejącą gałąź" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "Przemianuj zdalne repozytorium" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "Przemianuj repozytorium" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "Przemianuj gałąź" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "Przemianuj zdalne repozytorium z \"%(current)s\" na \"%(new)s\"?" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "Przemianuj wybrane ścieżki" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "Nie znaleziono repozytorium" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "Repozytorium: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Wyzeruj" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "Wyzerować \"%(branch)s\" do \"%(revision)s\"?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "Wyzeruj wszystko (zachowaj niedobrane zmiany)" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "Wyzeruj gałąź" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "Wyzeruj gałąź (miękko)" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "Wyzeruj gałąź i dobierz (mieszanie)" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "Wyzerować gałąź?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "Wyzeruj układ" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "Czy wyzerować drzewo pracy i wszystko?" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "Wyzeruj i przywróć" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "Czy wyzerować gałąź?" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "Wyzerowanie \"%(branch)s\" do \"%(revision)s\" spowoduje utratę zmian." #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "Zmień rozmiar kolumn przeglądarki plików" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "Uruchom aplikację ponownie po zmianie ustawień wyglądu." #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "Przywróć drzewo pracy" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "Przywróć drzewo i wyzeruj wszystko (twardo)" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "Przywróć drzewo i wyzeruj wszystko (zachowaj niedobrane zmiany)" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "Przywróć drzewo i wyzeruj wszystko (zachowaj niedobrane zmiany)" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "Przywróć drzewo i wyzeruj wszystko (scal)" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "Czy przywrócić drzewo i wyzerować wszystko?" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "Czy przywrócić drzewo pracy do %s?" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "Czy przywrócić drzewo pracy, wyzerować i zachować niedobrane zmiany?" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "Wycofaj" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "Wycofaj kawałek różnicy" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "Wycofaj kawałek różnicy..." #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "Wycofać kawałek różnicy?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "Wycofaj zaznaczone wiersze" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "Wycofaj zaznaczone wiersze..." #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "Wycofać zaznaczone wiersze?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "Wycofaj niezatwierdzone zmiany" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "Wycofać niezatwierdzone zmiany?" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "Wycofaj niezatwierdzone zmiany..." #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "Wycofaj niedobrane zmiany" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "Wycofać niedobrane zmiany?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "Wycofaj niedobrane zmiany..." #: cola/cmds.py:598 msgid "Revert failed" msgstr "Wycofywanie nie powiodło się" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "Wycofać niezatwierdzone zmiany?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "Wycofać niedobrane zmiany?" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "Wycofaj niezatwierdzone zmiany w wybranych ścieżkach" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "Wycofaj niezebrane zmiany w wybranych ścieżkach" #: cola/guicmds.py:320 msgid "Review" msgstr "Przejrzyj" #: cola/widgets/main.py:597 msgid "Review..." msgstr "Przejrzyj..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Wydanie" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Wyrażenie wydania:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Wydanie do scalenia" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "Zmień opis" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "Zmienić opublikowaną zmianę?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "Łącza pod prawym do otwarcia:" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "Wykonaj" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "Uruchom \"%s\"?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "Wykonać %s?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "Wykonać polecenie \"%s\"?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "Wykonywanie polecenia: %s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "Tłumaczenie na rosyjski" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "SHA-1" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "Tryb bezpieczny" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Zapisz" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "Zapisz archiwum" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "Zapisz jako tarball/zip..." #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "Zachowaj ustawienia interfejsu" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "Zachowaj przechowalnię" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "Zachowaj zmieniony stan w nowej przechowalni" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "Zapisano \"%(filename)s\" z \"%(ref)s\" do \"%(destination)s\"" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "Wyszukaj" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "Wyszukaj autorów" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "Poszukaj opisu zmiany" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "Wyszukaj zmieniających" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "Wyszukaj zakresu dat" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "Wyszukaj różnicy" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "Wyszukaj po wyrażeniu" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "Wyszukaj po ścieżce" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "Wyszukaj stały ciąg znaków" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "Poszukaj w różnicy" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "Znajdź repozytorium po nazwie..." #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "Wyszukaj przy użyciu podstawowego wyrażenia regularnego POSIX" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "Wyszukaj przy użyciu rozszerzonego wyrażenia regularnego POSIX" #: cola/widgets/main.py:507 msgid "Search..." msgstr "Wyszukaj..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "Poszukaj:" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Wybierz" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Zaznacz wszystko" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "Wybierz gałąź do przeglądnięcia" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "Wybierz potomnego" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "Wybierz zmianę" #: cola/guicmds.py:136 msgid "Select Directory..." msgstr "Wybierz katalog..." #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "Wybierz nową gałąź odgórną" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "Wybierz najnowszego potomnego" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "Wybierz najstarszego przodka" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "Wybierz przodka" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "Wybierz poprzednią wersję" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "Wybierz katalog nadrzędny do pobrania" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "Wybierz katalog" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "Wybierz katalog do wyników" #: cola/widgets/selectcommits.py:182 msgid "Select output directory" msgstr "Wybierz katalog do wyników" #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "Wybierz plik(i) łat(y)..." #: cola/widgets/editremotes.py:434 msgid "Select repository" msgstr "Wybierz repozytorium" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "Ustaw domyślne repozytorium" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "Ustaw gałąź odgórną" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" "Ustaw porządek szeregowania dla gałęzi i znaczników.\n" "Przełącz pomiędzy szeregowaniem wg daty oraz nazwy wersji." #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "Zapamiętaj gałąź odgórną" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "Ustawienia" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "Argumenty powłoki" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "Przesuń w dół" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "Przesuń w górę" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "Skróty" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Pokaż statystykę różnicy po scaleniu" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "Pokaż pełne ścieżki w nazwie okna" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "Pokaż pomoc" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "Pokaż historię" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "Pokaż liczbę plików w oknie stanu" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "Pokaż pomoc\n" "Skrót: ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "Pokaż numery wierszy" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "Pokaż całe funkcje otaczające zmiany" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "Wyświetlanie zmian od" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "Obok siebie" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Podpisz się" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "Podpisz znacznik" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "Podpisz się pod tą zmianą" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "Tłumaczenie na uproszczony chiński" #: cola/cmds.py:2527 msgid "Skip" msgstr "Pomiń" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "Pomiń bieżącą łatę" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "Pomiń nałożenie bieżącej łaty i kontynuuj stosowanie pozostałych łat" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "Uszereguj zakładki alfabetycznie" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "Tłumaczenie na hiszpański" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "Jest SHA-1 znacznika" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "Jest opisem znacznika" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "Jest nazwą znacznika" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "Sprawdź pisownię" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "Złącz" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "Złącz scalone zmiany w pojedynczą zmianę" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "Dobierz" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "Dobierz / odłóż" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "Dobierz / odłóż wszystkie" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "Dobierz kawałek różnicy" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Dobierz zmienone" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "Dobierz zmienione i niezarządzane" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "Dobierz zaznaczone" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "Dobierz zaznaczone wiersze" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "Dobierz niescalone" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "Dobierz niezarządzane" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "Zbierz i zatwierdź" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "Zebrać i zatwierdzić?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "Dobrać sprzeczności" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "Dobrać sprzeczności?" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "Dobierz/odłóż wybraną ścieżkę/ścieżki do zmiany" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "Dobrane" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "Dobieranie: %s" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "Zmień podstawę interaktywnie..." #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "Wydanie rozpoczynające" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "Przechowalnia" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "Przechowaj indeks" #: cola/widgets/stash.py:79 msgid "Stash staged changes only" msgstr "Przechowaj tylko dobrane zmiany" #: cola/widgets/stash.py:75 msgid "Stash unstaged changes only, keeping staged changes" msgstr "Przechowaj tylko niedobrane zmiany, nie dotykając dobranych zmian" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "Przechowalnia..." #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "Stan" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "Zaprzestań zarządzanie ścieżką/ścieżkami" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "Adres URL podmodułu (może być względny, np.: ../repo.git)" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "Gałąź podmodułu do śledzenia (niewymagane)" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "Ścieżka podmodułu z bieżącym repozytorium (niewymagane)" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "Podmoduły" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "Podsumuj zmianę scalenia" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "Nazwa" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Szerokość tabulacji" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Znacznik" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "Utworzono znacznik" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Opis znacznika..." #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "Zażądano podpisania znacznika, lecz opis znacznika jest pusty." #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "Znaczniki" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "Tekst obok ikony" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "Tylko tekst" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "Tekst pod ikoną" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "Szerokość tekstu" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "Po tym gałąź stanie się niedostępna." #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "Gałąź zostanie wyzerowana przy użyciu \"git reset --mixed %s\"" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "Gałąź zostanie wyzerowana przy użyciu \"git reset --soft %s\"" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "Opis zmiany zostanie wyczyszczony." #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" "Zapis daty i czasu używany do wyświetlania dat w Git DAG.\n" "Wartość ta będzie przekazywana do git log --date=" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "Plik %s już istnieje i zostanie zastąpiony." #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "Zostaną usunięte następujące pliki:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "Liczba poprzedzających ścieżek do usunięcia" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "Repozytorium zostanie wyzerowane przy użyciu \"git reset --hard %s\"" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "Repozytorium zostanie wyzerowane przy użyciu \"git reset --keep %s\"" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "Repozytorium zostanie wyzerowane przy użyciu \"git reset --merge %s\"" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "Wyrażenie wydania nie może być puste." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" "Zostanie dodany podmoduł przy użyciu\n" "\"%s\"" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" "Ten podmoduł zostanie uaktualniony przy użyciu\n" "\"%s\"" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "Drzewo pracy zostanie przywrócone przy użyciu \"git read-tree --reset -u %s\"" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "Nie będzie można się z tego wycofać. Czy wyczyścić opis zmiany?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "Ta zmiana została już opublikowana.\n" "Działanie to zmieni opublikowaną historię.\n" "Prawdopodobnie nie chcesz tego." #: cola/widgets/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "To działanie porzuci niezatwierdzone zmiany.\n" "Zmian tych nie będzie można przywrócić." #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "To działanie porzuci niezatwierdzone zmiany.\n" "Zmian tych nie będzie można przywrócić." #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "To działanie porzuci niedobrane zmiany.\n" "Nie będzie można ich później odzyskać." #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "To działanie zastąpi zaznaczone, niescalone pliki treścią ze scalanej gałęzi przy użyciu \"git checkout --theirs\".\n" "Utracisz *WSZYSTKIE* niezatwierdzone zmiany.\n" "Odzyskanie ich będzie niemożliwe." #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "To działanie zastąpi zaznaczone, niescalone pliki treścią z twojej obecnej gałęzi przy użyciu \"git checkout --ours\".\n" "Utracisz *WSZYSTKIE* niezatwierdzone zmiany.\n" "Odzyskanie ich będzie niemożliwe." #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" "To repozytorium ma nierozwiązane sprzeczności po nałożeniu łaty.\n" "Rozwiąż sprzeczności i zatwierdź zmiany." #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "To repozytorium jest w środku zmieniania jego podstawy.\n" "Wyjaśnij sprzeczności, zatwierdź zmiany i wykonaj:\n" " Zmiana podstawy > Dalej" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" "To repozytorium jest w środku zaciągania wybiórczego.\n" "Wyjaśnij sprzeczności i zatwierdź zmiany." #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "To repozytorium jest w środku scalania.\n" "Wyjaśnij sprzeczności i zatwierdź zmiany." #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "Aby przerwać stosowanie tej łaty, usuń wszystkie wiersze." #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "Aby uniknąć nakładania wierszy dodających ('+'), usuń je." #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "Aby uniknąć nakładania wierszy usuwających ('-'), zmień je na wiersze otoczenia (' ')." #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "Uwzględnij/nie uwzględniaj" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "Przełącz różnicę obrazu" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "Przełącz filtr gałęzi" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "Przełącz filtr ścieżek" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "Wygląd paska narzędzi:" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Odgórna gałąź" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "Odgórna gałąź" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "Tłumaczenia na tradycyjny chiński (Tajwan)" #: cola/widgets/about.py:421 msgid "Translation" msgstr "Tłumaczenie" #: cola/widgets/about.py:91 msgid "Translators" msgstr "Tłumacze" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "Tłumaczenie na turecki" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "Adres URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "Adres URL: %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "Tłumaczenie na ukraiński" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "Nie można zmienić podstawy" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "Nie można ustawić URL dla \"%(name)s\" na \"%(url)s\"" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "Nie udało się zapisać łaty do \"%s\". Czy masz uprawnienia?" #: cola/widgets/main.py:749 msgid "Undo" msgstr "Cofnij" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "Wycofaj ostatnią zmianę" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "Czy wycofać ostatnią zmianę?" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "Czy wycofać opublikowaną zmianę?" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "Niescalone" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "Odłóż" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "Odłóż wszystkie" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "Odłóż kawałek różnicy" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "Odłóż zaznaczone" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "Odłóż zaznaczone wiersze" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "Odkładanie: %s" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "Nie zarządzaj wybranymi" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "Niezarządzane" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "Nie zarządzaj: %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "Uaktualnij wszystkie podmoduły..." #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Uaktualnij bieżącą gałąź:" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "Uaktualnij podmoduł" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "Uaktualnij podmoduł..." #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "Uaktualnij podmoduły" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "Uaktualnić wszystkie podmoduły?" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "Uaktualnij nałożone gałęzie" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "Czy uaktualnić nałożone gałęzie przy zmienianiu podstawy?" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "Uaktualnij podmoduły..." #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "Uaktualnij ten podmoduł" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "Uaktualnić ten podmoduł?" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "Uaktualnianie" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "Użyj bloku jako kursora w edytorach różnicy" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "Użyj gravatar.com do poszukiwania ikon autorów na podstawie ich adresów" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Nazwa użytkownika" #: cola/widgets/about.py:89 msgid "Version" msgstr "Wersja" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "Widok" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "Przejrzyj historię..." #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "Przejrzyj historię dla wybranej ścieżki/ścieżek" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "Zobrazuj" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "Zobrazuj wszystkie gałęzie..." #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "Zobrazuj bieżącą gałąź..." #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "Określa czy podpisać znacznik (git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "Całe słowa" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "Czy chcesz zebrać i zatwierdzić wszystkie zmienione pliki?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "XOR" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "Tak" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "Jesteś w środku scalania.\n" "Nie można uzupełniać w trakcie scalania." #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "Nie można zmieniać podstawy, gdy masz niezatwierdzone zmiany." #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "Musisz podać wydanie do scalenia." #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "Musisz podać wydanie do obejrzenia." #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "Powiększ" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "Pomniejsz" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "Zmieść" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "argumenty wiersza poleceń" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "błąd: nie można uruchomić git" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "kod wyjścia %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "krytyczny: \"%s\" nie jest katalogiem. Podaj poprawne --repo <ścieżka>." #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "wersja git coli %s" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "Różnica git-cola" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "git://git.example.com/repo.git" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "wyszukaj w wynikach..." #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "hotkeys.html" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "ściezka/do/podmodułu" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "vX.Y.Z" #: cola/hidpi.py:43 msgid "x 1" msgstr "x 1" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "x 1.5" #: cola/hidpi.py:46 msgid "x 2" msgstr "x 2" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "yyyy-MM-dd" #~ msgid "" #~ "\n" #~ "Commands\n" #~ "--------\n" #~ "pick = use commit\n" #~ "reword = use commit, but edit the commit message\n" #~ "edit = use commit, but stop for amending\n" #~ "squash = use commit, but meld into previous commit\n" #~ "fixup = like \"squash\", but discard this commit's log message\n" #~ "exec = run command (the rest of the line) using shell\n" #~ "\n" #~ "These lines can be re-ordered; they are executed from top to bottom.\n" #~ "\n" #~ "If you disable a line here THAT COMMIT WILL BE LOST.\n" #~ "\n" #~ "However, if you disable everything, the rebase will be aborted.\n" #~ "\n" #~ "Keyboard Shortcuts\n" #~ "------------------\n" #~ "? = show help\n" #~ "j = move down\n" #~ "k = move up\n" #~ "J = shift row down\n" #~ "K = shift row up\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "spacebar = toggle enabled\n" #~ "\n" #~ "ctrl+enter = accept changes and rebase\n" #~ "ctrl+q = cancel and abort the rebase\n" #~ "ctrl+d = launch difftool\n" #~ msgstr "" #~ "\n" #~ "Polecenia\n" #~ "--------\n" #~ "pick = użyj wdrożenia\n" #~ "reword = użyj wdrożenia, lecz zmień jego opis\n" #~ "edit = użyj wdrożenia, lecz zatrzymaj się na uzupełnienie wdrożenia\n" #~ "squash = użyj wdrożenia, lecz złącz je z poprzednim\n" #~ "fixup = tak jak \"squash\", lecz z porzuceniem tego opis wdrożenia\n" #~ "exec = wykonaj polecenie (reszta wiersza) przy użyciu powłoki\n" #~ "\n" #~ "Można zmienić kolejność tych wierszy; będą one wykonywane od góry do dołu.\n" #~ "\n" #~ "Po wyłączeniu wiersza tutaj, to TO WDROŻENIE ZOSTANIE UTRACONE.\n" #~ "\n" #~ "Jednakże, po wyłączeniu wszystkiego, to zmiana podstawy zostanie przerwana.\n" #~ "\n" #~ "Skróty klawiszowe\n" #~ "------------------\n" #~ "? = pokaż pomoc\n" #~ "j = przesuń w dół\n" #~ "k = przesuń w górę\n" #~ "J = przesuń wiersz w dół\n" #~ "K = przesuń wiersz w górę\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "spacja = uwzględnij/nie uwzględniaj\n" #~ "\n" #~ "ctrl+enter = przyjmij zmiany i zmień podstawę\n" #~ "ctrl+q = zaniechaj i przerwij zmianę podstawę\n" #~ "ctrl+d = wywołaj narzędzie różnicy\n" #, fuzzy #~ msgid "\"%s\" returned exit status %d" #~ msgstr "\"%(command)s\" zwróciło kod wyjścia %(status)d" #~ msgid "\"git commit\" returned exit code %s" #~ msgstr "\"git commit\" zwróciło kod wyjścia %s" #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Przechowalnia o nazwie \"%s\" już istnieje" #~ msgid "Already up-to-date." #~ msgstr "Nic nowego." #~ msgid "Commit failed: %s" #~ msgstr "Nieudane wdrażanie: %s" #~ msgid "Created commit: %s" #~ msgstr "Utworzono wdrożenie: %s" #~ msgid "Delete selected branch?" #~ msgstr "Usunąć zdalną gałąź?" #~ msgid "Enter Git Repository" #~ msgstr "Podaj repozytorium git" #, fuzzy #~ msgid "Error %s" #~ msgstr "Błędy: %s" #~ msgid "Error: Stash exists" #~ msgstr "Błąd: Przechowalnia istnieje" #~ msgid "Errors: %s" #~ msgstr "Błędy: %s" #~ msgid "Exit code: %s" #~ msgstr "Kod wyjścia: %s" #~ msgid "Fast Forward Only " #~ msgstr "Tylko przewinięcie do przodu" #~ msgid "GPG-signed" #~ msgstr "Podpisane GPG" #~ msgid "Hide Details.." #~ msgstr "Ukryj szczegóły..." #, fuzzy #~ msgid "Local Branches" #~ msgstr "Lokalna gałąź" #~ msgid "" #~ "Output:\n" #~ "%s" #~ msgstr "" #~ "Wynik:\n" #~ "%s" #~ msgid "Output: %s" #~ msgstr "Wynik: %s" #~ msgid "PATCH %(current)d/%(count)d" #~ msgstr "ŁATA %(current)d/%(count)d" #~ msgid "Path to git repository" #~ msgstr "Ścieżka do repozytorium git" #, fuzzy #~ msgid "Remote Branches" #~ msgstr "Zdalna gałąź" #~ msgid "Rename remote?" #~ msgstr "Zmienić nazwę zdalnego repozytorium?" #~ msgid "Reset Branch Head" #~ msgstr "Wyzeruj HEAD gałęzi" #~ msgid "Reset Hard" #~ msgstr "Wyzeruj twardo" #~ msgid "Reset Merge" #~ msgstr "Wyzeruj ze scaleniem" #~ msgid "Reset Soft" #~ msgstr "Wyzeruj miękko" #~ msgid "Reset Worktree" #~ msgstr "Wyzeruj drzewo pracy" #~ msgid "Reset hard?" #~ msgstr "Wyzerować twardo?" #~ msgid "Reset merge?" #~ msgstr "Wyzerować ze scaleniem?" #~ msgid "Reset soft?" #~ msgstr "Wyzerować miękko?" #~ msgid "Reset worktree?" #~ msgstr "Wyzerować drzewo pracy?" #~ msgid "Select File" #~ msgstr "Wybierz plik" #~ msgid "Select Repository..." #~ msgstr "Wybierz repozytorium..." #~ msgid "Select file from \"%s\"" #~ msgstr "Wybierz plik z \"%s\"" #~ msgid "Select manually..." #~ msgstr "Wybierz ręcznie..." #~ msgid "Show Details..." #~ msgstr "Pokaż szczegóły..." #~ msgid "Show icon? (if available)" #~ msgstr "Pokazać ikonę? (jeśli dostępna)" #~ msgid "Staging Area" #~ msgstr "Punkt zbiorczy" #~ msgid "Summary:" #~ msgstr "Nazwa:" #~ msgid "The branch will be reset using \"git reset --hard %s\"" #~ msgstr "Gałąź zostanie wyzerowana przy użyciu \"git reset --hard %s\"" #~ msgid "The branch will be reset using \"git reset --merge %s\"" #~ msgstr "Gałąź zostanie wyzerowana przy użyciu \"git reset --merge %s\"" #~ msgid "The worktree will be reset using \"git reset --keep %s\"" #~ msgstr "Drzewo z pracą zostanie wyzerowane przy użyciu \"git reset --keep %s\"" #~ msgid "" #~ "This PyQt4 does not include QtWebKit.\n" #~ "The keyboard shortcuts feature is unavailable." #~ msgstr "" #~ "Ten PyQt4 nie zawiera QtWebKit.\n" #~ "Skróty klawiszowe są niedostępne." #~ msgid "git clone returned exit code %s" #~ msgstr "klonowanie git zwróciło kod wyjścia %s" #~ msgid "git tag returned exit code %s" #~ msgstr "git tag zwrócił kod wyjścia %s" #~ msgid "title" #~ msgstr "tytuł" #~ msgid "unknown" #~ msgstr "nieznany" git-cola-4.6.1/cola/i18n/pt_BR.po000066400000000000000000003224231457126473700163120ustar00rootroot00000000000000# Copyright (C) 2007, 2008 Shawn Pearce, et al. # This file is distributed under the same license as the git-cola package. # Vitor Lobo , 2013-2014. msgid "" msgstr "" "Project-Id-Version: git-cola VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-17 01:06-0700\n" "PO-Revision-Date: 2018-06-25 12:37-0300\n" "Last-Translator: Rafael Nascimento \n" "Language-Team: Brazillian \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.0.8\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " Arraste e solte ou use o botão Adicionar para adicionar\n" " patches à lista\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" "\n" "
\n" " Git Cola foi traduzido em diferentes linguagens graças\n" " à ajuda dos indivíduos listados abaixo.\n" "\n" "
\n" "

\n" " A tradução é aproximada. Se você achar um erro,\n" " por favor nos avise abrindo um issue no Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " Nós convidamos você a participar da tradução adicionando\n" " ou atualizando a tradução e abrindo um pull request.\n" "

\n" "\n" "
\n" "\n" " " #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" "\n" "
\n" " Por favor use %(bug_link)s para reportar problemas.\n" "
\n" " " #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" "\n" " String para formatação de Variáveis\n" " -----------------------\n" " %(path)s = caminho relativo do arquivo\n" " %(abspath)s = caminho absoluto do arquivo\n" " %(dirname)s = caminho relativo do diretório\n" " %(absdirname)s = caminho absoluto do diretório\n" " %(filename)s = nome base do arquivo\n" " %(basename)s = nome base do arquivo sem extensão\n" " %(ext)s = extensão do arquivo\n" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Mover para Cima\n" "K, Up = Mover para baixo\n" "Enter = Editar arquivos selecionados \n" "Spacebar = Abrir arquivo usando a aplicação padrão\n" "Ctrl + L = Focar campo de entrada de texto\n" "? = Mostrar ajuda\n" "\n" "As setas para cima e para baixo mudam o foco entre a caixa de entrada\n" "e os resultados.\n" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr "Visualizar o Histórico" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr "commits anteriores" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "\"%(branch)s\" foi removida do \"%(remote)s\"." #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "\"%(command)s\" retornou estado de saída \"%(status)d\"" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "\"%(command)s\" retornou estado de saída %(status)d" #: cola/guicmds.py:156 #, fuzzy, python-format msgid "\"%s\" already exists" msgstr "Branch \"%s\" já existe." #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "\"%s\" já existe, o cola já criou um novo diretório" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "\"%s\" requer um arquivo selecionado" #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "#" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s: %(branch)s - Navegar" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "%(project)s: %(ref)s - DAG" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "%d dias atrás" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "%d horas atrás" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "%d minutos atrás" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "%d patch(es) foram aplicados." #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d ignorado" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" "parece que %s contém conflitos de merge.\n" "\n" "Você provavelmente deveria pular este arquivo.\n" "Selecionar o arquivo de qualquer forma?" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, fuzzy, python-format msgid "%s is not a Git repository." msgstr "Entrar no Repositório Git" #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "%s será removido dos favoritos." #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "%s será removido dos seu repositórios recentes." #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: Não existe o arquivo ou diretório" #: cola/widgets/main.py:748 msgid "&Edit" msgstr "&Editar" #: cola/widgets/main.py:690 msgid "&File" msgstr "&Arquivo" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(Modificando)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "*** Ponto do Branch ***" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** Sandbox ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "100%" #: cola/widgets/diff.py:817 msgid "200%" msgstr "" #: cola/widgets/diff.py:814 msgid "25%" msgstr "" #: cola/widgets/diff.py:818 msgid "400%" msgstr "" #: cola/widgets/diff.py:815 msgid "50%" msgstr "" #: cola/widgets/diff.py:819 msgid "800%" msgstr "" #: cola/widgets/finder.py:118 msgid " ..." msgstr " ..." #: cola/cmds.py:1685 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 "" "Nenhum template de commit foi configurado.\n" "Use \"git config\"para definir \"commit.template\"\n" "para que aponte para um template de commit." #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "Um hook precisa ser fornecido em \"%s\"" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "Abortar" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "Abortar Ação" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "Abortar Mesclagem" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Abortar Mesclagem..." #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "Abortar a ação?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Abortando o merge atual irá causar a perda de *TODOS* as mudanças sem um commit. \n" "Não é possível recuperar mudanças sem commit." #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "Abordar o merge atual?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "Sobre" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "Sobre o git-cola" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "Aceitar" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "Aceitar as mudanças e usar rebase\n" "Atalho: Ctrl+Enter" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "Nome da Ação" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "Ações" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "Ações..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "Adicionar" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "Adicionar Favorito" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "Adicionar Remoto" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "Adicionar Separador" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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 "" "Adicionar e remover repositórios remotos usando os \n" "botões Adicionar(+) e Deletar(-) no lado esquerdo.\n" "\n" "Repositórios remotos podem ser renomeados, selecionando uma opção da lista\n" "e pressionando a \"enter\", ou clicando duas vezes." #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "Adicionar novo repositório git" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "Adicionar patches (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "Adicionar remoto" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "Adicionar este submódulo?" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "Adicionar ao .gitignore" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "Adicionar ao Git Annex" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "Adicionar ao Git LFS" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "Adições" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "Avançado" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "Idade" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "Todos os Repositórios" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "Permitir atualizações non-fast-forward. Usando \"force\" pode fazer com que o repositório perca commits; use com cuidado." #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "Sempre crie um commit de merge quando habilitado, mesmo quando o merge é uma atualização de fast-forward" #: cola/cmds.py:220 msgid "Amend" msgstr "Alterar" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "Alterar Commit" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Alterar o Último Commit" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "Alterar o commit publicado ?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "Alterando" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "Uma ação ainda está sendo executada.\n" "Finaliza-la pode resultar em perda de dados." #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "Uma tag leve e não assinada será criada.\n" "Criar uma tag não assinada?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "Aparência" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "Aplicar" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "Aplicar Patches" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "Aplicar Patches..." #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "Aplicar e cancelar o stash selecionado (git stash pop)" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "Aplicar o stash selecionar" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "Argumentos" #: cola/qtutils.py:886 msgid "Attach" msgstr "Anexar" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "Autor" #: cola/widgets/about.py:90 msgid "Authors" msgstr "Autores" #: cola/hidpi.py:41 msgid "Auto" msgstr "Automático" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "Auto-Quebra de Linhas" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "Autocompletar Caminhos" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "Carregar template de mensagens de commit automaticamente" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "Regexp Básico" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "Visualizador de Blame" #: cola/widgets/browse.py:206 #, fuzzy msgid "Blame selected paths" msgstr "Renomear caminhos selecionados" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "Blame..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "Fonte em negrito com o fundo escuro em vez de cabeçalhos em itálico" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Branch" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "Branch \"%(branch)s\" não existe em \"%(remote)s\".\n" "Um novo branch remoto será publicado." #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "Branch \"%s\" já existe." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "Visualizador de Diff do Branch" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "Branch Existe" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Nome do Branch" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "Nome do Branch" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "Branch: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "Branches" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "Branches..." #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "Tradução Brasileira" #: cola/guicmds.py:52 msgid "Browse" msgstr "Navegar" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "Navegar nos Commits..." #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "Navegar no Branch Atual..." #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "Navegar em Outro Branch..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "Navegar..." #: cola/widgets/main.py:87 msgid "Browser" msgstr "Navegar" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "Navegando %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "Ignorar Commit Hooks" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "Cancelar" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "Cancelar rebase\n" "Atalho: Ctrl+Q" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "Não pode alterar" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "Não é possível executar \"%s\": por favor configure o visualizador de blame" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "Não é possível executar \"%s\": por favor configure o navegador de histórico" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "Não é possível executar \"%s\": por favor configure seu editor" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "Upstream Modificado" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "Verificar commits publicados em Amending" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "Verificar Ortografia" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "Verificar ortografia" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Checkout" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "Checkout depois da criação" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Checkout Branch" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "Checkout HEAD desanexado" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "Checkout como um novo branch" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Checkout..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "Cherry Pick" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "Cherry-Pick Commit" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "Cherry-Pick..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "Escolha os caminhos" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "Escolha o modo de expressão regular do \"git grep\"" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "Limpar Repositório Atual" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "Limpar mensagem do commit" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "Limpar mensagem do Commit?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "Limpar..." #: cola/widgets/clone.py:124 msgid "Clone" msgstr "Clonar..." #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 #, fuzzy msgid "Clone Repository" msgstr "Clonar Repositório" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Clonar..." #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "Clonando repositório em %s" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Fechar" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "Fechar" #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "Recolher todos" #: cola/sequenceeditor.py:371 msgid "Command" msgstr "Comando" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "Commit" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "Falha no Commit" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "Commit as mudanças selecionadas" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "Commit as mudanças selecionadas\n" "Atalho: Ctrl+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "Descreva resumidamente o que modificou..." #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "Commit o merge se não houver conflitos. Desmarque para deixar o merge sem commit." #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "Commit@@verbo" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "Comparar" #: cola/difftool.py:102 msgid "Compare All" msgstr "Comparar Todos" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "Configurar Barra de Ferramentas" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "Configurar o branch remoto como novo upstream" #: cola/widgets/main.py:169 msgid "Console" msgstr "Console" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Continuar" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Copiar" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "Copiar Nome Base para o clipboard" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "Copiar o Caminho Principal para o Clipboard" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "Copiar o Caminho para o Clipboard" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "Copiar Caminho Relativo para o Clipboard" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "Copiar SHA-1" #: cola/widgets/status.py:738 msgid "Copy..." msgstr "Copiar..." #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "Não foi possível analisar o URL do Git \"%s\"" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Criar Branch" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "Criar Patch" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "Criar Branch Remoto" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "Criar Commit Assinado" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "Criar Tag" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "Criar Tag..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "Criar Tag Não Assinada." #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "Criar um commit de merge mesmo se o merge resultar em fast-foward" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "Criar um novo branch remoto?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "Criar..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "Criar uma nova tag chamada \"%s\"" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "Repositório Atual" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "Ações customizadas de copiar" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "Customizar..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "Cortar" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "Visualizar o histórico..." #: cola/icons.py:54 msgid "Dark Theme" msgstr "Tema Escuro" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "Data, Tempo" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "Padrão" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Deletar" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "Excluir %d arquiv(o)s?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "Remover Favorito" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "Remover Favorito?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Deletar Branch" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "Excluir Arquivos" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "Excluir Arquiv(o)s..." #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "Excluir Arquivos?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "Deletar Remoto ?" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "Remover Branch Remoto" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "Remover Branch Remoto..." #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "Remover barra de ferramentas" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "Remover branch \"%s\"?" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "Deletar Repositórios Remotos" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "Remover remoto \"%s\"" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "Remover remoto?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Deletar..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "A deleção de \"%s\" falhou" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "Deleções" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "Desanexar" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "Detectar Marcadores de Conflitos" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "Detectar marcadores de conflitos em arquivos que não entraram no merge" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "Desenvolvedor" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "Compare" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "Comparar com o antecessor" #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "Opções de Comparação" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "Ferramenta de Comparação" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "Comparar selecionado -> esse" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "Comparar esse -> selecionado" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "Compare Modificações (Antes/Depois)" #: cola/difftool.py:324 #, fuzzy msgid "Difftool" msgstr "Ferramenta de Comparação" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "Diretório Existe" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "Exibir Arquivos não Controlados" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "Documentação" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "Cancelar" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "Cancelar o Stash" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "Cancelar o Stash?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "Cancelar o \"%s\" stash?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "Cancelar o stash selecionado" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 #, fuzzy msgid "Edit" msgstr "&Editar" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "Editar Rebase" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "Editar Repositórios Remotos" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "Editar Repositórios Remotos..." #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "Editar os remotos os selecionando na lista" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "Editar caminhos selecionados" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "Editar..." #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "Editor" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "Endereço de Email" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "Email do Contribuidor" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "Habilitar autocomplete de caminhos em ferramentas" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "Habilitado" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "Digite o nome do novo Branch" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "Digite o nome para o novo repo vazio" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "Digite o nome para o stash" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "Erro" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "Erro ao Clonar" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "Erro ao Criar Branch" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "Erro ao Criar Repositório" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "Erro Removendo Branch Remoto" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "Erro Editando Arquivo" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "Erro Lançando o Visualizador de Blame" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "Erro Lançando o Visualizador de Histórico" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "Erro criando o remoto \"%s\"" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "Erro ao criar o stash" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "Erro ao remover branch \"%s\"" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Erro removendo o remoto \"%s\"" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "Erro renomeando \"%(name)s\" para \"%(new_name)s\"" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "Erro executando prepare-commitmsg hook" #: cola/cmds.py:2987 cola/cmds.py:3033 #, fuzzy, python-format msgid "Error updating submodule %s" msgstr "Erro criando o remoto \"%s\"" #: cola/cmds.py:3069 #, fuzzy msgid "Error updating submodules" msgstr "Erro Editando Arquivo" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "Erro: Não foi possível encontrar o template do commit" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "Erro: Template do Commit não foi configurado" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Erro: não é possível clonar \"%s\"" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "Erro: não foi possível criar tag \"%s\"" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "Executando ação \"%s\"" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "Expandir tudo" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "Exportar Patches" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "Exportar Patches..." #: cola/widgets/main.py:547 msgid "Expression..." msgstr "Expressão" #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "Regexp Extendido" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "Descreva em detalhes o que modificou..." #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Somente Fast Forward" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "Somente Fast Forward" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "Repositórios Favoritos" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "Favoritos" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "Fetch" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "Fetch..." #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "Navegador de Arquivos..." #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "Diferença de Arquivos" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "Arquivo Salvo" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "Arquivo salvo em \"%s\"" #: cola/fsmonitor.py:530 #, fuzzy msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "inotify está desativado por causa \"cola.inotift\" is false\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "Monitoramento de alterações do sistema de arquivos: desabilitado porque libc não suporta chamadas do sistema inotify.\n" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "Monitoramento de alterações do sistema de arquivos: desabilitado porque pywin32 não foi instalado.\n" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" "Monitoramento de alterações do sistema de arquivos: desabilitado porque o numero total de observadores inotify chegou ao limite. Você pode mudar o limite da quantidade de observadores executando:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "Monitoramento de alterações do sistema de arquivos: habilitado.\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "Nome do Arquivo" #: cola/widgets/dag.py:821 msgid "Files" msgstr "Arquivos" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "Filtrar branches..." #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "Filtrar caminhos..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "Procurar Arquivos" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "String Fixa" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "Fonte de Largura Fixa" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "Fixup Commit Anterior" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "Flat dark blue" #: cola/themes.py:705 msgid "Flat dark green" msgstr "Flat dark green" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "Flat dark grey" #: cola/themes.py:691 msgid "Flat dark red" msgstr "Flat dark red" #: cola/themes.py:656 msgid "Flat light blue" msgstr "Flat light blue" #: cola/themes.py:677 msgid "Flat light green" msgstr "Flat light green" #: cola/themes.py:670 msgid "Flat light grey" msgstr "Flat light grey" #: cola/themes.py:663 msgid "Flat light red" msgstr "Flat light red" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Tamanho de Fonte" #: cola/widgets/remote.py:197 msgid "Force" msgstr "Forçar" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "Forçar Fetch" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "Forçar Fetch?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "Forçar Push" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "Forçar Push?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "Forçar fetch de %s?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "Forçar push para %s?" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "Formatar String" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "Tradução francesa" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "Assinar com GPG o Commit de Merge" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "Reunindo Informação de \"%s\"..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "Tradução alemã" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "Obter Template da Mensagem do Commit" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "Descer" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "Subir" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "Arquivo Grab" #: cola/widgets/dag.py:848 msgid "Graph" msgstr "Gráfico" #: cola/widgets/main.py:354 msgid "Grep" msgstr "Grep" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "Você tem usado rebase/pull recentemente?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Ajuda" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "Ajuda - Ações de Copia Customizadas" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "Ajuda - Procurar Arquivos" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "Ajuda - git-cola-sequence-editor" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "DPI Alto" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "Navegador de Histórico" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "Ignorar todos espaços em branco." #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "Ignorar alterações na quantidade de espaço em branco" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "Ignorar alterações no espaço em branco no EOL (Fim da Linha)" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "Ignorar padrão customizado" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "Ignorar nome exato do arquivo" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "Ignorar nome do arquivo ou padrão" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "Ignorar..." #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "Incluir tags" #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "Inicializar Git Annex" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "Inicializar Git LFS" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "Inicializar submódulos" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "Inserir espaços em vez de tabs" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "Rebase Interativo" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "Revisão Inválida" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "Manter *.orig na Mesclagem de Backups" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "Manter Índice" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "Teclas de Atalho" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "Iniciar a Ferramenta de Comparação" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "Iniciar a Ferramenta de Comparação na Pasta" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "Iniciar Editor" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "Iniciar Terminal" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" "Atalho para lançar a ferramenta de comparação externa:\n" "Ctrl+D" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "Iniciar git-cola" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "Iniciar git-difftool contra as versões anteriores" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "Iniciar git-difftool no caminho atual" #: cola/icons.py:55 msgid "Light Theme" msgstr "" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "Carregar a Mensagem do Commit" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "Carregar a Mensagem do Commit..." #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "Carregar Mensagem Anterior do Commit..." #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "Carregando..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Branch Local" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "Branch local" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "Trancar Layout" #: cola/widgets/dag.py:816 msgid "Log" msgstr "" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "Mantenedor (desde 2007) e desenvolvedor" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Merge" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "Merge \"%(revision)s\" em \"%(branch)s\"" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "Ferramenta de Merge" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Verbosidade do Merge" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "Falha no Merge. Necessário resolução de Conflitos." #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "Merge em \"%s\"" #: cola/widgets/branch.py:242 #, fuzzy msgid "Merge into current branch" msgstr "Procurar Branch Atual..." #: cola/widgets/main.py:359 msgid "Merge..." msgstr "Merge..." #: cola/widgets/main.py:1177 msgid "Merging" msgstr "" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "Mensagem" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "Mensagem do Commit em Falta" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "Data em Falta" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "Nome em falta" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "Falta a Revisão" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "Falta a mensagem da tag" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "Modificado" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "Mais..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "Mover para Baixo" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "Mover para cima" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "Mover arquivos para lixeira" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "Nome" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "Nome do novo remoto" #: cola/guicmds.py:147 cola/widgets/main.py:281 #, fuzzy msgid "New Bare Repository..." msgstr "Novo Repositório" #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "Novo Repositório" #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "Adicionar Barra de Ferramentas" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Novo" #: cola/actions.py:56 msgid "Next File" msgstr "Próximo Arquivo" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "Não" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "Nenhuma revisão foi especificada" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Commit não possui mudanças.\n" "\n" "Você precisa selecionar pelo menos 1 arquivo antes de realizar um Commit." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "Não existe confirmações no branch" #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "Sem Fast Forward" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "Sem Fast Forward" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Nenhum repositório selecionado" #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "Fetch sem Fast Forward reescreve o histórico local !" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "Push sem Fast-Forward reescreve o histórico publicado !\n" "(Você deu pull primeiro ?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "Nada para comitar" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "Nada a fazer" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Número de Comparações no Contexto de Linhas" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Abrir" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Abrir o Repositório Git" #: cola/widgets/submodules.py:48 #, fuzzy msgid "Open Parent" msgstr "Aberto Recentemente" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "Abrir Pasta Pai" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "Aberto Recentemente" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "Abrir usando aplicação padrão" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "Abrir em uma Nova Janela" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "Abrir em uma Nova Janela" #: cola/widgets/main.py:410 msgid "Open..." msgstr "Abrir" #: cola/widgets/branch.py:354 #, fuzzy msgid "Other branches" msgstr "Redefinir..." #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "Sobrescrever" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "Sobrescrever \"%s\"?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "Sobrescrever Arquivo?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "Analisar argumento usando um shell.\n" "Consultas com espaços precisam de \"aspas duplas\"." #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "Stage Parcial" #: cola/widgets/main.py:758 msgid "Paste" msgstr "Colar" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "Patch(s) Aplicados" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "Caminho" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "Caminho ou URL para clonar (Env. $VARS okay)" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "Usar Commit" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "Por favor, forneça um nome ao branch e expressão revisão" #: cola/cmds.py:2297 msgid "Please select a file" msgstr "Por favor selecione um arquivo" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "Por favor especifique um nome para a nova tag." #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "Por favor especifique a revisão da tag." #: cola/widgets/commitmsg.py:417 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 "" "Por favor forneça uma mensagem de commit.\n" "\n" "Uma boa mensagem de commit contem o seguinte formato:\n" "\n" "- Primeira Linha: Descreva em uma sentença o que você fez.\n" "- Segunda linha: Branco\n" "- Linhas Remanescentes: Descreva porque esta mudança é boa.\n" #: cola/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "Apontar o HEAD do branch atual para um novo commit?" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Preferências" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "Prefixo" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "Preparar Mensagem do Commit" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "Previnir \"Stage\" de selecionar todos arquivos quando nada é selecionado" #: cola/actions.py:65 msgid "Previous File" msgstr "Arquivo Anterior" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "Perguntar ao Criar" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "Perguntar quando push criar novo branch" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "" #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 #, fuzzy msgid "Pull" msgstr "Puxar..." #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "Pull..." #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Push" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Push..." #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Sair" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Rebase" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "Rebase em %s" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "Rebase parou" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "Rebase o branch atual em vez de merge" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "Rebasing" #: cola/widgets/main.py:118 msgid "Recent" msgstr "Recente" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "Repositórios Recentes" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "Contagem de Repositórios Recentes" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "Arquivos Modificados Recentemente" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "Arquivos Modificados Recentemente" #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "Recuperação de uma stash derrubada não é possível" #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Recuperar commits perdidos pode não ser fácil." #: cola/widgets/main.py:751 msgid "Redo" msgstr "Refazer" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "Reduzir histórico de commits para o minimo" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Recarregar" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "Recusar merge a menos que o HEAD atual já esteja atualizado ou o merge pode ser resolvido como fast-forward" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Remoto" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "Branch Remoto" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "Branch Remoto Removido" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "Repositórios Remotos - duplo click para renomear" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "Remover" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "Remover %s da lista de recentes ?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "Remover Elemento" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "Remover rastreamento remoto de branchs que não existem mais no remoto " #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "Remover selecionado" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Renomear" #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "Renomear \"%s\"" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "Renomear Branch" #: cola/widgets/main.py:584 #, fuzzy msgid "Rename Branch..." msgstr "Branch Remoto" #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "Renomear Branch Existente" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "Renomear Remoto" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "Renomear Repositório" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "Renomear branch" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "Renomear remoto de \"%(current)s\" para \"%(new)s\"?" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "Renomear caminhos selecionados" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "Repositório: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Resetar" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "Resetar \"%(branch)s\" to \"%(revision)s\"?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "Resetar Branch" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "Resetar Branch?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "Resetar \"%(branch)s\" para \"%(revision)s\" irá perder commits." #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "A alteração de aparência necessita reiniciar a aplicação." #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "Reverter" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "Reverter pedaço do Diff" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "Reverter pedaço do Diff..." #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "Reverter pedaço do Diff ?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "Reverter Linhas Selecionadas" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "Reverter Linhas Selecionadas..." #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "Reverter Linhas Selecionadas?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "Reverter Mudanças sem Commit" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "Reverter Mudanças sem Commit?" #: cola/cmds.py:2247 #, fuzzy msgid "Revert Uncommitted Edits..." msgstr "Reverter edições Uncommitted" #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "Reverter Mudanças sem Stage" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "Reverter Mudanças sem Stage?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "Reverter Edições Unstaged" #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "Reverter as mudanças sem Commit?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "Reverter as mudanças sem stage?" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "Reverter as mudanças sem Commit nos caminhos selecionados" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "Reverter as mudanças sem Stage nos caminhos selecionados" #: cola/guicmds.py:320 msgid "Review" msgstr "Revisar" #: cola/widgets/main.py:597 msgid "Review..." msgstr "Revisar..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Revisão" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Revisar Expressões" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Revisão para Merge" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "Reescrever" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "Reescrever Commit Publicado?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "Executar" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "Executar \"%s\"?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "Executar %s?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "Executar o comando \"%s\"?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "Executando o comando: %s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "Tradução russa" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "SHA-1" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "Modo Seguro" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Salvar" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "Salvar Arquivo" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "Salvar Como Tarball/Zip..." #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "Salvar Configuração da GUI" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "Salvar o Stash" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "Salvar o estágio modificado do novo stash" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "\"%(filename)s\" salvo de \"%(ref)s\" para \"%(destination)s\"" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "Pesquisar" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "Pesquisar por Autores" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "Pesquisar por Mensagens de Commit" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "Pesquisar por responsáveis do Commit" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "Pesquisar por Intervalo de Data" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "Pesquisar por Diffs" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "Pesquisar pela Expressão" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "Pesquisar pelo Caminho" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "Pesquisar por uma String Fixa" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "Procurar usando expressão regular básica POSIX" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "Procurar usando expressão regular extendida POSIX" #: cola/widgets/main.py:507 msgid "Search..." msgstr "Pesquisar..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Selecionar" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Selecionar Tudo" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "Selecionar Branch para Revisar" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "Selecionar Filho" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "Selecionar Commit" #: cola/guicmds.py:136 #, fuzzy msgid "Select Directory..." msgstr "Selecionar Repositório" #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "Selecionar Novo Upstream" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "Selecionar Filho mais novo" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "Selecionar Pai mais velho" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "Selecionar Pai" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "Selecionar Versão Anterior" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "Selecionar um diretório pai para o novo clone" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "Selecionar pasta de saída" #: cola/widgets/selectcommits.py:182 msgid "Select output directory" msgstr "Selecionar pasta de saída" #: cola/widgets/diff.py:1770 #, fuzzy msgid "Select patch file(s)..." msgstr "Excluir %d arquiv(o)s?" #: cola/widgets/editremotes.py:434 #, fuzzy msgid "Select repository" msgstr "Selecionar Repositório" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "Definir Repositório Padrão" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "Definir Branch Upstream" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "Definir Upstream" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "Configurações" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "Argumentos do Shell" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "Shift Para Baixo" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "Shift Para Cima" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "Atalhos" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Mostrar o Status de Comparação após Mesclagem" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "Mostrar Caminhos Completos no Titulo da Janela" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 #, fuzzy msgid "Show Help" msgstr "Ajuda" #: cola/widgets/filelist.py:29 #, fuzzy msgid "Show History" msgstr "Ver Histórico..." #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "Exibe número de arquivos no título de status" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "Mostrar Ajuda\n" "Atalho: ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "Mostrar numero das linhas" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "Mostrar função pai inteira" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "Mostrar mudanças desde" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "Lado a Lado" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Não Assinar" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "Assinar a Tag" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "Cancelar Assinatura desse Commit" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "" #: cola/cmds.py:2527 msgid "Skip" msgstr "Pular" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "Pular Path Atual" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "Ordenar favoritos alfabeticamente" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "Trandução espanhola" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "Especificar o SHA-1 para a Tag" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "Especifique a mensagem da tag" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "Especifique o nome da tag" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "Sugestões de Ortografia" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "Squash" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "Unir os commits mesclados em um commit único" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "Estágio" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "Estágio / Sem estágio " #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "Reverter pedaço do Diff" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Stage Modificado" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "Stage Selecionado" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "Stage Linhas Selecionadas" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "Stage e Commit" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "Stage e Commit?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "Conflitos no Stage" #: cola/cmds.py:2517 #, fuzzy msgid "Stage conflicts?" msgstr "Stage Modificado" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "Stage/unstage os caminhos selecionados para o Commit" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "Iniciar Rebase Interativo..." #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "Iniciar Revisão" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "Stash" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "Stash Índice" #: cola/widgets/stash.py:79 msgid "Stash staged changes only" msgstr "Stage somente mudanças selecionadas" #: cola/widgets/stash.py:75 msgid "Stash unstaged changes only, keeping staged changes" msgstr "Stash somente em mudanças não selecionadas, mantendo mudanças selecionadas" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "" #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "Parar rastreamento de caminhos" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "Submódulos" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "Resumir os Commits de Merge" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "Sumário" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Largura da Aba" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "Tag Criada" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Mensagem da Tag..." #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "A assinatura de tags foi solicitada, mas a mensagem da tag está vazia." #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "Largura do Texto" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "O branch não ficará mais disponível" #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "O branch será resetado usando \"git reset --mixed %s\"" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "O branch será resetado usando \"git reset --soft %s\"" #: cola/widgets/commitmsg.py:310 #, fuzzy msgid "The commit message will be cleared." msgstr "Os arquivos a seguir serão apagados:" #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "O arquivo \"%s\" existe e será sobrescrito." #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "Os arquivos a seguir serão apagados:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "A revisão da expressão não pode ser vazia" #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "Isso não pode ser feito. Limpar mensagem do commit ?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "Este commit já foi publicado.\n" "Essa operação irá sobrescrever a história publicada.\n" "Você provavelmente não deseja fazer isso." #: cola/widgets/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "Essa operação cancela mudanças sem commit.\n" "Essas mudanças não podem ser recuperadas." #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Essa operação remove edições sem commit dos arquivos selecionados.\n" "Essas mudanças não podem ser recuperadas." #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Essa operação remove edições sem stage dos arquivos selecionados.\n" "Essas mudanças não podem ser recuperadas." #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "Esse repositório está em Rebase.\n" "Resolva os conflitos, comite as mudanças, e execute:\n" " Rebase > Continuar" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "Esse repositório está no meio de um merge.\n" "Resolva os conflitos e comite as mudanças." #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "Alternar Habilitado" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "Alternar os filtros dos branches" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "Alterar os caminhos do filtro" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Rastreando Branch" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "Rastreando branch" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "Tradutores" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "Incapaz de realizar Rebase" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "Incapaz de modificar a URL de \"%(name)s\" para \"%(url)s\"" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "Desfazer" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "Unstage" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "Unstage em Todos" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "Unstage pedaço do Diff" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "Unstage Selecionados" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "Unstage Linhas Selecionadas" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "Remover rastreio do selecionado" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "Não rastreado" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "Removendo rastreio: %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Atualizar Branch Existente:" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 #, fuzzy msgid "Update Submodules" msgstr "Inicializar Submódulos" #: cola/cmds.py:3053 #, fuzzy msgid "Update all submodules?" msgstr "Inicializar submódulos" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 #, fuzzy msgid "Update submodules..." msgstr "Inicializar submódulos" #: cola/widgets/status.py:953 #, fuzzy msgid "Update this submodule" msgstr "Inicializar submódulos" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "Atualizar este submódulo?" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "Atualizando" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Nome do Usuário" #: cola/widgets/about.py:89 msgid "Version" msgstr "Versão" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "Ver" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "Ver Histórico..." #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "Ver histórico dos caminhos selecionados" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "Visualizar" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "Visualizar todos os Branches..." #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "Visualizar Branch Atual..." #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "Se assinar a tag (git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "Gostaria de stage e commit todos os arquivos modificados ?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "Sim" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "Você está no meio de um merge.\n" "Você não pode modificar durante o merge." #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "Você não pode usar rebase com mudanças sem commit." #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "Você precisa especificar uma revisão para o merge." #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "Você precisa especificar uma revisão para visualizar." #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "Aumentar o Zoom" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "Reduzir o Zoom" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "Zoom para Ajustar" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "Argumentos da linha de comando" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "erro: incapaz de executar git" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "Código de Saída %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "fatal: \"%s\" não é um diretório. Por favor especifique um caminho correto --repo ." #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "Versão do Git Cola %s" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "resultados do grep..." #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "" #: cola/hidpi.py:43 msgid "x 1" msgstr "" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "" #: cola/hidpi.py:46 msgid "x 2" msgstr "" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "" #~ msgid "" #~ "\n" #~ "Commands\n" #~ "--------\n" #~ "pick = use commit\n" #~ "reword = use commit, but edit the commit message\n" #~ "edit = use commit, but stop for amending\n" #~ "squash = use commit, but meld into previous commit\n" #~ "fixup = like \"squash\", but discard this commit's log message\n" #~ "exec = run command (the rest of the line) using shell\n" #~ "\n" #~ "These lines can be re-ordered; they are executed from top to bottom.\n" #~ "\n" #~ "If you disable a line here THAT COMMIT WILL BE LOST.\n" #~ "\n" #~ "However, if you disable everything, the rebase will be aborted.\n" #~ "\n" #~ "Keyboard Shortcuts\n" #~ "------------------\n" #~ "? = show help\n" #~ "j = move down\n" #~ "k = move up\n" #~ "J = shift row down\n" #~ "K = shift row up\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "spacebar = toggle enabled\n" #~ "\n" #~ "ctrl+enter = accept changes and rebase\n" #~ "ctrl+q = cancel and abort the rebase\n" #~ "ctrl+d = launch difftool\n" #~ msgstr "" #~ "\n" #~ "Commands\n" #~ "--------\n" #~ "pick = usar commit\n" #~ "reword = usar commit, mas editar a mensagem do commit\n" #~ "edit = usar commit, mas parar para edita-ló\n" #~ "squash = usar commit, mas fundir com commit anterior\n" #~ "fixup = como \"squash\", mas descarta o log desse commit\n" #~ "exec = executa um comando (no resto da linha) usando shell\n" #~ "\n" #~ "Essas linhas podem ser reordenadas; Elas são executadas de cima para baixo.\n" #~ "\n" #~ "Se você desabilitar uma linha aqui O COMMIT SERÁ PERDIDO.\n" #~ "\n" #~ "Porem, se você desabilitar tudo, o rebase será abortado .\n" #~ "\n" #~ "Atalhos do Teclado\n" #~ "------------------\n" #~ "? = mostrar ajuda\n" #~ "j = mover para baixo\n" #~ "k = mover para cima\n" #~ "J = deslocar fila para baixo\n" #~ "K = deslocar fila para cima\n" #~ "\n" #~ "1, p = escolher\n" #~ "2, r = reescrever \n" #~ "3, e = editar\n" #~ "4, f = corrigir\n" #~ "5, s = squash\n" #~ "spacebar = alternar ativado\n" #~ "\n" #~ "ctrl+enter = aceitar mudanças e usar rebase\n" #~ "ctrl+q = cancelar e abortar o rebase\n" #~ "ctrl+d = lançar ferramenta de comparação\n" #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Um nome de stash \"%s\" já existe" #~ msgid "Already up-to-date." #~ msgstr "Até a data" #~ msgid "Bookmarks" #~ msgstr "Marcadores" #~ msgid "Bookmarks..." #~ msgstr "Marcadores..." #~ msgid "Commit failed: %s" #~ msgstr "Confirmação Falhou: %s" #~ msgid "Created commit: %s" #~ msgstr "Confirmação Criada: %s" #~ msgid "Delete selected branch?" #~ msgstr "Remover branch selecionada?" #~ msgid "Enter Git Repository" #~ msgstr "Entrar no Repositório Git" #, fuzzy #~ msgid "Error %s" #~ msgstr "Erros: %s" #~ msgid "Error: Stash exists" #~ msgstr "Erro: Stash já existe" #~ msgid "Errors: %s" #~ msgstr "Erros: %s" #~ msgid "Exit code: %s" #~ msgstr "Código de saída" #~ msgid "Fast Forward Only " #~ msgstr "Avançar Rapidamente" #~ msgid "Hide Details.." #~ msgstr "Esconder Detalhes..." #, fuzzy #~ msgid "Local Branches" #~ msgstr "Branch Local" #~ msgid "No files selected for checkout from HEAD." #~ msgstr "Arquivos não selecionados para checkout do cabeçalho" #~ msgid "Options" #~ msgstr "Opções" #~ msgid "" #~ "Output:\n" #~ "%s" #~ msgstr "" #~ "Saída:\n" #~ "%s" #~ msgid "Output: %s" #~ msgstr "Saída: %s" #~ msgid "Path to git repository" #~ msgstr "Caminho do repositório git" #~ msgid "Process Selection" #~ msgstr "Selecionar Processo" #, fuzzy #~ msgid "Remote Branches" #~ msgstr "Branch Remoto" #~ msgid "Rename remote?" #~ msgstr "Renomear Remoto?" #~ msgid "Reset Branch Head" #~ msgstr "Resetar Head do Branch" #~ msgid "Reset Hard" #~ msgstr "Resetar Hard" #~ msgid "Reset Merge" #~ msgstr "Resetar Merge" #~ msgid "Reset Soft" #~ msgstr "Resetar Soft" #~ msgid "Reset Worktree" #~ msgstr "Resetar Worktree" #~ msgid "Reset hard?" #~ msgstr "Resetar hard?" #~ msgid "Reset merge?" #~ msgstr "Resetar merge?" #~ msgid "Reset soft?" #~ msgstr "Resetar soft?" #~ msgid "Reset worktree?" #~ msgstr "Resetar Worktree?" #~ msgid "Select File" #~ msgstr "Selecionar Arquivo" #~ msgid "Select Repository..." #~ msgstr "Selecionar Repositório" #~ msgid "Select file from \"%s\"" #~ msgstr "Selecione um arquivo de \"%s\"" #~ msgid "Select manually..." #~ msgstr "Selecione manualmente" #~ msgid "Show Details..." #~ msgstr "Mostrar Detalhes..." #~ msgid "Show icon? (if available)" #~ msgstr "Mostrar Ícone? (Se disponível)" #~ msgid "Summary:" #~ msgstr "Sumário:" #~ msgid "The branch will be reset using \"git reset --hard %s\"" #~ msgstr "O branch será resetado usando \"git reset --hard %s\"" #~ msgid "The branch will be reset using \"git reset --merge %s\"" #~ msgstr "O branch será resetado usando \"git reset --merge %s\"" #~ msgid "The worktree will be reset using \"git reset --keep %s\"" #~ msgstr "O worktree será resetado usando \"git reset --keep %s\"" #~ msgid "Updating..." #~ msgstr "Atualização..." #~ msgid "unknown" #~ msgstr "desconhecido" git-cola-4.6.1/cola/i18n/ru.po000066400000000000000000004441251457126473700157360ustar00rootroot00000000000000# Translation of git-cola to russian # Copyright (C) 2007 Shawn Pearce at el. # This file is distributed under the same license as the git-cola package. # Irina Riesen , 2007. # Alex Riesen , 2007. # Vaiz , 2015 # msgid "" msgstr "" "Project-Id-Version: git-cola VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-17 01:06-0700\n" "PO-Revision-Date: 2015-10-24 12:00-0200\n" "Last-Translator: Vaiz \n" "Language-Team: Russian\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " Перетащите или используйте кнопку Добавить, чтобы добавить\n" " патчи в список\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 #, fuzzy msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" "\n" "Горячие клавиши\n" "------------------\n" "J, Down = Опуститься вниз\n" "K, Up = Подняться вверх\n" "Enter = Редактировать выбранные файлы\n" "Spacebar = Открыть файл используя приложенние по умолчанию\n" "Ctrl+L = Фокус на полее для ввода текста\n" "? = Показать справку\n" "\n" "Стрелки вверх и вниз переключают фокус между полем для ввода текста\n" "и результатом.\n" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr "" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr " коммитов назад" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "\"%(branch)s\" была удалена из \"%(remote)s\"." #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "\"%(command)s\" завершилась с кодом \"%(status)d\"" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "\"%(command)s\" завершилась с кодом %(status)d" #: cola/guicmds.py:156 #, fuzzy, python-format msgid "\"%s\" already exists" msgstr "Ветвь \"%s\" уже существует." #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "\"%s\" уже существует, cole создаст новый каталог" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "Для \"%s\" требуется выбрать файл." #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "%d дней назад" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "%d часов назад" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "%d минут назад" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "%d патч(ей) применено." #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d пропущенно" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" "%s содержит конфликты слияния.\n" "\n" "Скорее всего вы должны пропустить этот файл.\n" "Зафиксировать в любом случае?" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "%s не является git репозиторием." #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "%s будет удален из ваших закладок" #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "%s будет удален из вашего последнего репозитория." #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: нет такого файла или каталога" #: cola/widgets/main.py:748 msgid "&Edit" msgstr "Редактировать" #: cola/widgets/main.py:690 msgid "&File" msgstr "Файл" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(Отмена коммита)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/diff.py:816 msgid "100%" msgstr "" #: cola/widgets/diff.py:817 msgid "200%" msgstr "" #: cola/widgets/diff.py:814 msgid "25%" msgstr "" #: cola/widgets/diff.py:818 msgid "400%" msgstr "" #: cola/widgets/diff.py:815 msgid "50%" msgstr "" #: cola/widgets/diff.py:819 msgid "800%" msgstr "" #: cola/widgets/finder.py:118 msgid " ..." msgstr "" #: cola/cmds.py:1685 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 "" "Шаблон коммита не настроен.\n" "Используйте \"git config\" для определения \"commit.template\"\n" "так, чтобы он указывал на шаблон коммита." #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "Отменить" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "Отмена действия" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "Прервать слияние" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Прервать слияние..." #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "Отменить действие?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Прерывание объединения приведет к потере *ВСЕХ* незакомиченных изменений.\n" "Восстановить незакомиченные изменения будет невозможно." #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "Отменить текущее слияние?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "О программе" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "О git-cola" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "" #: cola/sequenceeditor.py:164 #, fuzzy msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "Закоммитить подготовленные изменения\n" "Ctrl+Enter" #: cola/widgets/status.py:1376 #, fuzzy msgid "Action Name" msgstr "Настройки" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "Действия" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "Действия..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "Добавить" #: cola/widgets/bookmarks.py:469 #, fuzzy msgid "Add Favorite" msgstr "Избранное" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "Добавить внешний репозиторий" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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 "" "Добавляйте и удаляйте внешние репозитории используя \n" "кнопки Добавить(+) и Удалить(-) на левой стороне.\n" "\n" "Можно переименовать репозиторий выбрав его из списка\n" "и нажав \"enter\", или с помощью двойного клика." #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "Добавить внешний репозиторий" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "Добавить патчи (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "Добавить внешний репозиторий" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "Добавить в .gitignore" #: cola/widgets/status.py:287 #, fuzzy msgid "Add to Git Annex" msgstr "Добавить в .gitignore" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "Добавлено строк" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "Дополнительно" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "Возраст" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "Все репозитории" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "Если эта опция активна, то даже при слиянии в режиме fast-forward update будет создан отдельный (merge) коммит" #: cola/cmds.py:220 msgid "Amend" msgstr "Отмена коммита" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "Отменить коммит" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Отменить последний коммит" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "Отменить опубликованный коммит?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "Отмена коммита" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "Команда до сих пор выполняется.\n" "Отмена приведет к потере данных." #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "Будет создан неподписанный, легкий тег.\n" "Создать неподписанный тег??" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "Применить" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "Применить патчи" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "Применить патчи..." #: cola/widgets/stash.py:66 #, fuzzy msgid "Apply and drop the selected stash (git stash pop)" msgstr "Применить выбранные заначки (stash)" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "Применить выбранные заначки (stash)" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "Аргументы" #: cola/qtutils.py:886 msgid "Attach" msgstr "Прикрепить" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "Автор" #: cola/widgets/about.py:90 #, fuzzy msgid "Authors" msgstr "Автор" #: cola/hidpi.py:41 msgid "Auto" msgstr "" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "Авто перенос строчек" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "Базовый синтаксис" #: cola/widgets/prefs.py:276 #, fuzzy msgid "Blame Viewer" msgstr "Просмотр файла" #: cola/widgets/browse.py:206 #, fuzzy msgid "Blame selected paths" msgstr "Редактировать выбранный путь(и)" #: cola/cmds.py:545 cola/widgets/status.py:283 #, fuzzy msgid "Blame..." msgstr "Переименовать..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Ветвь" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "Ветвь \"%(branch)s\" не существует в \"%(remote)s\".\n" "Будет добавлена новая внешняя ветвь." #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "Ветвь \"%s\" уже существует." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "Ветвь существует" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Название ветви" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "Ветвь: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 #, fuzzy msgid "Branches" msgstr "Ветвь" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "Ветви..." #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "" #: cola/guicmds.py:52 msgid "Browse" msgstr "Показать" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "Показать коммиты..." #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "Просмотреть текущую ветвь..." #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "Просмотреть другие ветви..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "Показать..." #: cola/widgets/main.py:87 msgid "Browser" msgstr "Просомтрщик" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "Просмотр %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "Отменить" #: cola/sequenceeditor.py:181 #, fuzzy msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "Закоммитить подготовленные изменения\n" "Ctrl+Enter" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "Нельзя отменить коммит" #: cola/cmds.py:560 #, fuzzy, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "Не удалось запустить \"%s\": пожалуйста, настройте ваш редактор" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "Неполучилось выполнить \"%s\": пожалуйста, настройте просмотрщик истории" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "Не удалось запустить \"%s\": пожалуйста, настройте ваш редактор" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "Проверить правописание" #: cola/widgets/prefs.py:286 #, fuzzy msgid "Check spelling" msgstr "Проверить правописание" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Перейти" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "После создания сделать текущей ветвью" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Перейти на ветвь" #: cola/widgets/dag.py:413 #, fuzzy msgid "Checkout Detached HEAD" msgstr "Перейти на ветвь" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 #, fuzzy msgid "Checkout as new branch" msgstr "Перейти на ветвь" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Перейти..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/guicmds.py:72 #, fuzzy msgid "Cherry-Pick Commit" msgstr "Cherry-Pick коммит" #: cola/widgets/main.py:324 #, fuzzy msgid "Cherry-Pick..." msgstr "Перейти..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "Выберите путь" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "Выберите тип синтаксиса для \"git grep\"" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 #, fuzzy msgid "Clear Default Repository" msgstr "Текущий репозиторий" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "Очистить комментарий к коммиту" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "Очистить комментарий к коммиту?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "Очистить..." #: cola/widgets/clone.py:124 msgid "Clone" msgstr "Склонировать" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "Клонировать репозиторий" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Клонировать..." #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "Клонировать существующий репозиторий в %s" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Закрыть" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "Закрыть..." #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "Свернуть все" #: cola/sequenceeditor.py:371 #, fuzzy msgid "Command" msgstr "Описание коммита" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "Описание коммита" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "Не удалось закоммитить" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "Закоммитить подготовленные изменения" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "Закоммитить подготовленные изменения\n" "Ctrl+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "Краткое описание коммита" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "Закоммитить слияние, если нет конфликтов. Снимите отметку, чтобы оставить слияние незакомиченным" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "Сравнить" #: cola/difftool.py:102 #, fuzzy msgid "Compare All" msgstr "Сравнить" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "" #: cola/widgets/main.py:169 msgid "Console" msgstr "Консоль" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Продолжить" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Копировать" #: cola/widgets/status.py:269 #, fuzzy msgid "Copy Basename to Clipboard" msgstr "Копировать путь в буфер" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 #, fuzzy msgid "Copy Leading Path to Clipboard" msgstr "Копировать относительный путь в буфер" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "Копировать путь в буфер" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "Копировать относительный путь в буфер" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "Копировать SHA-1" #: cola/widgets/status.py:738 #, fuzzy msgid "Copy..." msgstr "Копировать" #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "Неполучилось разобрать Git URL: \"%s\"" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Создать ветвь" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "Создать патч" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "Создать внешнюю ветвь" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "Создать подписанный коммит" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "Создать тег" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "Создать тег..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "Создать неподписанный тег" #: cola/widgets/remote.py:192 #, fuzzy msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "Если эта опция активна, то даже при слиянии в режиме fast-forward update будет создан отдельный (merge) коммит" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "Создать новую внешнюю ветвь?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "Создать..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "Создан новый тег с именем \"%s\"" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "Текущий репозиторий" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "" #: cola/widgets/status.py:274 #, fuzzy msgid "Customize..." msgstr "Закрыть..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "Вырезать" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "" #: cola/icons.py:54 msgid "Dark Theme" msgstr "" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "Дата, Время" #: cola/icons.py:53 cola/themes.py:643 #, fuzzy msgid "Default" msgstr "Восстановить настройки по умолчанию" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Удалить" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "Удалить %d файл(ы)?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "Удалить закладку" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "Удалить закладку?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Удалить ветвь" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "Удалить файлы" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "Удалить файл(ы)..." #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "Удалить файлы?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "Удалить внешнюю ветвь" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "Удалить внешнюю ветвь" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "Удалить внешнюю ветвь..." #: cola/widgets/toolbar.py:276 #, fuzzy msgid "Delete Toolbar" msgstr "Удалить закладку" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "Удалить внешний репозиторий" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "Удалить внешнюю ветвь \"%s\"" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "Удалить внешнюю ветвь?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Удалить..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "Не удалось удалить \"%s\"" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "Удалено строк" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "Открепить" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "Обнаруживать отметки о конфликтах" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "Обнаруживать отметки о конфликтах в неслитых файлах" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "Сравнение" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "" #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "Настройки сравнения" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "Программа сравнения" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "Сравнить выделенное состояние с текущим" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "Сравнить текущее состояние с выделенным" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "Список различий" #: cola/difftool.py:324 #, fuzzy msgid "Difftool" msgstr "Программа сравнения" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "Каталог существует" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "Показывать не добавленные в контроль версий файлы" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "Документация" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "Удалить" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "Удалить заначку (stash)" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "Удалить заначку (stash)?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "Удалить заначку (stash) \"%s\"" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "Удалить выбранную заначку (stash)" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 #, fuzzy msgid "Edit" msgstr "Редактировать" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "Редактировать перемещение (rebase)" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "Редактировать внешние репозитории" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "Редактировать внешние репозитории..." #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "Редактировать выбранный путь(и)" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "Редактировать..." #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "Редактор" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "Адрес электронной почты" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "" #: cola/guicmds.py:332 cola/widgets/branch.py:478 #, fuzzy msgid "Enter New Branch Name" msgstr "Введите новое имя ветви" #: cola/guicmds.py:146 #, fuzzy msgid "Enter a name for the new bare repo" msgstr "Введите имя для заначки (stash)" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "Введите имя для заначки (stash)" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "Ошибка" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "Ошибка клонирования" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "При создании ветви возникла ошибка" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "Не удалось создать репозиторий" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "Не удалось удалить внешную ветвь" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "Ошибка редактирования файла" #: cola/cmds.py:559 #, fuzzy msgid "Error Launching Blame Viewer" msgstr "Ошибка запуска Просмотрщика истории" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "Ошибка запуска Просмотрщика истории" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "Не удалось создать внешную ветвь \"%s\"" #: cola/models/stash.py:233 #, fuzzy msgid "Error creating stash" msgstr "При создании ветви возникла ошибка" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Не удалось удалить внешнюю ветвь \"%s\"" #: cola/cmds.py:954 #, fuzzy, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "Добавить тег \"%(revision)s\" к \"%(name)s\"" #: cola/cmds.py:1721 #, fuzzy msgid "Error running prepare-commitmsg hook" msgstr "Вызов программы поддержки репозитория pre-commit..." #: cola/cmds.py:2987 cola/cmds.py:3033 #, fuzzy, python-format msgid "Error updating submodule %s" msgstr "Не удалось создать внешную ветвь \"%s\"" #: cola/cmds.py:3069 #, fuzzy msgid "Error updating submodules" msgstr "Ошибка редактирования файла" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "Ошибка: Не получается найти шаблон коммита" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "Ошибка: шаблон коммита не настроен" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Ошибка: не получилось клонировать \"%s\"" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "Ошибка: не получилось создать тег \"%s\"" #: cola/widgets/branch.py:433 #, fuzzy, python-format msgid "Executing action %s" msgstr "Словарь вернут к %s." #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "Развернуть все" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "Экспортировать патчи" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "Экспортировать патчи..." #: cola/widgets/main.py:547 msgid "Expression..." msgstr "Выражения..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "Расширенный синтаксис" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "Расширенное описание..." #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Только Fast Forward" #: cola/widgets/remote.py:181 #, fuzzy msgid "Fast-forward only" msgstr "Только Fast Forward" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "Избранные репозитории" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "Избранное" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "Получить все (fetch)" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "Получить отслеживаемую ветвь" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "Скачать все ветки (fetch)..." #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "Файловый менеджер..." #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "Сравнение файлов" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "Файл сохранен" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "Файл сохранен в \"%s\"" #: cola/fsmonitor.py:530 #, fuzzy msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "inotify отключены, потому что \"cola.inotify\" имеет значение \"false\"\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "Имя файла" #: cola/widgets/dag.py:821 msgid "Files" msgstr "Файлы" #: cola/widgets/branch.py:837 #, fuzzy msgid "Filter branches..." msgstr "Фильтр путей..." #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "Фильтр путей..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "Поиск файлов" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "Фиксированная строка" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "Шрифт с фиксированной шириной" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "Исправить предыдущий коммит" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "" #: cola/themes.py:705 msgid "Flat dark green" msgstr "" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "" #: cola/themes.py:691 msgid "Flat dark red" msgstr "" #: cola/themes.py:656 msgid "Flat light blue" msgstr "" #: cola/themes.py:677 msgid "Flat light green" msgstr "" #: cola/themes.py:670 msgid "Flat light grey" msgstr "" #: cola/themes.py:663 msgid "Flat light red" msgstr "" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Размер шрифта" #: cola/widgets/remote.py:197 #, fuzzy msgid "Force" msgstr "Перезаписать все (push)" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "Перезаписать все (fetch)" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "Перезаписать все (fetch)?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "Перезаписать все (push)" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "Перезаписать все (push)?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "Перезаписать (fetch) все из %s " #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "Перезаписать все (push) в %s?" #: cola/widgets/status.py:1376 #, fuzzy msgid "Format String" msgstr "Фиксированная строка" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "Получение информации о \"%s\"..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "Получить шаблон комментария к коммиту" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "Вниз" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "Вверх" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "Захватить файл..." #: cola/widgets/dag.py:848 msgid "Graph" msgstr "График" #: cola/widgets/main.py:354 msgid "Grep" msgstr "Поиск подстроки (git grep)" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "Вы недавно выполняли rebase/pull?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Помощь" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "Помощь - Поиск файлов" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "Просмотрщик истории" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "Игнорировать все пробелы" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "" #: cola/widgets/gitignore.py:43 #, fuzzy msgid "Ignore exact filename" msgstr "Игнорировать все пробелы" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "" #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "Включая теги" #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "" #: cola/widgets/main.py:657 #, fuzzy msgid "Initialize Git Annex" msgstr "Инициализация..." #: cola/widgets/main.py:661 #, fuzzy msgid "Initialize Git LFS" msgstr "Инициализация..." #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "Интерактивное перемещение (rebase)" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "Неверная версия" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "Сохранить индекс" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "Горячие клавиши" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "Запустить средство сравнения" #: cola/widgets/dag.py:401 #, fuzzy msgid "Launch Directory Diff Tool" msgstr "Запустить средство сравнения" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "Запустить редактор" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "Запустить терминал" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "Запустить git-cola" #: cola/widgets/browse.py:173 #, fuzzy msgid "Launch git-difftool against previous versions" msgstr "Сравнить c помощью git-difftool с предыдущей версией." #: cola/widgets/browse.py:165 #, fuzzy msgid "Launch git-difftool on the current path" msgstr "Запустить git-difftool по выбранному пути" #: cola/icons.py:55 msgid "Light Theme" msgstr "" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "Загрузить комментарий к коммиту" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "Загрузить комментарий к коммиту..." #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "Загрузить комментарий к предыдущему коммиту" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "Загрузка..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Локальная ветвь:" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "Локальная ветвь:" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "Зафиксировать панели" #: cola/widgets/dag.py:816 msgid "Log" msgstr "Лог" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Слияние (merge)" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "Объединить (merge) \"%(revision)s\" в \"%(branch)s\"" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "Программа слияния (merge)" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Уровень детальности сообщений при объединении" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "Не удалось завершить объединение. Требуется разрешение конфликта." #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "Объединить (merge) с \"%s\"" #: cola/widgets/branch.py:242 #, fuzzy msgid "Merge into current branch" msgstr "Просмотреть текущую ветвь..." #: cola/widgets/main.py:359 msgid "Merge..." msgstr "Слияние (merge)..." #: cola/widgets/main.py:1177 msgid "Merging" msgstr "Слияние" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "Сообщение" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "Отсутсвует комментарий к коммиту" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "Отсутствуют данные" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "Отсутствует имя" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "Версия не найдена" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "Отсутсвует описание тега" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "Изменено" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "Далее..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "Опуститься вниз" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "Подняться вверх" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "Удалить файл(ы) в корзину" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "Имя:" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "Имя нового внешнего репозитория" #: cola/guicmds.py:147 cola/widgets/main.py:281 #, fuzzy msgid "New Bare Repository..." msgstr "Новый репозиторий..." #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "Новый репозиторий..." #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Новый..." #: cola/actions.py:56 msgid "Next File" msgstr "Следующий файл" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "Нет" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "Версия не указана" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Отсутствуют изменения для коммита.\n" "\n" "Добавить к коммиту хотя бы один файл перед созданием коммита." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "В данной ветке не существует коммитов" #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Не указан репозиторий." #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "Non-fast-forward fetch перепишет локальную историю!" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "Non-fast-forward push перепишет историю на сервере!\n" "(Вы выполнили pull?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "Отсуствуют измения для коммита" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "Нечего делать" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Число строк в контексте сравнения" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Открыть" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "Открыть каталог" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Открыть Git репозиторий" #: cola/widgets/submodules.py:48 #, fuzzy msgid "Open Parent" msgstr "Открыть последний" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "Открыть родительский каталог" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "Открыть последний" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "Открыть, используя приложение по умолчанию" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "Открыть рабочий каталог" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "Открыть в новом окне" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "Открыть в новом окне..." #: cola/widgets/main.py:410 msgid "Open..." msgstr "Открыть..." #: cola/widgets/branch.py:354 #, fuzzy msgid "Other branches" msgstr "Фильтр путей..." #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "Перезаписать" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "Перезаписать \"%s\"?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "Перезаписать файл?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "Разбор аргументов с помощью шелла.\n" "Запросы с пробелами должны быть в \"двойных кавычках\"." #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "Частично добавлено к коммиту" #: cola/widgets/main.py:758 msgid "Paste" msgstr "Вставить" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "Патчи применены" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "Путь или URL для клонирования (Env. $VARS okay)" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "Пожалуйста, предоставьте имя ветви и версию" #: cola/cmds.py:2297 msgid "Please select a file" msgstr "Пожалуйста, выберите файл" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "Укажите имя для нового тега" #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "Пожалуйста, укажите версию для тега." #: cola/widgets/commitmsg.py:417 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/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Настройки" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "Префикс" #: cola/widgets/main.py:341 #, fuzzy msgid "Prepare Commit Message" msgstr "Поиск комментария к коммиту" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "" #: cola/actions.py:65 msgid "Previous File" msgstr "Предыдущий файл" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "" #: cola/widgets/remote.py:170 #, fuzzy msgid "Prompt when pushing creates new remote branches" msgstr "Создать новую внешнюю ветвь?" #: cola/widgets/remote.py:212 #, fuzzy msgid "Prune " msgstr "Чистка" #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "Получить (pull)" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "Получить (pull)..." #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Отправить (push)" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Отправить (push)..." #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Выход" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Переместить (rebase)" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "Переместить (rebase) в %s" #: cola/cmds.py:2105 #, fuzzy msgid "Rebase stopped" msgstr "Переместить (rebase) " #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "Перемещение" #: cola/widgets/main.py:118 msgid "Recent" msgstr "Недавнее" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "Недавние репозитории" #: cola/widgets/prefs.py:279 #, fuzzy msgid "Recent repository count" msgstr "Недавние репозитории" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "Недавно измененные файлы" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "Недавно измененные файлы..." #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "Восстановить удаленные заначки (stash) будет невозможно" #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Восстановить потерянные коммиты будет сложно." #: cola/widgets/main.py:751 msgid "Redo" msgstr "Повторить" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Обновить" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "Пометки" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Внешние репозитории" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "Внешняя ветвь" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "Внешняя ветвь удалена" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "Внешний репозиторий git - двойной клик для переименования" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "Удалить" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "Удалить %s из списка последних изменений?" #: cola/widgets/toolbar.py:321 #, fuzzy msgid "Remove Element" msgstr "Удалить" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "Удалить выбранное (Delete)" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Переименовать" #: cola/cmds.py:1153 #, fuzzy, python-format msgid "Rename \"%s\"" msgstr "Переименовать" #: cola/widgets/branch.py:268 #, fuzzy msgid "Rename Branch" msgstr "Переименовать ветвь..." #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "Переименовать ветвь..." #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "Переименовать существующую ветвь:" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "Переименовать внешнюю ветвь" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 #, fuzzy msgid "Rename Repository" msgstr "Клонировать репозиторий" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 #, fuzzy msgid "Rename branch" msgstr "Переименовать ветвь..." #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "Переименовать внешнюю ветвь \"%(current)s\" на \"%(new)s\"?" #: cola/widgets/browse.py:159 #, fuzzy msgid "Rename selected paths" msgstr "Редактировать выбранный путь(и)" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "Репозиторий: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Сброс" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "Сбросить (reset) \"%(branch)s\" к \"%(revision)s\"?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "Сбросить (reset) ветвь" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "Сбросить (reset) ветвь?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "Сброс \"%(branch)s\" в \"%(revision)s\" приведет к потере коммитов." #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "Откатить изменения в этой части" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "Откатить изменения в этой части" #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "Откатить изменения в этой части?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "Отменить изменения в выбранных линиях" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "Откатить выделенные линии..." #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "Отменить изменения в выбранных линиях?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "Отменить незакомиченные изменения" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "Отменить незакомиченные изменения?" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "Отменить незакомиченные изменения..." #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "Откатить изменения" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "Откатить изменения?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "Откатить изменения..." #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "Отменить незакомиченные изменения?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "Откатить изменения?" #: cola/widgets/browse.py:190 #, fuzzy msgid "Revert uncommitted changes to selected paths" msgstr "Отменить незакомиченные изменения по выбранным путям." #: cola/widgets/browse.py:181 #, fuzzy msgid "Revert unstaged changes to selected paths" msgstr "Отменить незафиксированные изменения по выбранным путям." #: cola/guicmds.py:320 msgid "Review" msgstr "Просмотр" #: cola/widgets/main.py:597 msgid "Review..." msgstr "Просмотр..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Версия" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Выражение для определения версии:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Версия для объединения" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "Переписать опубликованный коммит?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "Запустить" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "Запустить \"%s\"?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "Запустить %s?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "Выполнить комманду \"%s\"?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "Запуск комманды: %s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "" #: cola/sequenceeditor.py:372 #, fuzzy msgid "SHA-1" msgstr "Копировать SHA-1" #: cola/widgets/prefs.py:205 #, fuzzy msgid "Safe Mode" msgstr "Добавить к коммиту измененые файлы" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Сохранить" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "Сохранить архив" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "Сохранить как архив..." #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "Сохранить настройки интерфейса" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "Сохранить заначку (stash)" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "Сохранить измененное состояние в новую заначку (stash)" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "Сохранен \"%(filename)s\" из \"%(ref)s\" в \"%(destination)s\"" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "Поиск" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "Поиск авторов" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "Поиск комментария к коммиту" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "Поиск авторов коммитов" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "Поиск по диапазону дат" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "Поиск различий" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "Поиск по выражению" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "Поиск по пути" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "Искать фиксированную строку" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "" #: cola/widgets/main.py:507 msgid "Search..." msgstr "Поиск..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Выбрать" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Выделить все" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "Выбрать ветвь для просмотра" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "Выбрать наследника" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "Выбрать коммит" #: cola/guicmds.py:136 #, fuzzy msgid "Select Directory..." msgstr "Выбрать репозиторий..." #: cola/cmds.py:2078 #, fuzzy msgid "Select New Upstream" msgstr "Выбрать" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "Выбрать нового наследника" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "Выбрать самого старшего родителя" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "Выбрать родителя" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "Выбрать предыдущую версию" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "Выберите родительский каталог для новой копии" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 #, fuzzy msgid "Select output dir" msgstr "Выбрать коммит" #: cola/widgets/selectcommits.py:182 #, fuzzy msgid "Select output directory" msgstr "Выбрать репозиторий..." #: cola/widgets/diff.py:1770 #, fuzzy msgid "Select patch file(s)..." msgstr "Выбрать файл(ы) патча..." #: cola/widgets/editremotes.py:434 #, fuzzy msgid "Select repository" msgstr "Выбрать репозиторий..." #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 #, fuzzy msgid "Set Default Repository" msgstr "Выбрать репозиторий..." #: cola/widgets/branch.py:291 #, fuzzy msgid "Set Upstream Branch" msgstr "Выбрать" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 #, fuzzy msgid "Set upstream" msgstr "Выбрать" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "Настройки" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "Ручной ввод аргументов \"git grep\"" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "Горячие клавиши" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Показать отчет об изменениях после объединения" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "Показать справку" #: cola/widgets/filelist.py:29 #, fuzzy msgid "Show History" msgstr "Показать историю" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "Показать помощь\n" "Горячая клавиша: ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "Показать изменения с" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Подписать" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "Подписать тег" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "Подписаться под этим коммитом" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "" #: cola/cmds.py:2527 msgid "Skip" msgstr "Пропустить" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "Пропустить текущий патч" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "Сортировать закладки по алфавиту" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "Укажите SHA-1 для тега" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "Укажите описание тега" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "Укажите имя тега" #: cola/widgets/spellcheck.py:45 #, fuzzy msgid "Spelling Suggestions" msgstr "Советы по правописанию" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "Объединить (squash)" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "Объединить слитые коммиты в один коммит" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "Добавить к коммиту" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "Добавить / Убрать" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "Добавить эту часть к коммиту" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Добавить к коммиту измененые файлы" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "Добавить к коммиту" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "Добавить к коммиту выделенные линии" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "Подготовить не слитые" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "Добавить к коммиту не отслеживаемые файлы" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "Добавить к коммиту и закоммитить" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "Добавить к коммиту и закоммитить?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "Конфликты добавления к коммиту" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "Добавить к коммиту конфликтующие файлы?" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "Добавить/убрать выбранные пути к/из коммита" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "Подготовленно к коммиту" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "Добавление к коммиту: %s" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "Начать интерактивное перемещение (rebase)..." #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "Начальная версия" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "Спрятать (stash)" #: cola/widgets/stash.py:79 #, fuzzy msgid "Stash Index" msgstr "Спрятать (stash)" #: cola/widgets/stash.py:79 #, fuzzy msgid "Stash staged changes only" msgstr "Закоммитить подготовленные изменения" #: cola/widgets/stash.py:75 #, fuzzy msgid "Stash unstaged changes only, keeping staged changes" msgstr "Отменить незафиксированные изменения по выбранным путям." #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "Спрятать (stash)..." #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "Статус" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "Описание" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Ширина табов" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Тег" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "Тег создан" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Описание тега..." #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "Требуется подписать тег, но описание тега пустое." #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "Ширина текста" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "" #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "Комментарий к коммиту был очищен." #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "Файл \"%s\" существует и будет перезаписан." #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "Следующие файлы будут удалены:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "Поле версии не может быть пустым." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "Это не может быть отменено. Очистить комментарий к коммиту?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "Этот коммит уже опубликован.\n" "Данная операция перепишет историю на сервере.\n" "Возможно лучше этого не делать." #: cola/widgets/diff.py:1232 #, fuzzy msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "Эта операция отменит незакомиченные изменения.\n" "Эти изменения нельзя будет восстановить" #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Эта операция отменит незакомиченные изменения.\n" "Эти изменения нельзя будет восстановить" #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Эта операция отменит незакомиченные изменения.\n" "Эти изменения нельзя будет восстановить" #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "Этот репозиторий сейчас будет перемещен (rebase).\n" "Исправьте конфликты, закоммитьте изменения, и запустите:\n" " Переместить (rebase) > Продолжить" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "Этот репозиторий в процессе слияния (merge).\n" "Исправьте конфликты и закоммитьте изменения." #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "Переключить пометку" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "Переключить пометку затрагивающих коммитов" #: cola/widgets/branch.py:65 #, fuzzy msgid "Toggle the branches filter" msgstr "Включить фильтр путей" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "Включить фильтр путей" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Ветвь слежения" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "Отслеживаемая ветвь" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "Не могу переместить (rebase)" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "Отменить" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "Не объединено" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "Убрать из коммита" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "Убрать все из коммита" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "Убрать эту часть из коммита" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "Убрать из коммита" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "Убрать из коммита выбранные линии" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "Удаление из коммита: %s" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "Убрать выбранные файлы из контроля версий" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "Не добавлены в контроль версий" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "Не добавлено в контроль версий: %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Обновить имеющуюся ветвь:" #: cola/cmds.py:3019 #, fuzzy msgid "Update Submodule" msgstr "Обновлено" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "" #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "Обновление" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Имя пользователя" #: cola/widgets/about.py:89 #, fuzzy msgid "Version" msgstr "Версия" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "Вид" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "Показать историю..." #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "Показать историю для выбранного пути" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "Визуализировать" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "Отобразить все ветви" #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "Отобразить текущую ветвь..." #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "Подписать тег (git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "Вы хотить добавить к коммиту и закоммитить все измененные файлы?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "Вы находитесь в процессе слияния (merge).\n" "Нельзя отменить коммит во время слияния." #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "Вы не можете выполнить перемещение (rebase) с незакомиченными изменениями." #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "Вы должны выбрать версию для слияния (merge)." #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "Вы должны выбрать версию для просмотра." #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "Приблизить" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "Отдалить" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "Подогнать по размеру" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "фраза для поиска / аргументы командной строки" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "код завершения %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "fatal: \"%s\" не является каталогом. Пожалуйста, укажите корректный --repo ." #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "результаты поиска..." #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "" #: cola/hidpi.py:43 msgid "x 1" msgstr "" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "" #: cola/hidpi.py:46 msgid "x 2" msgstr "" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "" #~ 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 "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "Это известная проблема с Tcl,\n" #~ "распространяемым Cygwin." #, fuzzy #~ msgid "\"%s\" returned exit status %d" #~ msgstr "\"%(command)s\" завершилась с кодом %(status)d" #~ msgid "\"git commit\" returned exit code %s" #~ msgstr "\"git commit\" вернул код %s" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%s ... %*i из %*i %s (%3i%%)" #~ msgid "%s Repository" #~ msgstr "для репозитория %s" #~ msgid "%s of %s" #~ msgstr "%s из %s" #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "Недопустимое название ветви '%s'." #~ msgid "* Binary file (not showing content)." #~ msgstr "* Двоичный файл (содержимое не показано)" #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "Для опции 'Объединено с' требуется указать ветвь." #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Заначка (stash) с именем '%s' уже существует." #~ msgid "Abort completed. Ready." #~ msgstr "Прервано." #~ msgid "Abort failed." #~ msgstr "Прервать не удалось." #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "Прерван переход на '%s' (требуется объединение на уровне файлов)" #~ msgid "Already up-to-date." #~ msgstr "И так последняя версия" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "Всегда (не выполнять проверку объединений)" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "Всегда (не выполнять проверку на объединение)" #~ msgid "Amended Commit Message:" #~ msgstr "Комментарий к исправленному состоянию:" #~ msgid "Amended Initial Commit Message:" #~ msgstr "Комментарий к исправленному первоначальному состоянию:" #~ msgid "Amended Merge Commit Message:" #~ msgstr "Комментарий к исправленному объединению:" #~ msgid "Annotation complete." #~ msgstr "Аннотация завершена." #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "Любые изменения, не подготовленные к сохранению, будут потеряны при данной операции." #~ msgid "Apply/Reverse Hunk" #~ msgstr "Применить/Убрать изменение" #~ msgid "Arbitrary URL:" #~ msgstr "по указанному URL:" #~ 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 "Branch '%s' does not exist." #~ msgstr "Ветвь '%s' не существует " #, fuzzy #~ msgid "Branch created" #~ msgstr "Название ветви" #~ msgid "Browse %s's Files" #~ msgstr "Показать файлы ветви %s" #~ msgid "Browse Branch Files" #~ msgstr "Показать файлы ветви" #, fuzzy #~ msgid "Browse Revision..." #~ msgstr "Версия" #~ msgid "Calling commit-msg hook..." #~ msgstr "Вызов программы поддержки репозитория commit-msg..." #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\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 "Cannot determine HEAD. See console output for details." #~ msgstr "Не могу определить HEAD. Дополнительная информация на консоли." #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "Не могу получить ветви и объекты. Дополнительная информация на консоли." #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "Не могу получить метки. Дополнительная информация на консоли." #~ msgid "Cannot find git in PATH." #~ msgstr "git не найден в PATH." #~ 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 "Cannot move to top of working directory:" #~ msgstr "Невозможно перейти к корню рабочего каталога репозитория: " #~ msgid "Cannot parse Git version string:" #~ msgstr "Невозможно распознать строку версии Git: " #~ msgid "Cannot resolve %s as a commit." #~ msgstr "Не могу распознать %s как состояние." #~ msgid "Cannot use funny .git directory:" #~ msgstr "Каталог.git испорчен: " #~ msgid "Cannot write shortcut:" #~ msgstr "Невозможно записать ссылку:" #~ msgid "Change Font" #~ msgstr "Изменить шрифт" #~ msgid "Checked out '%s'." #~ msgstr "Ветвь '%s' сделана текущей." #~ msgid "Clone Type:" #~ msgstr "Тип клона:" #~ msgid "Clone failed." #~ msgstr "Клонирование не удалось." #~ msgid "Cloning from %s" #~ msgstr "Клонирование %s" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "Состояние %s выглядит поврежденным" #~ msgid "Commit declined by commit-msg hook." #~ msgstr "Сохранение прервано программой поддержки репозитория commit-msg" #~ msgid "Commit declined by pre-commit hook." #~ msgstr "Сохранение прервано программой поддержки репозитория pre-commit" #~ msgid "Commit failed: %s" #~ msgstr "Не удалось создать коммит: %s" #~ msgid "Commit@@noun" #~ msgstr "Состояние" #~ msgid "Compress Database" #~ msgstr "Сжать базу данных" #~ msgid "Compressing the object database" #~ msgstr "Сжатие базы объектов" #~ msgid "Copied Or Moved Here By:" #~ msgstr "Скопировано/перемещено в:" #~ msgid "Copying objects" #~ msgstr "Копирование objects" #~ msgid "Counting objects" #~ msgstr "Считаю объекты" #~ msgid "Create Desktop Icon" #~ msgstr "Создать ярлык на рабочем столе" #~ msgid "Created commit: %s" #~ msgstr "Создан коммит: %s" #~ msgid "Creating working directory" #~ msgstr "Создаю рабочий каталог" #~ msgid "Current Branch:" #~ msgstr "Текущая ветвь:" #~ msgid "Database Statistics" #~ msgstr "Статистика базы данных" #~ msgid "Decrease Font Size" #~ msgstr "Уменьшить размер шрифта" #~ msgid "Delete Local Branch" #~ msgstr "Удалить локальную ветвь" #~ msgid "Delete Only If" #~ msgstr "Удалить только в случае, если" #~ msgid "Delete Only If Merged Into" #~ msgstr "Удалить только в случае, если было объединение с" #, fuzzy #~ msgid "Delete selected branch?" #~ msgstr "Удалить внешнюю ветвь" #~ msgid "Destination Repository" #~ msgstr "Репозиторий назначения" #~ msgid "Detach From Local Branch" #~ msgstr "Отсоединить от локальной ветви" #~ msgid "Diff/Console Font" #~ msgstr "Шрифт консоли и изменений (diff)" #~ msgid "Directory %s already exists." #~ msgstr "Каталог '%s' уже существует." #~ msgid "Disk space used by loose objects" #~ msgstr "Объем дискового пространства, занятый несвязанными объектами" #~ msgid "Disk space used by packed objects" #~ msgstr "Объем дискового пространства, занятый упакованными объектами" #~ msgid "Do Nothing" #~ msgstr "Ничего не делать" #~ msgid "Enter Git Repository" #~ msgstr "Введите git репозиторий" #, fuzzy #~ msgid "Error %s" #~ msgstr "Ошибки: %s" #~ msgid "Error loading commit data for amend:" #~ msgstr "Ошибка при загрузке данных для исправления сохраненного состояния:" #~ msgid "Error: Command Failed" #~ msgstr "Ошибка: не удалось выполнить команду" #~ msgid "Error: Stash exists" #~ msgstr "Ошибка: заначка (stash) уже существует" #~ msgid "Errors: %s" #~ msgstr "Ошибки: %s" #~ msgid "Exit code: %s" #~ msgstr "Код завершения: %s" #~ msgid "Failed to completely save options:" #~ msgstr "Не удалось полностью сохранить настройки:" #~ msgid "Failed to configure origin" #~ msgstr "Не могу сконфигурировать исходный репозиторий." #~ msgid "Failed to create repository %s:" #~ msgstr "Не удалось создать репозиторий %s:" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "Не удалось удалить ветви:\n" #~ "%s" #~ msgid "Failed to open repository %s:" #~ msgstr "Не удалось открыть репозиторий %s:" #~ msgid "Failed to rename '%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 "Failed to stage selected hunk." #~ msgstr "Не удалось подготовить к сохранению выбранную часть." #~ msgid "Failed to unstage selected hunk." #~ msgstr "Не удалось исключить выбранную часть." #~ msgid "Failed to update '%s'." #~ msgstr "Не удалось обновить '%s'." #~ msgid "Fast Forward Only " #~ msgstr "Только Fast Forward" #~ msgid "Fetch from" #~ msgstr "Получение из" #~ msgid "Fetching new changes from %s" #~ msgstr "Получение изменений из %s " #~ msgid "File level merge required." #~ msgstr "Требуется объединение на уровне файлов." #~ msgid "Font Example" #~ msgstr "Пример текста" #~ msgid "Font Family" #~ msgstr "Шрифт" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "Намеренно переписать существующую ветвь (возможна потеря изменений)" #~ msgid "From Repository" #~ msgstr "Из репозитория" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "Полная копия (Медленный, создает резервную копию)" #~ msgid "GPG-signed" #~ msgstr "Подписан GPG" #~ msgid "Garbage files" #~ msgstr "Мусор" #~ msgid "Git Repository (subproject)" #~ msgstr "Репозиторий Git (подпроект)" #~ msgid "Git directory not found:" #~ 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 "Hardlinks are unavailable. Falling back to copying." #~ msgstr "\"Жесткие ссылки\" не доступны. Буду использовать копирование." #~ msgid "In File:" #~ msgstr "Файл:" #~ msgid "Increase Font Size" #~ msgstr "Увеличить размер шрифта" #, fuzzy #~ msgid "Index" #~ msgstr "Ошибка индекса" #~ msgid "Initial Commit Message:" #~ msgstr "Комментарий к первому состоянию:" #~ msgid "Initial file checkout failed." #~ msgstr "Не удалось получить начальное состояние файлов репозитория." #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "Неверный GIT_COMMITTER_IDENT:" #~ msgid "Invalid date from Git: %s" #~ msgstr "Неправильная дата в репозитории: %s" #~ msgid "Invalid font specified in %s:" #~ msgstr "В %s установлен неверный шрифт:" #~ msgid "Invalid spell checking configuration" #~ msgstr "Неправильная конфигурация программы проверки правописания" #~ msgid "KiB" #~ 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 a merge can be performed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Последнее прочитанное состояние репозитория не соответствует текущему.\n" #~ "\n" #~ "С момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\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 another commit can be created.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Последнее прочитанное состояние репозитория не соответствует текущему.\n" #~ "\n" #~ "С момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \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 the current branch can be changed.\n" #~ "\n" #~ "The rescan will be automatically started now.\n" #~ msgstr "" #~ "Последнее прочитанное состояние репозитория не соответствует текущему.\n" #~ "\n" #~ "С момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\n" #~ "\n" #~ "Это будет сделано сейчас автоматически.\n" #~ msgid "Linking objects" #~ msgstr "Создание ссылок на objects" #~ msgid "Loading annotation..." #~ msgstr "Загрузка аннотации..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "Загрузка аннотации копирований/переименований..." #~ msgid "Loading original location annotations..." #~ msgstr "Загрузка аннотаций первоначального положения объекта..." #~ msgid "Local Branches" #~ msgstr "Локальные ветви" #~ msgid "Local Merge..." #~ msgstr "Локальное объединение..." #~ msgid "Location %s already exists." #~ msgstr "Путь '%s' уже существует." #~ msgid "Main Font" #~ msgstr "Шрифт интерфейса" #~ msgid "Match Tracking Branch Name" #~ msgstr "Взять из имен ветвей слежения" #~ msgid "Match Tracking Branches" #~ msgstr "Имя новой ветви взять из имен ветвей слежения" #~ msgid "Merge completed successfully." #~ msgstr "Объединение успешно завершено." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "Стратегия объединения '%s' не поддерживается." #~ msgid "Merged Into:" #~ msgstr "Объединено с:" #~ msgid "Merging %s and %s..." #~ msgstr "Объединение %s и %s..." #~ msgid "Modified, not staged" #~ msgstr "Изменено, не подготовлено" #~ msgid "New Branch Name Template" #~ msgstr "Шаблон для имени новой ветви" #~ msgid "New Commit" #~ msgstr "Новое состояние" #~ msgid "New Name:" #~ msgstr "Новое название:" #~ msgid "Next >" #~ msgstr "Дальше >" #~ 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 "No default branch obtained." #~ msgstr "Не было получено ветви по умолчанию." #~ 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 "No working directory" #~ msgstr "Отсутствует рабочий каталог" #~ msgid "Number of loose objects" #~ msgstr "Количество несвязанных объектов" #~ msgid "Number of packed objects" #~ msgstr "Количество упакованных объектов" #~ msgid "Number of packs" #~ msgstr "Количество pack-файлов" #~ msgid "On Debian-based systems try: sudo apt-get install python-pyinotify" #~ msgstr "Если система основана на Debian попробуйте: sudo apt-get install python-pyinotify" #~ 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 "Options" #~ msgstr "Настройки" #~ msgid "Original File:" #~ msgstr "Исходный файл:" #~ msgid "Originally By:" #~ msgstr "Источник:" #~ msgid "" #~ "Output:\n" #~ "%s" #~ msgstr "" #~ "Вывод:\n" #~ "%s" #~ msgid "Output: %s" #~ msgstr "Вывод: %s" #~ msgid "Packed objects waiting for pruning" #~ msgstr "Несвязанные объекты, которые можно удалить" #~ msgid "Path to git repository" #~ msgstr "Путь к git репозиторию" #~ msgid "Please select one or more branches to delete." #~ msgstr "Укажите одну или несколько ветвей для удаления." #~ msgid "Please supply a branch name." #~ msgstr "Укажите название ветви." #~ msgid "Portions staged for commit" #~ 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 "Preferences..." #~ msgstr "Настройки..." #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "Чистка ветвей слежения при получении изменений" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "Чистка ветвей слежения, удаленных из %s" #~ msgid "Push Branches" #~ msgstr "Отправить изменения в ветвях" #~ msgid "Push to" #~ msgstr "Отправить" #~ msgid "Pushing %s %s to %s" #~ msgstr "Отправка %s %s в %s" #~ msgid "Reading %s..." #~ msgstr "Чтение %s..." #~ msgid "Ready to commit." #~ msgstr "Подготовлено для сохранения" #~ msgid "Ready." #~ msgstr "Готово." #, fuzzy #~ msgid "Rebase Branch" #~ msgstr "Переименование ветви" #, fuzzy #~ msgid "Rebase..." #~ msgstr "Сбросить..." #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "Восстановить удаленные ветви сложно.\n" #~ "\n" #~ "Продолжить?" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "Восстанавливать удаленные ветви сложно. \n" #~ "\n" #~ " Удалить выбранные ветви?" #~ msgid "Refreshing file status..." #~ msgstr "Обновление информации о состоянии файлов..." #, fuzzy #~ msgid "Remote Branches" #~ msgstr "Внешняя ветвь" #~ msgid "Remote:" #~ msgstr "внешний:" #~ msgid "Rename remote?" #~ msgstr "Переименовать внешнюю ветвь?" #~ msgid "Repository" #~ msgstr "Репозиторий" #~ msgid "Requires merge resolution" #~ msgstr "Требуется разрешение конфликта при объединении" #~ msgid "Rescan" #~ msgstr "Перечитать" #, fuzzy #~ msgid "Reset Branch Head" #~ msgstr "Сбросить (reset) ветвь" #, fuzzy #~ msgid "Reset Hard" #~ msgstr "Сбросить (reset) ветвь" #, fuzzy #~ msgid "Reset Merge" #~ msgstr "Версия для объединения" #, fuzzy #~ msgid "Reset Soft" #~ msgstr "Сброс" #~ 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 "Reset hard?" #~ msgstr "Сбросить (reset) ветвь?" #, fuzzy #~ msgid "Reset merge?" #~ msgstr "Сбросить (reset) ветвь?" #, fuzzy #~ msgid "Reset soft?" #~ msgstr "Сбросить '%s'?" #~ msgid "Revert changes in these %i files?" #~ msgstr "Отменить изменения в %i файле(-ах)?" #~ msgid "Select File" #~ msgstr "Выбрать файл" #~ msgid "Select Repository..." #~ msgstr "Выбрать репозиторий..." #~ msgid "Select file from \"%s\"" #~ msgstr "Выбрать файл из \"%s\"" #~ msgid "Select manually..." #~ msgstr "Выбрать вручную..." #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "Общий (Самый быстрый, не рекомендуется, без резервной копии)" #~ msgid "Shared only available for local repository." #~ msgstr "Общий клон возможен только для локального репозитория." #, fuzzy #~ msgid "Show Details..." #~ msgstr "Удалить файл(ы)..." #~ msgid "Show Less Context" #~ msgstr "Меньше контекста" #~ msgid "Show More Context" #~ msgstr "Больше контекста" #~ msgid "Source Branches" #~ msgstr "Исходные ветви" #~ msgid "Spell Checker Failed" #~ msgstr "Ошибка проверки правописания" #~ msgid "Spell checker silently failed on startup" #~ msgstr "Программа проверки правописания не смогла запустится" #~ msgid "Spell checking is unavailable" #~ msgstr "Проверка правописания не доступна" #~ msgid "Spelling Dictionary:" #~ msgstr "Словарь для проверки правописания:" #~ msgid "Stage Hunk For Commit" #~ msgstr "Подготовить часть для сохранения" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "Подготовлено (будет сохранено)" #~ msgid "Staged for commit, missing" #~ msgstr "Подготовлено для сохранения, отсутствует" #~ msgid "Staged for removal" #~ msgstr "Подготовлено для удаления" #~ msgid "Staged for removal, still present" #~ msgstr "Подготовлено для удаления, еще не удалено" #~ msgid "Staging Area" #~ msgstr "Управление коммитом" #~ msgid "Staging area (index) is already locked." #~ msgstr "Рабочая область заблокирована другим процессом." #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "Стандартный (Быстрый, полуизбыточный, \"жесткие\" ссылки)" #~ msgid "Standard only available for local repository." #~ msgstr "Стандартный клон возможен только для локального репозитория." #~ msgid "Starting gitk... please wait..." #~ msgstr "Запускается gitk... пожалуйста, ждите..." #~ msgid "Staying on branch '%s'." #~ msgstr "Ветвь '%s' остается текущей." #~ msgid "Success" #~ msgstr "Процесс успешно завершен" #~ msgid "Summary:" #~ msgstr "Описание:" #~ msgid "The 'main' branch has not been initialized." #~ msgstr "Не инициализирована ветвь 'main'." #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "Следующие ветви объединены с %s не полностью:" #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "Следующие ветви объединены с %s не полностью:\n" #~ " - %s" #~ 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 "This Detached Checkout" #~ msgstr "Текущее отсоединенное состояние" #~ msgid "" #~ "This PyQt4 does not include QtWebKit.\n" #~ "The keyboard shortcuts feature is unavailable." #~ msgstr "" #~ "PyQt4 не включен в QtWebKit.\n" #~ "Горячие клавиши не доступны." #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "Это пример текста.\n" #~ "Если Вам нравится этот текст, это может быть Ваш шрифт." #~ 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 "Tracking branch %s is not a branch in the remote repository." #~ msgstr "Ветвь слежения %s не является ветвью во внешнем репозитории." #~ msgid "Transfer Options" #~ msgstr "Настройки отправки" #~ msgid "Unable to copy object: %s" #~ msgstr "Не могу скопировать объект: %s" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "Не могу скопировать objects/info/alternates: %s" #~ msgid "Unable to display %s" #~ msgstr "Не могу показать %s" #~ msgid "Unable to hardlink object: %s" #~ msgstr "Не могу \"жестко связать\" объект: %s" #~ msgid "Unable to obtain your identity:" #~ msgstr "Невозможно получить информацию об авторстве:" #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "Не удалось запустить gitk:\n" #~ "\n" #~ "%s не существует" #~ msgid "Unable to unlock the index." #~ msgstr "Не удалось разблокировать индекс" #~ msgid "Unexpected EOF from spell checker" #~ msgstr "Программа проверки правописания прервала передачу данных" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "Обнаружено неизвестное состояние файла %s.\n" #~ "\n" #~ "Файл %s не может быть сохранен данной программой.\n" #~ msgid "Unlock Index" #~ msgstr "Разблокировать индекс" #~ 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 "Unrecognized spell checker" #~ msgstr "Нераспознаная программа проверки правописания" #~ msgid "Unstage Hunk From Commit" #~ msgstr "Не сохранять часть" #~ msgid "Unsupported spell checker" #~ msgstr "Неподдерживаемая программа проверки правописания" #~ msgid "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui." #~ msgstr "Не удалось обновить индекс Git. Состояние репозитория будетперечитано автоматически." #~ msgid "Updating working directory to '%s'..." #~ msgstr "Обновление рабочего каталога из '%s'..." #~ msgid "Updating..." #~ msgstr "Обновление..." #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Использовать thin pack (для медленных сетевых подключений)" #~ msgid "Verify Database" #~ msgstr "Проверить базу данных" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "Проверка базы объектов при помощи fsck" #~ msgid "Visualize %s's History" #~ msgstr "История ветви %s наглядно" #~ msgid "Working... please wait..." #~ msgstr "В процессе... пожалуйста, ждите..." #~ 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 "" #~ "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 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 "You must correct the above errors before committing." #~ msgstr "Прежде чем сохранить, исправьте вышеуказанные ошибки." #~ msgid "[Up To Parent]" #~ msgstr "[На уровень выше]" #~ msgid "commit-tree failed:" #~ msgstr "Программа commit-tree завершилась с ошибкой:" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "критическая ошибка: невозможно разрешить %s" #~ msgid "" #~ "file notification: disabled\n" #~ "Note: install pywin32 to enable.\n" #~ msgstr "" #~ "оповещения файлов: отключено\n" #~ "Примечание: требуется установить pywin32 для включения.\n" #~ msgid "files" #~ msgstr "файлов" #~ msgid "files checked out" #~ msgstr "файлы извлечены" #~ msgid "files reset" #~ msgstr "изменения в файлах отменены" #~ msgid "git clone returned exit code %s" #~ msgstr "git clone завершился со статусом %s" #~ msgid "git tag returned exit code %s" #~ msgstr "Комманда git tag завершилась с кодом %s" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - графический пользовательский интерфейс к Git." #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: критическая ошибка" #~ msgid "inotify enabled." #~ msgstr "inotify включено" #~ msgid "lines annotated" #~ msgstr "строк прокомментировано" #~ msgid "objects" #~ msgstr "объекты" #~ msgid "push %s" #~ msgstr "отправить %s" # carbon copy #~ msgid "remote prune %s" #~ msgstr "чистка внешнего %s" #~ msgid "unknown" #~ msgstr "неизвестно" #~ msgid "update-ref failed:" #~ msgstr "Программа update-ref завершилась с ошибкой:" #~ msgid "warning" #~ msgstr "предупреждение" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "предупреждение: Tcl не поддерживает кодировку '%s'." #~ msgid "write-tree failed:" #~ msgstr "Программа write-tree завершилась с ошибкой:" git-cola-4.6.1/cola/i18n/sv.po000066400000000000000000003505071457126473700157400ustar00rootroot00000000000000# Swedish translation of git-cola. # Copyright (C) 2007, 2008 Shawn Pearce, et al. # This file is distributed under the same license as the git-cola package. # # Peter Karlsson , 2007-2008. msgid "" msgstr "" "Project-Id-Version: git-cola VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-17 01:06-0700\n" "PO-Revision-Date: 2008-03-14 07:23+0100\n" "Last-Translator: Peter Karlsson \n" "Language-Team: Swedish\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr "" #: cola/widgets/recent.py:52 #, fuzzy msgid " commits ago" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "" #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "" #: cola/guicmds.py:156 #, fuzzy, python-format msgid "\"%s\" already exists" msgstr "Grenen \"%s\" finns redan." #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "" #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, fuzzy, python-format msgid "%s is not a Git repository." msgstr "Gitarkiv" #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "" #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "" #: cola/cmds.py:1662 #, 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/widgets/main.py:748 msgid "&Edit" msgstr "Redigera" #: cola/widgets/main.py:690 #, fuzzy msgid "&File" msgstr "&Fil" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/diff.py:816 msgid "100%" msgstr "" #: cola/widgets/diff.py:817 msgid "200%" msgstr "" #: cola/widgets/diff.py:814 msgid "25%" msgstr "" #: cola/widgets/diff.py:818 msgid "400%" msgstr "" #: cola/widgets/diff.py:815 msgid "50%" msgstr "" #: cola/widgets/diff.py:819 msgid "800%" msgstr "" #: cola/widgets/finder.py:118 msgid " ..." msgstr "" #: cola/cmds.py:1685 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:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 #, fuzzy msgid "Abort" msgstr "Avbryter" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 #, fuzzy msgid "Abort Action" msgstr "Avbryter" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 #, fuzzy msgid "Abort Merge" msgstr "Avbryt sammanslagning..." #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Avbryt sammanslagning..." #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 #, 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/cmds.py:186 msgid "Aborting the current merge?" msgstr "" #: cola/widgets/about.py:88 cola/widgets/main.py:531 #, fuzzy msgid "About" msgstr "Om %s" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/status.py:1376 #, fuzzy msgid "Action Name" msgstr "Alternativ" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 #, fuzzy msgid "Actions" msgstr "Alternativ" #: cola/widgets/commitmsg.py:107 #, fuzzy msgid "Actions..." msgstr "Alternativ..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "" #: cola/widgets/bookmarks.py:469 #, fuzzy msgid "Add Favorite" msgstr "Fjärr" #: cola/widgets/editremotes.py:371 #, fuzzy msgid "Add Remote" msgstr "Fjärr" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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:78 #, fuzzy msgid "Add new remote git repository" msgstr "Inte ett Gitarkiv: %s" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "" #: cola/widgets/editremotes.py:430 #, fuzzy msgid "Add remote" msgstr "Fjärr" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 #, fuzzy msgid "Additions" msgstr "Alternativ" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "" #: cola/widgets/prefs.py:441 #, fuzzy msgid "All Repositories" msgstr "Globalt (alla arkiv)" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "" #: cola/cmds.py:220 msgid "Amend" msgstr "" #: cola/widgets/commitmsg.py:470 #, fuzzy msgid "Amend Commit" msgstr "Lägg till föregående incheckning" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Lägg till föregående incheckning" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 #, fuzzy msgid "Apply" msgstr "Äpple" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "" #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "" #: cola/qtutils.py:886 msgid "Attach" msgstr "" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 #, fuzzy msgid "Author" msgstr "Författare:" #: cola/widgets/about.py:90 #, fuzzy msgid "Authors" msgstr "Författare:" #: cola/hidpi.py:41 msgid "Auto" msgstr "" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "" #: cola/widgets/prefs.py:276 #, fuzzy msgid "Blame Viewer" msgstr "Filvisare" #: cola/widgets/browse.py:206 #, fuzzy msgid "Blame selected paths" msgstr "Byt namn på gren" #: cola/cmds.py:545 cola/widgets/status.py:283 #, fuzzy msgid "Blame..." msgstr "Byt namn..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Gren" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/createbranch.py:256 #, fuzzy, python-format msgid "Branch \"%s\" already exists." msgstr "Grenen \"%s\" finns redan." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 #, fuzzy msgid "Branch Exists" msgstr "Grenar" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Namn på gren" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, fuzzy, python-format msgid "Branch: %s" msgstr "Gren:" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 #, fuzzy msgid "Branches" msgstr "Gren" #: cola/widgets/main.py:552 #, fuzzy msgid "Branches..." msgstr "Grenar" #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "" #: cola/guicmds.py:52 #, fuzzy msgid "Browse" msgstr "Bläddra" #: cola/guicmds.py:52 #, fuzzy msgid "Browse Commits..." msgstr "Bläddra" #: cola/widgets/main.py:513 #, fuzzy msgid "Browse Current Branch..." msgstr "Bläddra i grenens filer" #: cola/widgets/main.py:519 #, fuzzy msgid "Browse Other Branch..." msgstr "Bläddra filer på gren..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 #, fuzzy msgid "Browse..." msgstr "Bläddra" #: cola/widgets/main.py:87 #, fuzzy msgid "Browser" msgstr "Bläddra" #: cola/widgets/browse.py:590 #, fuzzy, python-format msgid "Browsing %s" msgstr "Lägger till %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "Avbryt" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" #: cola/cmds.py:253 #, fuzzy msgid "Cannot Amend" msgstr "Kan inte skriva ikon:" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Checka ut" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "Checka ut när skapad" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Checka ut gren" #: cola/widgets/dag.py:413 #, fuzzy msgid "Checkout Detached HEAD" msgstr "Checka ut gren" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 #, fuzzy msgid "Checkout as new branch" msgstr "Checka ut gren" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Checka ut..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/guicmds.py:72 #, fuzzy msgid "Cherry-Pick Commit" msgstr "Kopiera incheckning" #: cola/widgets/main.py:324 #, fuzzy msgid "Cherry-Pick..." msgstr "Checka ut..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 #, fuzzy msgid "Choose Paths" msgstr "Välj %s" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 #, fuzzy msgid "Clear Default Repository" msgstr "Skapa nytt arkiv" #: cola/widgets/commitmsg.py:312 #, fuzzy msgid "Clear commit message" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/widgets/commitmsg.py:309 #, fuzzy msgid "Clear commit message?" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/widgets/commitmsg.py:63 #, fuzzy msgid "Clear..." msgstr "Klona..." #: cola/widgets/clone.py:124 msgid "Clone" msgstr "Klona" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 #, fuzzy msgid "Clone Repository" msgstr "Klona befintligt arkiv" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Klona..." #: cola/widgets/clone.py:61 #, fuzzy, python-format msgid "Cloning repository at %s" msgstr "Klona befintligt arkiv" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Stäng" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 #, fuzzy msgid "Close..." msgstr "Klona..." #: cola/widgets/recent.py:69 #, fuzzy msgid "Collapse all" msgstr "Stäng" #: cola/sequenceeditor.py:371 #, fuzzy msgid "Command" msgstr "Incheckning:" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 #, fuzzy msgid "Commit" msgstr "Incheckning:" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 #, fuzzy msgid "Commit failed" msgstr "Incheckningen misslyckades." #: cola/widgets/commitmsg.py:62 #, fuzzy msgid "Commit staged changes" msgstr "Checkar in ändringar..." #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:586 #, fuzzy msgid "Commit summary" msgstr "Incheckningsmeddelande:" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "Checka in" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "" #: cola/difftool.py:102 msgid "Compare All" msgstr "" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "" #: cola/widgets/main.py:169 #, fuzzy msgid "Console" msgstr "Stäng" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Forstätt" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Kopiera" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 #, fuzzy msgid "Copy SHA-1" msgstr "Kopiera alla" #: cola/widgets/status.py:738 #, fuzzy msgid "Copy..." msgstr "Kopiera" #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Skapa gren" #: cola/widgets/dag.py:372 #, fuzzy msgid "Create Patch" msgstr "Skapa gren" #: cola/widgets/remote.py:640 #, fuzzy msgid "Create Remote Branch" msgstr "Ta bort fjärrgren" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 #, fuzzy msgid "Create Signed Commit" msgstr "Skapade incheckningen %s: %s" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 #, fuzzy msgid "Create Tag" msgstr "Skapa" #: cola/widgets/main.py:558 #, fuzzy msgid "Create Tag..." msgstr "Skapa..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "" #: cola/widgets/remote.py:639 #, fuzzy msgid "Create a new remote branch?" msgstr "Skapa ny gren" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "Skapa..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 #, fuzzy msgid "Current Repository" msgstr "Skapa nytt arkiv" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "" #: cola/widgets/status.py:274 #, fuzzy msgid "Customize..." msgstr "Klona..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "Klipp ut" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "" #: cola/icons.py:54 msgid "Dark Theme" msgstr "" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "" #: cola/icons.py:53 cola/themes.py:643 #, fuzzy msgid "Default" msgstr "Återställ standardvärden" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Ta bort" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "" #: cola/cmds.py:1016 #, fuzzy msgid "Delete Bookmark" msgstr "Ta bort gren" #: cola/cmds.py:1014 #, fuzzy msgid "Delete Bookmark?" msgstr "Ta bort gren" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Ta bort gren" #: cola/cmds.py:1089 #, fuzzy msgid "Delete Files" msgstr "Ta bort" #: cola/widgets/status.py:312 #, fuzzy msgid "Delete Files..." msgstr "Ta bort..." #: cola/cmds.py:1085 #, fuzzy msgid "Delete Files?" msgstr "Ta bort" #: cola/cmds.py:919 #, fuzzy msgid "Delete Remote" msgstr "Ta bort fjärrgren" #: cola/guicmds.py:34 cola/widgets/branch.py:279 #, fuzzy msgid "Delete Remote Branch" msgstr "Ta bort fjärrgren" #: cola/widgets/main.py:578 #, fuzzy msgid "Delete Remote Branch..." msgstr "Ta bort fjärrgren" #: cola/widgets/toolbar.py:276 #, fuzzy msgid "Delete Toolbar" msgstr "Ta bort gren" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "" #: cola/widgets/editremotes.py:85 #, fuzzy msgid "Delete remote" msgstr "Ta bort fjärrgren" #: cola/cmds.py:921 #, fuzzy, python-format msgid "Delete remote \"%s\"" msgstr "Ta bort fjärrgren" #: cola/cmds.py:920 #, fuzzy msgid "Delete remote?" msgstr "Ta bort fjärrgren" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Ta bort..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "" #: cola/widgets/filelist.py:25 #, fuzzy msgid "Deletions" msgstr "Ta bort" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 #, fuzzy msgid "Detach" msgstr "Ta bort gren" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "" #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 #, fuzzy msgid "Diff Options" msgstr "Alternativ" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "" #: cola/difftool.py:324 #, fuzzy msgid "Difftool" msgstr "Alternativ" #: cola/widgets/clone.py:205 #, fuzzy msgid "Directory Exists" msgstr "Katalog:" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 #, fuzzy msgid "Documentation" msgstr "Webbdokumentation" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 #, fuzzy msgid "Edit" msgstr "Redigera" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 #, fuzzy msgid "Edit Rebase" msgstr "Återställ" #: cola/widgets/editremotes.py:34 #, fuzzy msgid "Edit Remotes" msgstr "Fjärr" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "" #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 #, fuzzy msgid "Edit..." msgstr "Redigera" #: cola/widgets/prefs.py:274 #, fuzzy msgid "Editor" msgstr "Redigera" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "E-postadress" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "" #: cola/guicmds.py:332 cola/widgets/branch.py:478 #, fuzzy msgid "Enter New Branch Name" msgstr "Namn på gren" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 #, fuzzy msgid "Error" msgstr "fel" #: cola/widgets/clone.py:189 #, fuzzy msgid "Error Cloning" msgstr "Fel vid läsning av fil:" #: cola/widgets/createbranch.py:312 #, fuzzy msgid "Error Creating Branch" msgstr "Skapa gren" #: cola/app.py:501 cola/guicmds.py:100 #, fuzzy msgid "Error Creating Repository" msgstr "Skapa nytt arkiv" #: cola/cmds.py:1205 #, fuzzy msgid "Error Deleting Remote Branch" msgstr "Skapa gren" #: cola/cmds.py:1572 #, fuzzy msgid "Error Editing File" msgstr "Fel vid inläsning av differens:" #: cola/cmds.py:559 #, fuzzy msgid "Error Launching Blame Viewer" msgstr "Filbläddrare" #: cola/cmds.py:3089 #, fuzzy msgid "Error Launching History Browser" msgstr "Filbläddrare" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "" #: cola/models/stash.py:233 #, fuzzy msgid "Error creating stash" msgstr "Skapa gren" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "" #: cola/cmds.py:1721 #, fuzzy msgid "Error running prepare-commitmsg hook" msgstr "Anropar krok före incheckning..." #: cola/cmds.py:2987 cola/cmds.py:3033 #, fuzzy, python-format msgid "Error updating submodule %s" msgstr "Fel vid inläsning av differens:" #: cola/cmds.py:3069 #, fuzzy msgid "Error updating submodules" msgstr "Fel vid inläsning av differens:" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "" #: cola/widgets/branch.py:433 #, fuzzy, python-format msgid "Executing action %s" msgstr "Återställer ordlistan till %s." #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "" #: cola/widgets/main.py:547 #, fuzzy msgid "Expression..." msgstr "Alternativ..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "" #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Endast snabbspolning" #: cola/widgets/remote.py:181 #, fuzzy msgid "Fast-forward only" msgstr "Endast snabbspolning" #: cola/widgets/bookmarks.py:90 #, fuzzy msgid "Favorite repositories" msgstr "Senaste arkiven" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "" #: cola/widgets/remote.py:735 #, fuzzy msgid "Fetch" msgstr "Återställ..." #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "Hämta spårande gren" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 #, fuzzy msgid "Fetch..." msgstr "Återställ..." #: cola/widgets/main.py:602 #, fuzzy msgid "File Browser..." msgstr "Bläddra" #: cola/widgets/compare.py:74 #, fuzzy msgid "File Differences" msgstr "Inställningar" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" #: cola/fsmonitor.py:145 #, fuzzy msgid "File system change monitoring: enabled.\n" msgstr "Lita på filändringstidsstämplar\n" #: cola/widgets/filelist.py:25 #, fuzzy msgid "Filename" msgstr "Byt namn" #: cola/widgets/dag.py:821 #, fuzzy msgid "Files" msgstr "Fil:" #: cola/widgets/branch.py:837 #, fuzzy msgid "Filter branches..." msgstr "Återställ..." #: cola/widgets/status.py:1333 #, fuzzy msgid "Filter paths..." msgstr "Återställ..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 #, fuzzy msgid "Find Files" msgstr "Fil:" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "" #: cola/widgets/commitmsg.py:154 #, fuzzy msgid "Fixup Previous Commit" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "" #: cola/themes.py:705 msgid "Flat dark green" msgstr "" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "" #: cola/themes.py:691 msgid "Flat dark red" msgstr "" #: cola/themes.py:656 msgid "Flat light blue" msgstr "" #: cola/themes.py:677 msgid "Flat light green" msgstr "" #: cola/themes.py:670 msgid "Flat light grey" msgstr "" #: cola/themes.py:663 msgid "Flat light red" msgstr "" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Storlek" #: cola/widgets/remote.py:197 msgid "Force" msgstr "" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:650 #, fuzzy, python-format msgid "Force fetching from %s?" msgstr "Hämtar %s från %s" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "" #: cola/widgets/editremotes.py:315 #, fuzzy, python-format msgid "Gathering info for \"%s\"..." msgstr "Läser differens för %s..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "" #: cola/widgets/main.py:525 #, fuzzy msgid "Get Commit Message Template" msgstr "Textbredd för incheckningsmeddelande" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "" #: cola/widgets/dag.py:848 msgid "Graph" msgstr "" #: cola/widgets/main.py:354 msgid "Grep" msgstr "" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Hjälp" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 #, fuzzy msgid "History Browser" msgstr "Filbläddrare" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "" #: cola/widgets/remote.py:207 #, fuzzy msgid "Include tags " msgstr "Ta med taggar" #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "" #: cola/widgets/main.py:657 #, fuzzy msgid "Initialize Git Annex" msgstr "Initierar..." #: cola/widgets/main.py:661 #, fuzzy msgid "Initialize Git LFS" msgstr "Initierar..." #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "" #: cola/cmds.py:2313 #, fuzzy msgid "Invalid Revision" msgstr "Ogiltig revision: %s" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "" #: cola/icons.py:55 msgid "Light Theme" msgstr "" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 #, fuzzy msgid "Load Commit Message" msgstr "Incheckningsmeddelande:" #: cola/widgets/main.py:335 #, fuzzy msgid "Load Commit Message..." msgstr "Incheckningsmeddelande:" #: cola/widgets/commitmsg.py:150 #, fuzzy msgid "Load Previous Commit Message" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/widgets/diff.py:264 #, fuzzy msgid "Loading..." msgstr "Läser %s..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Lokal gren" #: cola/widgets/createbranch.py:112 #, fuzzy msgid "Local branch" msgstr "Lokal gren" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "" #: cola/widgets/dag.py:816 msgid "Log" msgstr "" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Slå ihop" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/widgets/prefs.py:278 #, fuzzy msgid "Merge Tool" msgstr "Slå ihop" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Pratsamhet för sammanslagningar" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "Sammanslagningen misslyckades. Du måste lösa konflikterna." #: cola/widgets/merge.py:165 #, fuzzy, python-format msgid "Merge into \"%s\"" msgstr "Slå ihop i %s" #: cola/widgets/branch.py:242 #, fuzzy msgid "Merge into current branch" msgstr "Bläddra i grenens filer" #: cola/widgets/main.py:359 #, fuzzy msgid "Merge..." msgstr "Slå ihop" #: cola/widgets/main.py:1177 #, fuzzy msgid "Merging" msgstr "Slå ihop" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 #, fuzzy msgid "Message" msgstr "Slå ihop" #: cola/widgets/commitmsg.py:424 #, fuzzy msgid "Missing Commit Message" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/widgets/createbranch.py:250 #, fuzzy msgid "Missing Data" msgstr "Saknade" #: cola/cmds.py:2741 #, fuzzy msgid "Missing Name" msgstr "Saknade" #: cola/cmds.py:2735 #, fuzzy msgid "Missing Revision" msgstr "Inledande revision" #: cola/cmds.py:2745 #, fuzzy msgid "Missing Tag Message" msgstr "Revisioner att slå ihop" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 #, fuzzy msgid "Modified" msgstr "Oförändrade" #: cola/widgets/commitmsg.py:528 #, fuzzy msgid "More..." msgstr "Klona..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 #, fuzzy msgid "Name" msgstr "Namn:" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "" #: cola/guicmds.py:147 cola/widgets/main.py:281 #, fuzzy msgid "New Bare Repository..." msgstr "Gitarkiv" #: cola/guicmds.py:86 cola/widgets/main.py:276 #, fuzzy msgid "New Repository..." msgstr "Gitarkiv" #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Nytt..." #: cola/actions.py:56 #, fuzzy msgid "Next File" msgstr "Markera alla" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "Nej" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 #, fuzzy msgid "No Revision Specified" msgstr "Ingen revision vald." #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 #, 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." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/merge.py:63 #, fuzzy msgid "No fast forward" msgstr "Endast snabbspolning" #: cola/widgets/remote.py:190 #, fuzzy msgid "No fast-forward" msgstr "Endast snabbspolning" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Inget arkiv markerat." #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/commitmsg.py:451 #, fuzzy msgid "Nothing to commit" msgstr "Inga ändringar att checka in." #: cola/gitcmds.py:626 #, fuzzy msgid "Nothing to do" msgstr "Ingenting att klona från %s." #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Antal rader sammanhang i differenser" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Öppna" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 #, fuzzy msgid "Open Git Repository" msgstr "Öppna befintligt arkiv" #: cola/widgets/submodules.py:48 #, fuzzy msgid "Open Parent" msgstr "Öppna tidigare arkiv:" #: cola/cmds.py:1827 #, fuzzy msgid "Open Parent Directory" msgstr "Öppna tidigare arkiv:" #: cola/widgets/main.py:693 #, fuzzy msgid "Open Recent" msgstr "Öppna tidigare arkiv:" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "" #: cola/widgets/main.py:416 #, fuzzy msgid "Open in New Window..." msgstr "Öppna befintligt arkiv" #: cola/widgets/main.py:410 msgid "Open..." msgstr "Öppna..." #: cola/widgets/branch.py:354 #, fuzzy msgid "Other branches" msgstr "Återställ..." #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "" #: cola/widgets/main.py:758 msgid "Paste" msgstr "Klistra in" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/cmds.py:2297 #, fuzzy msgid "Please select a file" msgstr "Välj en gren att spåra." #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "" #: cola/cmds.py:2735 #, fuzzy msgid "Please specify a revision to tag." msgstr "Välj en gren att byta namn på." #: cola/widgets/commitmsg.py:417 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/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Inställningar" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "" #: cola/widgets/main.py:341 #, fuzzy msgid "Prepare Commit Message" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "" #: cola/actions.py:65 msgid "Previous File" msgstr "" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "" #: cola/widgets/remote.py:170 #, fuzzy msgid "Prompt when pushing creates new remote branches" msgstr "Skapa ny gren" #: cola/widgets/remote.py:212 #, fuzzy msgid "Prune " msgstr "Ta bort från" #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 #, fuzzy msgid "Pull" msgstr "Sänd..." #: cola/widgets/action.py:73 cola/widgets/main.py:402 #, fuzzy msgid "Pull..." msgstr "Sänd..." #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Sänd" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Sänd..." #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Avsluta" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 #, fuzzy msgid "Rebase" msgstr "Återställ" #: cola/cmds.py:2092 #, fuzzy, python-format msgid "Rebase onto %s" msgstr "Återställ" #: cola/cmds.py:2105 #, fuzzy msgid "Rebase stopped" msgstr "Återställ" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 #, fuzzy msgid "Rebasing" msgstr "Återställ" #: cola/widgets/main.py:118 #, fuzzy msgid "Recent" msgstr "Återställ" #: cola/widgets/bookmarks.py:92 #, fuzzy msgid "Recent repositories" msgstr "Senaste arkiven" #: cola/widgets/prefs.py:279 #, fuzzy msgid "Recent repository count" msgstr "Senaste arkiven" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "" #: cola/widgets/main.py:316 #, fuzzy msgid "Recently Modified Files..." msgstr "Söker efter ändrade filer..." #: cola/widgets/stash.py:274 #, fuzzy msgid "Recovering a dropped stash is not possible." msgstr "Det kanske inte är så enkelt att återskapa förlorade incheckningar." #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Det kanske inte är så enkelt att återskapa förlorade incheckningar." #: cola/widgets/main.py:751 msgid "Redo" msgstr "Gör om" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Uppdatera" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Fjärr" #: cola/widgets/remote.py:160 #, fuzzy msgid "Remote Branch" msgstr "Byt namn på gren" #: cola/cmds.py:1196 #, fuzzy msgid "Remote Branch Deleted" msgstr "Byt namn på gren" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 #, fuzzy msgid "Remove" msgstr "Fjärr" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "" #: cola/widgets/toolbar.py:321 #, fuzzy msgid "Remove Element" msgstr "Fjärr" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "" #: cola/widgets/diff.py:1704 #, fuzzy msgid "Remove selected (Delete)" msgstr "Byt namn på gren" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Byt namn" #: cola/cmds.py:1153 #, fuzzy, python-format msgid "Rename \"%s\"" msgstr "Byt namn" #: cola/widgets/branch.py:268 #, fuzzy msgid "Rename Branch" msgstr "Byt namn på gren" #: cola/widgets/main.py:584 #, fuzzy msgid "Rename Branch..." msgstr "Byt namn på gren" #: cola/guicmds.py:329 #, fuzzy msgid "Rename Existing Branch" msgstr "Uppdatera befintlig gren:" #: cola/cmds.py:941 #, fuzzy msgid "Rename Remote" msgstr "Fjärr" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 #, fuzzy msgid "Rename Repository" msgstr "Klona befintligt arkiv" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 #, fuzzy msgid "Rename branch" msgstr "Byt namn på gren" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/browse.py:159 #, fuzzy msgid "Rename selected paths" msgstr "Byt namn på gren" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, fuzzy, python-format msgid "Repository: %s" msgstr "Arkiv:" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Återställ" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 #, fuzzy msgid "Reset Branch" msgstr "Ta bort gren" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 #, fuzzy msgid "Reset Branch?" msgstr "Ta bort gren" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, 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/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "" #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:1223 #, fuzzy msgid "Revert Selected Lines?" msgstr "Återställ ändringarna i filen %s?" #: cola/cmds.py:2260 #, fuzzy msgid "Revert Uncommitted Changes" msgstr "Återställ ändringar" #: cola/cmds.py:2254 #, fuzzy msgid "Revert Uncommitted Changes?" msgstr "Återställ ändringar" #: cola/cmds.py:2247 #, fuzzy msgid "Revert Uncommitted Edits..." msgstr "Återställ ändringar" #: cola/cmds.py:2238 #, fuzzy msgid "Revert Unstaged Changes" msgstr "Oköade ändringar" #: cola/cmds.py:2232 #, fuzzy msgid "Revert Unstaged Changes?" msgstr "Oköade ändringar" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "" #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "" #: cola/cmds.py:2237 #, fuzzy msgid "Revert the unstaged changes?" msgstr "Oköade ändringar" #: cola/widgets/browse.py:190 #, fuzzy msgid "Revert uncommitted changes to selected paths" msgstr "Återställ ändringarna i filen %s?" #: cola/widgets/browse.py:181 #, fuzzy msgid "Revert unstaged changes to selected paths" msgstr "Återställ ändringarna i filen %s?" #: cola/guicmds.py:320 msgid "Review" msgstr "" #: cola/widgets/main.py:597 #, fuzzy msgid "Review..." msgstr "Återställ..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Revision" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Revisionsuttryck:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Revisioner att slå ihop" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "" #: cola/sequenceeditor.py:372 #, fuzzy msgid "SHA-1" msgstr "Kopiera alla" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Spara" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "" #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "" #: cola/widgets/search.py:223 #, fuzzy msgid "Search Commit Messages" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/widgets/search.py:226 #, fuzzy msgid "Search Committers" msgstr "Incheckare:" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:221 #, fuzzy msgid "Search by Expression" msgstr "Revisionsuttryck:" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "" #: cola/widgets/main.py:507 #, fuzzy msgid "Search..." msgstr "Startar..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Välj" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Markera alla" #: cola/guicmds.py:320 #, fuzzy msgid "Select Branch to Review" msgstr "Ta bort gren" #: cola/widgets/dag.py:1667 #, fuzzy msgid "Select Child" msgstr "Markera alla" #: cola/widgets/commitmsg.py:534 #, fuzzy msgid "Select Commit" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/guicmds.py:136 #, fuzzy msgid "Select Directory..." msgstr "Gitarkiv" #: cola/cmds.py:2078 #, fuzzy msgid "Select New Upstream" msgstr "Välj" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "" #: cola/widgets/dag.py:1656 #, fuzzy msgid "Select Parent" msgstr "Välj" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 #, fuzzy msgid "Select output dir" msgstr "Incheckningsmeddelande för sammanslagning:" #: cola/widgets/selectcommits.py:182 #, fuzzy msgid "Select output directory" msgstr "Gitarkiv" #: cola/widgets/diff.py:1770 #, fuzzy msgid "Select patch file(s)..." msgstr "Ta bort..." #: cola/widgets/editremotes.py:434 #, fuzzy msgid "Select repository" msgstr "Gitarkiv" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 #, fuzzy msgid "Set Default Repository" msgstr "Gitarkiv" #: cola/widgets/branch.py:291 #, fuzzy msgid "Set Upstream Branch" msgstr "Välj" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 #, fuzzy msgid "Set upstream" msgstr "Välj" #: cola/widgets/prefs.py:443 #, fuzzy msgid "Settings" msgstr "Startar..." #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Visa diffstatistik efter sammanslagning" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 #, fuzzy msgid "Show Help" msgstr "Hjälp" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/widgets/recent.py:56 #, fuzzy msgid "Showing changes since" msgstr "Sänder ändringar till %s" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Skriv under" #: cola/widgets/createtag.py:69 #, fuzzy msgid "Sign Tag" msgstr "Skriv under" #: cola/widgets/commitmsg.py:56 #, fuzzy msgid "Sign off on this commit" msgstr "Köade för incheckning" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "" #: cola/cmds.py:2527 msgid "Skip" msgstr "" #: cola/widgets/main.py:261 cola/widgets/main.py:631 #, fuzzy msgid "Skip Current Patch" msgstr "Skapa gren" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "" #: cola/widgets/spellcheck.py:45 #, fuzzy msgid "Spelling Suggestions" msgstr "Inga förslag" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 #, fuzzy msgid "Squash" msgstr "Sänd" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 #, fuzzy msgid "Stage" msgstr "Spara" #: cola/cmds.py:2697 #, fuzzy msgid "Stage / Unstage" msgstr "Köa ändrade" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Köa ändrade" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 #, fuzzy msgid "Stage Selected" msgstr "Välj" #: cola/widgets/diff.py:1050 #, fuzzy msgid "Stage Selected Lines" msgstr "Oköade ändringar" #: cola/cmds.py:2642 #, fuzzy msgid "Stage Unmerged" msgstr "Köa ändrade unmerged" #: cola/cmds.py:2653 #, fuzzy msgid "Stage Untracked" msgstr "Köa ändrade untracked" #: cola/widgets/commitmsg.py:445 #, fuzzy msgid "Stage and Commit" msgstr "Köa för incheckning" #: cola/widgets/commitmsg.py:442 #, fuzzy msgid "Stage and commit?" msgstr "Köade för incheckning" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 #, fuzzy msgid "Stage conflicts" msgstr "Köade för incheckning" #: cola/cmds.py:2517 #, fuzzy msgid "Stage conflicts?" msgstr "Köade för incheckning" #: cola/widgets/browse.py:146 #, fuzzy msgid "Stage/unstage selected paths for commit" msgstr "Köade för incheckning" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 #, fuzzy msgid "Staged" msgstr "Köa ändrade" #: cola/cmds.py:2545 #, fuzzy, python-format msgid "Staging: %s" msgstr "Söker %s..." #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "" #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "Inledande revision" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "" #: cola/widgets/stash.py:79 #, fuzzy msgid "Stash Index" msgstr "Indexfel" #: cola/widgets/stash.py:79 #, fuzzy msgid "Stash staged changes only" msgstr "Checkar in ändringar..." #: cola/widgets/stash.py:75 #, fuzzy msgid "Stash unstaged changes only, keeping staged changes" msgstr "Återställ ändringarna i filen %s?" #: cola/widgets/action.py:76 cola/widgets/main.py:423 #, fuzzy msgid "Stash..." msgstr "Sänd..." #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "Summera sammanslagningsincheckningar" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Tagg" #: cola/cmds.py:2786 #, fuzzy msgid "Tag Created" msgstr "Skapa" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "" #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "" #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "" #: cola/widgets/commitmsg.py:310 #, fuzzy msgid "The commit message will be cleared." msgstr "Textbredd för incheckningsmeddelande" #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 #, fuzzy msgid "The revision expression cannot be empty." msgstr "Revisionsuttrycket är tomt." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 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/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Spårande gren" #: cola/widgets/createbranch.py:113 #, fuzzy msgid "Tracking branch" msgstr "Spårande gren" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "Webbadress" #: cola/widgets/remote.py:496 #, fuzzy, python-format msgid "URL: %s" msgstr "Webbadress:" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "" #: cola/cmds.py:2071 #, fuzzy msgid "Unable to rebase" msgstr "Kunde inte städa upp %s" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "Ångra" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 #, fuzzy msgid "Unmerged" msgstr "Slå ihop" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 #, fuzzy msgid "Unstage" msgstr "Oköade ändringar" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "" #: cola/widgets/diff.py:1015 #, fuzzy msgid "Unstage Selected Lines" msgstr "Oköade ändringar" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, fuzzy, python-format msgid "Unstaging: %s" msgstr "Tar bort %s för incheckningskön" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "" #: cola/widgets/status.py:159 cola/widgets/status.py:647 #, fuzzy msgid "Untracked" msgstr "Ej spårade, ej köade" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Uppdatera befintlig gren:" #: cola/cmds.py:3019 #, fuzzy msgid "Update Submodule" msgstr "Uppdaterad" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "" #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 #, fuzzy msgid "Updating" msgstr "Startar..." #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Användarnamn" #: cola/widgets/about.py:89 #, fuzzy msgid "Version" msgstr "Revision" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "" #: cola/widgets/browse.py:138 #, fuzzy msgid "View history for selected paths" msgstr "Återställ ändringarna i filen %s?" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "Visualisera" #: cola/widgets/main.py:502 #, fuzzy msgid "Visualize All Branches..." msgstr "Visualisera alla grenars historik" #: cola/widgets/main.py:496 #, fuzzy msgid "Visualize Current Branch..." msgstr "Visualisera grenens historik" #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" #: cola/cmds.py:2072 #, fuzzy msgid "You cannot rebase with uncommitted changes." msgstr "Återställ ändringar" #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "" #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "" #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "" #: cola/widgets/log.py:52 #, fuzzy, python-format msgid "exit code %s" msgstr "hämta %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "" #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "" #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "" #: cola/hidpi.py:43 msgid "x 1" msgstr "" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "" #: cola/hidpi.py:46 msgid "x 2" msgstr "" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "" #~ 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 "" #~ "\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 "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%s... %*i av %*i %s (%3i%%)" #~ msgid "%s Repository" #~ msgstr "Arkivet %s" #~ msgid "%s of %s" #~ msgstr "%s av %s" #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "\"%s\" kan inte användas som namn på grenen." #~ msgid "* Binary file (not showing content)." #~ msgstr "* Binärfil (visar inte innehållet)." #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "En gren krävs för \"Sammanslagen i\"." #, fuzzy, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Filen %s finns redan." #~ msgid "Abort completed. Ready." #~ msgstr "Avbrytning fullbordad. Redo." #~ msgid "Abort failed." #~ msgstr "Misslyckades avbryta." #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "Avbryter utcheckning av \"%s\" (sammanslagning på filnivå krävs)." #~ msgid "Always (Do not perform merge checks)" #~ msgstr "Alltid (utför inte sammanslagningstest)" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "Alltid (utför inte sammanslagningstest)." #~ 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 "Annotation complete." #~ msgstr "Annotering fullbordad." #~ 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 "Apply/Reverse Hunk" #~ msgstr "Använd/återställ del" #~ msgid "Arbitrary URL:" #~ msgstr "Godtycklig webbadress:" #~ 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 "Branch '%s' does not exist." #~ msgstr "Grenen \"%s\" finns inte." #, fuzzy #~ msgid "Branch created" #~ msgstr "Namn på gren" #~ msgid "Browse %s's Files" #~ msgstr "Bläddra i filer för %s" #~ msgid "Browse Branch Files" #~ msgstr "Bläddra filer på grenen" #, fuzzy #~ msgid "Browse Revision..." #~ msgstr "Revision" #~ msgid "Calling commit-msg hook..." #~ msgstr "Anropar krok för incheckningsmeddelande..." #~ 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 "" #~ "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 "Cannot determine HEAD. See console output for details." #~ msgstr "Kunde inte avgöra HEAD. Se konsolutdata för detaljer." #~ 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 find git in PATH." #~ msgstr "Hittar inte git i PATH." #~ 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 "Cannot move to top of working directory:" #~ msgstr "Kan inte gå till början på arbetskatalogen:" #~ msgid "Cannot parse Git version string:" #~ msgstr "Kan inte tolka versionssträng från Git:" #~ msgid "Cannot resolve %s as a commit." #~ msgstr "Kunde inte slå upp %s till någon incheckning." #~ msgid "Cannot use funny .git directory:" #~ msgstr "Kan inte använda underlig .git-katalog:" #~ msgid "Cannot write shortcut:" #~ msgstr "Kan inte skriva genväg:" #~ msgid "Change Font" #~ msgstr "Byt teckensnitt" #~ msgid "Checked out '%s'." #~ msgstr "Checkade ut \"%s\"." #~ msgid "Clone Type:" #~ msgstr "Typ av klon:" #~ msgid "Clone failed." #~ msgstr "Kloning misslyckades." #~ msgid "Cloning from %s" #~ msgstr "Klonar från %s" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "Incheckningen %s verkar vara trasig" #~ msgid "Commit declined by commit-msg hook." #~ msgstr "Incheckning avvisad av krok för incheckningsmeddelande." #~ msgid "Commit declined by pre-commit hook." #~ msgstr "Incheckningen avvisades av krok före incheckning." #, fuzzy #~ msgid "Commit failed: %s" #~ msgstr "Incheckningen misslyckades." #~ msgid "Commit@@noun" #~ msgstr "Incheckning" #~ msgid "Compress Database" #~ msgstr "Komprimera databas" #~ msgid "Compressing the object database" #~ msgstr "Komprimerar objektdatabasen" #~ msgid "Copied Or Moved Here By:" #~ msgstr "Kopierad eller flyttad hit av:" #~ msgid "Copying objects" #~ msgstr "Kopierar objekt" #~ msgid "Counting objects" #~ msgstr "Räknar objekt" #~ msgid "Create Desktop Icon" #~ msgstr "Skapa skrivbordsikon" #, fuzzy #~ msgid "Created commit: %s" #~ msgstr "Skapade incheckningen %s: %s" #~ msgid "Creating working directory" #~ msgstr "Skapar arbetskatalog" #~ msgid "Current Branch:" #~ msgstr "Aktuell gren:" #~ msgid "Database Statistics" #~ msgstr "Databasstatistik" #~ msgid "Decrease Font Size" #~ msgstr "Minska teckensnittsstorlek" #~ msgid "Delete Local Branch" #~ msgstr "Ta bort lokal gren" #~ msgid "Delete Only If" #~ msgstr "Ta endast bort om" #~ msgid "Delete Only If Merged Into" #~ msgstr "Ta bara bort om sammanslagen med" #, fuzzy #~ msgid "Delete selected branch?" #~ msgstr "Ta bort fjärrgren" #~ msgid "Destination Repository" #~ msgstr "Destinationsarkiv" #~ msgid "Detach From Local Branch" #~ msgstr "Koppla bort från lokal gren" #~ msgid "Diff/Console Font" #~ msgstr "Diff/konsolteckensnitt" #~ msgid "Directory %s already exists." #~ msgstr "Katalogen %s finns redan." #~ msgid "Disk space used by loose objects" #~ msgstr "Diskutrymme använt av lösa objekt" #~ msgid "Disk space used by packed objects" #~ msgstr "Diskutrymme använt av packade objekt" #~ msgid "Do Nothing" #~ msgstr "Gör ingenting" #, fuzzy #~ msgid "Enter Git Repository" #~ msgstr "Gitarkiv" #, fuzzy #~ msgid "Error %s" #~ msgstr "fel" #~ msgid "Error loading commit data for amend:" #~ msgstr "Fel vid inläsning av incheckningsdata för utökning:" #~ msgid "Error: Command Failed" #~ msgstr "Fel: Kommando misslyckades" #~ msgid "Failed to completely save options:" #~ msgstr "Misslyckades med att helt spara alternativ:" #~ msgid "Failed to configure origin" #~ msgstr "Kunde inte konfigurera ursprung" #~ msgid "Failed to create repository %s:" #~ msgstr "Kunde inte skapa arkivet %s:" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "Kunde inte ta bort grenar:\n" #~ "%s" #~ msgid "Failed to open repository %s:" #~ msgstr "Kunde inte öppna arkivet %s:" #~ msgid "Failed to rename '%s'." #~ msgstr "Kunde inte byta namn på \"%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 "Failed to stage selected hunk." #~ msgstr "Kunde inte lägga till den valda delen till kön." #~ msgid "Failed to unstage selected hunk." #~ msgstr "Kunde inte ta bort den valda delen från kön." #~ msgid "Failed to update '%s'." #~ msgstr "Misslyckades med att uppdatera \"%s\"." #, fuzzy #~ msgid "Fast Forward Only " #~ msgstr "Endast snabbspolning" #~ msgid "Fetch from" #~ msgstr "Hämta från" #~ msgid "Fetching new changes from %s" #~ msgstr "Hämtar nya ändringar från %s" #~ msgid "File level merge required." #~ msgstr "Sammanslagning på filnivå krävs." #~ msgid "Font Example" #~ msgstr "Exempel" #~ msgid "Font Family" #~ msgstr "Teckensnittsfamilj" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "Tvinga överskrivning av befintlig gren (kan kasta bort ändringar)" #~ msgid "From Repository" #~ msgstr "Från arkiv" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "Full kopia (långsammare, redundant säkerhetskopia)" #~ msgid "Garbage files" #~ msgstr "Skräpfiler" #~ msgid "Git Gui" #~ msgstr "Git Gui" #~ msgid "Git Repository (subproject)" #~ msgstr "Gitarkiv (underprojekt)" #~ msgid "Git directory not found:" #~ msgstr "Git-katalogen hittades inte:" #~ 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 "Hardlinks are unavailable. Falling back to copying." #~ msgstr "Hårda länkar är inte tillgängliga. Faller tillbaka på kopiering." #~ msgid "In File:" #~ msgstr "I filen:" #~ msgid "Increase Font Size" #~ msgstr "Öka teckensnittsstorlek" #~ msgid "Initial Commit Message:" #~ msgstr "Inledande incheckningsmeddelande:" #~ msgid "Initial file checkout failed." #~ msgstr "Inledande filutcheckning misslyckades." #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "Felaktig GIT_COMMITTER_IDENT:" #~ msgid "Invalid date from Git: %s" #~ msgstr "Ogiltigt datum från Git: %s" #~ msgid "Invalid font specified in %s:" #~ msgstr "Ogiltigt teckensnitt angivet i %s:" #~ msgid "Invalid spell checking configuration" #~ msgstr "Ogiltig inställning för stavningskontroll" #~ msgid "KiB" #~ msgstr "KiB" #~ 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 "" #~ "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 "" #~ "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 "Linking objects" #~ msgstr "Länkar objekt" #~ msgid "Loading annotation..." #~ msgstr "Läser in annotering..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "Läser annoteringar för kopiering/flyttning..." #~ msgid "Loading original location annotations..." #~ msgstr "Läser in annotering av originalplacering..." #~ msgid "Local Branches" #~ msgstr "Lokala grenar" #~ msgid "Local Merge..." #~ msgstr "Lokal sammanslagning..." #~ msgid "Location %s already exists." #~ msgstr "Platsen %s finns redan." #~ msgid "Main Font" #~ msgstr "Huvudteckensnitt" #~ msgid "Match Tracking Branch Name" #~ msgstr "Använd namn på spårad gren" #~ msgid "Match Tracking Branches" #~ msgstr "Matcha spårade grenar" #~ msgid "Merge completed successfully." #~ msgstr "Sammanslagningen avslutades framgångsrikt." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "Sammanslagningsstrategin \"%s\" stöds inte." #~ msgid "Merged Into:" #~ msgstr "Sammanslagen i:" #~ msgid "Merging %s and %s..." #~ msgstr "Slår ihop %s och %s..." #~ msgid "Modified, not staged" #~ msgstr "Förändrade, ej köade" #~ msgid "New Branch Name Template" #~ msgstr "Mall för namn på nya grenar" #~ msgid "New Commit" #~ msgstr "Ny incheckning" #~ msgid "New Name:" #~ msgstr "Nytt namn:" #~ 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 "No default branch obtained." #~ msgstr "Hämtade ingen standardgren." #~ 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 "No working directory" #~ msgstr "Ingen arbetskatalog" #~ msgid "Not connected to aspell" #~ msgstr "Inte ansluten till aspell" #~ msgid "Number of loose objects" #~ msgstr "Antal lösa objekt" #~ msgid "Number of packed objects" #~ msgstr "Antal packade objekt" #~ msgid "Number of packs" #~ msgstr "Antal paket" #~ 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 "Options" #~ msgstr "Alternativ" #~ msgid "Original File:" #~ msgstr "Ursprunglig fil:" #~ msgid "Originally By:" #~ msgstr "Ursprungligen av:" #~ msgid "Packed objects waiting for pruning" #~ msgstr "Packade objekt som väntar på städning" #, fuzzy #~ msgid "Path to git repository" #~ msgstr "Inte ett Gitarkiv: %s" #~ msgid "Please select one or more branches to delete." #~ msgstr "Välj en eller flera grenar att ta bort." #~ msgid "Please supply a branch name." #~ msgstr "Ange ett namn för grenen." #~ msgid "Portions staged for commit" #~ msgstr "Delar köade för incheckning" #~ 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 "Preferences..." #~ msgstr "Inställningar..." #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "Städa spårade grenar vid hämtning" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "Tar bort spårande grenar som tagits bort från %s" #~ msgid "Push Branches" #~ msgstr "Sänder grenar" #~ msgid "Push to" #~ msgstr "Sänd till" #~ msgid "Pushing %s %s to %s" #~ msgstr "Sänder %s %s till %s" #~ msgid "Reading %s..." #~ msgstr "Läser %s..." #~ msgid "Ready to commit." #~ msgstr "Redo att checka in." #~ msgid "Ready." #~ msgstr "Klar." #, fuzzy #~ msgid "Rebase Branch" #~ msgstr "Byt namn på gren" #, fuzzy #~ msgid "Rebase..." #~ msgstr "Återställ..." #~ 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 "" #~ "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 "Refreshing file status..." #~ msgstr "Uppdaterar filstatus..." #, fuzzy #~ msgid "Remote Branches" #~ msgstr "Byt namn på gren" #~ msgid "Remote:" #~ msgstr "Fjärr:" #, fuzzy #~ msgid "Rename remote?" #~ msgstr "Fjärr" #~ msgid "Repository" #~ msgstr "Arkiv" #~ msgid "Requires merge resolution" #~ msgstr "Kräver konflikthantering efter sammanslagning" #~ msgid "Rescan" #~ msgstr "Sök på nytt" #, fuzzy #~ msgid "Reset Branch Head" #~ msgstr "Ta bort gren" #, fuzzy #~ msgid "Reset Hard" #~ msgstr "Ta bort gren" #, fuzzy #~ msgid "Reset Merge" #~ msgstr "Revisioner att slå ihop" #, fuzzy #~ msgid "Reset Soft" #~ msgstr "Återställ" #~ 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?" #, fuzzy #~ msgid "Reset hard?" #~ msgstr "Ta bort gren" #, fuzzy #~ msgid "Reset merge?" #~ msgstr "Ta bort gren" #, fuzzy #~ msgid "Reset soft?" #~ msgstr "Återställa \"%s\"?" #~ msgid "Revert changes in these %i files?" #~ msgstr "Återställ ändringarna i dessa %i filer?" #, fuzzy #~ msgid "Select File" #~ msgstr "Markera alla" #, fuzzy #~ msgid "Select Repository..." #~ msgstr "Gitarkiv" #, fuzzy #~ msgid "Select file from \"%s\"" #~ msgstr "Tar bort grenar från %s" #, fuzzy #~ msgid "Select manually..." #~ msgstr "Markera alla" #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "Delad (snabbast, rekommenderas ej, ingen säkerhetskopia)" #~ msgid "Shared only available for local repository." #~ msgstr "Delat är endast tillgängligt för lokala arkiv." #, fuzzy #~ msgid "Show Details..." #~ msgstr "Ta bort..." #~ msgid "Show Less Context" #~ msgstr "Visa mindre sammanhang" #~ msgid "Show More Context" #~ msgstr "Visa mer sammanhang" #~ msgid "Source Branches" #~ msgstr "Källgrenar" #~ msgid "Spell Checker Failed" #~ msgstr "Stavningskontroll misslyckades" #~ msgid "Spell checker silently failed on startup" #~ msgstr "Stavningskontroll misslyckades tyst vid start" #~ msgid "Spell checking is unavailable" #~ msgstr "Stavningskontroll är ej tillgänglig" #~ msgid "Spelling Dictionary:" #~ msgstr "Stavningsordlista:" #~ msgid "Stage Hunk For Commit" #~ msgstr "Ställ del i incheckningskö" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "Köade ändringar (kommer att checkas in)" #~ 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" #, fuzzy #~ msgid "Staging Area" #~ msgstr "Söker %s..." #~ msgid "Staging area (index) is already locked." #~ msgstr "Köområdet (index) är redan låst." #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "Standard (snabb, semiredundant, hårda länkar)" #~ msgid "Standard only available for local repository." #~ msgstr "Standard är endast tillgängligt för lokala arkiv." #~ msgid "Starting gitk... please wait..." #~ msgstr "Startar gitk... vänta..." #~ msgid "Staying on branch '%s'." #~ msgstr "Stannar på grenen \"%s\"." #~ msgid "Success" #~ msgstr "Lyckades" #~ msgid "The 'main' branch has not been initialized." #~ msgstr "Grenen \"main\" har inte initierats." #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "Följande grenar är inte till fullo sammanslagna med %s:" #~ 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 "" #~ "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 "This Detached Checkout" #~ msgstr "Denna frånkopplade utcheckning" #~ 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 "" #~ "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 "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 "Transfer Options" #~ msgstr "Överföringsalternativ" #~ msgid "Unable to copy object: %s" #~ msgstr "Kunde inte kopiera objekt: %s" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "Kunde inte kopiera objekt/info/alternativ: %s" #~ msgid "Unable to display %s" #~ msgstr "Kan inte visa %s" #~ msgid "Unable to hardlink object: %s" #~ msgstr "Kunde inte hårdlänka objekt: %s" #~ msgid "Unable to obtain your identity:" #~ msgstr "Kunde inte hämta din identitet:" #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "Kan inte starta gitk:\n" #~ "\n" #~ "%s finns inte" #~ msgid "Unable to unlock the index." #~ msgstr "Kunde inte låsa upp indexet." #~ msgid "Unexpected EOF from spell checker" #~ msgstr "Oväntat filslut från stavningskontroll" #~ 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 "Unlock Index" #~ msgstr "Lås upp index" #~ 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 "Unrecognized spell checker" #~ msgstr "Stavningskontrollprogrammet känns inte igen" #~ msgid "Unstage Hunk From Commit" #~ msgstr "Ta bort del ur incheckningskö" #~ msgid "Unsupported spell checker" #~ msgstr "Stavningskontrollprogrammet stöds inte" #~ 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 "Updating working directory to '%s'..." #~ msgstr "Uppdaterar arbetskatalogen till \"%s\"..." #, fuzzy #~ msgid "Updating..." #~ msgstr "Startar..." #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "Använd tunt paket (för långsamma nätverksanslutningar)" #~ msgid "Verify Database" #~ msgstr "Verifiera databas" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "Verifierar objektdatabasen med fsck-objects" #~ msgid "Visualize %s's History" #~ msgstr "Visualisera historik för %s" #~ msgid "Working... please wait..." #~ msgstr "Arbetar... vänta..." #~ 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 "" #~ "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 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 "You must correct the above errors before committing." #~ msgstr "Du måste rätta till felen ovan innan du checkar in." #~ msgid "[Up To Parent]" #~ msgstr "[Upp till förälder]" #~ msgid "buckets" #~ msgstr "hinkar" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree misslyckades:" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "ödesdigert: Kunde inte slå upp %s" #~ msgid "files" #~ msgstr "filer" #~ msgid "files checked out" #~ msgstr "filer utcheckade" #~ msgid "files reset" #~ msgstr "filer återställda" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - ett grafiskt användargränssnitt för Git." #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: ödesdigert fel" #~ msgid "lines annotated" #~ msgstr "rader annoterade" #~ msgid "objects" #~ msgstr "objekt" #~ msgid "pt." #~ msgstr "p." #~ msgid "push %s" #~ msgstr "sänd %s" #~ msgid "remote prune %s" #~ msgstr "fjärrborttagning %s" #~ msgid "update-ref failed:" #~ msgstr "update-ref misslyckades:" #~ msgid "warning" #~ msgstr "varning" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "varning: Tcl stöder inte teckenkodningen \"%s\"." #~ msgid "write-tree failed:" #~ msgstr "write-tree misslyckades:" git-cola-4.6.1/cola/i18n/tr_TR.po000066400000000000000000002556031457126473700163430ustar00rootroot00000000000000# Translation of git-cola to Turkish. # Copyright (C) 2015, 2017 Barış ÇELİK. # This file is distributed under the same license as the git-cola package. # # Barış ÇELİK , 2015. # Sabri ÜNAL , 2019 # Adil GÜRBÜZ , 2019 # msgid "" msgstr "" "Project-Id-Version: git-cola\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: \n" "PO-Revision-Date: 2019-11-15 10:20+0300\n" "Last-Translator: Adil GÜRBÜZ \n" "Language-Team: Turkish\n" "Language: tr_TR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.1.7\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr "" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr "" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "\"%(branch)s\" öğesi \"%(remote)s\" uzak kaynağından silindi." #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "\"%(command)s\" çıkış durumu döndürdü %(status)d" #: cola/guicmds.py:156 #, python-format msgid "\"%s\" already exists" msgstr "" #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "" #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "%d gün önce" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "%d saat önce" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "%d dakika önce" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "%d düzeltme uygulandı." #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d geçildi" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "" #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "%s işaretlerinizden kaldırılacak." #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "%s son kullanılan repolardan silinecek." #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: Böyle bir dosya ya da dizin yok." #: cola/widgets/main.py:748 msgid "&Edit" msgstr "" #: cola/widgets/main.py:690 msgid "&File" msgstr "Dosya" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "" #: cola/widgets/diff.py:816 msgid "100%" msgstr "" #: cola/widgets/diff.py:817 msgid "200%" msgstr "" #: cola/widgets/diff.py:814 msgid "25%" msgstr "" #: cola/widgets/diff.py:818 msgid "400%" msgstr "" #: cola/widgets/diff.py:815 msgid "50%" msgstr "" #: cola/widgets/diff.py:819 msgid "800%" msgstr "" #: cola/widgets/finder.py:118 msgid " ..." msgstr "" #: cola/cmds.py:1685 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 "" "Bir işleme şablonu doğru yapılandırılmadı\n" "\"commit.template\" tanımlamak için \"git config\" komutunu kullanın\n" "yaptığınız ayarla doğru yeri işaret edin." #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "" #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "Hakkında" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "Aksiyon Adı" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "İşlemler" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "İşlemler..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "Ekle" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "Ayraç Ekle" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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:78 msgid "Add new remote git repository" msgstr "Yeni uzak git deposu ekle" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "Yaş" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "Tüm Depolar" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "" #: cola/cmds.py:220 msgid "Amend" msgstr "" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "Uygula" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "Düzeltmeleri Uygula..." #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "Argümanlar" #: cola/qtutils.py:886 msgid "Attach" msgstr "" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "Yazar" #: cola/widgets/about.py:90 msgid "Authors" msgstr "Yazarlar" #: cola/hidpi.py:41 msgid "Auto" msgstr "Otamatik" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "" #: cola/widgets/browse.py:206 msgid "Blame selected paths" msgstr "" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "" #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Dal" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "" #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Dal Adı" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "Dal: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "Dallar" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "Dallar..." #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "" #: cola/guicmds.py:52 msgid "Browse" msgstr "Gözat" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "İşlemelere Gözat..." #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "Geçerli Dala Gözat..." #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "Diğer Dala Gözat..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "Gözat..." #: cola/widgets/main.py:87 msgid "Browser" msgstr "Görüntüleyici" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "İptal" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "Çalıştırılamayan sorgu \"%s\": lütfen editörü ayarlayın" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "" #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "" #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "Varsayılan Depoyu Temizle" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "Temizle..." #: cola/widgets/clone.py:124 msgid "Clone" msgstr "" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "" #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Kapat" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "Kapat..." #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "" #: cola/sequenceeditor.py:371 msgid "Command" msgstr "Komut" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "" #: cola/difftool.py:102 msgid "Compare All" msgstr "" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "" #: cola/widgets/main.py:169 msgid "Console" msgstr "Uçbirim" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Devam et" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Kopyala" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "Ana Adı Panoya Kopyala" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "Yolu Panoya Kopyala" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "Sabit Yolu Panoya Kopyala" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "Copy SHA-1" #: cola/widgets/status.py:738 msgid "Copy..." msgstr "Kopyala..." #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Dal Oluştur" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "Yol Oluştur" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "Uzak Dal Oluştur" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "Etiket Oluştur" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "Etiket Oluştur..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "Oluştur..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "Güncel Depo" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "" #: cola/widgets/main.py:754 msgid "Cut" msgstr "Kes" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "" #: cola/icons.py:54 msgid "Dark Theme" msgstr "Koyu Tema" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "Tarih, Saat" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "Varsayılan" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Sil" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "%d dosyayı sil?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "İşareti Sil" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "İşareti Sil?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Dalı Sil" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "Dosyaları Sil" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "Dosyaları Sil..." #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "Dosyaları Sil?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "Uzaktakini Sil" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "Uzaktaki Dalı Sil..." #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "Araç çubuğunu sil" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "Uzaktakini sil \"%s\"" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "Uzaktakini sil?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Sil..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "\"%s\" silme işlemi başarısız" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "Geliştirici" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "" #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "Karşılaştırma Aracı" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "" #: cola/difftool.py:324 msgid "Difftool" msgstr "Karşılaştırma Aracı" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "Belgelendirme" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 msgid "Edit" msgstr "Düzenle" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "Konumlandırmayı Düzenle" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "Uzaktakini Düzenle" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "Uzaktakini Düzenle..." #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "Düzenle..." #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "Düzenleyici" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "E-Posta Adresi" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "Yeni Dal Adı Gir" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "Hata" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "Hata Dalı Oluştur" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "Hata Deposu Oluştur" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "Uzak Dal Silinirken Hata" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "Dosyayı Düzenlemede Hata" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "Uzak \"%s\" oluşturulurken hata" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Uzaktaki silinirken hata \"%s\"" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "" #: cola/cmds.py:2987 cola/cmds.py:3033 #, python-format msgid "Error updating submodule %s" msgstr "" #: cola/cmds.py:3069 msgid "Error updating submodules" msgstr "" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "Hata: İşleme şablonu bulunamadı" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "Hata: Ayarlanmamış işleme şablonu" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Hata: \"%s\" klonlanamadı" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "Düzeltmeleri Dışa Aktar" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "Düzeltmeleri Dışa Aktar..." #: cola/widgets/main.py:547 msgid "Expression..." msgstr "İfade..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "" #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "Favori depolar" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "Favoriler" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "" #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "" #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "Dosya Kaydedildi" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "\"%s\" dosyası kaydedildi" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "Dosya adı" #: cola/widgets/dag.py:821 msgid "Files" msgstr "Dosyalar" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "" #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "" #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "Dosyaları Bul" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "Düz koyu mavi" #: cola/themes.py:705 msgid "Flat dark green" msgstr "Düz koyu yeşil" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "Düz koyu gri" #: cola/themes.py:691 msgid "Flat dark red" msgstr "Düz koyu kırmızı" #: cola/themes.py:656 msgid "Flat light blue" msgstr "Düz açık mavi" #: cola/themes.py:677 msgid "Flat light green" msgstr "Düz açık yeşil" #: cola/themes.py:670 msgid "Flat light grey" msgstr "Düz açık gri" #: cola/themes.py:663 msgid "Flat light red" msgstr "Düz açık kırmızı" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Yazı Tipi Boyutu" #: cola/widgets/remote.py:197 msgid "Force" msgstr "" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "Arayüz teması" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "" #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "Yukarı Git" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "" #: cola/widgets/dag.py:848 msgid "Graph" msgstr "" #: cola/widgets/main.py:354 msgid "Grep" msgstr "" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Yardım" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "Yardım - Dosyaları Ara" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "Geçmiş Görüntüleyici" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "Simge Teması" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "" #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "" #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "Klavye Kısayolları" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "Karşılaştırma Aracını Çalıştır" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "Editörü Çalıştır" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "Terminali Çalıştır" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "" #: cola/icons.py:55 msgid "Light Theme" msgstr "Açık Tema" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "İşleme Mesajını Yükle" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "İşleme Mesajını Yükle..." #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "Yükleniyor..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "Yerel" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Yerel Dal" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "Yerel dal" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "" #: cola/widgets/dag.py:816 msgid "Log" msgstr "Kayıt" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "Birleştirme Aracı" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "" #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "" #: cola/widgets/main.py:1177 msgid "Merging" msgstr "Birleştiriliyor" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "Mesaj" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "Kayıp Veri" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "Kayıp Ad" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "Düzenlenmiş" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "" #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "Yukarı Kaydır" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "Ad" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "" #: cola/guicmds.py:147 cola/widgets/main.py:281 msgid "New Bare Repository..." msgstr "" #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "Yeni Depo..." #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "Araç Çubuğu Ekle" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Yeni..." #: cola/actions.py:56 msgid "Next File" msgstr "Sonraki Dosya" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "Hayır" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "" #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "" #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Aç" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Git Deposunu Aç" #: cola/widgets/submodules.py:48 msgid "Open Parent" msgstr "" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "Üst Klasörü Aç" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "Varsayılan Uygulamayla Aç" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "Yeni Pencere Aç" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "Yeni Pencere Aç..." #: cola/widgets/main.py:410 msgid "Open..." msgstr "Aç..." #: cola/widgets/branch.py:354 msgid "Other branches" msgstr "Diğer dallar" #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "" #: cola/widgets/main.py:758 msgid "Paste" msgstr "Yapıştır" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "Uygulanan Düzeltmeler" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "Yol" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "" #: cola/cmds.py:2297 msgid "Please select a file" msgstr "Lütfen bir dosya seçin" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "" #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "" #: cola/widgets/commitmsg.py:417 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/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Seçenekler" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "Ön Ek" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "" #: cola/actions.py:65 msgid "Previous File" msgstr "Önceki Dosya" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "" #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "" #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "" #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Çık" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Konumlandır" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "%s öğesine konumlandır" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "" #: cola/widgets/main.py:118 msgid "Recent" msgstr "Son" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "En Son Düzenlenen Dosyalar..." #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "" #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "" #: cola/widgets/main.py:751 msgid "Redo" msgstr "" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Yenile" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "Uzaktaki Dal Silindi" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "Kaldır" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "%s öğesini son kullanılanlardan sil?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Yeniden Adlandır" #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "Dalı Yeniden Adlandır" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "Dalı Yeniden Adlandır..." #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "Uzaktakini Yeniden Adlandır" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "Depoyu Yeniden Adlandır" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "Dalı yeniden adlandır" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "Depo: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Sıfırla" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "Dalı Sıfırla" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "Dalı Sıfırla?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "" #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "" #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "" #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "" #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "" #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "" #: cola/guicmds.py:320 msgid "Review" msgstr "Önizle" #: cola/widgets/main.py:597 msgid "Review..." msgstr "Önizle..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "Çalıştır" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "\"%s\" çalıştırılsın mı?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "%s çalıştırılsın mı?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "Komut çalıştırılıyor: %s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Kaydet" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "Arşivi Kaydet" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "" #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "Arayüz Ayarlarını Kaydet" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "Ara" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "Yazarları Ara" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "" #: cola/widgets/main.py:507 msgid "Search..." msgstr "Arama..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Seç" #: cola/widgets/main.py:764 msgid "Select All" msgstr "" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "" #: cola/guicmds.py:136 msgid "Select Directory..." msgstr "Dosyayı Seç..." #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "" #: cola/widgets/selectcommits.py:182 msgid "Select output directory" msgstr "" #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "" #: cola/widgets/editremotes.py:434 msgid "Select repository" msgstr "Depoyu seç" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "Varsayılan Depoyu Seç" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "Ayarlar" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "Kısayollar" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "Yardımı Göster" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "Geçmişi Göster" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "Yardımı göster\n" "Kısayol: ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "" #: cola/cmds.py:2527 msgid "Skip" msgstr "Atla" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "" #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "" #: cola/widgets/stash.py:79 msgid "Stash staged changes only" msgstr "" #: cola/widgets/stash.py:75 msgid "Stash unstaged changes only, keeping staged changes" msgstr "" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "" #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "Durum" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Tab Genişliği" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Etiket" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Etiket mesajı..." #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "" #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "Etiketler" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "Yazı Genişliği" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "" #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "" #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "" #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "Aşağıdaki satırlar silinecek:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "" #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 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/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "Türkçe çeviri" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "URL: %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "Birleştirilmemiş" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "Takip Edilmemiş" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "" #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Kullanıcı Adı" #: cola/widgets/about.py:89 msgid "Version" msgstr "Versiyon" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "Göster" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "Geçmişi Göster..." #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "" #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "" #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "Evet" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "Bir birleştirme işleminin ortasındasınız.\n" "Birleştirme yapılırken değişiklik yapamazsınız." #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "" #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "" #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "" #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "Yakınlaş" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "Uzaklaş" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "" #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "git cola sürümü %s" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "git-cola diff" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "grep sonucu..." #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "hotkeys.html" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "vX.Y.Z" #: cola/hidpi.py:43 msgid "x 1" msgstr "x 1" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "x 1.5" #: cola/hidpi.py:46 msgid "x 2" msgstr "x 2" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "yyyy-AA-gg" #, fuzzy #~ msgid "\"%s\" returned exit status %d" #~ msgstr "\"%(command)s\" çıkış durumu döndürdü %(status)d" #~ msgid "\"git commit\" returned exit code %s" #~ msgstr "\"git commit\" returned exit code %s" #~ msgid "Already up-to-date." #~ msgstr "Already up-to-date." #~ msgid "Commit failed: %s" #~ msgstr "İşleme başarısız: %s" #~ msgid "Created commit: %s" #~ msgstr "Oluşturulan işleme: %s" #~ msgid "Enter Git Repository" #~ msgstr "Enter Git Repository" #, fuzzy #~ msgid "Error %s" #~ msgstr "Errors: %s" #~ msgid "Errors: %s" #~ msgstr "Errors: %s" #~ msgid "Exit code: %s" #~ msgstr "Exit code: %s" #~ msgid "Fast Forward Only " #~ msgstr "Fast Forward Only " #~ msgid "GPG-signed" #~ msgstr "GPG-signed" #, fuzzy #~ msgid "Local Branches" #~ msgstr "Local Branch" #~ msgid "On Debian-based systems try: sudo apt-get install python-pyinotify" #~ msgstr "On Debian-based systems try: sudo apt-get install python-pyinotify" #~ msgid "Options" #~ msgstr "Seçenekler" #~ msgid "" #~ "Output:\n" #~ "%s" #~ msgstr "" #~ "Output:\n" #~ "%s" #~ msgid "Output: %s" #~ msgstr "Output: %s" #~ msgid "Path to git repository" #~ msgstr "Path to git repository" #, fuzzy #~ msgid "Remote Branches" #~ msgstr "Remote Branch" #~ msgid "Rename remote?" #~ msgstr "Uzaktakini yeniden adlandır?" #~ msgid "Select File" #~ msgstr "Select File" #~ msgid "Select Repository..." #~ msgstr "Depoyu Seç..." #~ msgid "Select file from \"%s\"" #~ msgstr "Select file from \"%s\"" #~ msgid "Show Details..." #~ msgstr "Ayrıntıları Göster..." #~ msgid "Staging Area" #~ msgstr "Staging Area" #~ msgid "Summary:" #~ msgstr "Özet:" #~ msgid "" #~ "This PyQt4 does not include QtWebKit.\n" #~ "The keyboard shortcuts feature is unavailable." #~ msgstr "" #~ "This PyQt4 does not include QtWebKit.\n" #~ "The keyboard shortcuts feature is unavailable." #~ msgid "Updating..." #~ msgstr "Updating..." #~ msgid "" #~ "file notification: disabled\n" #~ "Note: install pywin32 to enable.\n" #~ msgstr "" #~ "file notification: disabled\n" #~ "Note: install pywin32 to enable.\n" #~ msgid "git clone returned exit code %s" #~ msgstr "git clone çıkış kodu döndürdü %s" #~ msgid "git tag returned exit code %s" #~ msgstr "git tag returned exit code %s" #~ msgid "inotify enabled." #~ msgstr "inotify enabled." #~ msgid "" #~ "inotify: disabled\n" #~ "Note: install python-pyinotify to enable inotify.\n" #~ msgstr "" #~ "inotify: disabled\n" #~ "Note: install python-pyinotify to enable inotify.\n" #~ msgid "unknown" #~ msgstr "bilinmeyen" git-cola-4.6.1/cola/i18n/uk.po000066400000000000000000003502751457126473700157310ustar00rootroot00000000000000# Translation of git-cola to ukrainian # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Igor Kopach , 2017. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-17 01:06-0700\n" "PO-Revision-Date: 2017-08-30 08:16+0200\n" "Last-Translator: Igor Kopach \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " Перетягніть та відпустіть або використовуйте кнопку\n" " Додати, щоб додати латки до списку\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" "\n" "
\n" " Git Cola була перекладена на різні мови завдяки\n" " завдяки допомозі осіб вказаних нижче.\n" "\n" "
\n" "

\n" " Переклад є приблизним. Якщо ви знайшли помилку,\n" " будь ласка, дайте нам знати, створивши проблему на Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " Запрошуємо вас до участі в перекладі, додаючи або оновлюючи\n" " переклад та відкриванні запитів на стягнення (pull request).\n" "

\n" "\n" "
\n" "\n" " " #: cola/widgets/about.py:181 #, fuzzy, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" "\n" "
\n" " Git Cola версії %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" "\n" "
\n" " Будь ласка, використовуйте %(bug_link)s щоб повідомляти про проблеми.\n" "
\n" " " #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" "\n" "Поєднання клавіш\n" "------------------\n" "J, Down = Переміститись донизу\n" "K, Up = Перейменувати вгору\n" "Enter = Редагувати вибрані файли\n" "Spacebar = Відкрити файл, використовуючи застосунок за замовчуванням\n" "Ctrl + L = Фокус на полі для введення тексту\n" "? = Показати довідку\n" "\n" "Стрілки вготу та вниз змінюють фокус поміж полем для введення тексту\n" "та результатами.\n" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr " - Граф (DAG)" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr " комітів тому" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "\"%(branch)s\" було видалено з \"%(remote)s\"." #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "\"%(command)s\" завершилась з кодом \"%(status)d\"" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "\"%(command)s\" завершилась з кодом %(status)d" #: cola/guicmds.py:156 #, fuzzy, python-format msgid "\"%s\" already exists" msgstr "Гілка \"%s\" вже існує." #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "\"%s\" вже існує, cola створить новий каталог" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "\"%s\" потребує вибраного файла." #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s: %(branch)s - Переглянути" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "%(project)s: %(ref)s - Граф (DAG)" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "%d днів тому" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "%d годин тому" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "%d хвилин тому" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "%d латку(ок) застосовано." #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d пропущено" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" "%s здається містить конфлікт злиття.\n" "\n" "Скоріш за все, ви маєте пропустити цей файл.\n" "Проіндексувати в будь-якому випадку?" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "%s не є репозиторієм Git." #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "%s буде видалено з ваших закладок." #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "%s буде видалено зі списку останніх репозиторіїв." #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: Немає такого файла або каталогу." #: cola/widgets/main.py:748 msgid "&Edit" msgstr "Редагувати" #: cola/widgets/main.py:690 msgid "&File" msgstr "Файл" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(Зміна коміту)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "*** Вказівка на гілку ***" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** Пісочниця ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "" #: cola/widgets/diff.py:817 msgid "200%" msgstr "" #: cola/widgets/diff.py:814 msgid "25%" msgstr "" #: cola/widgets/diff.py:818 msgid "400%" msgstr "" #: cola/widgets/diff.py:815 msgid "50%" msgstr "" #: cola/widgets/diff.py:819 msgid "800%" msgstr "" #: cola/widgets/finder.py:118 msgid " ..." msgstr "<шлях> ..." #: cola/cmds.py:1685 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 "" "Шаблон коміту не сконфігуровано.\n" "Використовуйте \"git config\" щоб задати \"commit.template\"\n" "так, щоб він вказував на шаблон коміту" #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "Гак (hook) має бути в \"%s\"" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "Перервати" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "Перервати дію" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "Перервати злиття" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "Перервати злиття..." #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "Перервати дію?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "Переривання поточного злиття спричинить втрату *ВСІХ* незакомітованих змін.\n" "Відновлення незакомітованих змін неможливе." #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "Перервати поточне злиття?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "Про програму" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "Про git-cola" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "Погодитись" #: cola/sequenceeditor.py:164 #, fuzzy msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "Закомітувати проіндексовані зміни\n" "Поєднання клавіш: Ctrl+Enter" #: cola/widgets/status.py:1376 #, fuzzy msgid "Action Name" msgstr "Дії" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "Дії" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "Дії..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "Додати" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "Додати улюбление" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "Додати віддалений репозиторій" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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 "" "Додавайте та видаляйте віддалені репозиторіїї використовуючи\n" "кнопки Додати(+) та Видалити(-) в лівій частині програми.\n" "\n" "Віддалені репозиторіїї можна перейменувати, вибрабравши один зі списку\n" "та натиснувши \"enter\", або подвійним кліком мишки." #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "Додати новий віддалений репозиторій git" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "Додати латки (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "Додати віддалений репозиторій" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "Додати до .gitignore" #: cola/widgets/status.py:287 #, fuzzy msgid "Add to Git Annex" msgstr "Додати до .gitignore" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "Додано" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "Розширено" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "Вік" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "Всі репозиторіїї" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "Дозволити оновлення без перемотки. Використання \"примусу\" може призвести до того, що віддалений репозиторій втратить коміти; використовйте це з обережністю" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "Якщо увімкнено, завжди створювати коміт злиття, навіть якщо злиття може бути виконано використовуючи метод перемотки (fast-forward)" #: cola/cmds.py:220 msgid "Amend" msgstr "Змінити" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "Змінити коміт" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "Змінити останній коміт" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "Змінити опублікований коміт?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "Змінення" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "Дія все ще виконується.\n" "Переривання може призвести до втрати даних." #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "Замість цього буде створено легкий непідписаний теґ.\n" "Створити непідписаний теґ?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "Застосувати" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "Застосувати латки" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "Примінити латки..." #: cola/widgets/stash.py:66 #, fuzzy msgid "Apply and drop the selected stash (git stash pop)" msgstr "Застосувати виділений сховок" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "Застосувати виділений сховок" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "Аргументи" #: cola/qtutils.py:886 msgid "Attach" msgstr "Прикріпити" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "Автор" #: cola/widgets/about.py:90 msgid "Authors" msgstr "Автори" #: cola/hidpi.py:41 msgid "Auto" msgstr "" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "Авто-перенос рядків" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "Базовий регулярний вираз" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "Переглядач анотацій (blame)" #: cola/widgets/browse.py:206 #, fuzzy msgid "Blame selected paths" msgstr "Редагувати вибрані шляхи" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "Анотувати (blame)..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "Напівжирний з темним фоном шрифт замість заголовків курсивом" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "Гілка" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "Гілка \"%(branch)s\" не існує в \"%(remote)s\".\n" "Нова гілка буде опублікована." #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "Гілка \"%s\" вже існує." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "Переглядач різниц на гілкаї" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "Гілка існує" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "Назва гілки" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "Гілка: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "Гілки" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "Гілки..." #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "Бразильський переклад" #: cola/guicmds.py:52 msgid "Browse" msgstr "Переглянути" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "Переглянути коміти..." #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "Переглянути поточну гілку..." #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "Переглянути іншу гілку..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "Переглянути..." #: cola/widgets/main.py:87 msgid "Browser" msgstr "Переглядач" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "Перегляд %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "Оминути гаки (hooks) коміту" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "" #: cola/sequenceeditor.py:181 #, fuzzy msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "Закомітувати проіндексовані зміни\n" "Поєднання клавіш: Ctrl+Enter" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "Не вдається змінити" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "Не вдалось виконати \"%s\": будь ласка налаштуйте переглядач анотацій (blame)" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "Не вдалось виконати \"%s\": будь ласка налаштуйте переглядач історії" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "Не вдалось виконати \"%s\": будь ласка, налаштуйте ваш редактор" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "Змінено в віддаленому джерелі" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "Перевірити правопис" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "Перевірити правопис" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "Переключитись" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "Переключитись після створення" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "Переключитись на гілку" #: cola/widgets/dag.py:413 #, fuzzy msgid "Checkout Detached HEAD" msgstr "Переключитись на гілку" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 #, fuzzy msgid "Checkout as new branch" msgstr "Переключитись на гілку" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "Переключитись..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "Висмикнути коміт (cherry pick)" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "Висмикнути коміт (cherry pick)" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "Висмикнути коміт (cherry pick)..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "Вибрати шляхи" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "Виберіть режим регулярного виразу \"git grep\"" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "Очистити репозиторій за замовчуванням" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "Очистити повідомлення коміту" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "Очистити повідомлення коміту?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "Очистити..." #: cola/widgets/clone.py:124 #, fuzzy msgid "Clone" msgstr "Клонувати..." #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "Клонувати репозиторій" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "Клонувати..." #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "Клонувати репозиторій в %s" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "Закрити" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "Закрити..." #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "Згорнути все" #: cola/sequenceeditor.py:371 #, fuzzy msgid "Command" msgstr "Коміт" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "Коміт" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "Не вдалось зробити коміт" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "Закомітувати проіндексовані зміни" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "Закомітувати проіндексовані зміни\n" "Поєднання клавіш: Ctrl+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "Опис коміту" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "Закомітувати злиття, якщо немає конфліктів. Зніміть прапорець щоб залишити злиття незакомітованим" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "Закомітувати" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "Порівняти" #: cola/difftool.py:102 msgid "Compare All" msgstr "Порівняти все" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "Налаштувати віддалену гілку як нове віддалене джерело" #: cola/widgets/main.py:169 msgid "Console" msgstr "Консоль" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "Продовжити" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "Скопіювати" #: cola/widgets/status.py:269 #, fuzzy msgid "Copy Basename to Clipboard" msgstr "Скопіювати шлях в буфер обміну" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 #, fuzzy msgid "Copy Leading Path to Clipboard" msgstr "Скопіювати відносний шлях в буфер обміну" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "Скопіювати шлях в буфер обміну" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "Скопіювати відносний шлях в буфер обміну" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "Скопіювати SHA-1" #: cola/widgets/status.py:738 #, fuzzy msgid "Copy..." msgstr "Скопіювати" #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "Не вдалось розпізнати Git URL: \"%s\"" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "Створити гілку" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "Створити латку" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "Створити віддалену гілку" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "Створити підписаний коміт" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "Створити теґ" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "Створити теґ..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "Створити непідписаний теґ" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "Створити коміт злиття навіть якщо злиття може бути вирішено методом перемотки" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "Створити нову віддалену гілку?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "Створити..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "Створено новий теґ з назвою \"%s\"" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "Поточний репозиторій" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "" #: cola/widgets/status.py:274 #, fuzzy msgid "Customize..." msgstr "Закрити..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "" #: cola/widgets/about.py:393 cola/widgets/about.py:424 #, fuzzy msgid "Czech translation" msgstr "Французький переклад" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "Граф (DAG)..." #: cola/icons.py:54 msgid "Dark Theme" msgstr "" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "Дата, час" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "Видалити" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "Видалити %d файл(ів)?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "Видалити закладку" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "Видалити закладку?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "Видалити гілку" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "Видалити файли" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "Видалити файли..." #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "Видалити файли?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "Видалити віддалений репозиторій" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "Видалити віддалену гілку" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "Видалити віддалену гілку..." #: cola/widgets/toolbar.py:276 #, fuzzy msgid "Delete Toolbar" msgstr "Видалити закладку" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "Видалити віддалений репозиторій" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "Видалити віддалений репозиторій \"%s\"" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "Видалити віддалений репозиторій?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "Видалити..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "Не вдалось видалити \"%s\"" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "Видалено" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "Відкріпити" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "Виявити мітки конфліктів" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "Виявити мітки конфліктів в незлитих файлах" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "Розробник" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "Різниця" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "Різниця до попередника..." #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "Опції порівняння" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "Інструмент порівняння" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "Порівняти виділене з цим" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "Порівняти це з виділеним" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "Список різниць" #: cola/difftool.py:324 #, fuzzy msgid "Difftool" msgstr "Інструмент порівняння" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "Каталог існує" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "Показати файли, що не відслідковуються" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "Документація" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "Видалити" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "Видалити сховок" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "Видалити сховок?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "Видалити \"%s\" сховок?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "Видалити вибраний сховок" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 #, fuzzy msgid "Edit" msgstr "Редагувати" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "Редагувати переміщення (rebase)" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "Редагувати віддалені репозиторіїї" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "Редагувати віддалені репозиторіїї..." #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "Редагувати вибрані шляхи" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "Редагувати..." #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "Редактор" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "Адреса електронної пошти" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "Електронна пошта учасника" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "Введіть ім'я для нової гілки" #: cola/guicmds.py:146 #, fuzzy msgid "Enter a name for the new bare repo" msgstr "Введіть назву для сховка" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "Введіть назву для сховка" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "Помилка" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "Помилка клонування" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "Помилка при створенні гілки" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "Помилка створення репозиторію" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "Не вдалось видалити віддалену гілку" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "Помилка редагування файла" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "Помилка запуску переглядача анотацій (blame)" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "Помилка запуску браузера історії" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "Не вдалось створити віддалений репозиторій \"%s\"" #: cola/models/stash.py:233 #, fuzzy msgid "Error creating stash" msgstr "Помилка при створенні гілки" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "Не вдалось видалити віддалений репозиторій \"%s\"" #: cola/cmds.py:954 #, fuzzy, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "Позначення \"%(revision)s\" як \"%(name)s\"" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "Помилка застосування prepare-commitmsg гака (hook)" #: cola/cmds.py:2987 cola/cmds.py:3033 #, fuzzy, python-format msgid "Error updating submodule %s" msgstr "Не вдалось створити віддалений репозиторій \"%s\"" #: cola/cmds.py:3069 #, fuzzy msgid "Error updating submodules" msgstr "Помилка редагування файла" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "Помилка: Не вдається знайти шаблон коміту" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "Помилка: Шаблон коміту не сконфігуровано" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "Помилка: не вдалось клонувати \"%s\"" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "Помилка: не вдалось створити теґ \"%s\"" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "Виконання дії %s" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "Розгорнути все" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "Експорт латок" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "Експортувати латки..." #: cola/widgets/main.py:547 msgid "Expression..." msgstr "Вираз..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "Розширений регулярний вираз" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "Розширений опис..." #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "Лише перемотка (fast-forward)" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "Лише перемотка (fast-forward)" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "Улюблені репозиторіїї" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "Улюбене" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "Отримати" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "Отримати гілку, що відстежується" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "Отримати" #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "Переглядач файлів..." #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "Різниця між файлами" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "Файл збережено" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "Дайл збережено до \"%s\"" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "Відстеження змін файлової системи: вимкнено, тому що \"cola.inotify\" є хибним (false).\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "Відстеження змін файлової системи: вимкнено, тому що libc не підтримує системних викликів inotify.\n" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "Відстеження змін файлової системи: вимкнено, тому що не встановлено pywin32.\n" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" "Відстеження змін файлової системи: вимкнено, тому що досягнуто верхньої межі кількості спостерігачів inotify. Ви можете збільшити ліміт кількості спостерігачів, виконавши:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "Відстеження змін файлової системи: увімкнено.\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "Ім'я файла" #: cola/widgets/dag.py:821 msgid "Files" msgstr "Файли" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "Фільтрувати гілки..." #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "Фільтрувати шляхи..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "Пошук файлів" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "Фіксована послідовність знаків" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "Моноширний шрифт" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "Виправити попередній коміт" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "" #: cola/themes.py:705 msgid "Flat dark green" msgstr "" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "" #: cola/themes.py:691 msgid "Flat dark red" msgstr "" #: cola/themes.py:656 msgid "Flat light blue" msgstr "" #: cola/themes.py:677 msgid "Flat light green" msgstr "" #: cola/themes.py:670 msgid "Flat light grey" msgstr "" #: cola/themes.py:663 msgid "Flat light red" msgstr "" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "Розмір шрифта" #: cola/widgets/remote.py:197 msgid "Force" msgstr "Надіслати примусово" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "Отримати примусово" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "Отримати примусово?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "Надіслати примусово" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "Надіслати примусово?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "Примусове отримання з %s?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "Надіслати примусово до %s?" #: cola/widgets/status.py:1376 #, fuzzy msgid "Format String" msgstr "Фіксована послідовність знаків" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "Французький переклад" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "Підписати-GPG коміт злиття" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "Збирання інформації для \"%s\"..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "Німецький переклад" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "Отримати шаблон тексту коміту" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "Вниз" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "Вгору" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "Взяти файл..." #: cola/widgets/dag.py:848 msgid "Graph" msgstr "Графік" #: cola/widgets/main.py:354 msgid "Grep" msgstr "Пошук (grep)" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "Чи ви робили переміщення/стягнення останнім часом?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "Допомога" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "Допомога - Пошук файлів" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "Переглядач історії" #: cola/widgets/about.py:409 cola/widgets/about.py:423 #, fuzzy msgid "Hungarian translation" msgstr "Російський переклад" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "Ігнорувати всі пробіли" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "Ігнорувати зміни в кількості пробілів" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "Ігнорувати зміни в пробільних знаках в кінці рядка" #: cola/widgets/gitignore.py:45 #, fuzzy msgid "Ignore custom pattern" msgstr "Ігнорувати специфічний шаблон" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "Ігнорувати точне ім'я файлу" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "Ігнорувати ім'я файлу або шаблон" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "" #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "Включити теґ" #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "Індонезійський переклад" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "Інтерактивне переміщення" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "Неправильна ревізія" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "Зберігати резервні копії *.orig файлів після злиття" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "Зберегти індекс" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "Поєднання клавіш" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "Запустити інструмент порівняння" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "Запустити каталоговий інструмент порівняння" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "Відкрити редактор" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "Запустити термінал" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "Запустити git-cola" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "Запустити git-difftool до попередньої версії" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "Запустити git-difftool для поточного шляху" #: cola/icons.py:55 msgid "Light Theme" msgstr "" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "Завантажити повідомлення коміту" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "Завантажити текст коміту..." #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "Завантажити повідомлення попереднього коміту" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "Завантаження..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "Локальна" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "Локальна гілка" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "Локальна гілка" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "Закріпити положення елементів" #: cola/widgets/dag.py:816 msgid "Log" msgstr "Журнал подій" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "Супроводжуючий (з 2007) та розробник" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "Злиття" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "Злити \"%(revision)s\" в \"%(branch)s\"" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "Інструмент злиття" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "Детальність злиття" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "" #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "Злити в \"%s\"" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "Злити до поточної гілки" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "Злиття" #: cola/widgets/main.py:1177 msgid "Merging" msgstr "Злиття" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "Повідомлення" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "Відсутнє повідомлення коміту" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "Дані відсутні" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "Назва відсутня" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "Ревізія відсутня" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "Назва теґу відсутня" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "Змінене" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "Більше..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "Перемістити вниз" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "Перемістити вгору" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "Перемістити файл до смітника" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "Ім'я" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "Назва нового віддаленого репозиторію" #: cola/guicmds.py:147 cola/widgets/main.py:281 #, fuzzy msgid "New Bare Repository..." msgstr "Новий репозиторій..." #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "Новий репозиторій..." #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "" #: cola/widgets/startup.py:52 msgid "New..." msgstr "Новий..." #: cola/actions.py:56 msgid "Next File" msgstr "Наступний файл" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "Ні" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "Ревізію не вказано" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "Немає змін для коміту.\n" "\n" "Ви маєте проіндексувати принаймні 1 файл перед тим, як ви зможете зробити коміт." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "На цій гілці немає комітів." #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "Без перемотки (fast-forward)" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "Без перемотки" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "Не вибрано жодного репозиторію." #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "Отримання без використання методу перемотки перезапише локальну історію!" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "Надсилання без використання методу перемотки перезапише опубліковану історію!\n" "(Чи всі зміни стягнуто?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "Немає що комітувати" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "Нічого робити" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Число рядків контексту різниці" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "Відкрити" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "Відкрити Git репозиторій" #: cola/widgets/submodules.py:48 #, fuzzy msgid "Open Parent" msgstr "Відкрити останній" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "Відкрити батьківський каталог" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "Відкрити останній" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "Відкрити, використовуючи застосунок за замовчуванням" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "Відкрити в новому вікні" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "Відкрити в новому вікні..." #: cola/widgets/main.py:410 msgid "Open..." msgstr "Відкрити" #: cola/widgets/branch.py:354 #, fuzzy msgid "Other branches" msgstr "Фільтрувати гілки..." #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "Перезаписати" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "Перезаписати \"%s\"?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "Перезаписати файл?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "Розібрати аргументи використовуючи командну стрічку.\n" "Запити з пробілами вимагатимуть \"лапок\"." #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "Частково проіндексоване" #: cola/widgets/main.py:758 msgid "Paste" msgstr "" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "Латку(и) застосовано" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "Шлях" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "Шлях або URL для клонування (Env. $VARS okay)" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "Будь ласка, надайте як ім'я гілки так і вираз ревізії." #: cola/cmds.py:2297 msgid "Please select a file" msgstr "Будь ласка, виберіть файл" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "Будь ласка, вкажіть назву для теґу." #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "Будь ласка, вкажіть ревізію для теґу." #: cola/widgets/commitmsg.py:417 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/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "Встановити HEAD поточної гілки на новий коміт?" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "Польський переклад" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "Налаштування" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "Префікс" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "Підготувати текст коміту" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "" #: cola/actions.py:65 msgid "Previous File" msgstr "Попередній файл" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "Підказати при створенні" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "Підказати коли надсилаются новостворені віддалені гілки" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "" #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "Стягнути" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "Стягнути" #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "Надіслати" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "Надіслати" #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "Вихід" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "Перемістити (rebase)" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "Перемістити (rebase) на %s" #: cola/cmds.py:2105 #, fuzzy msgid "Rebase stopped" msgstr "Перемістити (rebase) на %s" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "Перемістити поточну гілку замість злиття" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "Переміщення" #: cola/widgets/main.py:118 msgid "Recent" msgstr "Недавнє" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "Недавні репозиторіїї" #: cola/widgets/prefs.py:279 #, fuzzy msgid "Recent repository count" msgstr "Недавні репозиторіїї" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "Недавно змінені файли" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "Недавно змінені файли..." #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "Неможливо відновити видалений сховок." #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "Відновлення втрачених комітів може бути нелегким." #: cola/widgets/main.py:751 msgid "Redo" msgstr "" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "Оновити" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "Відмовтесь від злиття за винятком, коли поточний HEAD є оновленим або злиття може бети вирішено методом перемотки" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "Віддалений репозиторій" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "Віддалена гілка" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "Видалено віддалену гілку" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "Віддалені репозиторіїї git - подвійний клік для перейменування" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "Видалити" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "Видалити %s зі списку останніх?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "Видалити елемент" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "Видалити виділене (Видалити)" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "Перейменувати" #: cola/cmds.py:1153 #, fuzzy, python-format msgid "Rename \"%s\"" msgstr "Перейменувати" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "Перейменувати гілку" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "Перейменувати гілку..." #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "Перейменувати існуючу гілку" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "Перейменувати віддалений репозиторій" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "Перейменувати репозиторій" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "Перейменувати гілку" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "Перейменувати віддалений репозиторій \"%(current)s\" в \"%(new)s\"?" #: cola/widgets/browse.py:159 #, fuzzy msgid "Rename selected paths" msgstr "Редагувати вибрані шляхи" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "Репозиторій: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "Скинути" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "Скинути \"%(branch)s\" до \"%(revision)s\"?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "Скинути гілку" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "Скинути гілку?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "Скидання \"%(branch)s\" до \"%(revision)s\" призведе до втрати комітів." #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "Скасувати частину різниці" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "Скасувати частину різниці..." #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "Скасувати частину різниці?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "Скасувати виділені рядки" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "Скасування виділених рядків..." #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "Скасувати виділені рядки?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "Відмінити незакомітовані зміни" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "Відмінити незакомітовані зміни?" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "Відмінити незакомітовані зміни..." #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "Відмінити непроіндексовані зміни" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "Відмінити непроіндексовані зміни?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "Відмінити непроіндексовані зміни..." #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "Відмінити незакомітовані зміни?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "Відмінити непроіндексовані зміни?" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "Відмінити незакомітовані зміни на вибраних шляхах" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "Відмінити непроіндексовані зміни на вибраних шляхах" #: cola/guicmds.py:320 msgid "Review" msgstr "Перевірка" #: cola/widgets/main.py:597 msgid "Review..." msgstr "Перевірка..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "Ревізія" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "Вираз для визначення ревізії:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "Ревізія для злиття" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "Перезаписати опублікований коміт?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "Запустити" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "Виконати \"%s\"?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "Запустити %s?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "Виконати команду \"%s\"?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "Запуск команди: %s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "Російський переклад" #: cola/sequenceeditor.py:372 #, fuzzy msgid "SHA-1" msgstr "Скопіювати SHA-1" #: cola/widgets/prefs.py:205 #, fuzzy msgid "Safe Mode" msgstr "Проіндексувати зміни" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "Зберегти" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "Зберегти архів" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "Зберегти як Tarball/Zip..." #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "Зберегти налаштування графічного інтерфейсу" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "Зберегти сховок" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "Зберегти змінений стан до нового сховка" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "Збережено \"%(filename)s\" з \"%(ref)s\" до \"%(destination)s\"" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "Пошук" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "Пошук авторів" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "Пошук тексту коіта" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "Пошук комітерів" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "Пошук діапазону дат" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "Пошук різниць" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "Пошук за виразом" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "Пошук за шляхом" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "Шукати фіксовану послідовність знаків" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "Шукати, використовуючи базовий регулярний вираз POSIX" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "Шукати, використовуючи розширений регулярний вираз POSIX" #: cola/widgets/main.py:507 msgid "Search..." msgstr "Пошук..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "Вибрати" #: cola/widgets/main.py:764 msgid "Select All" msgstr "Виділити все" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "Виберіть гілку для перевірки" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "Вибрати потомка" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "Вибрати коміт" #: cola/guicmds.py:136 #, fuzzy msgid "Select Directory..." msgstr "Вибрати репозиторій..." #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "Вибрати нове віддалене джерело" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "Вибрати найновішого потомка" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "Вибрати найстаршого предка" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "Вибрати предка" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "Вибрати попередню версію" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "Виберіть батьківський каталог для нового клонування" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 #, fuzzy msgid "Select output dir" msgstr "Вибрати коміт" #: cola/widgets/selectcommits.py:182 #, fuzzy msgid "Select output directory" msgstr "Вибрати репозиторій..." #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "Виберіть файл(и) латки(ок)..." #: cola/widgets/editremotes.py:434 #, fuzzy msgid "Select repository" msgstr "Вибрати репозиторій..." #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "Встановити репозиторій за замовчуванням" #: cola/widgets/branch.py:291 #, fuzzy msgid "Set Upstream Branch" msgstr "Встановити віддалене джерело" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "Встановити віддалене джерело" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "Налаштування" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "Аргументи командної стрічки" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "Поєднання клавіш" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "Показати список різниць після злиття" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "Показати допомогу" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "Показати історію" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "Показати допомогу\n" "Клавіша: ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "Показати нумерацію рядків" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "Показати всі оточуючі функції при змінах" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "Показ змін від" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "Підписати" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "Підписати теґ" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "Підписатись під цим комітом" #: cola/widgets/about.py:394 cola/widgets/about.py:407 #, fuzzy msgid "Simplified Chinese translation" msgstr "Китайський переклад" #: cola/cmds.py:2527 msgid "Skip" msgstr "Пропустити" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "Пропустити поточну латку" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "Сортувати закладки за алфавітом" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "Іспанський переклад" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "Визначає SHA-1 теґу" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "Визначає повідомлення теґу" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "Задає ім'я теґу" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "Поради з правопису" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "Об'єднати" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "Об'єднати злиті коміти в один коміт" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "Проіндексувати" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "Проіндексувати / Видалити з проіндексованого" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "Додати частину різниці до проіндексованого" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "Проіндексувати зміни" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "Додати виділене до проіндексованого" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "Додати виділені рядки до проіндексованого" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "Проіндексувати незлите" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "Проіндексувати файли, що не відслідковуються" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "Проіндексувати та закомітувати" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "Проіндексувати та закомітувати?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "Проіндексувати конфлікт" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "Проіндексувати конфлікт?" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "Додати/видалити з проіндексованого шляхи для коміту" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "Проіндексоване" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "Індексація: %s" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "Розпочати інтерактивне переміщення..." #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "Початкова ревізія" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "Сховати (stash)" #: cola/widgets/stash.py:79 #, fuzzy msgid "Stash Index" msgstr "Сховати (stash)" #: cola/widgets/stash.py:79 #, fuzzy msgid "Stash staged changes only" msgstr "Закомітувати проіндексовані зміни" #: cola/widgets/stash.py:75 #, fuzzy msgid "Stash unstaged changes only, keeping staged changes" msgstr "Відмінити непроіндексовані зміни на вибраних шляхах" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "Сховок" #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "Статус" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "Перестати відслідковувати виділене" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "Підсумувати коміти злиття" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "Опис" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Ширина табуляції" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "Теґ" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "Теґ створено" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "Повідомлення теґу..." #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "Вібувся запит на підписання теґу, але повідомлення для теґу порожнє." #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "Теґи" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "Ширина тексту" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "Гілка не буде більше доступна." #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "Глку буде скинуто, використовуючи \"git reset --mixed %s\"" #: cola/cmds.py:700 cola/cmds.py:791 #, fuzzy, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "Глку буде скинуто, використовуючи \"git reset --mixed %s\"" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "Повідомлення коміту буде очищено." #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "Файл \"%s\" вже існує і буде перезаписаний." #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "Наступні файли будуть видалені:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "Поле ревізії не може бути порожнім." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "Це неможливо буде відмінити. Очистити повідомлення коміту?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "Цей коміт вже опубліковано.\n" "Ця операція перезапише опубліковану історію.\n" "Скоріш за все ви не хочете цього." #: cola/widgets/diff.py:1232 #, fuzzy msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "Ця операція відмінить незакомітовані зміни.\n" "Ці зміни не можна буде відновити." #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Ця операція відмінить незакомітовані зміни.\n" "Ці зміни не можна буде відновити." #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "Ця операція відмінить непроіндексовані зміни.\n" "Ці зміни не можна буде відновити." #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "Цей репозиторій переміщено.\n" "Виправте конфлікти, закомітуйте зміни, і виконайте:\n" " Перемістити (rebase) > Продовжити" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "Цей репозиторій в процесі злиття.\n" "Виправте конфлікти та закомітуйте зміни." #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "Перемкнути фільтр гілок" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "Перемкнути фільтр шляхів" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "Гілка, що відслідковуються" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "Гілка, що відстежується" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "Традиційний китайський (Тайвань) переклад" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "Перекладачі" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "Турецький переклад" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "Адреса URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "Адреса URL: %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "Український переклад" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "Не вдалось перемістити (rebase)" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "Незлите" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "Видалити з індексу" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "Видалити все з проіндексованого" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "Видалити частину різниці з проіндексованого" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "Видалити виділене з проіндексованого" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "Видалити виділені рядки з проіндексованого" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "Видалення з проіндексованого: %s" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "Не відслідковувати виділене" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "Не відслідковується" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "Видалення зі списку файлів, що відслідковуються: %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "Оновити існуючу гілку:" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "" #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "Оновлення" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "Ім'я користувача" #: cola/widgets/about.py:89 msgid "Version" msgstr "Версія" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "Вигляд" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "Переглянути історію..." #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "Подивитись історію для вибраних шляхів" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "Відобразити" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "Відобразити всі гілки..." #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "Відобразити поточну гілку..." #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "Визначає, чи піписувати теґ (git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "Хочете проіндексувати та закомітувати всі змінені файли?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "Ви знаходитесь в процесі злиття.\n" "Не можна робити зміни під час злиття." #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "Не можна робити переміщення (rebase), якщо є незакомітовані зміни." #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "Ви маєте вказати ревізію для злиття." #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "Ви маєте вказати ревізію для перегляду." #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "Приблизити" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "Віддалити" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "Допасувати за розміром" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "аргументи командного рядка" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "код завершення %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "критично: \"%s\" не є каталогом. Будь ласка, вкажіть коректний --repo <шлях>." #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "версія git cola %s" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "Різниця git-cola" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "шукати в результатах..." #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "vX.Y.Z" #: cola/hidpi.py:43 msgid "x 1" msgstr "" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "" #: cola/hidpi.py:46 msgid "x 2" msgstr "" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "рррр-ММ-дд" #~ msgid "\"%s\" returned exit status %d" #~ msgstr "\"%s\" завершилась з кодом %d" #~ msgid "\"git commit\" returned exit code %s" #~ msgstr "команда \"git commit\" поверула код виходу %s" #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "Сховок з назвою \"%s\" вже існує" #~ msgid "Already up-to-date." #~ msgstr "Вже оновлено." #~ msgid "Commit failed: %s" #~ msgstr "Не вдалось створити коміт: %s" #~ msgid "Created commit: %s" #~ msgstr "Створено коміт: %s" #~ msgid "Delete selected branch?" #~ msgstr "Видалити виділену гілку?" #~ msgid "Error %s" #~ msgstr "Помилка %s" #~ msgid "Error: Stash exists" #~ msgstr "Помилка: сховок вже існує" #~ msgid "Errors: %s" #~ msgstr "Помилки: %s" #~ msgid "Exit code: %s" #~ msgstr "Код завершення: %s" #~ msgid "GPG-signed" #~ msgstr "Підписане GPG" #~ msgid "" #~ "Output:\n" #~ "%s" #~ msgstr "" #~ "Вивід:\n" #~ "%s" #~ msgid "Output: %s" #~ msgstr "Вивід: %s" #~ msgid "PATCH %(current)d/%(count)d" #~ msgstr "Латка %(current)d/%(count)d" #~ msgid "Rename remote?" #~ msgstr "Перейменувати віддалений репозиторій?" #~ msgid "Reset Branch Head" #~ msgstr "Скинути HEAD гілки" #, fuzzy #~ msgid "Reset Hard" #~ msgstr "Скинути HEAD гілки" #, fuzzy #~ msgid "Reset Merge" #~ msgstr "Ревізія для злиття" #, fuzzy #~ msgid "Reset Soft" #~ msgstr "Скинути робоче дерево" #~ msgid "Reset Worktree" #~ msgstr "Скинути робоче дерево" #, fuzzy #~ msgid "Reset hard?" #~ msgstr "Скинути гілку?" #, fuzzy #~ msgid "Reset merge?" #~ msgstr "Скинути робоче дерево?" #, fuzzy #~ msgid "Reset soft?" #~ msgstr "Скинути робоче дерево?" #~ msgid "Reset worktree?" #~ msgstr "Скинути робоче дерево?" #~ msgid "Select File" #~ msgstr "Вибрати файл" #~ msgid "Select Repository..." #~ msgstr "Вибрати репозиторій..." #~ msgid "Select file from \"%s\"" #~ msgstr "Вибрати файл з \"%s\"" #~ msgid "Select manually..." #~ msgstr "Вибрати вручну..." #, fuzzy #~ msgid "Show Details..." #~ msgstr "Видалити файли..." #~ msgid "Summary:" #~ msgstr "Підсумок:" #, fuzzy #~ msgid "The branch will be reset using \"git reset --hard %s\"" #~ msgstr "Глку буде скинуто, використовуючи \"git reset --mixed %s\"" #, fuzzy #~ msgid "The branch will be reset using \"git reset --merge %s\"" #~ msgstr "Глку буде скинуто, використовуючи \"git reset --mixed %s\"" #, fuzzy #~ msgid "The worktree will be reset using \"git reset --keep %s\"" #~ msgstr "Робче дерево буде скинуто, використовуючи \"git reset --merge %s\"" #~ msgid "git clone returned exit code %s" #~ msgstr "git clone завершилась з кодом %s" #~ msgid "git tag returned exit code %s" #~ msgstr "команда git tag завершилась з кодом %s" #~ msgid "unknown" #~ msgstr "невідомий" git-cola-4.6.1/cola/i18n/zh_CN.po000066400000000000000000003636361457126473700163200ustar00rootroot00000000000000# Translation of git-cola to Chinese # Copyright (C) 2007, 2008 Shawn Pearce # This file is distributed under the same license as the git-cola package. # Xudong Guan , 2007. # Eric Miao , 2008. # ZH , 2014-2015. # # Please use the following translation throughout the file for consistence: # # repository 版本库 # commit 提交 # revision 版本 # branch 分支 # tag 标签 # annotation 标注 # merge 合并 # fast forward 快进合并 # stage 缓存 (译自 index/cache) # amend 修正 # reset 复位 # checkout 签出 # cherry-pick 挑取 # # Refer to 术语表 / Git Community Book 中文版 # http://gitbook.liuhui998.com/7_8.html # msgid "" msgstr "" "Project-Id-Version: git-cola VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: \n" "PO-Revision-Date: 2019-04-22 00:10+0300\n" "Last-Translator: Guo Yunhe \n" "Language-Team: Chinese\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Language: zh_CN\n" "X-Source-Language: C\n" "X-Generator: Poedit 2.2.1\n" #: cola/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " 拖放或使用 添加 按钮\n" " 将补丁加入列表\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 #, fuzzy msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" "\n" "键盘快捷键\n" "------------------\n" "J, 向上 = 下移\n" "K, 向下 = 上移\n" "Enter = 编辑所选文件\n" "Spacebar = 使用默认程序打开文件\n" "Ctrl+L = 聚焦于文本输入区\n" "? = 显示帮助\n" "\n" "在文本输入区和结果区之间\n" "使用向上/向下键以切换聚焦\n" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr " - 历史视图" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr " 个提交之前" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "已从远程 \"%(remote)s\" 删除分支 \"%(branch)s\"." #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "\"%(command)s\" 命令返回状态 \"%(status)d\"" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "\"%(command)s\" 命令返回状态 %(status)d" #: cola/guicmds.py:156 #, fuzzy, python-format msgid "\"%s\" already exists" msgstr "分支 '%s' 已经存在." #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "\"%s\" 已经存在, 程序会新建文件夹" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "\"%s\" 需要选择一个文件." #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s: %(branch)s - 浏览器" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "%(project)s: %(ref)s - 历史视图" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "%d 天前" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "%d 小时前" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "%d 分钟前" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "已应用 %d 个补丁." #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d 已跳过" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "%s 不是 Git 版本库。" #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "%s 会将被从书签中移除。" #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "%s 将从最近使用的版本库列表中被移除。" #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s: 此文件或文件夹不存在." #: cola/widgets/main.py:748 msgid "&Edit" msgstr "编辑" #: cola/widgets/main.py:690 msgid "&File" msgstr "文件" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(正在修正)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "*** 分支点 ***" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** 沙盒 ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "100%" #: cola/widgets/diff.py:817 msgid "200%" msgstr "200%" #: cola/widgets/diff.py:814 msgid "25%" msgstr "25%" #: cola/widgets/diff.py:818 msgid "400%" msgstr "400%" #: cola/widgets/diff.py:815 msgid "50%" msgstr "50%" #: cola/widgets/diff.py:819 msgid "800%" msgstr "800%" #: cola/widgets/finder.py:118 msgid " ..." msgstr "<路径> ..." #: cola/cmds.py:1685 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 "" "提交模板未创建.\n" "使用 \"git config\" 定义 \"commit template\"\n" "而指定一个提交模板." #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "钩子必须位于 \"%s\"" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "中止" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "中止操作" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "中止合并" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "中止合并..." #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "终止此操作?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "中止当前的合并会丢失所有未提交的修改.\n" "将无法恢复未提交的修改." #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "终止当前合并吗?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "关于" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "关于 git-cola" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "接受" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "接受变更并衍合\n" "快捷键:Ctrl+Enter" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "操作名称" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "操作" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "操作..." #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "添加" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "添加收藏" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "添加远程" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "添加分隔符" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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 "" "用左边的添加(+)和删除(-)按钮\n" "来添加或移除远程版本库\n" "\n" "从列表中选定可为远程改名\n" "完成后按回车键或直接双击." #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "添加新远程版本库" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "添加补丁 (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "添加远程" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "添加至 .gitignore" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "添加至 Git Annex" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "添加至 Git LFS" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "添加内容" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "高级" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "修改时间" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "全部版本库" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "启用时总是在合并时创建一个提交,即使是快进合并方式" #: cola/cmds.py:220 msgid "Amend" msgstr "修正" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "修正提交" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "修正上次提交" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "修正已发布的提交吗?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "修正中" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "操作正在进行中.\n" "若终止有可能造成数据损失." #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "一个无签名的轻量标签会取而代之.\n" "创建无签名标签吗?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "外观" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "应用" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "应用补丁" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "应用补丁..." #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "应用并丢弃所选暂存 (git stash pop)" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "应用所选暂存" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "参数" #: cola/qtutils.py:886 msgid "Attach" msgstr "结合" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "作者" #: cola/widgets/about.py:90 msgid "Authors" msgstr "作者" #: cola/hidpi.py:41 msgid "Auto" msgstr "自动" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "自动换行" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "基本正则表达式" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "问责查看器" #: cola/widgets/browse.py:206 #, fuzzy msgid "Blame selected paths" msgstr "编辑所选路径" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "问责..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "暗色背景粗体字体而斜体头部" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "分支" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "远程 \"%(remote)s\" 不存在分支 \"%(branch)s\".\n" "一个新的远程分支会被建立." #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "分支 '%s' 已经存在." #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "分支差异查看器" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "分支已存在" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "分支名" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "分支: %s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "分支" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "分支..." #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "巴西语翻译" #: cola/guicmds.py:52 msgid "Browse" msgstr "浏览" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "浏览提交..." #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "浏览当前分支上的文件..." #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "浏览其他分支..." #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "浏览..." #: cola/widgets/main.py:87 msgid "Browser" msgstr "浏览器" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "浏览 %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "跳过提交钩子" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "取消" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "取消衍合\n" "快捷键: Ctrl+Q" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "无法修正" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "无法执行 \"%s\": 请配置问责查看器" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "无法执行 \"%s\": 请配置历史浏览器" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "无法执行 \"%s\": 请配置编辑器" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "上游已更改" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "检查拼写" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "检查拼写" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "签出" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "在创建后签出" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "签出分支" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "签出分离的 HEAD" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "签出为新分支" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "签出..." #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "挑取(Cherry Pick)" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "挑取(Cherry-Pick)提交" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "挑取(Cherry-Pick)..." #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "选择路径" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "选择 \"git grep\" 正则表达式模式" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "清除默认版本库" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "清除提交信息" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "清除提交消息吗?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "清除..." #: cola/widgets/clone.py:124 msgid "Clone" msgstr "克隆" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "克隆已有版本库" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "克隆(clone)..." #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "克隆位于 %s 的已有版本库" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "关闭" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "关闭..." #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "全部合起" #: cola/sequenceeditor.py:371 msgid "Command" msgstr "命令" #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "提交" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "克隆失败" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "提交已缓存修改" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "提交已缓存变更\n" "快捷键: Ctrl+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "提交概要" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "若合并无冲突即可提交.取消勾选以保持此合并操作的未提交状态" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "提交@@verb" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "比较" #: cola/difftool.py:102 msgid "Compare All" msgstr "比较全部" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "配置工具栏" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "将远程分支设为新的上游" #: cola/widgets/main.py:169 msgid "Console" msgstr "控制台" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "继续" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "复制" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "复制基名到剪贴板" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "复制前导路径到剪贴板" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "复制路径到剪贴板" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "复制相对路径到剪贴板" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "复制 SHA-1" #: cola/widgets/status.py:738 #, fuzzy msgid "Copy..." msgstr "复制" #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "无法解析 URL \"%s\"" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "创建分支" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "创建补丁" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "创建远程分支" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "创建带签名提交: %s" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "创建标签" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "新建标签..." #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "创建无签名标签" #: cola/widgets/remote.py:192 #, fuzzy msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "启用时总是在合并时创建一个提交,即使是快进合并方式" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "创建远程分支吗?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "新建..." #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "创建了名为“%s”的新标签" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "当前版本库" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "自定义复制操作" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "自定义..." #: cola/widgets/main.py:754 msgid "Cut" msgstr "剪切" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "捷克语翻译" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "历史视图..." #: cola/icons.py:54 msgid "Dark Theme" msgstr "" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "日期, 时间" #: cola/icons.py:53 cola/themes.py:643 msgid "Default" msgstr "默认" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "删除" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "删除 %d 个文件吗?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "删除书签" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "删除书签吗?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "删除分支" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "删除文件" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "删除文件..." #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "删除文件吗?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "删除远程" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "删除远程分支" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "删除远程分支..." #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "删除工具栏" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "删除远程" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "删除远程 \"%s\"" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "删除远程吗?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "删除..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "删除 \"%s\" 失败" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "删除内容" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "分离" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "检测冲突标记" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "在未合并文件中检测冲突标记" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "开发者" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "差异比较" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "与之前提交比较差异..." #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "差异选项" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "差异比较工具" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "所选文件 -> 此文件 比较差异" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "此文件 -> 所选文件 比较差异" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "差异统计" #: cola/difftool.py:324 msgid "Difftool" msgstr "差异工具" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "目录已存在" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "显示未跟踪文件" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "帮助文档" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "丢弃" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "丢弃暂存" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "丢弃暂存吗?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "丢弃暂存 \"%s\" 吗?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "丢弃所选暂存" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 msgid "Edit" msgstr "编辑" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "编辑衍合" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "编辑远程" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "编辑远程..." #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "从列表中选择远程进行编辑" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "编辑所选路径" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "编辑..." #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "编辑器" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "电子邮件地址" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "电子邮件贡献者" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "已启用" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "输入新分支名" #: cola/guicmds.py:146 #, fuzzy msgid "Enter a name for the new bare repo" msgstr "为暂存输入名称" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "为暂存输入名称" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "错误" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "克隆出错" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "创建分支出错" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "创建版本库出错" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "删除远程分支出错" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "编辑文件出错" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "启动问责查看器出错" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "启动历史浏览器出错" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "创建远程 \"%s\" 出错" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "创建暂存出错" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "删除远程 \"%s\" 出错" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "重命名 \"%(name)s\" 为 \"%(new_name)s\" 出错" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "运行 prepare-commitmsg 钩子出错" #: cola/cmds.py:2987 cola/cmds.py:3033 #, python-format msgid "Error updating submodule %s" msgstr "更新子模块 \"%s\" 出错" #: cola/cmds.py:3069 msgid "Error updating submodules" msgstr "更新子模块出错" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "错误: 无法找到提交模板" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "错误: 未配置提交模板" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "错误: 无法克隆 \"%s\"" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "错误: 无法创建标签 \"%s\"" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "执行动作 %s" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "全部展开" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "导出补丁" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "导出补丁..." #: cola/widgets/main.py:547 msgid "Expression..." msgstr "表达式..." #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "拓展正则表达式" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "拓展描述..." #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "仅快速合并" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "仅快速合并" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "版本库收藏夹" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "收藏夹" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "获取" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "获取跟踪分支" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "获取..." #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "文件浏览器..." #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "文件差异" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "文件已保存" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "文件保存为 \"%s\"" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "监视文件系统更改:已禁用,因为 cola.notify 选项设置为 false。\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "监视文件系统更改:已开启。\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "文件名" #: cola/widgets/dag.py:821 msgid "Files" msgstr "文件" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "过滤分支..." #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "对路径进行过滤..." #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "查找文件" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "特定字符串" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "等宽字体" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "修正" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "修正前一次提交" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "扁平深蓝" #: cola/themes.py:705 msgid "Flat dark green" msgstr "扁平深绿" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "扁平深灰" #: cola/themes.py:691 msgid "Flat dark red" msgstr "扁平深红" #: cola/themes.py:656 msgid "Flat light blue" msgstr "扁平浅蓝" #: cola/themes.py:677 msgid "Flat light green" msgstr "扁平浅绿" #: cola/themes.py:670 msgid "Flat light grey" msgstr "扁平浅灰" #: cola/themes.py:663 msgid "Flat light red" msgstr "扁平浅红" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "字体大小" #: cola/widgets/remote.py:197 msgid "Force" msgstr "强制" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "强制获取" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "强制获取?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "强制推送" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "强制推送吗?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "强制获取从 %s 吗?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "强制推送到 %s 吗?" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "格式化字符串" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "法语翻译" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "GPG 签名合并提交" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "界面主题" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "为 \"%s\" 收集信息..." #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "德语翻译" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "取得提交信息模板" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "下一项" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "上一项" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "抓取文件..." #: cola/widgets/dag.py:848 msgid "Graph" msgstr "图示" #: cola/widgets/main.py:354 msgid "Grep" msgstr "筛选 (grep)" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "最近有衍合或拉取操作吗?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "帮助" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "帮助 - 自定义复制操作" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "帮助 - 查找文件" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "帮助 - git-cola-sequence-editor" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "高分辨率" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "历史浏览器" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "匈牙利语翻译" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "忽略所有空格" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "忽略空格数量" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "行尾忽略空格" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "忽略自定义模式" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "忽略精确文件名" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "忽略文件名或匹配模式" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "" #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "包含标签 " #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "缩进状态路径" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "印尼语翻译" #: cola/widgets/main.py:657 #, fuzzy msgid "Initialize Git Annex" msgstr "初始化..." #: cola/widgets/main.py:661 #, fuzzy msgid "Initialize Git LFS" msgstr "初始化..." #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "初始化子模块" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "插入空格而非制表符" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "交互式衍合" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "无效版本" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "保留合并备份 (*.orig)" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "保留索引" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "键盘快捷键" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "启动差异工具" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "启动目录差异工具" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "启动编辑器" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "启动终端" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" "加载外部差异工具\n" "快捷键: Ctrl+D" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "启动 git-cola" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "对之前的版本启动 git-difftool" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "在当前路径运行 git-difftool" #: cola/icons.py:55 msgid "Light Theme" msgstr "" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "加载提交消息" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "加载提交信息..." #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "加载前一次提交信息" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "加载中..." #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "本地" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "本地分支" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "本地分支" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "锁定布局" #: cola/widgets/dag.py:816 msgid "Log" msgstr "记录" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "维护者 (从 2007 年开始) 和开发者" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "合并" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "合并 \"%(revision)s\" 到分支 \"%(branch)s\"" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "合并工具" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "合并冗余度" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "合并失败. 需要解决冲突." #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "合并到 \"%s\"" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "合并到当前分支" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "合并 (merge)..." #: cola/widgets/main.py:1177 msgid "Merging" msgstr "合并中" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "消息" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "提交信息不存在" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "数据不存在" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "名称不存在" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "版本不存在" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "标签信息不存在" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "已修改" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "更多..." #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "下移" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "上移" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "移动文件到回收站" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "名称" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "新远程的名称" #: cola/guicmds.py:147 cola/widgets/main.py:281 msgid "New Bare Repository..." msgstr "新建空版本库..." #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "新建版本库..." #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "添加工具栏" #: cola/widgets/startup.py:52 msgid "New..." msgstr "新建..." #: cola/actions.py:56 msgid "Next File" msgstr "下一个文件" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "号码" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "没有指定版本" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "没有需要提交的改动.\n" "\n" "提交前你必须首先缓存至少一个文件." #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "此分支内没有提交." #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "不进行快速合并" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "不进行快速合并" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "没有选择版本库." #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "非快进合并式获取会覆盖本地历史!" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "非快进合并式上传会覆盖远程历史!\n" "(之前拉取了吗?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "没有改动可提交" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "不做操作" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "Diff 上下文行数" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "打开" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "打开已有版本库" #: cola/widgets/submodules.py:48 msgid "Open Parent" msgstr "打开父级" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "打开上级目录" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "打开最近版本库" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "用默认程序打开" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "新窗口打开" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "在新窗口打开..." #: cola/widgets/main.py:410 msgid "Open..." msgstr "打开..." #: cola/widgets/branch.py:354 msgid "Other branches" msgstr "其他分支" #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "覆盖" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "覆盖 \"%s\" 吗?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "覆盖文件吗?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "用 Shell 解析参数\n" "若命令行条目包含空格, 请添加双引号." #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "部分已缓存" #: cola/widgets/main.py:758 msgid "Paste" msgstr "粘贴" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "已应用补丁" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "路径" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "克隆路径或 URL (可以使用环境变量)" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "像素异或" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "请同时提供分支名称和版本表达式." #: cola/cmds.py:2297 msgid "Please select a file" msgstr "请选择一个文件" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "请为新标签指定名称." #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "请指定一个版本进行标记." #: cola/widgets/commitmsg.py:417 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/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "波兰语翻译" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "弹出" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "首选项" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "前缀" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "准备提交信息" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "" #: cola/actions.py:65 msgid "Previous File" msgstr "上一个文件" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "在创建时提醒" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "推送创建远程分支时提醒" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "从..清除(prune) " #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "拉取" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "拉取..." #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "推送" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "上传..." #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "退出" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "衍合" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "衍合到 %s" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "衍合已停止" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "衍合当前分支而不是合并" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "衍合中" #: cola/widgets/main.py:118 msgid "Recent" msgstr "最近" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "最近使用版本库" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "最近使用版本库数目" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "最近修改过的文件" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "最近修改过的文件 ..." #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "已丢弃的暂存是无法恢复的." #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "恢复丢失的提交是比较困难的." #: cola/widgets/main.py:751 msgid "Redo" msgstr "重做" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "尽量减少提交历史" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "刷新" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "远程(remote)" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "远程分支" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "远程分支已删除" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "远程版本库 - 双击以改名" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "移除" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "将 %s 从最近使用列表中移除吗?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "移除元素" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "移除所选 (删除)" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "重命名" #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "重命名 \"%s\"" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "重命名分支" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "重命名分支..." #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "重命名已有分支" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "重命名远程" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "重命名版本库" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "重命名分支" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "重命名远程 \"%(current)s\" 为 \"%(new)s\"?" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "重命名所选路径" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "版本库: %s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "复位" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "复位分支 \"%(branch)s\" 到 \"%(revision)s\" 吗?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "重置分支" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "重置分支吗?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "复位 \"%(branch)s\" to \"%(revision)s\" 将丢失提交." #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "撤销" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "撤销差异区域" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "撤销差异区域..." #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "撤销差异区域吗?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "撤销所选行" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "撤销所选行..." #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "撤销所选行吗?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "撤销未提交的修改" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "撤销未提交的修改吗?" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "撤销未缓存修订..." #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "恢复未缓存的改动" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "恢复未缓存的改动?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "恢复未缓存修订..." #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "撤销未提交的修改吗?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "恢复这个未缓存的改动?" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "撤销所选路径未提交的改动" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "撤销所选路径未缓存的改动" #: cola/guicmds.py:320 msgid "Review" msgstr "审阅" #: cola/widgets/main.py:597 msgid "Review..." msgstr "审阅..." #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "版本" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "版本表达式:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "要合并的版本" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "改写" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "重写已发布的提交吗?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "运行" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "运行 \"%s\"?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "运行 %s?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "运行 \"%s\" 命令吗?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "正运行命令:%s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "俄语翻译" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "SHA-1" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "安全模式" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "保存" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "保存归档" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "存为压缩存档 Tar/Zip..." #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "保存界面设定" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "进行暂存" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "保存修改状态到新暂存" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "已从 \"%(ref)s\" 保存 \"%(filename)s\" 到 \"%(destination)s\"" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "搜寻" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "查找作者" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "查找提交信息" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "查找提交者" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "查找日期范围" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "查找差异" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "按表达式查找" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "按路径查找" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "用特定字符串查找" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "使用 POSIX 基本正则表达式查找" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "使用 POSIX 拓展正则表达式查找" #: cola/widgets/main.py:507 msgid "Search..." msgstr "查找..." #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "选择" #: cola/widgets/main.py:764 msgid "Select All" msgstr "全选" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "选择分支进行审阅" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "选择子项目" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "选择提交" #: cola/guicmds.py:136 msgid "Select Directory..." msgstr "选择目录..." #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "选择上游项目" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "选择最新子项目" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "选择最旧父项目" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "选择父项目" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "选择之前版本" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "为新克隆选择上级文件夹" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "选择输出目录" #: cola/widgets/selectcommits.py:182 #, fuzzy msgid "Select output directory" msgstr "选择版本库..." #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "选择补丁文件..." #: cola/widgets/editremotes.py:434 #, fuzzy msgid "Select repository" msgstr "选择版本库..." #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "选择默认版本库" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "设置上游分支" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "设置上游" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "设置" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "Shell 参数" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "Shift 上箭" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "Shift 下键" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "快捷键" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "在合并后显示 Diffstat" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "在窗口标题中显示完整路径" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "显示帮助" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "显示历史" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "在状态标题中显示文件计数" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "显示帮助\n" "快捷键: ?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "显示行号" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "显示包含修改的整个函数" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "显示改动自" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "并排" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "签名(Sign Off)" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "为标签签名" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "对本次提交签名" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "简体中文翻译" #: cola/cmds.py:2527 msgid "Skip" msgstr "跳过" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "跳过当前补丁" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "按字母顺序排列书签" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "西班牙语翻译" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "指定标签的 SHA-1 值" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "指定标签信息" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "指定标签名称" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "拼写建议" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "压缩" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "压缩合并中提交成单一提交" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "缓存" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "缓存 / 取消缓存" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "缓存差异区域" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "缓存已修改的文件" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "缓存已选项目" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "缓存所选行" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "缓存未合并的文件" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "缓存未跟踪的文件" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "缓存并提交" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "缓存并提交吗?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "缓存冲突" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "缓存冲突?" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "缓存/取消缓存已选路径以提交" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "已缓存" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "正在缓存: %s" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "开始交互式衍合..." #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "起始版本" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "暂存" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "暂存索引" #: cola/widgets/stash.py:79 #, fuzzy msgid "Stash staged changes only" msgstr "提交已缓存修改" #: cola/widgets/stash.py:75 #, fuzzy msgid "Stash unstaged changes only, keeping staged changes" msgstr "撤销所选路径未缓存的改动" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "暂存..." #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "状态" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "停止跟踪路径" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "子模块" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "概述合并提交" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "概要" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Tab 宽度" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "标签" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "标签已创建" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "标签信息..." #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "标签需要签名但其内容为空." #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "标签" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "字符宽度" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "分支已不可用。" #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "提交消息会被清除。" #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "文件 \"%s\" 已存在,将被覆盖." #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "如下文件会被删除:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "版本表达式不能为空." #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "此操作无法恢复. 清空提交消息吗?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "此提交已发布.\n" "此操作会重写同步历史.\n" "很可能这不是你的心意." #: cola/widgets/diff.py:1232 #, fuzzy msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "此操作将丢弃未提交的修改.\n" "造成的改动将无法撤销." #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "此操作将丢弃未提交的修改.\n" "造成的改动将无法撤销." #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "这个操作会留下未缓存的改动.\n" "这些改动将无法恢复." #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "此版本库正在衍合中.\n" "解决内容冲突, 提交更改, 并执行\n" " 衍合 > 继续" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "此版本库正在合并中.\n" "解决内容冲突并提交更改." #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "切换已启用" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "切换分支过滤器" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "切换路径过滤器开关" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "正跟踪分支" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "跟踪分支" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "繁体中文 (台湾) 翻译" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "翻译者" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "土耳其语翻译" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "URL: %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "乌克兰语翻译" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "无法进行衍合" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "撤销" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "未合并" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "取消缓存" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "全部取消缓存" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "取消缓存差异区域" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "取消缓存已选项目" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "取消缓存所选行(&S)" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "正取消缓存: %s" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "取消跟踪所选项目" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "未跟踪" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "跟踪: %s" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "更新所有子模块..." #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "更新已有分支:" #: cola/cmds.py:3019 msgid "Update Submodule" msgstr "更新子模块" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "更新子模块..." #: cola/cmds.py:3055 msgid "Update Submodules" msgstr "更新子模块" #: cola/cmds.py:3053 msgid "Update all submodules?" msgstr "更新所有子模块?" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 msgid "Update submodules..." msgstr "更新子模块..." #: cola/widgets/status.py:953 msgid "Update this submodule" msgstr "更新此子模块" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "更新此子模块?" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "更新" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "用户名" #: cola/widgets/about.py:89 msgid "Version" msgstr "版本" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "视图" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "查看历史..." #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "查看所选路径历史" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "图示" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "图示所有分支的历史..." #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "图示当前分支的历史..." #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "是否为标签签名 (git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "要缓存并提交所有已修改文件吗?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "异或" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "是" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "合并正在进行中.\n" "在合并过程中无法修正." #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "有未提交修改时无法衍合。" #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "指定一个版本进行合并." #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "指定一个版本进行查看." #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "放大" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "缩小" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "缩放到适合" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "命令行参数" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "错误: 无法执行 git" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "退出代码 %s" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "致命错误: \"%s\" 不是有效目录. 请用 --repo <路径> 指定." #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "git cola 版本 %s" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "git-cola 比较差异" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "筛选结果..." #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "hotkeys_zh_CN.html" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "vX.Y.Z" #: cola/hidpi.py:43 msgid "x 1" msgstr "x 1" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "x 1.5" #: cola/hidpi.py:46 msgid "x 2" msgstr "x 2" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "yyyy-MM-dd" #~ 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 "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "这是由 Cygwin 发布的 Tcl 代码中一个\n" #~ "已知问题所引起." #, fuzzy #~ msgid "\"%s\" returned exit status %d" #~ msgstr "\"%(command)s\" 命令返回状态 %(status)d" #~ msgid "\"git commit\" returned exit code %s" #~ msgstr "\"git commit\" 命令返回状态 %s" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%s ... %*i of %*i %s (%3i%%)" #~ msgid "%s Repository" #~ msgstr "%s 版本库" #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "'%s'不是一个可接受的分支名." #~ msgid "* Binary file (not showing content)." #~ msgstr "* 二进制文件 (不显示内容)." #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "'合并到' 需要指定某个分支" #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "名为 \"%s\" 的暂存已存在" #~ msgid "Abort completed. Ready." #~ msgstr "中止完成. 就绪." #~ msgid "Abort failed." #~ msgstr "中止失败" #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "中止 '%s' 的 checkout 操作 (需要做文件级合并)." #~ msgid "Already up-to-date." #~ msgstr "已为最新版本." #~ msgid "Always (Do not perform merge checks)" #~ msgstr "总是合并 (不作合并检查)" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "总是合并 (不作合并测试.)" #~ msgid "Amended Commit Message:" #~ msgstr "修正的提交描述:" #~ msgid "Amended Initial Commit Message:" #~ msgstr "修正的初始提交描述:" #~ msgid "Amended Merge Commit Message:" #~ msgstr "修正的合并提交描述:" #~ msgid "Annotation complete." #~ msgstr "标注完成." #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "任何未缓存的改动将在这次撤销中永久丢失." #~ msgid "Apply Diff Selection to Work Tree" #~ msgstr "应用所选差异到工作目录" #~ msgid "Apply/Reverse Hunk" #~ msgstr "应用/撤消此修改块" #~ msgid "Arbitrary URL:" #~ msgstr "任意 URL:" #~ msgid "Bookmarks" #~ msgstr "书签" #~ msgid "Bookmarks..." #~ msgstr "书签..." #~ 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 "Branch '%s' does not exist." #~ msgstr "分支 '%s' 并不存在." #~ msgid "Branch created" #~ msgstr "分支名" #~ msgid "Browse %s's Files" #~ msgstr "浏览 %s 上的文件" #~ msgid "Browse Branch Files" #~ msgstr "浏览分支文件" #~ msgid "Browse Revision..." #~ msgstr "版本" #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\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 "Cannot determine HEAD. See console output for details." #~ msgstr "无法确定 HEAD. 请查看控制终端的输出." #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "无法获取分支和对象. 请查看控制终端的输出." #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "无法获取标签. 请查看控制终端的输出." #~ msgid "Cannot find git in PATH." #~ msgstr "PATH 中没有找到 git" #~ 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 "Cannot move to top of working directory:" #~ msgstr "无法移动到工作根目录:" #~ msgid "Cannot parse Git version string:" #~ msgstr "无法解析 Git 的版本信息:" #~ msgid "Cannot resolve %s as a commit." #~ msgstr "无法解析 %s 为提交." #~ msgid "Cannot use funny .git directory:" #~ msgstr "无法使用 .git 目录:" #~ msgid "Cannot write shortcut:" #~ msgstr "无法修改快捷方式:" #~ msgid "Change Font" #~ msgstr "更改字体" #~ msgid "Checked out '%s'." #~ msgstr "'%s' 已被 checkout" #~ msgid "Clone Type:" #~ msgstr "克隆类型:" #~ msgid "Clone failed." #~ msgstr "克隆失败." #~ msgid "Cloning from %s" #~ msgstr "从 %s 克隆" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "提交 %s 似乎已损坏" #~ msgid "Commit failed: %s" #~ msgstr "提交失败: %s" #~ msgid "Commit@@noun" #~ msgstr "提交(commit)" #~ msgid "Compress Database" #~ msgstr "压缩数据库" #~ msgid "Compressing the object database" #~ msgstr "压缩对象数据库" #~ msgid "Copied Or Moved Here By:" #~ msgstr "由复制或移动至此:" #~ msgid "Copying objects" #~ msgstr "复制 objects" #~ msgid "Counting objects" #~ msgstr "清点对象" #~ msgid "Create Desktop Icon" #~ msgstr "创建桌面图标" #~ msgid "Created commit: %s" #~ msgstr "创建了提交: %s" #~ msgid "Creating working directory" #~ msgstr "创建工作目录" #~ msgid "Current Branch:" #~ msgstr "当前分支:" #~ msgid "Database Statistics" #~ msgstr "数据库统计信息" #~ msgid "Decrease Font Size" #~ msgstr "缩小字体" #~ msgid "Delete Local Branch" #~ msgstr "删除本地分支" #~ msgid "Delete Only If" #~ msgstr "删除仅当" #~ msgid "Delete Only If Merged Into" #~ msgstr "仅在合并后删除" #~ msgid "Delete selected branch?" #~ msgstr "删除选中分支?" #~ msgid "Destination Repository" #~ msgstr "目标版本库" #~ msgid "Detach From Local Branch" #~ msgstr "从本地分支脱离" #~ msgid "Diff/Console Font" #~ msgstr "Diff/控制终端字体" #~ msgid "Directory %s already exists." #~ msgstr "目录 %s 已经存在." #~ msgid "Disk space used by loose objects" #~ msgstr "松散对象所使用的磁盘空间" #~ msgid "Disk space used by packed objects" #~ msgstr "压缩对象所使用的磁盘空间" #~ msgid "Do Nothing" #~ msgstr "不做操作" #~ msgid "Enter Git Repository" #~ msgstr "输入版本库" #, fuzzy #~ msgid "Error %s" #~ msgstr "错误: %s" #~ msgid "Error loading commit data for amend:" #~ msgstr "为修正装载提交数据出错:" #~ msgid "Error: Command Failed" #~ msgstr "错误: 命令失败" #~ msgid "Error: Stash exists" #~ msgstr "错误: 暂存已存在" #~ msgid "Errors: %s" #~ msgstr "错误: %s" #~ msgid "Exit code: %s" #~ msgstr "退出代码: %s" #~ msgid "Failed to completely save options:" #~ msgstr "无法完全保存选项:" #~ msgid "Failed to configure origin" #~ msgstr "无法配置 origin" #~ msgid "Failed to create repository %s:" #~ msgstr "无法创建版本库 %s:" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "无法删除分支:\n" #~ "%s" #~ msgid "Failed to open repository %s:" #~ msgstr "无法打开版本库 %s:" #~ msgid "Failed to rename '%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 "Failed to stage selected hunk." #~ msgstr "无法缓存所选代码段." #~ msgid "Failed to unstage selected hunk." #~ msgstr "无法将选择的代码段从缓存中删除." #~ msgid "Failed to update '%s'." #~ msgstr "无法更新 '%s'." #~ msgid "Fast Forward Only " #~ msgstr "仅快进合并" #~ msgid "Fetch from" #~ msgstr "从..获取(fetch)" #~ msgid "Fetching new changes from %s" #~ msgstr "从 %s 处获取新的改动" #~ msgid "File level merge required." #~ msgstr "需要文件级合并." #~ msgid "Font Example" #~ msgstr "字体样例" #~ msgid "Font Family" #~ msgstr "字体族" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "强制覆盖已有的分支 (可能会丢失改动)" #~ msgid "From Repository" #~ msgstr "从版本库" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "全部复制 (较慢, 做备份)" #~ msgid "GPG-signed" #~ msgstr "GPG 已签名" #~ msgid "Garbage files" #~ msgstr "垃圾文件" #~ msgid "Git Gui" #~ msgstr "Git Gui" #~ msgid "Git Repository (subproject)" #~ msgstr "Git 版本库 (子项目)" #~ msgid "Git directory not found:" #~ 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 "Hardlinks are unavailable. Falling back to copying." #~ msgstr "硬连接不可用. 使用复制." #~ msgid "Hide Details.." #~ msgstr "隐藏细节.." #~ msgid "In File:" #~ msgstr "在文件:" #~ msgid "Increase Font Size" #~ msgstr "放大字体" #~ msgid "Index" #~ msgstr "缓存(Index)错误" #~ msgid "Initial Commit Message:" #~ msgstr "初始的提交描述:" #~ msgid "Initial file checkout failed." #~ msgstr "初始的文件checkout失败" #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "无效的 GIT_COMMITTER_IDENT" #~ msgid "Invalid date from Git: %s" #~ msgstr "无效的日期: %s" #~ msgid "Invalid font specified in %s:" #~ msgstr "%s 中指定的字体无效:" #~ msgid "KiB" #~ msgstr "KiB" #~ 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 "" #~ "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 "" #~ "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 "Linking objects" #~ msgstr "链接 objects" #~ msgid "Loading annotation..." #~ msgstr "裝載标注..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "装载复制/移动跟踪标注..." #~ msgid "Loading original location annotations..." #~ msgstr "装载原始位置标注..." #~ msgid "Local Branches" #~ msgstr "本地分支" #~ msgid "Local Merge..." #~ msgstr "本地合并..." #~ msgid "Location %s already exists." #~ msgstr "位置 %s 已经存在." #~ msgid "Main Font" #~ msgstr "主要字体" #~ msgid "Match Tracking Branch Name" #~ msgstr "匹配跟踪分支名字" #~ msgid "Match Tracking Branches" #~ msgstr "匹配跟踪分支" #~ msgid "Merge completed successfully." #~ msgstr "合并成功完成." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "合并策略 '%s' 不支持." #~ msgid "Merged Into:" #~ msgstr "合并到" #~ msgid "Merging %s and %s..." #~ msgstr "合并 %s 和 %s" #~ msgid "Modified, not staged" #~ msgstr "修改但未缓存" #~ msgid "New Branch Name Template" #~ msgstr "新建分支命名模板" #~ msgid "New Commit" #~ msgstr "新建提交" #~ msgid "New Name:" #~ msgstr "新名字:" #~ 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 "No default branch obtained." #~ msgstr "没有获取缺省分支" #~ 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 "No files selected for checkout from HEAD." #~ msgstr "未选择从 HEAD 中签出的文件." #~ msgid "No working directory" #~ msgstr "没有工作目录" #~ msgid "Number of loose objects" #~ msgstr "松散对象的数量" #~ msgid "Number of packed objects" #~ msgstr "压缩对象数量" #~ msgid "Number of packs" #~ msgstr "压缩包数量" #~ msgid "On Debian-based systems try: sudo apt-get install python-pyinotify" #~ msgstr "若使用 Debian 系统, 请尝试如下命令: sudo apt-get install python-pyinotify" #~ 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 "Options" #~ msgstr "选项" #~ msgid "Original File:" #~ msgstr "原始文件:" #~ msgid "Originally By:" #~ msgstr "最初由:" #~ msgid "" #~ "Output:\n" #~ "%s" #~ msgstr "" #~ "输出:\n" #~ "%s" #~ msgid "Output: %s" #~ msgstr "输出: %s" #~ msgid "PATCH %(current)d/%(count)d" #~ msgstr "补丁 %(current)d/%(count)d" #~ msgid "Packed objects waiting for pruning" #~ msgstr "压缩对象等待清理" #~ msgid "Path to git repository" #~ msgstr "版本库路径" #~ msgid "Please select one or more branches to delete." #~ msgstr "请选择某个或多个分支来删除" #~ msgid "Please supply a branch name." #~ msgstr "请提供分支名字." #~ msgid "Portions staged for commit" #~ 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 "Preferences..." #~ msgstr "首选项..." #~ msgid "Process Diff Hunk" #~ msgstr "处理差异部分" #~ msgid "Process Selection" #~ msgstr "处理所选部分" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "获取时清除跟踪分支" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "清除" #~ msgid "Push Branches" #~ msgstr "上传分支" #~ msgid "Push to" #~ msgstr "上传到(push)" #~ msgid "Pushing %s %s to %s" #~ msgstr "上传 %s %s 到 %s" #~ msgid "Reading %s..." #~ msgstr "读取 %s..." #~ msgid "Ready to commit." #~ msgstr "缓存为提交" #~ msgid "Ready." #~ msgstr "就绪" #~ msgid "Rebase Branch" #~ msgstr "更改分支名:" #~ msgid "Rebase..." #~ msgstr "复位(Reset)..." #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "恢复被删除的分支非常困难.\n" #~ "\n" #~ "是否要删除所选分支?" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "恢复被删除的分支非常困难.\n" #~ "\n" #~ "是否要删除所选分支?" #~ msgid "Refreshing file status..." #~ msgstr "更新文件状态..." #, fuzzy #~ msgid "Remote Branches" #~ msgstr "远程分支" #~ msgid "Remote:" #~ msgstr "Remote:" #~ msgid "Remove selected paths from the staging area." #~ msgstr "从缓存区移除所选路径." #~ msgid "Rename remote?" #~ msgstr "重命名远程吗?" #~ msgid "Repository" #~ msgstr "版本库(repository)" #~ msgid "Requires merge resolution" #~ msgstr "需要解决合并冲突" #~ msgid "Rescan" #~ msgstr "重新扫描" #~ msgid "Reset Branch Head" #~ msgstr "复位分支头" #, fuzzy #~ msgid "Reset Hard" #~ msgstr "复位分支头" #, fuzzy #~ msgid "Reset Merge" #~ msgstr "要合并的版本" #, fuzzy #~ msgid "Reset Soft" #~ msgstr "重置工作树" #~ msgid "Reset Worktree" #~ msgstr "重置工作树" #~ 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 "Reset hard?" #~ msgstr "重置分支吗?" #, fuzzy #~ msgid "Reset merge?" #~ msgstr "要重置工作树吗?" #, fuzzy #~ msgid "Reset soft?" #~ msgstr "复位 '%s'?" #~ msgid "Reset worktree?" #~ msgstr "要重置工作树吗?" #~ msgid "Revert Uncommitted Changes..." #~ msgstr "撤销未提交修改..." #~ msgid "Revert changes in these %i files?" #~ msgstr "撤销这些 (%i个) 文件的改动?" #~ msgid "Select File" #~ msgstr "选择文件" #~ msgid "Select Repository..." #~ msgstr "选择版本库..." #~ msgid "Select file from \"%s\"" #~ msgstr "从“%s”中选择文件" #~ msgid "Select manually..." #~ msgstr "手动选择..." #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "共享方式 (最快, 不推荐, 不做备份)" #~ msgid "Shared only available for local repository." #~ msgstr "共享方式仅当是本地版本库时有效." #~ msgid "Show Details..." #~ msgstr "显示细节..." #~ msgid "Show Less Context" #~ msgstr "显示更少上下文" #~ msgid "Show More Context" #~ msgstr "显示更多上下文" #~ msgid "Show icon? (if available)" #~ msgstr "显示图标?(如果可用)" #~ msgid "Source Branches" #~ msgstr "源端分支:" #~ msgid "Stage Hunk For Commit" #~ msgstr "缓存修改块为提交" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "已缓存的改动 (将被提交)" #~ msgid "Staged for commit, missing" #~ msgstr "缓存为提交, 不存在" #~ msgid "Staged for removal" #~ msgstr "缓存为删除" #~ msgid "Staged for removal, still present" #~ msgstr "缓存为删除, 但仍存在" #~ msgid "Staging Area" #~ msgstr "缓存区" #~ msgid "Staging area (index) is already locked." #~ msgstr "缓存区域 (index) 已被锁定." #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "标准方式 (快速, 部分备份, 作硬连接)" #~ msgid "Standard only available for local repository." #~ msgstr "标准方式仅当是本地版本库时有效." #~ msgid "Starting gitk... please wait..." #~ msgstr "启动 gitk... 请等待..." #~ msgid "Staying on branch '%s'." #~ msgstr "停留在分支 '%s'." #~ msgid "Success" #~ msgstr "成功" #~ msgid "Summary:" #~ msgstr "概要:" #~ msgid "The 'main' branch has not been initialized." #~ msgstr "'main'分支尚未初始化." #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "下列分支没有完全被合并到 %s:" #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "下列分支没有被全部合并到 %s 中:\n" #~ "\n" #~ " - %s" #~ 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 "This Detached Checkout" #~ msgstr "该脱节的Checkout" #~ msgid "" #~ "This PyQt4 does not include QtWebKit.\n" #~ "The keyboard shortcuts feature is unavailable." #~ msgstr "" #~ "此程序使用的 PyQt4 不包含 QtWebkit 模块.\n" #~ "键盘快捷键功能不可用." #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "这是样例文本.\n" #~ "如果你喜欢, 你可以设置该字体." #~ 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 "Tracking branch %s is not a branch in the remote repository." #~ msgstr "跟踪分支 %s 并不是远程版本库中的一个分支" #~ msgid "Transfer Options" #~ msgstr "传输选项" #~ msgid "Unable to copy object: %s" #~ msgstr "无法复制 object: %s" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "无法复制 objects/info/alternates: %s" #~ msgid "Unable to display %s" #~ msgstr "无法显示 %s" #~ msgid "Unable to hardlink object: %s" #~ msgstr "无法硬链接 object: %s" #~ msgid "Unable to obtain your identity:" #~ msgstr "无法获知你的身份:" #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "无法启动 gitk:\n" #~ "\n" #~ "%s 不存在" #~ msgid "Unable to unlock the index." #~ msgstr "无法解锁缓存 (index)" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "检测到未知文件状态 %s.\n" #~ "\n" #~ "文件 %s 无法由该程序提交.\n" #~ msgid "Unlock Index" #~ msgstr "解锁 Index" #~ 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 "Unstage Hunk From Commit" #~ msgstr "从提交中撤除修改块" #~ msgid "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui." #~ msgstr "更新 Git 缓存(Index)失败, 重新扫描将自动开始以重新同步 git-gui." #~ msgid "Updating working directory to '%s'..." #~ msgstr "更新工作目录到 '%s'..." #~ msgid "Updating..." #~ msgstr "更新..." #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "使用 thin pack (适用于低速网络连接)" #~ msgid "Verify Database" #~ msgstr "验证数据库" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "使用 fsck-objects 验证对象数据库" #~ msgid "Visualize %s's History" #~ msgstr "图示 %s 分支的历史" #~ msgid "Working... please wait..." #~ msgstr "工作中... 请等待..." #~ 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 "" #~ "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 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 "You must correct the above errors before committing." #~ msgstr "你必须在提交前修正上述错误." #~ msgid "[Up To Parent]" #~ msgstr "[上层目录]" #~ msgid "buckets" #~ msgstr "水桶??" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree 失败:" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "致命错误: 无法解决 %s" #~ msgid "" #~ "file notification: disabled\n" #~ "Note: install pywin32 to enable.\n" #~ msgstr "" #~ "文件提示已禁用\n" #~ "注: 安装 pywin32 以启用.\n" #~ msgid "files" #~ msgstr "文件" #~ msgid "files reset" #~ msgstr "文件" #~ msgid "git clone returned exit code %s" #~ msgstr "git clone 命令返回状态 %s" #~ msgid "git tag returned exit code %s" #~ msgstr "git tag 命令返回状态 %s" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - Git 的图形化用户界面" #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: 致命错误" #~ msgid "inotify enabled." #~ msgstr "inotify 已启用." #~ msgid "" #~ "inotify: disabled\n" #~ "Note: install python-pyinotify to enable inotify.\n" #~ msgstr "" #~ "inotify 已禁用\n" #~ "提示: 安装 python-pyinotify 以启用 inotify.\n" #~ msgid "lines annotated" #~ msgstr "标注行" #~ msgid "objects" #~ msgstr "objects" #~ msgid "pt." #~ msgstr "磅" #~ msgid "push %s" #~ msgstr "上传 %s" #~ msgid "remote prune %s" #~ msgstr "清除远程 %s" #~ msgid "unknown" #~ msgstr "未知" #~ msgid "update-ref failed:" #~ msgstr "update-ref 失败:" #~ msgid "warning" #~ msgstr "警告" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "警告: Tcl 不支持编码方式 '%s'." #~ msgid "write-tree failed:" #~ msgstr "write-tree 失败:" git-cola-4.6.1/cola/i18n/zh_TW.po000066400000000000000000004117561457126473700163470ustar00rootroot00000000000000# Translation of git-cola to Traditional Chinese(Taiwan) # Copyright (C) 2007, 2008 Shawn Pearce at el. # This file is distributed under the same license as the git-cola package. # # 敬請參考 glossary/zh_tw.po 的辭彙翻譯 # # Xudong Guan , 2007. # Eric Miao , 2008. # V字龍(Vdragon) , 2017, 2018. # 林博仁(Buo-ren, Lin) , 2018. msgid "" msgstr "" "Project-Id-Version: git-cola VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-17 01:06-0700\n" "PO-Revision-Date: 2018-08-30 13:29+0800\n" "Last-Translator: 林博仁(Buo-ren, Lin) \n" "Language-Team: Chinese l10n \n" "Language: zh_TW\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/widgets/diff.py:1681 msgid "" "\n" "

\n" " Drag and drop or use the Add button to add\n" " patches to the list\n" "

\n" " " msgstr "" "\n" "

\n" " 拖放或使用新增按鈕以將\n" " 修正檔加到清單中\n" "

\n" " " #: cola/widgets/about.py:437 #, python-format msgid "" "\n" "
\n" " Git Cola has been translated into different languages thanks\n" " to the help of the individuals listed below.\n" "\n" "
\n" "

\n" " Translation is approximate. If you find a mistake,\n" " please let us know by opening an issue on Github:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " We invite you to participate in translation by adding or updating\n" " a translation and opening a pull request.\n" "

\n" "\n" "
\n" "\n" " " msgstr "" "\n" "
\n" " 感謝下列眾位的協助,\n" " Git Cola 已被翻譯為多種不同的語言。\n" "\n" "
\n" "

\n" " 翻譯不一定都是精確的。惝若您發現了翻譯不當之處,\n" " 請透過在 GitHub 上建立議題的方式讓我們知道:\n" "

\n" "\n" "

\n" " %(bug_link)s\n" "

\n" "\n" "
\n" "

\n" " 我們邀請您透過新增或更新翻譯並提交變更拉取請求的方式\n" " 來參與本軟體的翻譯\n" "

\n" "\n" "
\n" "\n" " " #: cola/widgets/about.py:181 #, python-format msgid "" "\n" "
\n" " Git Cola version %(cola_version)s\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) %(python_version)s\n" "
  • Git %(git_version)s\n" "
  • Qt %(qt_version)s\n" "
  • QtPy %(qtpy_version)s\n" "
  • %(pyqt_api_name)s %(pyqt_api_version)s\n" "
\n" " " msgstr "" "\n" "
\n" " Git Cola 第 %(cola_version)s 版\n" "
    \n" "
  • %(platform_version)s\n" "
  • Python (%(python_path)s) 第 %(python_version)s 版\n" "
  • Git 第 %(git_version)s 版\n" "
  • Qt 第 %(qt_version)s 版\n" "
  • QtPy 第 %(qtpy_version)s 版\n" "
  • %(pyqt_api_name)s 第 %(pyqt_api_version)s 版\n" "
\n" " " #: cola/widgets/about.py:369 #, python-format msgid "" "\n" "
\n" " Please use %(bug_link)s to report issues.\n" "
\n" " " msgstr "" "\n" "
\n" " 請透過 %(bug_link)s 來回報使用問題\n" "
\n" " " #: cola/widgets/status.py:1310 #, python-format msgid "" "\n" " Format String Variables\n" " -----------------------\n" " %(path)s = relative file path\n" " %(abspath)s = absolute file path\n" " %(dirname)s = relative directory path\n" " %(absdirname)s = absolute directory path\n" " %(filename)s = file basename\n" " %(basename)s = file basename without extension\n" " %(ext)s = file extension\n" msgstr "" "\n" " 格式化字串變數\n" " -------\n" " %(path)s = 相對檔案路徑\n" " %(abspath)s = 絕對檔案路徑\n" " %(dirname)s = 相對目錄路徑\n" " %(absdirname)s = 絕對目錄路徑\n" " %(filename)s = 檔名\n" " %(basename)s = 檔名(去副檔名)\n" " %(ext)s = 副檔名\n" #: cola/sequenceeditor.py:796 msgid "" "\n" "Commands\n" "--------\n" "pick = use commit\n" "reword = use commit, but edit the commit message\n" "edit = use commit, but stop for amending\n" "squash = use commit, but meld into previous commit\n" "fixup = like \"squash\", but discard this commit's log message\n" "exec = run command (the rest of the line) using shell\n" "update-ref = update branches that point to commits\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" "\n" "If you disable a line here THAT COMMIT WILL BE LOST.\n" "\n" "However, if you disable everything, the rebase will be aborted.\n" "\n" "Keyboard Shortcuts\n" "------------------\n" "? = show help\n" "j = move down\n" "k = move up\n" "J = shift row down\n" "K = shift row up\n" "\n" "1, p = pick\n" "2, r = reword\n" "3, e = edit\n" "4, f = fixup\n" "5, s = squash\n" "spacebar = toggle enabled\n" "\n" "ctrl+enter = accept changes and rebase\n" "ctrl+q = cancel and abort the rebase\n" "ctrl+d = launch difftool\n" msgstr "" #: cola/widgets/finder.py:64 msgid "" "\n" "Keyboard Shortcuts\n" "------------------\n" "J, Down = Move Down\n" "K, Up = Move Up\n" "Enter = Edit Selected Files\n" "Spacebar = Open File Using Default Application\n" "Ctrl + L = Focus Text Entry Field\n" "? = Show Help\n" "\n" "The up and down arrows change focus between the text entry field\n" "and the results.\n" msgstr "" "\n" "鍵盤快捷鍵\n" "------------------\n" "J, Down = 往下移動\n" "K, Up = 往上移動\n" "Enter = 編輯選取的檔案\n" "Spacebar = 以預設應用軟體開啟檔案\n" "Ctrl+L = 將焦點移至文字輸入欄位\n" "? = 顯示幫助訊息\n" "\n" "用上、下方向鍵在文字輸入欄位與執行結果間\n" "變更焦點。\n" #: cola/widgets/prefs.py:133 msgid "" "\n" "This option determines how the supplied commit message should be\n" "cleaned up before committing.\n" "\n" "The can be strip, whitespace, verbatim, scissors or default.\n" "\n" "strip\n" " Strip leading and trailing empty lines, trailing whitespace,\n" " commentary and collapse consecutive empty lines.\n" "\n" "whitespace\n" " Same as strip except #commentary is not removed.\n" "\n" "verbatim\n" " Do not change the message at all.\n" "\n" "scissors\n" " Same as whitespace except that everything from (and including) the line\n" " found below is truncated, if the message is to be edited.\n" " \"#\" can be customized with core.commentChar.\n" "\n" " # ------------------------ >8 ------------------------" msgstr "" #: cola/widgets/dag.py:960 msgid " - DAG" msgstr " - 有向無環圖(DAG)" #: cola/widgets/recent.py:52 msgid " commits ago" msgstr " 個修訂版提交前" #: cola/cmds.py:1197 #, python-format msgid "\"%(branch)s\" has been deleted from \"%(remote)s\"." msgstr "「%(branch)s」分支已從「%(remote)s」版控庫中移除。" #: cola/widgets/createbranch.py:314 #, python-format msgid "\"%(command)s\" returned exit status \"%(status)d\"" msgstr "「%(command)s」命令傳回了 %(status)d 結束狀態代碼" #: cola/interaction.py:38 #, python-format msgid "\"%(command)s\" returned exit status %(status)d" msgstr "「%(command)s」命令傳回了 %(status)d 結束狀態碼" #: cola/guicmds.py:156 #, python-format msgid "\"%s\" already exists" msgstr "「%s」早已存在" #: cola/widgets/clone.py:204 #, python-format msgid "\"%s\" already exists, cola will create a new directory" msgstr "「%s」目錄已存在,cola 將會另外建立一個新的目錄" #: cola/cmds.py:2298 #, python-format msgid "\"%s\" requires a selected file." msgstr "「%s」操作需要有選取檔案才能執行。" #: cola/cmds.py:2036 msgid "" "\"git rebase --update-refs\" automatically force-updates any\n" "branches that point to commits that are being rebased.\n" "\n" "Any branches that are checked out in a worktree are not updated.\n" "\n" "Using this feature is helpful for \"stacked\" branch workflows." msgstr "" #: cola/models/stash.py:145 msgid "\"git stash drop\" did not return a ref to rename." msgstr "" #: cola/sequenceeditor.py:369 msgid "#" msgstr "" #: cola/widgets/browse.py:96 #, python-format msgid "%(project)s: %(branch)s - Browse" msgstr "%(project)s:%(branch)s - 瀏覽" #: cola/widgets/dag.py:953 #, python-format msgid "%(project)s: %(ref)s - DAG" msgstr "%(project)s: %(ref)s - 有向無環圖(DAG)" #: cola/models/browse.py:314 #, python-format msgid "%d days ago" msgstr "%d 天前" #: cola/models/browse.py:313 #, python-format msgid "%d hours ago" msgstr "%d 小時前" #: cola/models/browse.py:306 cola/models/browse.py:310 #, python-format msgid "%d minutes ago" msgstr "%d 分鐘前" #: cola/cmds.py:377 #, python-format msgid "%d patch(es) applied." msgstr "已套用 %d 個修正。" #: cola/widgets/createbranch.py:279 #, python-format msgid "%d skipped" msgstr "%d 個跳過了" #: cola/cmds.py:2520 #, python-format msgid "" "%s appears to contain merge conflicts.\n" "\n" "You should probably skip this file.\n" "Stage it anyways?" msgstr "" "%s 看起來包含未解決的合併衝突。\n" "\n" "您可能應該要跳過這個檔案。\n" "無論如何都要將它移入新修訂版準備區域嗎?" #: cola/widgets/startup.py:262 #, python-format msgid "%s could not be opened. Remove from bookmarks?" msgstr "" #: cola/app.py:497 cola/widgets/bookmarks.py:481 #, python-format msgid "%s is not a Git repository." msgstr "%s 不是一個 Git 版控庫。" #: cola/cmds.py:1015 #, python-format msgid "%s will be removed from your bookmarks." msgstr "「%s」版控庫將會從您的書籤中被刪除。" #: cola/cmds.py:1028 #, python-format msgid "%s will be removed from your recent repositories." msgstr "「%s」版控庫將從您最近使用的版控庫中移除。" #: cola/cmds.py:1662 #, python-format msgid "%s: No such file or directory." msgstr "%s:無此檔案或目錄。" #: cola/widgets/main.py:748 msgid "&Edit" msgstr "編輯" #: cola/widgets/main.py:690 msgid "&File" msgstr "檔案" #: cola/widgets/browse.py:98 msgid "(Amending)" msgstr "(正在修正前一個修訂版提交)" #: cola/widgets/compare.py:35 msgid "*** Branch Point ***" msgstr "*** 分支點 ***" #: cola/widgets/compare.py:36 msgid "*** Sandbox ***" msgstr "*** 沙盒 ***" #: cola/widgets/diff.py:816 msgid "100%" msgstr "100%" #: cola/widgets/diff.py:817 msgid "200%" msgstr "200%" #: cola/widgets/diff.py:814 msgid "25%" msgstr "25%" #: cola/widgets/diff.py:818 msgid "400%" msgstr "400%" #: cola/widgets/diff.py:815 msgid "50%" msgstr "50%" #: cola/widgets/diff.py:819 msgid "800%" msgstr "800%" #: cola/widgets/finder.py:118 msgid " ..." msgstr "〈路徑〉……" #: cola/cmds.py:1685 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 "" "修訂版提交範本尚未被設定。\n" "使用「git config」命令來定義「commit.template」設定值\n" "使其指向一個修訂版提交範本。" #: cola/cmds.py:1734 #, python-format msgid "A hook must be provided at \"%s\"" msgstr "一個掛勾程式必須在「%s」被提供" #: cola/widgets/cfgactions.py:81 cola/widgets/main.py:636 msgid "Abort" msgstr "中止" #: cola/widgets/cfgactions.py:148 cola/widgets/cfgactions.py:154 msgid "Abort Action" msgstr "中止操作" #: cola/cmds.py:131 msgid "Abort Applying Patch" msgstr "" #: cola/cmds.py:125 msgid "Abort Applying Patch..." msgstr "" #: cola/widgets/main.py:245 msgid "Abort Applying Patches..." msgstr "" #: cola/cmds.py:161 msgid "Abort Cherry-Pick" msgstr "" #: cola/cmds.py:155 cola/widgets/main.py:330 msgid "Abort Cherry-Pick..." msgstr "" #: cola/cmds.py:192 msgid "Abort Merge" msgstr "中止分支合併(merge)" #: cola/cmds.py:185 cola/widgets/main.py:364 msgid "Abort Merge..." msgstr "中止分支合併(merge)……" #: cola/widgets/cfgactions.py:153 msgid "Abort the action?" msgstr "要中止操作嗎?" #: cola/widgets/main.py:246 msgid "Abort the current \"git am\" patch session" msgstr "" #: cola/cmds.py:158 msgid "" "Aborting a cherry-pick can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:128 msgid "" "Aborting a patch can cause uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:126 msgid "Aborting applying the current patch?" msgstr "" #: cola/cmds.py:156 msgid "Aborting the current cherry-pick?" msgstr "" #: cola/cmds.py:188 msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" "中止目前的分支合併操作將導致 *所有* 尚未提交到版控庫的內容變更遺失,\n" "且所有遺失的變更將無法被復原或找回。" #: cola/cmds.py:186 msgid "Aborting the current merge?" msgstr "中止目前正在進行的分支合併?" #: cola/widgets/about.py:88 cola/widgets/main.py:531 msgid "About" msgstr "關於" #: cola/widgets/about.py:64 msgid "About git-cola" msgstr "關於 git-cola" #: cola/widgets/bookmarks.py:216 cola/widgets/startup.py:339 msgid "Accept" msgstr "接受" #: cola/sequenceeditor.py:164 msgid "" "Accept changes and rebase\n" "Shortcut: Ctrl+Enter" msgstr "" "接受變更並變更基底(rebase)\n" "鍵盤快捷鍵:Ctrl+Enter" #: cola/widgets/status.py:1376 msgid "Action Name" msgstr "操作名稱" #: cola/sequenceeditor.py:596 cola/widgets/bookmarks.py:320 #: cola/widgets/branch.py:221 cola/widgets/browse.py:375 #: cola/widgets/commitmsg.py:105 cola/widgets/dag.py:314 #: cola/widgets/filelist.py:122 cola/widgets/main.py:93 #: cola/widgets/main.py:771 cola/widgets/startup.py:435 msgid "Actions" msgstr "操作" #: cola/widgets/commitmsg.py:107 msgid "Actions..." msgstr "操作……" #: cola/widgets/bookmarks.py:70 cola/widgets/diff.py:1698 #: cola/widgets/diff.py:1712 cola/widgets/gitignore.py:63 #: cola/widgets/status.py:1381 msgid "Add" msgstr "新增" #: cola/widgets/bookmarks.py:469 msgid "Add Favorite" msgstr "新增喜愛的版控庫" #: cola/widgets/editremotes.py:371 msgid "Add Remote" msgstr "新增遠端版控庫" #: cola/widgets/toolbar.py:320 msgid "Add Separator" msgstr "新增分隔器" #: cola/cmds.py:2974 cola/widgets/submodules.py:41 #: cola/widgets/submodules.py:110 msgid "Add Submodule" msgstr "" #: cola/cmds.py:2971 cola/widgets/main.py:377 msgid "Add Submodule..." msgstr "" #: cola/widgets/editremotes.py:60 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 "" "使用左手測的新增(+)與移除(-)按鈕\n" "新增或移除遠端版控庫\n" "\n" "選取其中一個清單中的遠端版控庫\n" "再按下 Enter 或是連續點兩下就可以將其重新命名。" #: cola/widgets/editremotes.py:78 msgid "Add new remote git repository" msgstr "加一個新的遠端 Git 版控庫" #: cola/widgets/diff.py:1698 msgid "Add patches (+)" msgstr "加入修正檔 (+)" #: cola/widgets/editremotes.py:430 msgid "Add remote" msgstr "新增遠端版控庫" #: cola/cmds.py:2972 msgid "Add this submodule?" msgstr "" #: cola/widgets/gitignore.py:53 msgid "Add to .gitignore" msgstr "新增到 Git 忽略規則(.gitignore)" #: cola/widgets/status.py:287 msgid "Add to Git Annex" msgstr "新增到 Git Annex" #: cola/widgets/status.py:291 msgid "Add to Git LFS" msgstr "新增到 Git LFS" #: cola/widgets/gitignore.py:27 msgid "Add to exclusions" msgstr "" #: cola/widgets/gitignore.py:54 msgid "Add to local .git/info/exclude" msgstr "" #: cola/widgets/filelist.py:25 msgid "Additions" msgstr "新增行數" #: cola/widgets/archive.py:132 msgid "Advanced" msgstr "進階選項" #: cola/widgets/main.py:536 msgid "Against Commit... (Diff Mode)" msgstr "" #: cola/models/browse.py:32 msgid "Age" msgstr "建立時間" #: cola/widgets/prefs.py:441 msgid "All Repositories" msgstr "所有的版控庫" #: cola/cmds.py:3054 #, python-format msgid "" "All submodules will be updated using\n" "\"%s\"" msgstr "" #: cola/widgets/remote.py:199 msgid "Allow non-fast-forward updates. Using \"force\" can cause the remote repository to lose commits; use it with care" msgstr "允許非快速前移式更新。使用「強制」可能會造成遠端版控庫遺失修訂版提交;請小心使用" #: cola/widgets/merge.py:59 msgid "Always create a merge commit when enabled, even when the merge is a fast-forward update" msgstr "於啟用時,就算該合併是一個快速前移式更新也總是建立一個合併修訂版提交" #: cola/cmds.py:220 msgid "Amend" msgstr "修正前一次的修訂版提交" #: cola/widgets/commitmsg.py:470 msgid "Amend Commit" msgstr "修正前一個修訂版提交" #: cola/widgets/commitmsg.py:116 cola/widgets/main.py:194 msgid "Amend Last Commit" msgstr "修正上次提交" #: cola/widgets/commitmsg.py:469 msgid "Amend the published commit?" msgstr "要修正已被推送出去的修訂版提交嗎?" #: cola/widgets/main.py:1171 msgid "Amending" msgstr "正在修正前一個修訂版提交" #: cola/widgets/cfgactions.py:150 msgid "" "An action is still running.\n" "Terminating it could result in data loss." msgstr "" "一個操作仍在進行。\n" "將其中止可能會造成資料損失。" #: cola/cmds.py:2748 msgid "" "An unsigned, lightweight tag will be created instead.\n" "Create an unsigned tag?" msgstr "" "一個無簽名的,輕量的標籤將會被建立。\n" "要建立此無簽名的標籤嗎?" #: cola/widgets/prefs.py:444 msgid "Appearance" msgstr "" #: cola/widgets/diff.py:1304 msgid "Append Patch" msgstr "" #: cola/widgets/diff.py:1373 msgid "Append Patch..." msgstr "" #: cola/widgets/diff.py:1707 cola/widgets/stash.py:50 cola/widgets/stash.py:110 #: cola/widgets/toolbar.py:328 msgid "Apply" msgstr "套用" #: cola/widgets/diff.py:1670 msgid "Apply Patches" msgstr "套用修正" #: cola/widgets/main.py:239 msgid "Apply Patches..." msgstr "套用修正……" #: cola/widgets/stash.py:66 msgid "Apply and drop the selected stash (git stash pop)" msgstr "套用並丟棄被選取的珍藏項目(git stash pop)" #: cola/widgets/stash.py:50 msgid "Apply the selected stash" msgstr "套用被選取的珍藏項目" #: cola/widgets/main.py:1181 msgid "Applying Patch" msgstr "" #: cola/widgets/cfgactions.py:205 msgid "Arguments" msgstr "參數" #: cola/qtutils.py:886 msgid "Attach" msgstr "連接" #: cola/models/browse.py:32 cola/models/browse.py:71 cola/widgets/dag.py:572 msgid "Author" msgstr "作者" #: cola/widgets/about.py:90 msgid "Authors" msgstr "作者群" #: cola/hidpi.py:41 msgid "Auto" msgstr "" #: cola/widgets/commitmsg.py:143 cola/widgets/prefs.py:280 msgid "Auto-Wrap Lines" msgstr "自動折行" #: cola/widgets/prefs.py:206 msgid "Autocomplete Paths" msgstr "" #: cola/widgets/prefs.py:198 msgid "Automatically Load Commit Message Template" msgstr "" #: cola/widgets/grep.py:115 msgid "Basic Regexp" msgstr "基本正規表達式" #: cola/widgets/prefs.py:276 msgid "Blame Viewer" msgstr "指謫(blame)查看器" #: cola/widgets/browse.py:206 #, fuzzy msgid "Blame selected paths" msgstr "重新命名選取的路徑" #: cola/cmds.py:545 cola/widgets/status.py:283 msgid "Blame..." msgstr "指摘(Blame)..." #: cola/widgets/prefs.py:367 msgid "Bold on dark headers instead of italic" msgstr "標題用帶深色底色的粗體而非斜體" #: cola/widgets/main.py:820 cola/widgets/submodules.py:118 msgid "Branch" msgstr "分支" #: cola/widgets/remote.py:634 #, python-format msgid "" "Branch \"%(branch)s\" does not exist in \"%(remote)s\".\n" "A new remote branch will be published." msgstr "" "「%(branch)s」分支並無存在於「%(remote)s」遠端版控庫。\n" "一個新的遠端方支將被發佈。" #: cola/widgets/createbranch.py:256 #, python-format msgid "Branch \"%s\" already exists." msgstr "「%s」分支早已存在。" #: cola/widgets/compare.py:43 msgid "Branch Diff Viewer" msgstr "分支差異檢視器" #: cola/widgets/createbranch.py:257 cola/widgets/createbranch.py:269 msgid "Branch Exists" msgstr "分支已存在" #: cola/widgets/createbranch.py:96 msgid "Branch Name" msgstr "分支名稱" #: cola/widgets/submodules.py:88 msgid "Branch name" msgstr "" #: cola/widgets/browse.py:89 cola/widgets/main.py:1111 #, python-format msgid "Branch: %s" msgstr "分支:%s" #: cola/widgets/branch.py:87 cola/widgets/main.py:129 msgid "Branches" msgstr "分支" #: cola/widgets/main.py:552 msgid "Branches..." msgstr "比較分支之間的內容差異……" #: cola/widgets/about.py:396 cola/widgets/about.py:399 #: cola/widgets/about.py:419 msgid "Brazilian translation" msgstr "巴西語翻譯" #: cola/guicmds.py:52 msgid "Browse" msgstr "瀏覽" #: cola/guicmds.py:52 msgid "Browse Commits..." msgstr "瀏覽修訂版提交……" #: cola/widgets/main.py:513 msgid "Browse Current Branch..." msgstr "瀏覽目前分支中的檔案……" #: cola/widgets/main.py:519 msgid "Browse Other Branch..." msgstr "瀏覽其他分支中的檔案……" #: cola/widgets/editremotes.py:434 cola/widgets/search.py:45 #: cola/widgets/startup.py:64 cola/widgets/startup.py:284 msgid "Browse..." msgstr "瀏覽……" #: cola/widgets/main.py:87 msgid "Browser" msgstr "檔案瀏覽器" #: cola/widgets/browse.py:590 #, python-format msgid "Browsing %s" msgstr "正在瀏覽 %s" #: cola/widgets/commitmsg.py:124 msgid "Bypass Commit Hooks" msgstr "不執行提交掛勾程式" #: cola/sequenceeditor.py:180 cola/widgets/standard.py:1056 msgid "Cancel" msgstr "取消" #: cola/sequenceeditor.py:181 msgid "" "Cancel rebase\n" "Shortcut: Ctrl+Q" msgstr "" "取消變更基底\n" "鍵盤快捷鍵:Ctrl+Q" #: cola/cmds.py:253 msgid "Cannot Amend" msgstr "無法修正前一次的修訂版提交" #: cola/cmds.py:560 #, python-format msgid "Cannot exec \"%s\": please configure a blame viewer" msgstr "無法執行「%s」:請設定您慣用的 Blame 檢視器" #: cola/cmds.py:3090 #, python-format msgid "Cannot exec \"%s\": please configure a history browser" msgstr "無法執行「%s」:請設定一個變動紀錄瀏覽器" #: cola/cmds.py:1570 #, python-format msgid "Cannot exec \"%s\": please configure your editor" msgstr "無法執行「%s」:請設定您慣用的文字編輯器" #: cola/models/browse.py:335 msgid "Changed Upstream" msgstr "在上游被變更" #: cola/widgets/prefs.py:208 msgid "Check Published Commits when Amending" msgstr "" #: cola/widgets/commitmsg.py:136 msgid "Check Spelling" msgstr "檢查拼字問題" #: cola/widgets/prefs.py:286 msgid "Check spelling" msgstr "檢查拼字問題" #: cola/widgets/prefs.py:186 msgid "Check whether a commit has been published when amending" msgstr "" #: cola/guicmds.py:61 cola/widgets/branch.py:233 msgid "Checkout" msgstr "取出" #: cola/widgets/createbranch.py:128 msgid "Checkout After Creation" msgstr "在建立新分支後取出該分支" #: cola/guicmds.py:61 cola/widgets/dag.py:409 msgid "Checkout Branch" msgstr "取出分支內容" #: cola/widgets/dag.py:413 msgid "Checkout Detached HEAD" msgstr "取出脫離的 HEAD 指標版本" #: cola/cmds.py:480 cola/cmds.py:518 msgid "Checkout Files" msgstr "" #: cola/widgets/branch.py:237 msgid "Checkout as new branch" msgstr "取出為一新分支" #: cola/cmds.py:507 msgid "Checkout files from our branch (HEAD)" msgstr "" #: cola/cmds.py:511 msgid "Checkout files from our branch?" msgstr "" #: cola/cmds.py:469 msgid "Checkout files from their branch (MERGE_HEAD)" msgstr "" #: cola/cmds.py:473 msgid "Checkout files from their branch?" msgstr "" #: cola/widgets/main.py:590 msgid "Checkout..." msgstr "取出……" #: cola/widgets/dag.py:386 cola/widgets/search.py:78 msgid "Cherry Pick" msgstr "挑取(cherry-pick)" #: cola/guicmds.py:72 msgid "Cherry-Pick Commit" msgstr "挑取(cherry-pick)修訂版提交並合併至當前分支" #: cola/widgets/main.py:324 msgid "Cherry-Pick..." msgstr "挑取(cherry-pick)……" #: cola/cmds.py:584 msgid "Cherry-pick failed" msgstr "" #: cola/widgets/main.py:1175 msgid "Cherry-picking" msgstr "" #: cola/widgets/diff.py:1321 msgid "Choose Patch..." msgstr "" #: cola/widgets/search.py:318 msgid "Choose Paths" msgstr "選取路徑" #: cola/widgets/grep.py:114 msgid "Choose the \"git grep\" regular expression mode" msgstr "選擇「git grep」命令的正規表達式模式" #: cola/widgets/bookmarks.py:228 cola/widgets/startup.py:351 msgid "Clear Default Repository" msgstr "清除預設版控庫" #: cola/widgets/commitmsg.py:312 msgid "Clear commit message" msgstr "清除修訂版提交訊息" #: cola/widgets/commitmsg.py:309 msgid "Clear commit message?" msgstr "清除修訂版提交訊息?" #: cola/widgets/commitmsg.py:63 msgid "Clear..." msgstr "清除……" #: cola/widgets/clone.py:124 msgid "Clone" msgstr "克隆" #: cola/widgets/clone.py:61 cola/widgets/clone.py:102 msgid "Clone Repository" msgstr "克隆版控庫" #: cola/widgets/main.py:479 cola/widgets/startup.py:57 msgid "Clone..." msgstr "克隆另一個版控庫……" #: cola/widgets/clone.py:61 #, python-format msgid "Cloning repository at %s" msgstr "正在克隆位於 %s 的版控庫" #: cola/qtutils.py:787 cola/qtutils.py:837 cola/widgets/about.py:490 #: cola/widgets/remote.py:361 cola/widgets/text.py:1087 msgid "Close" msgstr "關閉" #: cola/widgets/remote.py:222 msgid "Close dialog when completed" msgstr "" #: cola/widgets/remote.py:221 msgid "Close on completion" msgstr "" #: cola/widgets/text.py:397 msgid "Close the find bar" msgstr "" #: cola/qtutils.py:650 msgid "Close..." msgstr "關閉……" #: cola/widgets/recent.py:69 msgid "Collapse all" msgstr "全部折疊" # V字龍:注意此應翻譯為動詞。 #: cola/sequenceeditor.py:371 msgid "Command" msgstr "命令" # V字龍:注意此應翻譯為動詞。 #: cola/widgets/main.py:161 cola/widgets/merge.py:72 msgid "Commit" msgstr "提交變更" #: cola/widgets/prefs.py:192 msgid "Commit Message Cleanup" msgstr "" #: cola/widgets/commitmsg.py:491 msgid "Commit failed" msgstr "提交失敗" #: cola/widgets/commitmsg.py:62 msgid "Commit staged changes" msgstr "提交新修訂版準備區域中的變更" #: cola/widgets/commitmsg.py:94 msgid "" "Commit staged changes\n" "Shortcut: Ctrl+Enter" msgstr "" "提交新修訂版準備區域中的變更\n" "鍵盤快捷鍵:Ctrl+Enter" #: cola/widgets/commitmsg.py:586 msgid "Commit summary" msgstr "修訂版提交描述" #: cola/widgets/main.py:254 msgid "Commit the current state and continue applying patches" msgstr "" #: cola/widgets/merge.py:68 msgid "Commit the merge if there are no conflicts. Uncheck to leave the merge uncommitted" msgstr "若不存在版本衝突時提交該合併。取消勾選以保持合併於尚未提交狀態" #: cola/widgets/commitmsg.py:59 cola/widgets/commitmsg.py:96 #: cola/widgets/main.py:792 cola/widgets/main.py:793 msgid "Commit@@verb" msgstr "提交" #: cola/widgets/dag.py:487 msgid "Commits authored by me" msgstr "" #: cola/difftool.py:97 cola/widgets/compare.py:69 msgid "Compare" msgstr "比較差異" #: cola/difftool.py:102 msgid "Compare All" msgstr "比較全部檔案差異" #: cola/widgets/toolbar.py:274 cola/widgets/toolbar.py:311 msgid "Configure Toolbar" msgstr "設定工具列" #: cola/widgets/remote.py:218 msgid "Configure the remote branch as the the new upstream" msgstr "將此遠端分支設為新的上游分支" #: cola/widgets/main.py:169 msgid "Console" msgstr "終端機輸出" #: cola/interaction.py:109 cola/widgets/main.py:624 msgid "Continue" msgstr "繼續" #: cola/widgets/main.py:253 msgid "Continue Applying Patches" msgstr "" #: cola/widgets/bookmarks.py:247 cola/widgets/main.py:756 #: cola/widgets/startup.py:370 msgid "Copy" msgstr "複製" #: cola/widgets/status.py:269 msgid "Copy Basename to Clipboard" msgstr "將基底檔名複製到剪貼簿" #: cola/widgets/diff.py:209 msgid "Copy Diff" msgstr "" #: cola/widgets/status.py:746 msgid "Copy Leading Path to Clipboard" msgstr "將前導路徑複製到剪貼簿" #: cola/widgets/status.py:252 msgid "Copy Path to Clipboard" msgstr "將路徑複製到剪貼簿" #: cola/widgets/status.py:260 msgid "Copy Relative Path to Clipboard" msgstr "將相對路徑複製到剪貼簿" #: cola/sequenceeditor.py:382 cola/widgets/dag.py:473 msgid "Copy SHA-1" msgstr "複製 SHA-1 雜湊" #: cola/widgets/status.py:738 msgid "Copy..." msgstr "複製……" #: cola/app.py:489 #, python-format msgid "Could not open %s." msgstr "" #: cola/widgets/clone.py:189 cola/widgets/clone.py:191 #, python-format msgid "Could not parse Git URL: \"%s\"" msgstr "無法分析 Git URL:「%s」" #: cola/app.py:499 msgid "Create" msgstr "" #: cola/widgets/createbranch.py:84 cola/widgets/createbranch.py:133 #: cola/widgets/createbranch.py:299 cola/widgets/dag.py:368 msgid "Create Branch" msgstr "建立一個新的分支" #: cola/widgets/dag.py:372 msgid "Create Patch" msgstr "產生修正檔" #: cola/widgets/remote.py:640 msgid "Create Remote Branch" msgstr "建立新的遠端分支" #: cola/widgets/commitmsg.py:130 cola/widgets/merge.py:76 msgid "Create Signed Commit" msgstr "建立經 GPG 簽署過的修訂版提交" #: cola/widgets/createtag.py:53 cola/widgets/createtag.py:89 #: cola/widgets/dag.py:376 msgid "Create Tag" msgstr "建立新的標籤" #: cola/widgets/main.py:558 msgid "Create Tag..." msgstr "建立新的標籤(tag)……" #: cola/cmds.py:2751 msgid "Create Unsigned Tag" msgstr "建立一個無簽名的標籤" #: cola/widgets/remote.py:192 msgid "Create a merge commit even when the merge resolves as a fast-forward" msgstr "就算該合併是一個快速前移式合併也總是建立一個合併修訂版提交" #: cola/widgets/remote.py:639 msgid "Create a new remote branch?" msgstr "要建立新的遠端分支嗎?" #: cola/app.py:498 msgid "Create a new repository at that location?" msgstr "" #: cola/widgets/submodules.py:99 msgid "Create a shallow clone with history truncated to the specified number of revisions. 0 performs a full clone." msgstr "" #: cola/widgets/main.py:565 msgid "Create..." msgstr "新建……" #: cola/cmds.py:2787 #, python-format msgid "Created a new tag named \"%s\"" msgstr "建立了一個名為「%s」的新標籤" #: cola/widgets/prefs.py:287 msgid "Ctrl+MouseWheel to Zoom" msgstr "" #: cola/widgets/prefs.py:442 msgid "Current Repository" msgstr "當前的版控庫" #: cola/widgets/status.py:1371 msgid "Custom Copy Actions" msgstr "自訂複製操作" #: cola/widgets/status.py:274 msgid "Customize..." msgstr "自訂……" #: cola/widgets/main.py:754 msgid "Cut" msgstr "剪切" #: cola/widgets/about.py:393 cola/widgets/about.py:424 msgid "Czech translation" msgstr "捷克語翻譯" #: cola/widgets/main.py:606 msgid "DAG..." msgstr "有向無環圖(DAG)……" #: cola/icons.py:54 msgid "Dark Theme" msgstr "" #: cola/widgets/dag.py:572 msgid "Date, Time" msgstr "時間,日期" #: cola/icons.py:53 cola/themes.py:643 #, fuzzy msgid "Default" msgstr "恢復默認值" #: cola/widgets/prefs.py:124 msgid "" "Default directory when exporting patches.\n" "Relative paths are relative to the current repository.\n" "Absolute path are used as-is." msgstr "" #: cola/cmds.py:922 cola/guicmds.py:25 cola/guicmds.py:34 #: cola/widgets/bookmarks.py:74 cola/widgets/bookmarks.py:250 #: cola/widgets/main.py:760 cola/widgets/startup.py:372 msgid "Delete" msgstr "移除" #: cola/cmds.py:1088 #, python-format msgid "Delete %d file(s)?" msgstr "刪除 %d 個檔案?" #: cola/cmds.py:1016 msgid "Delete Bookmark" msgstr "刪除書籤" #: cola/cmds.py:1014 msgid "Delete Bookmark?" msgstr "要刪除書籤嗎?" #: cola/cmds.py:1114 cola/cmds.py:1117 cola/guicmds.py:25 #: cola/widgets/branch.py:277 msgid "Delete Branch" msgstr "移除分支" #: cola/cmds.py:1089 msgid "Delete Files" msgstr "刪除檔案" #: cola/widgets/status.py:312 msgid "Delete Files..." msgstr "刪除檔案……" #: cola/cmds.py:1085 msgid "Delete Files?" msgstr "要刪除檔案嗎?" #: cola/cmds.py:919 msgid "Delete Remote" msgstr "移除遠端版控庫" #: cola/guicmds.py:34 cola/widgets/branch.py:279 msgid "Delete Remote Branch" msgstr "移除遠端分支" #: cola/widgets/main.py:578 msgid "Delete Remote Branch..." msgstr "移除遠端分支……" #: cola/widgets/toolbar.py:276 msgid "Delete Toolbar" msgstr "刪除工具列" #: cola/cmds.py:1115 #, python-format msgid "Delete branch \"%s\"?" msgstr "" #: cola/widgets/editremotes.py:85 msgid "Delete remote" msgstr "移除遠端版控庫" #: cola/cmds.py:921 #, python-format msgid "Delete remote \"%s\"" msgstr "移除「%s」遠端版控庫" #: cola/cmds.py:920 msgid "Delete remote?" msgstr "要移除遠端版控庫嗎?" #: cola/widgets/main.py:572 msgid "Delete..." msgstr "移除..." #: cola/cmds.py:1067 #, python-format msgid "Deleting \"%s\" failed" msgstr "「%s」移除失敗" #: cola/widgets/filelist.py:25 msgid "Deletions" msgstr "移除行數" #: cola/widgets/submodules.py:119 msgid "Depth" msgstr "" #: cola/qtutils.py:841 cola/qtutils.py:888 msgid "Detach" msgstr "分離" #: cola/widgets/prefs.py:203 msgid "Detect Conflict Markers" msgstr "偵測衝突標記" #: cola/widgets/prefs.py:174 msgid "Detect conflict markers in unmerged files" msgstr "偵測尚未合併檔案中的衝突標記" #: cola/widgets/about.py:253 cola/widgets/about.py:256 #: cola/widgets/about.py:259 cola/widgets/about.py:260 #: cola/widgets/about.py:261 cola/widgets/about.py:262 #: cola/widgets/about.py:263 cola/widgets/about.py:264 #: cola/widgets/about.py:265 cola/widgets/about.py:266 #: cola/widgets/about.py:267 cola/widgets/about.py:268 #: cola/widgets/about.py:269 cola/widgets/about.py:270 #: cola/widgets/about.py:271 cola/widgets/about.py:272 #: cola/widgets/about.py:273 cola/widgets/about.py:274 #: cola/widgets/about.py:275 cola/widgets/about.py:276 #: cola/widgets/about.py:277 cola/widgets/about.py:278 #: cola/widgets/about.py:279 cola/widgets/about.py:280 #: cola/widgets/about.py:281 cola/widgets/about.py:282 #: cola/widgets/about.py:283 cola/widgets/about.py:284 #: cola/widgets/about.py:285 cola/widgets/about.py:286 #: cola/widgets/about.py:287 cola/widgets/about.py:288 #: cola/widgets/about.py:289 cola/widgets/about.py:290 #: cola/widgets/about.py:291 cola/widgets/about.py:292 #: cola/widgets/about.py:293 cola/widgets/about.py:294 #: cola/widgets/about.py:295 cola/widgets/about.py:296 #: cola/widgets/about.py:297 cola/widgets/about.py:298 #: cola/widgets/about.py:299 cola/widgets/about.py:300 #: cola/widgets/about.py:301 cola/widgets/about.py:302 #: cola/widgets/about.py:303 cola/widgets/about.py:304 #: cola/widgets/about.py:305 cola/widgets/about.py:306 #: cola/widgets/about.py:307 cola/widgets/about.py:308 #: cola/widgets/about.py:309 cola/widgets/about.py:310 #: cola/widgets/about.py:311 cola/widgets/about.py:312 #: cola/widgets/about.py:313 cola/widgets/about.py:314 #: cola/widgets/about.py:315 cola/widgets/about.py:316 #: cola/widgets/about.py:317 cola/widgets/about.py:318 #: cola/widgets/about.py:319 cola/widgets/about.py:320 #: cola/widgets/about.py:321 cola/widgets/about.py:322 #: cola/widgets/about.py:323 cola/widgets/about.py:324 #: cola/widgets/about.py:325 cola/widgets/about.py:326 #: cola/widgets/about.py:327 cola/widgets/about.py:328 #: cola/widgets/about.py:329 cola/widgets/about.py:330 #: cola/widgets/about.py:331 cola/widgets/about.py:332 #: cola/widgets/about.py:333 cola/widgets/about.py:334 #: cola/widgets/about.py:335 cola/widgets/about.py:336 #: cola/widgets/about.py:337 cola/widgets/about.py:338 #: cola/widgets/about.py:339 cola/widgets/about.py:340 #: cola/widgets/about.py:341 cola/widgets/about.py:342 #: cola/widgets/about.py:343 cola/widgets/about.py:344 #: cola/widgets/about.py:345 cola/widgets/about.py:346 #: cola/widgets/about.py:347 cola/widgets/about.py:348 #: cola/widgets/about.py:349 cola/widgets/about.py:350 #: cola/widgets/about.py:351 cola/widgets/about.py:352 #: cola/widgets/about.py:353 cola/widgets/about.py:354 #: cola/widgets/about.py:355 cola/widgets/about.py:356 #: cola/widgets/about.py:357 cola/widgets/about.py:358 #: cola/widgets/about.py:359 cola/widgets/about.py:360 #: cola/widgets/about.py:361 cola/widgets/about.py:362 msgid "Developer" msgstr "軟體開發者" #: cola/guicmds.py:184 cola/widgets/dag.py:830 cola/widgets/diff.py:809 #: cola/widgets/main.py:176 cola/widgets/main.py:811 msgid "Diff" msgstr "內容差異" #: cola/guicmds.py:184 msgid "Diff Against Commit" msgstr "" #: cola/widgets/browse.py:172 msgid "Diff Against Predecessor..." msgstr "與過去版本比較內容差異……" #: cola/widgets/main.py:1173 msgid "Diff Mode" msgstr "" #: cola/widgets/diff.py:800 cola/widgets/diff.py:824 msgid "Diff Options" msgstr "內容差異選項" #: cola/widgets/prefs.py:277 msgid "Diff Tool" msgstr "顯示內容差異的工具" #: cola/widgets/dag.py:363 msgid "Diff selected -> this" msgstr "顯示被選取的修訂版→此修訂版的內容差異" #: cola/widgets/dag.py:357 msgid "Diff this -> selected" msgstr "顯示此修訂版→被選取的修訂版的內容差異" #: cola/widgets/main.py:218 msgid "Diffstat" msgstr "顯示內容差異" #: cola/difftool.py:324 msgid "Difftool" msgstr "內容差異檢視器" #: cola/widgets/clone.py:205 msgid "Directory Exists" msgstr "目錄已存在" #: cola/hidpi.py:42 msgid "Disable" msgstr "" #: cola/widgets/prefs.py:202 msgid "Display Untracked Files" msgstr "顯示未納入版本追蹤的檔案" #: cola/widgets/remote.py:176 msgid "Display remote messages in a separate dialog" msgstr "" #: cola/cmds.py:2043 msgid "Do not update stacked branches" msgstr "" #: cola/widgets/main.py:485 msgid "Documentation" msgstr "說明文件" #: cola/widgets/stash.py:61 msgid "Drop" msgstr "丟棄" #: cola/widgets/stash.py:276 msgid "Drop Stash" msgstr "丟棄珍藏項目" #: cola/widgets/stash.py:273 msgid "Drop Stash?" msgstr "要丟棄珍藏項目嗎?" #: cola/widgets/stash.py:275 #, python-format msgid "Drop the \"%s\" stash?" msgstr "是否要丟棄名為「%s」的珍藏項目?" #: cola/widgets/stash.py:61 msgid "Drop the selected stash" msgstr "丟棄被選取的珍藏項目" #: cola/qtutils.py:794 cola/sequenceeditor.py:405 cola/widgets/grep.py:100 msgid "Edit" msgstr "編輯" #: cola/widgets/diff.py:1058 msgid "Edit Diff Hunk to Revert..." msgstr "" #: cola/widgets/diff.py:1056 msgid "Edit Diff Hunk to Stage..." msgstr "" #: cola/widgets/diff.py:1124 msgid "Edit Diff Hunk to Unstage..." msgstr "" #: cola/cmds.py:2115 msgid "Edit Rebase" msgstr "編輯變更基底" #: cola/widgets/editremotes.py:34 msgid "Edit Remotes" msgstr "編輯遠端版控庫" #: cola/widgets/main.py:294 msgid "Edit Remotes..." msgstr "編輯遠端版控庫……" #: cola/widgets/diff.py:1053 msgid "Edit Selected Lines to Revert..." msgstr "" #: cola/widgets/diff.py:1051 msgid "Edit Selected Lines to Stage..." msgstr "" #: cola/widgets/diff.py:1122 msgid "Edit Selected Lines to Unstage..." msgstr "" #: cola/widgets/editremotes.py:42 msgid "Edit remotes by selecting them from the list" msgstr "藉由從清單中選取它們來編輯遠端版控庫" #: cola/widgets/browse.py:198 cola/widgets/common.py:38 msgid "Edit selected paths" msgstr "編輯選取的路徑" #: cola/editpatch.py:45 msgid "Edit the following patch, which will then be applied to the staging area to stage the changes:" msgstr "" #: cola/editpatch.py:40 msgid "Edit the following patch, which will then be applied to the staging area to unstage the changes:" msgstr "" #: cola/editpatch.py:34 msgid "Edit the following patch, which will then be applied to the worktree to revert the changes:" msgstr "" #: cola/widgets/main.py:618 msgid "Edit..." msgstr "編輯……" #: cola/widgets/prefs.py:274 msgid "Editor" msgstr "文字編輯器" #: cola/editpatch.py:88 #, python-format msgid "Editor returned %s exit code. Not applying patch." msgstr "" #: cola/widgets/prefs.py:190 msgid "Email Address" msgstr "電子郵件地址" #: cola/widgets/about.py:240 cola/widgets/about.py:383 msgid "Email contributor" msgstr "寄電子郵件給這位貢獻者" #: cola/widgets/prefs.py:204 msgid "Enable Gravatar Icons" msgstr "" #: cola/widgets/prefs.py:183 msgid "Enable path autocompletion in tools" msgstr "" #: cola/widgets/diff.py:796 msgid "Enable word wrapping" msgstr "" #: cola/sequenceeditor.py:370 msgid "Enabled" msgstr "啟用" #: cola/guicmds.py:332 cola/widgets/branch.py:478 msgid "Enter New Branch Name" msgstr "輸入新的分支名稱" #: cola/guicmds.py:146 msgid "Enter a name for the new bare repo" msgstr "輸入新裸裝版本庫(bare repo)的名稱" #: cola/widgets/stash.py:253 msgid "Enter a name for the stash" msgstr "輸入珍藏項目的名稱" #: cola/widgets/stash.py:216 msgid "Enter a new name for the stash" msgstr "" #: cola/cmds.py:145 cola/cmds.py:175 cola/cmds.py:206 cola/cmds.py:284 #: cola/cmds.py:293 cola/cmds.py:308 cola/cmds.py:318 cola/cmds.py:460 #: cola/cmds.py:496 cola/cmds.py:534 cola/cmds.py:634 cola/cmds.py:752 #: cola/cmds.py:1067 cola/cmds.py:1164 cola/cmds.py:1955 cola/cmds.py:2343 #: cola/cmds.py:2577 cola/cmds.py:2583 cola/cmds.py:2591 cola/cmds.py:2816 #: cola/cmds.py:2834 cola/cmds.py:3123 cola/gitcmds.py:1015 cola/guicmds.py:156 #: cola/models/stash.py:70 cola/models/stash.py:90 cola/models/stash.py:112 #: cola/models/stash.py:138 cola/widgets/bookmarks.py:481 #: cola/widgets/branch.py:829 msgid "Error" msgstr "發生錯誤" #: cola/widgets/clone.py:189 msgid "Error Cloning" msgstr "克隆發生錯誤" #: cola/widgets/createbranch.py:312 msgid "Error Creating Branch" msgstr "建立新的分支時發生錯誤" #: cola/app.py:501 cola/guicmds.py:100 msgid "Error Creating Repository" msgstr "無法建立新的版控庫" #: cola/cmds.py:1205 msgid "Error Deleting Remote Branch" msgstr "移除遠端分支失敗" #: cola/cmds.py:1572 msgid "Error Editing File" msgstr "編輯檔案發生錯誤" #: cola/cmds.py:559 msgid "Error Launching Blame Viewer" msgstr "啟動指謫(Blame)檢視器時發生錯誤" #: cola/cmds.py:3089 msgid "Error Launching History Browser" msgstr "無法啟動變動紀錄瀏覽器" #: cola/app.py:488 msgid "Error Opening Repository" msgstr "" #: cola/models/stash.py:144 msgid "Error Renaming Stash" msgstr "" #: cola/widgets/browse.py:567 msgid "Error Saving File" msgstr "" #: cola/cmds.py:911 #, python-format msgid "Error creating remote \"%s\"" msgstr "建立「%s」遠端分支時發生錯誤" #: cola/models/stash.py:233 msgid "Error creating stash" msgstr "建立新的珍藏項目時發生錯誤" #: cola/cmds.py:1126 #, python-format msgid "Error deleting branch \"%s\"" msgstr "" #: cola/cmds.py:929 #, python-format msgid "Error deleting remote \"%s\"" msgstr "移除「%s」遠端分支時發生錯誤" #: cola/cmds.py:954 #, python-format msgid "Error renaming \"%(name)s\" to \"%(new_name)s\"" msgstr "將「%(name)s」更名為「%(new_name)s」時發生錯誤" #: cola/cmds.py:1721 msgid "Error running prepare-commitmsg hook" msgstr "執行 prepare-commitmsg 掛勾程式時發生錯誤" #: cola/cmds.py:2987 cola/cmds.py:3033 #, fuzzy, python-format msgid "Error updating submodule %s" msgstr "建立「%s」遠端分支時發生錯誤" #: cola/cmds.py:3069 #, fuzzy msgid "Error updating submodules" msgstr "編輯檔案發生錯誤" #: cola/widgets/diff.py:1400 msgid "Error writing patch" msgstr "" #: cola/cmds.py:1661 msgid "Error: Cannot find commit template" msgstr "錯誤:無法找到修訂版提交範本" #: cola/cmds.py:1683 msgid "Error: Unconfigured commit template" msgstr "錯誤:未被設定的修訂版提交範本" #: cola/widgets/clone.py:52 #, python-format msgid "Error: could not clone \"%s\"" msgstr "錯誤:無法克隆「%s」版控庫" #: cola/cmds.py:2779 #, python-format msgid "Error: could not create tag \"%s\"" msgstr "錯誤:無法建立標籤「%s」" #: cola/widgets/branch.py:433 #, python-format msgid "Executing action %s" msgstr "正在執行「%s」動作" #: cola/widgets/status.py:66 msgid "Exit \"Diff\" mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff" msgstr "" #: cola/widgets/main.py:542 msgid "Exit Diff Mode" msgstr "" #: cola/widgets/action.py:81 msgid "Exit Diff mode" msgstr "" #: cola/widgets/recent.py:65 msgid "Expand all" msgstr "全部展開" #: cola/widgets/diff.py:1297 msgid "Export Patch" msgstr "" #: cola/guicmds.py:167 cola/widgets/search.py:74 msgid "Export Patches" msgstr "匯出修正檔" #: cola/widgets/main.py:269 msgid "Export Patches..." msgstr "匯出修正……" #: cola/widgets/main.py:547 msgid "Expression..." msgstr "比較表達式之間的內容差異……" #: cola/widgets/grep.py:115 msgid "Extended Regexp" msgstr "延伸正規表達式" #: cola/widgets/commitmsg.py:634 msgid "Extended description..." msgstr "延伸描述……" #: cola/cmds.py:388 msgid "Failed to commit and continue applying patches" msgstr "" #: cola/cmds.py:404 msgid "Failed to continue applying patches after skipping the current patch" msgstr "" #: cola/widgets/createbranch.py:122 msgid "Fast Forward Only" msgstr "僅更新可進行快速前移式合併者" #: cola/widgets/remote.py:181 msgid "Fast-forward only" msgstr "只允許快速前移式合併" #: cola/widgets/bookmarks.py:90 msgid "Favorite repositories" msgstr "喜愛的版控庫" #: cola/widgets/main.py:109 msgid "Favorites" msgstr "喜愛的版控庫" #: cola/widgets/remote.py:735 msgid "Fetch" msgstr "自遠端版控庫撈取(fetch)" #: cola/widgets/createbranch.py:125 msgid "Fetch Tracking Branch" msgstr "撈取(fetch)追蹤分支" #: cola/widgets/action.py:67 cola/widgets/main.py:385 msgid "Fetch from one or more remotes using \"git fetch\"" msgstr "" #: cola/widgets/action.py:65 cola/widgets/main.py:384 msgid "Fetch..." msgstr "自遠端版控庫撈取(fetch)……" #: cola/widgets/main.py:602 msgid "File Browser..." msgstr "檔案瀏覽器……" #: cola/widgets/compare.py:74 msgid "File Differences" msgstr "檔案變化" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 msgid "File Saved" msgstr "檔案已保存" #: cola/widgets/archive.py:197 cola/widgets/browse.py:579 #, python-format msgid "File saved to \"%s\"" msgstr "檔案已保存至「%s」" #: cola/fsmonitor.py:530 msgid "File system change monitoring: disabled because \"cola.inotify\" is false.\n" msgstr "檔案系統變動監控:因為「cola.inotify」 Git 設定值被設定為 false 而被停用。\n" #: cola/fsmonitor.py:547 msgid "File system change monitoring: disabled because libc does not support the inotify system calls.\n" msgstr "檔案系統變動監控:因為 libc 程式庫不支援 inotify 系統呼叫而被停用。\n" #: cola/fsmonitor.py:541 msgid "File system change monitoring: disabled because pywin32 is not installed.\n" msgstr "檔案系統變動監控:因為 pywin32 沒有安裝而被停用。\n" #: cola/fsmonitor.py:184 msgid "" "File system change monitoring: disabled because the limit on the total number of inotify watches was reached. You may be able to increase the limit on the number of watches by running:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" msgstr "" "檔案系統變動監控:因為已經達到 inotify watch 的總數上限而被停用。您可以執行下列命令來增加 watch 的數量限制:\n" "\n" " echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n" #: cola/fsmonitor.py:145 msgid "File system change monitoring: enabled.\n" msgstr "檔案系統變動監控:已啟用。\n" #: cola/widgets/filelist.py:25 msgid "Filename" msgstr "檔案名稱" #: cola/widgets/dag.py:821 msgid "Files" msgstr "檔案" #: cola/widgets/branch.py:837 msgid "Filter branches..." msgstr "過濾分支名稱……" #: cola/widgets/status.py:1333 msgid "Filter paths..." msgstr "過濾檔案路徑……" #: cola/widgets/finder.py:112 cola/widgets/main.py:308 msgid "Find Files" msgstr "尋找檔案" #: cola/widgets/text.py:383 msgid "Find in diff" msgstr "" #: cola/widgets/text.py:420 msgid "Find next item" msgstr "" #: cola/widgets/text.py:426 msgid "Find previous item" msgstr "" #: cola/widgets/text.py:390 msgid "Find the next occurrence of the phrase" msgstr "" #: cola/widgets/text.py:386 msgid "Find the previous occurrence of the phrase" msgstr "" #: cola/widgets/grep.py:115 msgid "Fixed String" msgstr "固定內容字串" #: cola/widgets/prefs.py:270 msgid "Fixed-Width Font" msgstr "等寬字型" #: cola/sequenceeditor.py:410 msgid "Fixup" msgstr "修理" #: cola/widgets/commitmsg.py:154 msgid "Fixup Previous Commit" msgstr "修理先前的修訂版提交" #: cola/themes.py:684 msgid "Flat dark blue" msgstr "" #: cola/themes.py:705 msgid "Flat dark green" msgstr "" #: cola/themes.py:698 msgid "Flat dark grey" msgstr "" #: cola/themes.py:691 msgid "Flat dark red" msgstr "" #: cola/themes.py:656 msgid "Flat light blue" msgstr "" #: cola/themes.py:677 msgid "Flat light green" msgstr "" #: cola/themes.py:670 msgid "Flat light grey" msgstr "" #: cola/themes.py:663 msgid "Flat light red" msgstr "" #: cola/widgets/startup.py:72 msgid "Folder" msgstr "" #: cola/widgets/toolbar.py:181 msgid "Follow System Style" msgstr "" #: cola/widgets/prefs.py:271 msgid "Font Size" msgstr "字體大小" #: cola/widgets/remote.py:197 msgid "Force" msgstr "強制" #: cola/widgets/remote.py:651 msgid "Force Fetch" msgstr "強制撈取(fetch)" #: cola/widgets/remote.py:648 msgid "Force Fetch?" msgstr "要進行強制撈取(fetch)嗎?" #: cola/widgets/remote.py:659 msgid "Force Push" msgstr "強制推送" #: cola/widgets/remote.py:653 msgid "Force Push?" msgstr "要進行強制推送(push)嗎?" #: cola/widgets/remote.py:650 #, python-format msgid "Force fetching from %s?" msgstr "是否要強制自「%s」撈取(fetch)?" #: cola/widgets/remote.py:658 #, python-format msgid "Force push to %s?" msgstr "要強制推送至「%s」遠端版控庫嗎?" #: cola/widgets/status.py:1376 msgid "Format String" msgstr "格式字串" #: cola/widgets/about.py:412 cola/widgets/about.py:413 msgid "French translation" msgstr "法語翻譯" #: cola/widgets/merge.py:78 msgid "GPG-sign the merge commit" msgstr "用 GPG 簽署合併修訂版提交" #: cola/widgets/prefs.py:364 msgid "GUI theme" msgstr "" #: cola/widgets/editremotes.py:315 #, python-format msgid "Gathering info for \"%s\"..." msgstr "正在蒐集「%s」遠端版控庫的資訊……" #: cola/widgets/about.py:402 cola/widgets/about.py:410 #: cola/widgets/about.py:411 msgid "German translation" msgstr "德語翻譯" #: cola/widgets/main.py:525 msgid "Get Commit Message Template" msgstr "取得修訂版提交訊息範本" #: cola/widgets/dag.py:586 msgid "Go Down" msgstr "往下移動" #: cola/widgets/dag.py:582 msgid "Go Up" msgstr "往上移動" #: cola/widgets/dag.py:466 cola/widgets/filelist.py:41 msgid "Grab File..." msgstr "提取檔案……" #: cola/widgets/dag.py:848 msgid "Graph" msgstr "圖" #: cola/widgets/main.py:354 msgid "Grep" msgstr "搜尋(grep)" #: cola/widgets/remote.py:707 msgid "Have you rebased/pulled lately?" msgstr "您最近有作變更基底或 pull 操作嗎?" #: cola/sequenceeditor.py:109 cola/sequenceeditor.py:176 #: cola/widgets/finder.py:137 cola/widgets/main.py:868 msgid "Help" msgstr "尋求幫助" #: cola/widgets/status.py:1322 msgid "Help - Custom Copy Actions" msgstr "求助 - 自訂複製操作" #: cola/widgets/finder.py:78 msgid "Help - Find Files" msgstr "尋求幫助 - 尋找檔案" #: cola/sequenceeditor.py:833 msgid "Help - git-cola-sequence-editor" msgstr "尋求幫助 - git-cola-sequence-editor" #: cola/widgets/prefs.py:366 msgid "High DPI" msgstr "" #: cola/gitcmds.py:907 msgid "Hint: The \"Actions > Abort Cherry-Pick\" menu action can be used to cancel the current cherry-pick." msgstr "" #: cola/widgets/prefs.py:275 msgid "History Browser" msgstr "變更紀錄瀏覽器" #: cola/widgets/about.py:409 cola/widgets/about.py:423 msgid "Hungarian translation" msgstr "匈牙利語翻譯" #: cola/widgets/toolbar.py:182 msgid "Icon Only" msgstr "" #: cola/widgets/prefs.py:365 msgid "Icon theme" msgstr "" #: cola/widgets/diff.py:787 msgid "Ignore all whitespace" msgstr "忽略所有的空白" #: cola/widgets/diff.py:785 msgid "Ignore changes in amount of whitespace" msgstr "忽略空白數量的變更" #: cola/widgets/diff.py:782 msgid "Ignore changes in whitespace at EOL" msgstr "忽略行結尾處空白的變更" #: cola/widgets/gitignore.py:45 msgid "Ignore custom pattern" msgstr "忽略自訂式樣" #: cola/widgets/gitignore.py:43 msgid "Ignore exact filename" msgstr "忽略完全一致的檔名" #: cola/widgets/gitignore.py:31 msgid "Ignore filename or pattern" msgstr "忽略檔案名稱或是式樣" #: cola/widgets/dag.py:498 msgid "Ignore merge commits" msgstr "" #: cola/widgets/status.py:933 msgid "Ignore..." msgstr "" #: cola/widgets/remote.py:207 msgid "Include tags " msgstr "包含標籤 " #: cola/widgets/prefs.py:369 msgid "Indent Status paths" msgstr "" #: cola/widgets/about.py:401 cola/widgets/about.py:408 msgid "Indonesian translation" msgstr "印度尼西亞語翻譯" #: cola/widgets/main.py:657 msgid "Initialize Git Annex" msgstr "初始化 Git Annex" #: cola/widgets/main.py:661 msgid "Initialize Git LFS" msgstr "初始化 Git LFS" #: cola/widgets/clone.py:114 msgid "Inititalize submodules" msgstr "初始化子模組" #: cola/widgets/prefs.py:281 msgid "Insert spaces instead of tabs" msgstr "插入空白字元而非跨欄字元(tab)" #: cola/widgets/action.py:73 cola/widgets/main.py:403 msgid "Integrate changes using \"git pull\"" msgstr "" #: cola/cmds.py:2079 msgid "Interactive Rebase" msgstr "互動式變更基底" #: cola/cmds.py:2313 msgid "Invalid Revision" msgstr "無效的修訂版" #: cola/editpatch.py:61 msgid "It is not necessary to update the hunk header lines as they will be regenerated automatically." msgstr "" #: cola/widgets/about.py:403 cola/widgets/about.py:406 msgid "Japanese translation" msgstr "" #: cola/widgets/prefs.py:283 msgid "Keep *.orig Merge Backups" msgstr "保留 *.orig merge 備份檔" #: cola/widgets/stash.py:73 msgid "Keep Index" msgstr "保留 index" #: cola/widgets/main.py:491 msgid "Keyboard Shortcuts" msgstr "鍵盤快捷鍵" #: cola/difftool.py:27 cola/sequenceeditor.py:170 cola/sequenceeditor.py:386 #: cola/widgets/dag.py:394 cola/widgets/filelist.py:33 msgid "Launch Diff Tool" msgstr "啟動差異檢視工具" #: cola/widgets/dag.py:401 msgid "Launch Directory Diff Tool" msgstr "啟動目錄差異檢視工具" #: cola/cmds.py:1528 cola/cmds.py:1630 cola/widgets/filelist.py:37 msgid "Launch Editor" msgstr "啟動文字編輯器" #: cola/cmds.py:1595 msgid "Launch Terminal" msgstr "啟動終端機" #: cola/sequenceeditor.py:171 msgid "" "Launch external diff tool\n" "Shortcut: Ctrl+D" msgstr "" "啟動外部內容差異檢視工具\n" "鍵盤快捷鍵:Ctrl+D" #: cola/widgets/diff.py:1044 cola/widgets/diff.py:1106 #: cola/widgets/status.py:852 cola/widgets/status.py:948 msgid "Launch git-cola" msgstr "啟動 git-cola" #: cola/widgets/browse.py:173 msgid "Launch git-difftool against previous versions" msgstr "對先前的版本啟動 git-difftool" #: cola/widgets/browse.py:165 msgid "Launch git-difftool on the current path" msgstr "在當前路徑中啟動 git-difftool" #: cola/icons.py:55 msgid "Light Theme" msgstr "" #: cola/editpatch.py:59 #, python-format msgid "Lines starting with '%s' will be ignored." msgstr "" #: cola/widgets/startup.py:73 msgid "List" msgstr "" #: cola/guicmds.py:266 msgid "Load Commit Message" msgstr "自檔案載入修訂版提交訊息" #: cola/widgets/main.py:335 msgid "Load Commit Message..." msgstr "自檔案載入修訂版提交訊息……" #: cola/widgets/commitmsg.py:150 msgid "Load Previous Commit Message" msgstr "載入先前的修訂版提交的訊息" #: cola/widgets/diff.py:264 msgid "Loading..." msgstr "正在載入……" #: cola/widgets/branch.py:173 cola/widgets/branch.py:250 #: cola/widgets/branch.py:290 cola/widgets/compare.py:37 #: cola/widgets/compare.py:52 cola/widgets/compare.py:57 msgid "Local" msgstr "本地" #: cola/widgets/cfgactions.py:225 cola/widgets/merge.py:44 #: cola/widgets/remote.py:136 msgid "Local Branch" msgstr "本地分支" #: cola/widgets/createbranch.py:112 msgid "Local branch" msgstr "本地分支" #: cola/widgets/dag.py:854 cola/widgets/main.py:665 msgid "Lock Layout" msgstr "鎖住版面" #: cola/widgets/dag.py:816 msgid "Log" msgstr "紀錄" #: cola/widgets/prefs.py:191 msgid "Log Date Format" msgstr "" #: cola/themes.py:769 msgid "MacOS Aqua dark" msgstr "" #: cola/themes.py:765 msgid "MacOS Aqua light" msgstr "" #: cola/themes.py:781 msgid "MacOS Vibrant dark" msgstr "" #: cola/themes.py:775 msgid "MacOS Vibrant light" msgstr "" #: cola/widgets/about.py:250 msgid "Maintainer (since 2007) and developer" msgstr "(自從 2007 年開始)維護者與開發者" #: cola/widgets/text.py:393 msgid "Match Case" msgstr "" #: cola/widgets/merge.py:86 msgid "Merge" msgstr "合併" #: cola/widgets/merge.py:160 #, python-format msgid "Merge \"%(revision)s\" into \"%(branch)s\"" msgstr "合併「%(revision)s」修訂版至「%(branch)s」分支中" #: cola/widgets/prefs.py:278 msgid "Merge Tool" msgstr "合併(merge)工具" #: cola/widgets/prefs.py:193 msgid "Merge Verbosity" msgstr "合併資訊詳細程度" #: cola/cmds.py:1779 msgid "Merge failed. Conflict resolution is required." msgstr "合併失敗. 需要解決衝突." #: cola/widgets/merge.py:165 #, python-format msgid "Merge into \"%s\"" msgstr "合併到「%s」分支" #: cola/widgets/branch.py:242 msgid "Merge into current branch" msgstr "合併進當前分支" #: cola/widgets/main.py:359 msgid "Merge..." msgstr "分支合併(merge)……" #: cola/widgets/main.py:1177 msgid "Merging" msgstr "正在進行分支合併" #: cola/models/browse.py:32 cola/widgets/createtag.py:76 msgid "Message" msgstr "訊息" #: cola/widgets/commitmsg.py:424 msgid "Missing Commit Message" msgstr "缺少修訂版提交訊息" #: cola/widgets/createbranch.py:250 msgid "Missing Data" msgstr "缺少資料" #: cola/cmds.py:2741 msgid "Missing Name" msgstr "缺少標籤名稱" #: cola/cmds.py:2735 msgid "Missing Revision" msgstr "缺少的修訂版" #: cola/cmds.py:2745 msgid "Missing Tag Message" msgstr "缺少標籤訊息" #: cola/models/browse.py:331 cola/widgets/status.py:158 #: cola/widgets/status.py:632 msgid "Modified" msgstr "已被修改" #: cola/widgets/commitmsg.py:528 msgid "More..." msgstr "更多……" #: cola/widgets/standard.py:242 cola/widgets/status.py:234 msgid "Move Down" msgstr "往下移動" #: cola/widgets/standard.py:234 cola/widgets/status.py:226 msgid "Move Up" msgstr "往上移動" #: cola/widgets/status.py:301 msgid "Move files to trash" msgstr "將檔案移動到資源回收筒" #: cola/models/browse.py:32 cola/widgets/bookmarks.py:466 #: cola/widgets/createtag.py:59 cola/widgets/editremotes.py:447 #: cola/widgets/status.py:1452 cola/widgets/toolbar.py:317 msgid "Name" msgstr "名稱" #: cola/widgets/editremotes.py:431 msgid "Name for the new remote" msgstr "新遠端版控庫的名稱" #: cola/guicmds.py:147 cola/widgets/main.py:281 msgid "New Bare Repository..." msgstr "新的裸裝版控庫(bare repository)……" #: cola/guicmds.py:86 cola/widgets/main.py:276 msgid "New Repository..." msgstr "新版控庫……" #: cola/widgets/main.py:997 msgid "New Toolbar" msgstr "新增工具列" #: cola/widgets/startup.py:52 msgid "New..." msgstr "新建……" #: cola/actions.py:56 msgid "Next File" msgstr "下個檔案" #: cola/widgets/createbranch.py:121 cola/widgets/standard.py:1181 msgid "No" msgstr "不更新" #: cola/widgets/merge.py:215 cola/widgets/merge.py:225 msgid "No Revision Specified" msgstr "沒有選取修訂版" #: cola/widgets/stash.py:225 msgid "No change made" msgstr "" #: cola/widgets/commitmsg.py:434 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit." msgstr "" "沒有可以提交的內容變動。\n" "\n" "提交前你必須至少將至少一個檔案移入新修訂版準備區域。" #: cola/widgets/selectcommits.py:117 msgid "No commits exist in this branch." msgstr "此分支中無任何修訂版提交。" #: cola/widgets/merge.py:63 msgid "No fast forward" msgstr "不進行快速前移式合併" #: cola/widgets/remote.py:190 msgid "No fast-forward" msgstr "不進行快速前移式合併" #: cola/widgets/remote.py:611 msgid "No repository selected." msgstr "沒有選擇版控庫。" #: cola/widgets/remote.py:649 msgid "Non-fast-forward fetch overwrites local history!" msgstr "非快速前移式的撈取(fetch)將會覆寫本地版控庫的變更紀錄!" #: cola/widgets/remote.py:655 msgid "" "Non-fast-forward push overwrites published history!\n" "(Did you pull first?)" msgstr "" "非快速前移式的推送(push)將會覆寫遠端版控庫的變更紀錄!\n" "(您有先 Pull 過了嗎?)" #: cola/widgets/commitmsg.py:451 msgid "Nothing to commit" msgstr "沒有東西可以提交" #: cola/gitcmds.py:626 msgid "Nothing to do" msgstr "沒有事情可做" #: cola/widgets/prefs.py:194 msgid "Number of Diff Context Lines" msgstr "內容差異上下文行數" #: cola/widgets/bookmarks.py:78 cola/widgets/bookmarks.py:212 #: cola/widgets/startup.py:335 msgid "Open" msgstr "開啟" #: cola/widgets/text.py:226 #, python-format msgid "Open \"%s\"" msgstr "" #: cola/cmds.py:1807 msgid "Open Directory" msgstr "" #: cola/guicmds.py:204 cola/guicmds.py:213 cola/widgets/editremotes.py:470 #: cola/widgets/startup.py:54 cola/widgets/startup.py:214 msgid "Open Git Repository" msgstr "開啟一個 Git 版控庫" #: cola/widgets/submodules.py:48 #, fuzzy msgid "Open Parent" msgstr "打開最近使用的版控庫" #: cola/cmds.py:1827 msgid "Open Parent Directory" msgstr "開啟上一層目錄" #: cola/widgets/main.py:693 msgid "Open Recent" msgstr "打開最近使用的版控庫" #: cola/cmds.py:1790 msgid "Open Using Default Application" msgstr "以系統預設的軟體開啟" #: cola/cmds.py:1840 msgid "Open Worktree" msgstr "" #: cola/widgets/bookmarks.py:220 cola/widgets/startup.py:343 msgid "Open in New Window" msgstr "於新 git-cola 視窗中開啟" #: cola/widgets/main.py:416 msgid "Open in New Window..." msgstr "於新 git-cola 視窗中開啟版控庫……" #: cola/widgets/main.py:410 msgid "Open..." msgstr "打開版控庫……" #: cola/widgets/branch.py:354 msgid "Other branches" msgstr "其他分支" #: cola/widgets/archive.py:208 msgid "Overwrite" msgstr "覆寫" #: cola/widgets/archive.py:207 #, python-format msgid "Overwrite \"%s\"?" msgstr "要覆寫「%s」嗎?" #: cola/widgets/archive.py:205 msgid "Overwrite File?" msgstr "要覆寫檔案嗎?" #: cola/widgets/grep.py:142 msgid "" "Parse arguments using a shell.\n" "Queries with spaces will require \"double quotes\"." msgstr "" "使用殼程式(shell)來解析參數。\n" "內含空白字元的查詢需使用 \"雙引號\" 括住。" #: cola/models/browse.py:329 msgid "Partially Staged" msgstr "部份內容變更被移入新修訂版準備區域" #: cola/widgets/main.py:758 msgid "Paste" msgstr "粘貼" #: cola/cmds.py:364 msgid "Patch failed to apply" msgstr "" #: cola/cmds.py:376 msgid "Patch(es) Applied" msgstr "已套用所有修正" #: cola/widgets/diff.py:1293 cola/widgets/main.py:709 msgid "Patches" msgstr "" #: cola/widgets/prefs.py:195 msgid "Patches Directory" msgstr "" #: cola/widgets/bookmarks.py:467 cola/widgets/submodules.py:117 msgid "Path" msgstr "所在路徑" #: cola/widgets/clone.py:110 msgid "Path or URL to clone (Env. $VARS okay)" msgstr "要克隆的路徑或 URL(可使用環境 $變數 )" #: cola/sequenceeditor.py:394 msgid "Pick" msgstr "" #: cola/widgets/dag.py:490 msgid "Pickaxe search for changes containing text" msgstr "" #: cola/widgets/diff.py:809 msgid "Pixel XOR" msgstr "像素互斥或(XOR)" #: cola/widgets/createbranch.py:251 msgid "Please provide both a branch name and revision expression." msgstr "請填寫分支名稱與修訂版表達式。" #: cola/cmds.py:2297 msgid "Please select a file" msgstr "請選擇一個檔案" #: cola/cmds.py:2741 msgid "Please specify a name for the new tag." msgstr "請指定新標籤的名稱。" #: cola/cmds.py:2735 msgid "Please specify a revision to tag." msgstr "請指定一個修訂版來套用標籤。" #: cola/widgets/commitmsg.py:417 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/cmds.py:654 msgid "Point the current branch head to a new commit?" msgstr "將當前分支的 head 指向一個新的修訂版提交?" #: cola/widgets/about.py:398 msgid "Polish translation" msgstr "波蘭語翻譯" #: cola/widgets/stash.py:65 cola/widgets/stash.py:114 cola/widgets/stash.py:118 msgid "Pop" msgstr "POP" #: cola/widgets/main.py:289 cola/widgets/prefs.py:433 msgid "Preferences" msgstr "偏好設定" #: cola/widgets/archive.py:127 msgid "Prefix" msgstr "前綴路徑" #: cola/widgets/main.py:341 msgid "Prepare Commit Message" msgstr "準備修訂版提交訊息" #: cola/widgets/prefs.py:180 msgid "Prevent \"Stage\" from staging all files when nothing is selected" msgstr "避免 Stage 快捷鍵在沒有選取任何項目時將所有檔案移至修訂版提交準備區域" #: cola/actions.py:65 msgid "Previous File" msgstr "上個檔案" #: cola/widgets/remote.py:169 msgid "Prompt on creation" msgstr "建新分支時提示" #: cola/widgets/remote.py:170 msgid "Prompt when pushing creates new remote branches" msgstr "在建立新的遠端分支時提示使用者" #: cola/widgets/remote.py:212 msgid "Prune " msgstr "清除(prune) " #: cola/widgets/bookmarks.py:254 cola/widgets/startup.py:375 msgid "Prune Missing Entries" msgstr "" #: cola/widgets/branch.py:256 cola/widgets/remote.py:783 msgid "Pull" msgstr "自遠端分支撈取並合併(pull)" #: cola/widgets/action.py:73 cola/widgets/main.py:402 msgid "Pull..." msgstr "自遠端分支撈取並合併(pull)……" #: cola/widgets/branch.py:262 cola/widgets/remote.py:627 #: cola/widgets/remote.py:758 msgid "Push" msgstr "推送至遠端版控庫" #: cola/widgets/action.py:70 cola/widgets/main.py:394 msgid "Push to one or more remotes using \"git push\"" msgstr "" #: cola/widgets/action.py:70 cola/widgets/main.py:393 msgid "Push..." msgstr "推送至遠端版控庫(push)……" #: cola/guicmds.py:251 msgid "Quick Open Repository" msgstr "" #: cola/widgets/main.py:674 msgid "Quick Open..." msgstr "" #: cola/widgets/main.py:351 msgid "Quit" msgstr "結束" #: cola/cmds.py:2093 cola/cmds.py:2129 cola/cmds.py:2130 cola/cmds.py:2143 #: cola/cmds.py:2144 cola/sequenceeditor.py:163 cola/sequenceeditor.py:205 #: cola/widgets/main.py:836 cola/widgets/remote.py:215 msgid "Rebase" msgstr "變更基底" #: cola/cmds.py:2092 #, python-format msgid "Rebase onto %s" msgstr "變更基底至 %s" #: cola/cmds.py:2105 msgid "Rebase stopped" msgstr "變更基底已停止" #: cola/widgets/remote.py:214 msgid "Rebase the current branch instead of merging" msgstr "不合併分支,而是將遠端分支變更基底到當前分支" #: cola/widgets/dag.py:418 msgid "Rebase to this commit" msgstr "" #: cola/widgets/main.py:1179 msgid "Rebasing" msgstr "正在進行變更基底程序" #: cola/widgets/main.py:118 msgid "Recent" msgstr "最近使用的版控庫" #: cola/widgets/bookmarks.py:92 msgid "Recent repositories" msgstr "最近使用的版控庫" #: cola/widgets/prefs.py:279 msgid "Recent repository count" msgstr "最近使用的版控庫數量" #: cola/widgets/recent.py:44 msgid "Recently Modified Files" msgstr "最近修改過的檔案" #: cola/widgets/main.py:316 msgid "Recently Modified Files..." msgstr "最近修改過的檔案……" #: cola/widgets/stash.py:274 msgid "Recovering a dropped stash is not possible." msgstr "要救回一個丟棄的珍藏項目是不可能的。" #: cola/widgets/createbranch.py:281 msgid "Recovering lost commits may not be easy." msgstr "恢復丟失的提交是比較困難的." #: cola/widgets/main.py:751 msgid "Redo" msgstr "重做" #: cola/widgets/clone.py:119 msgid "Reduce commit history to minimum" msgstr "將版本提交歷史量降到最低" #: cola/widgets/submodules.py:120 msgid "Reference Repository" msgstr "" #: cola/widgets/submodules.py:104 msgid "Reference URL" msgstr "" #: cola/widgets/submodules.py:105 msgid "Reference repository to use when cloning (optional)" msgstr "" #: cola/cmds.py:2171 cola/qtutils.py:800 cola/widgets/action.py:63 #: cola/widgets/dag.py:858 cola/widgets/editremotes.py:82 #: cola/widgets/grep.py:103 cola/widgets/recent.py:114 #: cola/widgets/submodules.py:44 msgid "Refresh" msgstr "重新整理" #: cola/widgets/remote.py:183 msgid "Refuse to merge unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward" msgstr "除非當前 HEAD 指標早就是最新版本或是分支合併能以快速前移式處理否則拒絕合併分支" #: cola/sequenceeditor.py:373 msgid "Remarks" msgstr "" #: cola/widgets/branch.py:177 cola/widgets/branch.py:236 #: cola/widgets/branch.py:278 cola/widgets/branch.py:513 #: cola/widgets/compare.py:53 cola/widgets/compare.py:58 #: cola/widgets/remote.py:145 msgid "Remote" msgstr "遠端" #: cola/widgets/remote.py:160 msgid "Remote Branch" msgstr "遠端分支名" #: cola/cmds.py:1196 msgid "Remote Branch Deleted" msgstr "已移除遠端分支" #: cola/widgets/log.py:100 msgid "Remote Messages" msgstr "" #: cola/widgets/editremotes.py:47 msgid "Remote git repositories - double-click to rename" msgstr "遠端 Git 版控庫 - 連續點兩下以重新命名" #: cola/cmds.py:1029 cola/widgets/diff.py:1702 cola/widgets/diff.py:1717 #: cola/widgets/startup.py:264 cola/widgets/status.py:1382 msgid "Remove" msgstr "移除" #: cola/cmds.py:1027 #, python-format msgid "Remove %s from the recent list?" msgstr "要將「%s」版控庫從最近使用的版控庫清單中移除嗎?" #: cola/widgets/toolbar.py:321 msgid "Remove Element" msgstr "移除元素" #: cola/widgets/remote.py:210 msgid "Remove remote-tracking branches that no longer exist on the remote" msgstr "移除不再存在於遠端板控庫上的遠端追蹤分支" #: cola/widgets/diff.py:1704 msgid "Remove selected (Delete)" msgstr "移除被選取的項目(刪除)" #: cola/widgets/bookmarks.py:257 cola/widgets/startup.py:378 msgid "Remove stale entries for repositories that no longer exist" msgstr "" #: cola/guicmds.py:332 cola/widgets/browse.py:159 cola/widgets/stash.py:44 msgid "Rename" msgstr "重新命名" #: cola/cmds.py:1153 #, python-format msgid "Rename \"%s\"" msgstr "重新命名「%s」" #: cola/widgets/branch.py:268 msgid "Rename Branch" msgstr "重新命名分支" #: cola/widgets/main.py:584 msgid "Rename Branch..." msgstr "重新命名分支……" #: cola/guicmds.py:329 msgid "Rename Existing Branch" msgstr "重新命名已存在的分支" #: cola/cmds.py:941 msgid "Rename Remote" msgstr "重新命名遠端版控庫" #: cola/widgets/bookmarks.py:232 cola/widgets/startup.py:355 msgid "Rename Repository" msgstr "更名版控庫" #: cola/widgets/stash.py:218 msgid "Rename Stash" msgstr "" #: cola/widgets/branch.py:478 msgid "Rename branch" msgstr "重新命名分支" #: cola/cmds.py:942 #, python-format msgid "Rename remote \"%(current)s\" to \"%(new)s\"?" msgstr "要將「%(current)s」遠端版控庫改名為「%(new)s」嗎?" #: cola/widgets/browse.py:159 msgid "Rename selected paths" msgstr "重新命名選取的路徑" #: cola/widgets/stash.py:45 msgid "Rename the selected stash" msgstr "" #: cola/app.py:496 cola/widgets/startup.py:261 msgid "Repository Not Found" msgstr "" #: cola/widgets/browse.py:87 cola/widgets/main.py:1109 #, python-format msgid "Repository: %s" msgstr "版控庫:%s" #: cola/guicmds.py:350 cola/widgets/createbranch.py:123 cola/widgets/dag.py:330 #: cola/widgets/editremotes.py:56 cola/widgets/main.py:846 msgid "Reset" msgstr "重設" #: cola/widgets/createbranch.py:284 #, python-format msgid "Reset \"%(branch)s\" to \"%(revision)s\"?" msgstr "要重設「%(branch)s」分支到 「%(revision)s」修訂版嗎?" #: cola/guicmds.py:358 msgid "Reset All (Keep Unstaged Changes)" msgstr "" #: cola/cmds.py:656 cola/cmds.py:707 cola/guicmds.py:341 #: cola/widgets/createbranch.py:293 msgid "Reset Branch" msgstr "重設分支" #: cola/cmds.py:704 cola/guicmds.py:340 cola/widgets/dag.py:424 #: cola/widgets/main.py:432 msgid "Reset Branch (Soft)" msgstr "" #: cola/cmds.py:653 cola/guicmds.py:349 cola/widgets/dag.py:430 #: cola/widgets/main.py:440 msgid "Reset Branch and Stage (Mixed)" msgstr "" #: cola/widgets/createbranch.py:290 msgid "Reset Branch?" msgstr "要重設分支嗎?" #: cola/widgets/main.py:669 msgid "Reset Layout" msgstr "" #: cola/cmds.py:688 msgid "Reset Worktree and Reset All?" msgstr "" #: cola/cmds.py:673 cola/cmds.py:690 cola/cmds.py:724 cola/guicmds.py:359 #: cola/guicmds.py:372 cola/guicmds.py:381 msgid "Reset and Restore" msgstr "" #: cola/cmds.py:705 msgid "Reset branch?" msgstr "" #: cola/widgets/createbranch.py:264 #, python-format msgid "Resetting \"%(branch)s\" to \"%(revision)s\" will lose commits." msgstr "重置「%(branch)s」分支到「%(revision)s」修訂版將導致修訂版提交的丟失。" #: cola/widgets/prefs.py:285 msgid "Resize File Browser columns" msgstr "" #: cola/widgets/prefs.py:412 msgid "Restart the application after changing appearance settings." msgstr "" #: cola/cmds.py:758 cola/cmds.py:761 cola/guicmds.py:389 cola/guicmds.py:390 #: cola/widgets/dag.py:460 cola/widgets/main.py:472 msgid "Restore Worktree" msgstr "" #: cola/cmds.py:721 cola/guicmds.py:380 cola/widgets/dag.py:453 #: cola/widgets/main.py:464 msgid "Restore Worktree and Reset All (Hard)" msgstr "" #: cola/cmds.py:670 cola/widgets/main.py:448 msgid "Restore Worktree and Reset All (Keep Unstaged Changes)" msgstr "" #: cola/widgets/dag.py:437 msgid "Restore Worktree and Reset All (Keep Unstaged Edits)" msgstr "" #: cola/cmds.py:687 cola/guicmds.py:371 cola/widgets/dag.py:445 #: cola/widgets/main.py:456 msgid "Restore Worktree and Reset All (Merge)" msgstr "" #: cola/cmds.py:722 msgid "Restore Worktree and Reset All?" msgstr "" #: cola/cmds.py:759 #, python-format msgid "Restore Worktree to %s?" msgstr "" #: cola/cmds.py:671 msgid "Restore worktree, reset, and preserve unstaged edits?" msgstr "" #: cola/widgets/dag.py:389 msgid "Revert" msgstr "撤銷修訂版提交" #: cola/widgets/diff.py:1227 msgid "Revert Diff Hunk" msgstr "撤銷選取內容差異區塊的內容變更" #: cola/widgets/diff.py:1057 msgid "Revert Diff Hunk..." msgstr "撤銷此內容差異區塊的內容變更……" #: cola/widgets/diff.py:1226 msgid "Revert Diff Hunk?" msgstr "要撤銷選取內容差異區塊的內容變更嗎?" #: cola/widgets/diff.py:1224 msgid "Revert Selected Lines" msgstr "撤銷選取行的內容變更" #: cola/widgets/diff.py:1052 msgid "Revert Selected Lines..." msgstr "撤銷選取行的內容變更……" #: cola/widgets/diff.py:1223 msgid "Revert Selected Lines?" msgstr "要撤銷選取行的內容變更嗎?" #: cola/cmds.py:2260 msgid "Revert Uncommitted Changes" msgstr "撤銷尚未提交至版控庫的內容變更" #: cola/cmds.py:2254 msgid "Revert Uncommitted Changes?" msgstr "要撤銷尚未提交至版控庫的內容變更嗎?" #: cola/cmds.py:2247 msgid "Revert Uncommitted Edits..." msgstr "撤銷尚未提交到版控庫的內容變更……" #: cola/cmds.py:2238 msgid "Revert Unstaged Changes" msgstr "撤銷尚未移入新修訂版準備區域的內容變動" #: cola/cmds.py:2232 msgid "Revert Unstaged Changes?" msgstr "要撤銷尚未移入新修訂版準備區域的內容變動嗎?" #: cola/cmds.py:2224 msgid "Revert Unstaged Edits..." msgstr "撤銷尚未移入新修訂版準備區域的內容修改……" #: cola/cmds.py:598 msgid "Revert failed" msgstr "" #: cola/cmds.py:2259 cola/widgets/diff.py:1235 msgid "Revert the uncommitted changes?" msgstr "要撤銷尚未提交至版控庫的內容變更嗎?" #: cola/cmds.py:2237 msgid "Revert the unstaged changes?" msgstr "要撤銷尚未移入新修訂版準備區域的內容變動嗎?" #: cola/widgets/browse.py:190 msgid "Revert uncommitted changes to selected paths" msgstr "在被選取的路徑中撤銷尚未提交進版控的內容變更" #: cola/widgets/browse.py:181 msgid "Revert unstaged changes to selected paths" msgstr "在被選取的路徑中撤銷尚未移入新修訂版準備區域的內容變更" #: cola/guicmds.py:320 msgid "Review" msgstr "審視(review)" #: cola/widgets/main.py:597 msgid "Review..." msgstr "審視(review)……" #: cola/widgets/cfgactions.py:231 cola/widgets/createtag.py:82 msgid "Revision" msgstr "修訂版" #: cola/widgets/selectcommits.py:61 msgid "Revision Expression:" msgstr "修訂版表達式:" #: cola/widgets/merge.py:37 cola/widgets/merge.py:40 msgid "Revision to Merge" msgstr "要合併的修訂版" #: cola/sequenceeditor.py:399 msgid "Reword" msgstr "重新敘述" #: cola/cmds.py:777 cola/widgets/commitmsg.py:463 msgid "Rewrite Published Commit?" msgstr "要重寫已推送出去的修訂版提交嗎?" #: cola/widgets/log.py:32 cola/widgets/log.py:134 msgid "Right-click links to open:" msgstr "" #: cola/interaction.py:125 cola/widgets/cfgactions.py:243 msgid "Run" msgstr "執行" #: cola/cmds.py:2290 #, python-format msgid "Run \"%s\"?" msgstr "要執行「%s」操作嗎?" #: cola/interaction.py:122 #, python-format msgid "Run %s?" msgstr "執行 %s?" #: cola/interaction.py:123 #, python-format msgid "Run the \"%s\" command?" msgstr "要執行「%s」命令嗎?" #: cola/cmds.py:2329 #, python-format msgid "Running command: %s" msgstr "執行命令:%s" #: cola/widgets/about.py:404 msgid "Russian translation" msgstr "俄羅斯語翻譯" #: cola/sequenceeditor.py:372 msgid "SHA-1" msgstr "SHA-1 雜湊" #: cola/widgets/prefs.py:205 msgid "Safe Mode" msgstr "安全模式" #: cola/cmds.py:2116 cola/widgets/archive.py:124 cola/widgets/browse.py:610 #: cola/widgets/editremotes.py:52 cola/widgets/stash.py:54 #: cola/widgets/status.py:1388 msgid "Save" msgstr "保存" #: cola/widgets/archive.py:111 msgid "Save Archive" msgstr "保存封存檔" #: cola/widgets/dag.py:381 cola/widgets/main.py:347 msgid "Save As Tarball/Zip..." msgstr "保存為 Tarball/Zip 封存檔…" #: cola/widgets/prefs.py:284 msgid "Save GUI Settings" msgstr "保存圖形介面設定" #: cola/widgets/stash.py:253 msgid "Save Stash" msgstr "保存珍藏項目" #: cola/widgets/stash.py:55 msgid "Save modified state to new stash" msgstr "將被修改的狀態保存為一個新的珍藏項目" #: cola/widgets/browse.py:571 #, python-format msgid "Saved \"%(filename)s\" from \"%(ref)s\" to \"%(destination)s\"" msgstr "已將「%(filename)s」檔案自「%(ref)s」修訂版保存至「%(destination)s」目錄" #: cola/widgets/bookmarks.py:82 cola/widgets/grep.py:96 #: cola/widgets/search.py:41 cola/widgets/search.py:61 msgid "Search" msgstr "搜尋" #: cola/widgets/search.py:225 msgid "Search Authors" msgstr "搜尋作者名" #: cola/widgets/search.py:223 msgid "Search Commit Messages" msgstr "搜尋修訂版提交訊息" #: cola/widgets/search.py:226 msgid "Search Committers" msgstr "搜尋提交者名" #: cola/widgets/search.py:227 msgid "Search Date Range" msgstr "搜尋日期範圍" #: cola/widgets/search.py:224 msgid "Search Diffs" msgstr "搜尋內容變更" #: cola/widgets/search.py:221 msgid "Search by Expression" msgstr "以表達式搜尋" #: cola/widgets/search.py:222 msgid "Search by Path" msgstr "以路徑搜尋" #: cola/widgets/dag.py:494 msgid "Search commit messages" msgstr "" #: cola/widgets/grep.py:122 msgid "Search for a fixed string" msgstr "搜尋一個固定內容字串" #: cola/widgets/diff.py:526 cola/widgets/diff.py:1577 msgid "Search in Diff" msgstr "" #: cola/guicmds.py:252 cola/widgets/bookmarks.py:61 msgid "Search repositories by name..." msgstr "" #: cola/widgets/grep.py:120 msgid "Search using a POSIX basic regular expression" msgstr "使用 POSIX 基本正規表達式來搜尋" #: cola/widgets/grep.py:121 msgid "Search using a POSIX extended regular expression" msgstr "使用 POSIX 延伸正規表達式來搜尋" #: cola/widgets/main.py:507 msgid "Search..." msgstr "尋找……" #: cola/widgets/selectcommits.py:66 msgid "Search:" msgstr "" #: cola/guicmds.py:329 cola/widgets/selectcommits.py:73 msgid "Select" msgstr "選擇" #: cola/widgets/main.py:764 msgid "Select All" msgstr "全選" #: cola/guicmds.py:320 msgid "Select Branch to Review" msgstr "選擇要審視(review)的分支" #: cola/widgets/dag.py:1667 msgid "Select Child" msgstr "選擇子節點" #: cola/widgets/commitmsg.py:534 msgid "Select Commit" msgstr "選取修訂版提交" #: cola/guicmds.py:136 msgid "Select Directory..." msgstr "選擇目錄……" #: cola/cmds.py:2078 msgid "Select New Upstream" msgstr "選擇新的上游版本" #: cola/widgets/dag.py:1671 msgid "Select Newest Child" msgstr "選取最新的子節點" #: cola/widgets/dag.py:1661 msgid "Select Oldest Parent" msgstr "選取最舊的母節點" #: cola/widgets/dag.py:1656 msgid "Select Parent" msgstr "選取" #: cola/widgets/browse.py:526 msgid "Select Previous Version" msgstr "選擇先前版本" #: cola/widgets/clone.py:195 msgid "Select a parent directory for the new clone" msgstr "選取新克隆的 Git 版控庫要放置的目錄" #: cola/widgets/standard.py:824 cola/widgets/standard.py:846 msgid "Select directory" msgstr "" #: cola/widgets/selectcommits.py:161 msgid "Select output dir" msgstr "選取輸出目錄" #: cola/widgets/selectcommits.py:182 msgid "Select output directory" msgstr "選擇要輸出的目錄" #: cola/widgets/diff.py:1770 msgid "Select patch file(s)..." msgstr "選擇修正檔……" #: cola/widgets/editremotes.py:434 msgid "Select repository" msgstr "選擇版控庫" #: cola/widgets/bookmarks.py:224 cola/widgets/startup.py:347 msgid "Set Default Repository" msgstr "設定預設版控庫" #: cola/widgets/branch.py:291 msgid "Set Upstream Branch" msgstr "設為上游追蹤分支" #: cola/widgets/branch.py:74 msgid "" "Set the sort order for branches and tags.\n" "Toggle between date-based and version-name-based sorting." msgstr "" #: cola/widgets/remote.py:217 msgid "Set upstream" msgstr "設為上游追蹤分支" #: cola/widgets/prefs.py:443 msgid "Settings" msgstr "設定值" #: cola/widgets/grep.py:140 msgid "Shell arguments" msgstr "殼程式參數" #: cola/sequenceeditor.py:423 msgid "Shift Down" msgstr "往下平移" #: cola/sequenceeditor.py:427 msgid "Shift Up" msgstr "往上平移" #: cola/widgets/about.py:481 msgid "Shortcuts" msgstr "鍵盤快捷鍵" #: cola/widgets/prefs.py:201 msgid "Show Diffstat After Merge" msgstr "在合併後顯示內容差異" #: cola/widgets/prefs.py:200 msgid "Show Full Paths in the Window Title" msgstr "在視窗標題列中顯示版控庫的完整路徑" #: cola/sequenceeditor.py:106 cola/widgets/finder.py:186 #: cola/widgets/status.py:1384 msgid "Show Help" msgstr "顯示幫助訊息" #: cola/widgets/filelist.py:29 msgid "Show History" msgstr "檢視變更紀錄" #: cola/widgets/prefs.py:368 msgid "Show file counts in Status titles" msgstr "" #: cola/widgets/diff.py:794 msgid "Show filenames" msgstr "" #: cola/sequenceeditor.py:176 cola/widgets/finder.py:137 msgid "" "Show help\n" "Shortcut: ?" msgstr "" "顯示幫助訊息\n" "鍵盤快捷鍵:?" #: cola/widgets/diff.py:792 msgid "Show line numbers" msgstr "顯示行號" #: cola/widgets/remote.py:175 msgid "Show remote messages" msgstr "" #: cola/widgets/diff.py:789 msgid "Show whole surrounding functions of changes" msgstr "秀出整個包含變更的函式內容" #: cola/widgets/recent.py:56 msgid "Showing changes since" msgstr "顯示變更自前" #: cola/widgets/diff.py:809 msgid "Side by side" msgstr "並列檢視" #: cola/cmds.py:2461 msgid "Sign Off" msgstr "署名(Sign Off)" #: cola/widgets/createtag.py:69 msgid "Sign Tag" msgstr "為標籤簽名" #: cola/widgets/commitmsg.py:56 msgid "Sign off on this commit" msgstr "於此修訂版提交上簽名" #: cola/widgets/about.py:394 cola/widgets/about.py:407 msgid "Simplified Chinese translation" msgstr "簡體中文翻譯" #: cola/cmds.py:2527 msgid "Skip" msgstr "跳過" #: cola/widgets/main.py:261 cola/widgets/main.py:631 msgid "Skip Current Patch" msgstr "跳過目前的修正" #: cola/widgets/main.py:262 msgid "Skip applying the current patch and continue applying patches" msgstr "" #: cola/widgets/prefs.py:282 msgid "Sort bookmarks alphabetically" msgstr "以字母順序排序書籤" #: cola/widgets/about.py:395 cola/widgets/about.py:418 #: cola/widgets/about.py:422 msgid "Spanish translation" msgstr "西班牙語翻譯" #: cola/widgets/createtag.py:86 msgid "Specifies the SHA-1 to tag" msgstr "指定 SHA-1 雜湊給標籤" #: cola/widgets/createtag.py:79 msgid "Specifies the tag message" msgstr "指定標籤訊息" #: cola/widgets/createtag.py:63 msgid "Specifies the tag name" msgstr "指定標籤的名稱" #: cola/widgets/spellcheck.py:45 msgid "Spelling Suggestions" msgstr "拼字建議" #: cola/sequenceeditor.py:417 cola/widgets/merge.py:56 msgid "Squash" msgstr "壓為單一修訂版提交" #: cola/widgets/merge.py:55 msgid "Squash the merged commits into a single commit" msgstr "將合併之修訂版提交(們)壓為單一修訂版提交" #: cola/cmds.py:2538 cola/widgets/action.py:58 cola/widgets/diff.py:1168 msgid "Stage" msgstr "移動到新修訂版準備區域" #: cola/cmds.py:2697 msgid "Stage / Unstage" msgstr "移入/移出新修訂版準備區域" #: cola/cmds.py:2679 msgid "Stage / Unstage All" msgstr "" #: cola/widgets/diff.py:1055 msgid "Stage Diff Hunk" msgstr "將此內容差異區塊移入新修訂版準備區域" #: cola/cmds.py:2631 msgid "Stage Modified" msgstr "將已變更的項目移入新修訂版準備區域" #: cola/cmds.py:2668 msgid "Stage Modified and Untracked" msgstr "" #: cola/widgets/status.py:872 cola/widgets/status.py:894 #: cola/widgets/status.py:962 msgid "Stage Selected" msgstr "將被選取的項目移入新修訂版準備區域" #: cola/widgets/diff.py:1050 msgid "Stage Selected Lines" msgstr "將選取的行移入新修訂版準備區域(&S)" #: cola/cmds.py:2642 msgid "Stage Unmerged" msgstr "將尚未合併的檔案移動到新修訂版準備區域" #: cola/cmds.py:2653 msgid "Stage Untracked" msgstr "將尚未追蹤其版本的項目移動到新修訂版準備區域" #: cola/widgets/commitmsg.py:445 msgid "Stage and Commit" msgstr "移入新修訂版準備區域並提交出去" #: cola/widgets/commitmsg.py:442 msgid "Stage and commit?" msgstr "要移入新修訂版準備區域並提交出去嗎?" #: cola/widgets/action.py:58 msgid "Stage changes using \"git add\"" msgstr "" #: cola/cmds.py:2526 msgid "Stage conflicts" msgstr "將合併衝突移入新修訂版準備區域" #: cola/cmds.py:2517 msgid "Stage conflicts?" msgstr "要將合併衝突移入新修訂版準備區域嗎?" #: cola/widgets/browse.py:146 msgid "Stage/unstage selected paths for commit" msgstr "將被選取的路徑移進/移出新修訂版準備區域" #: cola/models/browse.py:333 cola/widgets/status.py:156 #: cola/widgets/status.py:621 msgid "Staged" msgstr "已被移入新修訂版準備區域" #: cola/cmds.py:2545 #, python-format msgid "Staging: %s" msgstr "正在移動到新修訂版準備區域:%s" #: cola/widgets/main.py:611 msgid "Start Interactive Rebase..." msgstr "開始互動式變更基底……" #: cola/widgets/createbranch.py:105 msgid "Starting Revision" msgstr "起始修訂版" #: cola/widgets/stash.py:36 msgid "Stash" msgstr "珍藏項目" #: cola/widgets/stash.py:79 msgid "Stash Index" msgstr "將修訂版提交準備區域中的變更存為珍藏項目" #: cola/widgets/stash.py:79 msgid "Stash staged changes only" msgstr "只將移入新修訂版提交準備區域中的變更存為珍藏項目" #: cola/widgets/stash.py:75 msgid "Stash unstaged changes only, keeping staged changes" msgstr "只將尚未移入新修訂版提交準備區域的變更存入珍藏項目,保留移入新修訂版提交準備區域的變更" #: cola/widgets/action.py:76 cola/widgets/main.py:423 msgid "Stash..." msgstr "珍藏項目(STASH)..." #: cola/models/browse.py:32 cola/widgets/main.py:100 msgid "Status" msgstr "狀態" #: cola/widgets/browse.py:154 msgid "Stop tracking paths" msgstr "停止追蹤路徑" #: cola/widgets/submodules.py:81 msgid "Submodule URL (can be relative, ex: ../repo.git)" msgstr "" #: cola/widgets/submodules.py:89 msgid "Submodule branch to track (optional)" msgstr "" #: cola/widgets/submodules.py:85 msgid "Submodule path within the current repository (optional)" msgstr "" #: cola/widgets/main.py:141 cola/widgets/submodules.py:31 msgid "Submodules" msgstr "" #: cola/widgets/prefs.py:196 msgid "Summarize Merge Commits" msgstr "概述合併進來的內容提交(commit)" #: cola/sequenceeditor.py:374 cola/widgets/dag.py:572 msgid "Summary" msgstr "總結" #: cola/widgets/prefs.py:273 msgid "Tab Width" msgstr "Tab 字元的顯示寬度" #: cola/widgets/cfgactions.py:227 cola/widgets/createbranch.py:114 #: cola/widgets/merge.py:46 msgid "Tag" msgstr "標籤" #: cola/cmds.py:2786 msgid "Tag Created" msgstr "標籤已建立" #: cola/widgets/createtag.py:78 msgid "Tag message..." msgstr "標籤訊息……" #: cola/cmds.py:2746 msgid "Tag-signing was requested but the tag message is empty." msgstr "被要求要有標籤簽名但是標籤訊息是空的。" #: cola/widgets/branch.py:183 cola/widgets/branch.py:248 msgid "Tags" msgstr "標籤" #: cola/widgets/action.py:78 cola/widgets/main.py:424 msgid "Temporarily stash away uncommitted changes using \"git stash\"" msgstr "" #: cola/widgets/toolbar.py:184 msgid "Text Beside Icon" msgstr "" #: cola/widgets/toolbar.py:183 msgid "Text Only" msgstr "" #: cola/widgets/toolbar.py:185 msgid "Text Under Icon" msgstr "" #: cola/widgets/prefs.py:272 msgid "Text Width" msgstr "單行文字寬度限制" #: cola/cmds.py:1116 msgid "The branch will be no longer available." msgstr "此分支將不再存在。" #: cola/cmds.py:649 #, python-format msgid "The branch will be reset using \"git reset --mixed %s\"" msgstr "這個分支將會被用「git reset --mixed %s」命令重設" #: cola/cmds.py:700 cola/cmds.py:791 #, python-format msgid "The branch will be reset using \"git reset --soft %s\"" msgstr "這個分支將會被用「git reset --soft %s」命令重設" #: cola/widgets/commitmsg.py:310 msgid "The commit message will be cleared." msgstr "修訂版提交訊息將會被移除。" #: cola/widgets/prefs.py:169 msgid "" "The date-time format used when displaying dates in Git DAG.\n" "This value is passed to git log --date=" msgstr "" #: cola/widgets/archive.py:206 #, python-format msgid "The file \"%s\" exists and will be overwritten." msgstr "檔案「%s」已存在且將會被覆寫。" #: cola/cmds.py:1086 msgid "The following files will be deleted:" msgstr "下列檔案將會被移除:" #: cola/widgets/status.py:1646 msgid "The number of leading paths to strip" msgstr "" #: cola/cmds.py:717 #, python-format msgid "The repository will be reset using \"git reset --hard %s\"" msgstr "" #: cola/cmds.py:666 #, python-format msgid "The repository will be reset using \"git reset --keep %s\"" msgstr "" #: cola/cmds.py:683 #, python-format msgid "The repository will be reset using \"git reset --merge %s\"" msgstr "" #: cola/cmds.py:2314 msgid "The revision expression cannot be empty." msgstr "修訂版表達式不可以是空的。" #: cola/widgets/stash.py:225 msgid "The stash has not been renamed" msgstr "" #: cola/cmds.py:2973 #, python-format msgid "" "The submodule will be added using\n" "\"%s\"" msgstr "" #: cola/cmds.py:3018 #, python-format msgid "" "The submodule will be updated using\n" "\"%s\"" msgstr "" #: cola/cmds.py:737 #, python-format msgid "The worktree will be restored using \"git read-tree --reset -u %s\"" msgstr "" #: cola/widgets/commitmsg.py:311 msgid "This cannot be undone. Clear commit message?" msgstr "此操作將無法復原。要清除提交訊息嗎?" #: cola/cmds.py:779 cola/widgets/commitmsg.py:465 msgid "" "This commit has already been published.\n" "This operation will rewrite published history.\n" "You probably don't want to do this." msgstr "" "此修訂版提交已經被推送到遠端版控庫。\n" "此操作將會重寫已推送出去的變更紀錄。\n" "您可能不想要做此操作。" #: cola/widgets/diff.py:1232 msgid "" "This operation drops uncommitted changes.\n" "These changes cannot be recovered." msgstr "" "此操作將會丟棄尚未提交進版控庫的內容變更。\n" "這些內容變更將無法被救回。" #: cola/cmds.py:2256 msgid "" "This operation removes uncommitted edits from selected files.\n" "These changes cannot be recovered." msgstr "" "此操作將會丟棄尚未提交至版控庫的內容變更。\n" "這些內容變更將無法被救回。" #: cola/cmds.py:2234 msgid "" "This operation removes unstaged edits from selected files.\n" "These changes cannot be recovered." msgstr "" "此操作將丟棄尚未移入新修訂版準備區域的內容變動。\n" "這些內容變動將無法被還原。" #: cola/cmds.py:475 msgid "" "This operation will replace the selected unmerged files with content from the branch being merged using \"git checkout --theirs\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/cmds.py:513 msgid "" "This operation will replace the selected unmerged files with content from your current branch using \"git checkout --ours\".\n" "*ALL* uncommitted changes will be lost.\n" "Recovering uncommitted changes is not possible." msgstr "" #: cola/widgets/main.py:1123 msgid "" "This repository has unresolved conflicts after applying a patch.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1116 msgid "" "This repository is currently being rebased.\n" "Resolve conflicts, commit changes, and run:\n" " Rebase > Continue" msgstr "" "這個版控庫正在進行變更基底程序。\n" "解決所有的變更基底衝突,提交變更,然後執行:\n" " 變更基底 > 繼續" #: cola/widgets/main.py:1129 msgid "" "This repository is in the middle of a cherry-pick.\n" "Resolve conflicts and commit changes." msgstr "" #: cola/widgets/main.py:1135 msgid "" "This repository is in the middle of a merge.\n" "Resolve conflicts and commit changes." msgstr "" "本版控庫正在進行分支合併程序。\n" "將所有的合併衝突解決並提交內容變更。" #: cola/editpatch.py:58 msgid "To abort applying this patch, remove all lines." msgstr "" #: cola/editpatch.py:57 msgid "To avoid applying addition lines ('+'), delete them." msgstr "" #: cola/editpatch.py:55 msgid "To avoid applying removal lines ('-'), change them to context lines (' ')." msgstr "" #: cola/sequenceeditor.py:390 msgid "Toggle Enabled" msgstr "切換為啟用" #: cola/widgets/diff.py:804 msgid "Toggle image diff" msgstr "" #: cola/sequenceeditor.py:610 msgid "Toggle Remark" msgstr "" #: cola/widgets/filelist.py:128 msgid "Toggle remark of touching commits" msgstr "" #: cola/widgets/branch.py:65 msgid "Toggle the branches filter" msgstr "切換分支過濾器開關" #: cola/widgets/status.py:58 msgid "Toggle the paths filter" msgstr "切換路徑過濾器開關" #: cola/widgets/toolbar.py:322 msgid "Toolbar Style:" msgstr "" #: cola/widgets/cfgactions.py:226 cola/widgets/merge.py:45 msgid "Tracking Branch" msgstr "跟蹤分支" #: cola/widgets/createbranch.py:113 msgid "Tracking branch" msgstr "追蹤分支" #: cola/widgets/about.py:390 cola/widgets/about.py:416 #: cola/widgets/about.py:427 msgid "Traditional Chinese (Taiwan) translation" msgstr "傳統中文(台灣)翻譯" #: cola/widgets/about.py:421 msgid "Translation" msgstr "" #: cola/widgets/about.py:91 msgid "Translators" msgstr "翻譯者群" #: cola/widgets/about.py:400 cola/widgets/about.py:405 #: cola/widgets/about.py:420 msgid "Turkish translation" msgstr "土耳其語翻譯" #: cola/widgets/clone.py:107 cola/widgets/editremotes.py:448 #: cola/widgets/submodules.py:116 msgid "URL" msgstr "URL" #: cola/widgets/remote.py:496 #, python-format msgid "URL: %s" msgstr "URL: %s" #: cola/widgets/about.py:397 msgid "Ukranian translation" msgstr "烏克蘭語翻譯" #: cola/cmds.py:2071 msgid "Unable to rebase" msgstr "無法變更基底" #: cola/cmds.py:972 #, python-format msgid "Unable to set URL for \"%(name)s\" to \"%(url)s\"" msgstr "無法將「%(name)s」的 URL 設定為 %(url)s" #: cola/widgets/diff.py:1401 #, python-format msgid "Unable to write patch to \"%s\". Check permissions?" msgstr "" #: cola/widgets/main.py:749 msgid "Undo" msgstr "撤銷" #: cola/cmds.py:784 cola/cmds.py:789 cola/cmds.py:792 cola/widgets/main.py:208 msgid "Undo Last Commit" msgstr "" #: cola/cmds.py:790 msgid "Undo last commit?" msgstr "" #: cola/cmds.py:783 msgid "Undo the published commit?" msgstr "" #: cola/models/browse.py:327 cola/widgets/status.py:157 #: cola/widgets/status.py:641 msgid "Unmerged" msgstr "尚未合併" #: cola/cmds.py:2799 cola/widgets/action.py:61 cola/widgets/diff.py:1165 #: cola/widgets/main.py:213 msgid "Unstage" msgstr "移出新修訂版準備區域" #: cola/widgets/main.py:203 cola/widgets/status.py:790 msgid "Unstage All" msgstr "將所有項目移出新修訂版準備區域" #: cola/widgets/diff.py:1017 msgid "Unstage Diff Hunk" msgstr "將此內容差異區塊移出新修訂版準備區域" #: cola/widgets/status.py:823 cola/widgets/status.py:858 msgid "Unstage Selected" msgstr "將被選取的項目移出新修訂版準備區域" #: cola/widgets/diff.py:1015 msgid "Unstage Selected Lines" msgstr "將被選取的行移出新修訂版準備區域" #: cola/widgets/action.py:61 msgid "Unstage changes using \"git reset\"" msgstr "" #: cola/cmds.py:2811 #, python-format msgid "Unstaging: %s" msgstr "正在將「%s」移出新修訂版準備區域" #: cola/widgets/browse.py:153 msgid "Untrack Selected" msgstr "將被選取的項目移出新修訂版準備區域" #: cola/widgets/status.py:159 cola/widgets/status.py:647 msgid "Untracked" msgstr "未納入版本追蹤" #: cola/cmds.py:1141 cola/cmds.py:2867 #, python-format msgid "Untracking: %s" msgstr "正在將「%s」移出新修訂版準備區域" #: cola/widgets/main.py:370 msgid "Update All Submodules..." msgstr "" #: cola/widgets/createbranch.py:119 msgid "Update Existing Branch:" msgstr "是否更新既有分支:" #: cola/cmds.py:3019 #, fuzzy msgid "Update Submodule" msgstr "已更新" #: cola/cmds.py:3016 msgid "Update Submodule..." msgstr "" #: cola/cmds.py:3055 #, fuzzy msgid "Update Submodules" msgstr "初始化子模組" #: cola/cmds.py:3053 #, fuzzy msgid "Update all submodules?" msgstr "初始化子模組" #: cola/cmds.py:2042 msgid "Update stacked branches" msgstr "" #: cola/cmds.py:2034 cola/cmds.py:2041 msgid "Update stacked branches when rebasing?" msgstr "" #: cola/cmds.py:3052 #, fuzzy msgid "Update submodules..." msgstr "初始化子模組" #: cola/widgets/status.py:953 #, fuzzy msgid "Update this submodule" msgstr "初始化子模組" #: cola/cmds.py:3017 msgid "Update this submodule?" msgstr "" #: cola/widgets/branch.py:433 cola/widgets/createbranch.py:300 msgid "Updating" msgstr "正在更新" #: cola/widgets/prefs.py:370 msgid "Use a block cursor in diff editors" msgstr "" #: cola/widgets/prefs.py:177 msgid "Use gravatar.com to lookup icons for author emails" msgstr "" #: cola/widgets/prefs.py:189 msgid "User Name" msgstr "使用者名稱" #: cola/widgets/about.py:89 msgid "Version" msgstr "版本" #: cola/widgets/dag.py:866 cola/widgets/main.py:859 cola/widgets/main.py:980 msgid "View" msgstr "檢視" #: cola/widgets/browse.py:137 cola/widgets/status.py:279 msgid "View History..." msgstr "檢視變更紀錄……" #: cola/widgets/browse.py:138 msgid "View history for selected paths" msgstr "檢視被選取的路徑(們)的變更紀錄" #: cola/widgets/branch.py:224 cola/widgets/merge.py:52 msgid "Visualize" msgstr "視覺化顯示" #: cola/widgets/main.py:502 msgid "Visualize All Branches..." msgstr "視覺化顯示所有分支……" #: cola/widgets/main.py:496 msgid "Visualize Current Branch..." msgstr "視覺化顯示當前分支……" #: cola/widgets/createtag.py:71 msgid "Whether to sign the tag (git tag -s)" msgstr "是否簽名此標籤 (git tag -s)" #: cola/widgets/text.py:394 msgid "Whole Words" msgstr "" #: cola/widgets/commitmsg.py:439 msgid "Would you like to stage and commit all modified files?" msgstr "您要將所有被修改的檔案移入新修訂版準備區域並提交出去嗎?" #: cola/widgets/diff.py:809 msgid "XOR" msgstr "互斥或(XOR)" #: cola/widgets/standard.py:1180 msgid "Yes" msgstr "是" #: cola/cmds.py:255 msgid "" "You are in the middle of a merge.\n" "Cannot amend while merging." msgstr "" "您現在正在進行分支合併。\n" "您不能在進行分支合併時修正前一次的修訂版提交。" #: cola/cmds.py:2072 msgid "You cannot rebase with uncommitted changes." msgstr "您不能在還有尚未提交至版控庫的內容變更的時候進行變更基底。" #: cola/widgets/merge.py:225 msgid "You must specify a revision to merge." msgstr "您必須要選擇一個修訂版來合併。" #: cola/widgets/merge.py:215 msgid "You must specify a revision to view." msgstr "您必須要選擇一個修訂版來檢視。" #: cola/widgets/dag.py:776 cola/widgets/dag.py:1645 msgid "Zoom In" msgstr "放大" #: cola/widgets/dag.py:772 cola/widgets/dag.py:1651 msgid "Zoom Out" msgstr "縮小" #: cola/widgets/dag.py:590 cola/widgets/dag.py:780 cola/widgets/dag.py:1653 #: cola/widgets/diff.py:813 msgid "Zoom to Fit" msgstr "縮放以符合視窗大小" #: cola/widgets/grep.py:110 msgid "command-line arguments" msgstr "命令列參數" #: cola/widgets/main.py:946 cola/widgets/main.py:952 msgid "error: unable to execute git" msgstr "錯誤:無法執行 git" #: cola/widgets/log.py:52 #, python-format msgid "exit code %s" msgstr "程式以 %s 狀態碼結束" #: cola/app.py:300 #, python-format msgid "fatal: \"%s\" is not a directory. Please specify a correct --repo ." msgstr "致命錯誤:「%s」並不是個目錄。請指定一個正確的 --repo 〈路徑〉。" #: cola/widgets/main.py:942 #, python-format msgid "git cola version %s" msgstr "git cola 第 %s 版" #: cola/widgets/startup.py:34 msgid "git-cola" msgstr "git-cola" #: cola/difftool.py:82 msgid "git-cola diff" msgstr "git-cola diff" #: cola/widgets/submodules.py:80 msgid "git://git.example.com/repo.git" msgstr "" #: cola/widgets/grep.py:130 msgid "grep result..." msgstr "搜尋結果……" #: cola/widgets/about.py:468 msgid "hotkeys.html" msgstr "hotkeys_zh_TW.html" #: cola/widgets/submodules.py:84 msgid "path/to/submodule" msgstr "" #: cola/widgets/createtag.py:61 msgid "vX.Y.Z" msgstr "X.Y.Z版本" #: cola/hidpi.py:43 msgid "x 1" msgstr "" #: cola/hidpi.py:44 msgid "x 1.25" msgstr "" #: cola/hidpi.py:45 msgid "x 1.5" msgstr "" #: cola/hidpi.py:46 msgid "x 2" msgstr "" #: cola/widgets/search.py:52 cola/widgets/search.py:57 msgid "yyyy-MM-dd" msgstr "yyyy-MM-dd" #~ 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 "" #~ "\n" #~ "Commands\n" #~ "--------\n" #~ "pick = use commit\n" #~ "reword = use commit, but edit the commit message\n" #~ "edit = use commit, but stop for amending\n" #~ "squash = use commit, but meld into previous commit\n" #~ "fixup = like \"squash\", but discard this commit's log message\n" #~ "exec = run command (the rest of the line) using shell\n" #~ "\n" #~ "These lines can be re-ordered; they are executed from top to bottom.\n" #~ "\n" #~ "If you disable a line here THAT COMMIT WILL BE LOST.\n" #~ "\n" #~ "However, if you disable everything, the rebase will be aborted.\n" #~ "\n" #~ "Keyboard Shortcuts\n" #~ "------------------\n" #~ "? = show help\n" #~ "j = move down\n" #~ "k = move up\n" #~ "J = shift row down\n" #~ "K = shift row up\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "spacebar = toggle enabled\n" #~ "\n" #~ "ctrl+enter = accept changes and rebase\n" #~ "ctrl+q = cancel and abort the rebase\n" #~ "ctrl+d = launch difftool\n" #~ msgstr "" #~ "\n" #~ "可用命令\n" #~ "--------\n" #~ "pick = 選用這個修訂版提交\n" #~ "reword = 選用這個修訂版提交,但編輯修訂版提交訊息\n" #~ "edit = 選用這個修訂版提交,但停下來以進行修正(amending)\n" #~ "squash = 選用這個修訂版提交,但是將其併入前一個修訂版提交\n" #~ "fixup = 跟 squash 雷同,但丟棄此修訂版提交的紀錄訊息\n" #~ "exec = 使用殼層(shell)執行命令(剩下的行)\n" #~ "\n" #~ "這些行可以被更動順序,他們將被從上至下執行。\n" #~ "\n" #~ "如果你停用任一行**該修訂版提交將會遺失**。\n" #~ "\n" #~ "但是,如果您停用所有行,這次變更基底(rebase)將被中止。\n" #~ "\n" #~ "鍵盤快捷鍵\n" #~ "------------------\n" #~ "? = 顯示此幫助訊息\n" #~ "j = 往下移動\n" #~ "k = 往上移動\n" #~ "J = 將選取的行往下平移\n" #~ "K = 將選取的行往上平移\n" #~ "\n" #~ "1, p = pick\n" #~ "2, r = reword\n" #~ "3, e = edit\n" #~ "4, f = fixup\n" #~ "5, s = squash\n" #~ "空白鍵 = 切換啟用/停用\n" #~ "\n" #~ "ctrl+enter = 接受變更並變更基底\n" #~ "ctrl+q = 取消並中止變更基底程序\n" #~ "ctrl+d = 啟動內容差異檢視工具\n" #~ msgid "" #~ "\n" #~ "This is due to a known issue with the\n" #~ "Tcl binary distributed by Cygwin." #~ msgstr "" #~ "\n" #~ "這是由 Cygwin 發佈的 Tcl 代碼中一個\n" #~ "已知問題所引起." #~ msgid "\"%s\" returned exit status %d" #~ msgstr "「%s」命令傳回了 %d 結束狀態碼" #~ msgid "\"git commit\" returned exit code %s" #~ msgstr "「git commit」命令傳回 %s 結束狀態碼" #~ msgid "%s ... %*i of %*i %s (%3i%%)" #~ msgstr "%s ... %*i of %*i %s (%3i%%)" #~ msgid "%s Repository" #~ msgstr "%s 版本庫" #~ msgid "'%s' is not an acceptable branch name." #~ msgstr "'%s'不是一個可接受的分支名." #~ msgid "* Binary file (not showing content)." #~ msgstr "* 二進制文件 (不顯示內容)." #~ msgid "A branch is required for 'Merged Into'." #~ msgstr "'合併到' 需要指定某個分支" #, python-format #~ msgid "A stash named \"%s\" already exists" #~ msgstr "名為「%s」的珍藏項目已經存在" #~ msgid "Abort completed. Ready." #~ msgstr "中止完成. 就緒." #~ msgid "Abort failed." #~ msgstr "中止失敗" #~ msgid "Aborted checkout of '%s' (file level merging is required)." #~ msgstr "中止 '%s' 的 checkout 操作 (需要做文件級合併)." #~ msgid "Already up-to-date." #~ msgstr "早就已經是最新版本。" #~ msgid "Always (Do not perform merge checks)" #~ msgstr "總是合併 (不作合併檢查)" #~ msgid "Always (Do not perform merge test.)" #~ msgstr "總是合併 (不作合併測試.)" #~ msgid "Amended Commit Message:" #~ msgstr "修正的提交描述:" #~ msgid "Amended Initial Commit Message:" #~ msgstr "修正的初始提交描述:" #~ msgid "Amended Merge Commit Message:" #~ msgstr "修正的合併提交描述:" #~ msgid "Annotation complete." #~ msgstr "標註完成." #~ msgid "Any unstaged changes will be permanently lost by the revert." #~ msgstr "任何未緩存的改動將在這次撤銷中永久丟失." #~ msgid "Apply Diff Selection to Work Tree" #~ msgstr "套用選取的內容差異至當前工作目錄樹" #~ msgid "Apply/Reverse Hunk" #~ msgstr "應用/撤消此修改塊" #~ msgid "Arbitrary URL:" #~ msgstr "任意 URL:" #~ msgid "Bookmarks" #~ msgstr "書籤" #~ msgid "Bookmarks..." #~ msgstr "書籤……" #~ 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 "Branch '%s' does not exist." #~ msgstr "分支 '%s' 並不存在." #~ msgid "Branch created" #~ msgstr "分支已建立" #~ msgid "Browse %s's Files" #~ msgstr "瀏覽 %s 上的文件" #~ msgid "Browse Branch Files" #~ msgstr "瀏覽分支文件" #, fuzzy #~ msgid "Browse Revision..." #~ msgstr "版本" #~ msgid "" #~ "Cannot abort while amending.\n" #~ "\n" #~ "You must finish amending this commit.\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 "Cannot determine HEAD. See console output for details." #~ msgstr "無法確定 HEAD. 請查看控制終端的輸出." #~ msgid "Cannot fetch branches and objects. See console output for details." #~ msgstr "無法獲取分支和對象. 請查看控制終端的輸出." #~ msgid "Cannot fetch tags. See console output for details." #~ msgstr "無法獲取標籤. 請查看控制終端的輸出." #~ msgid "Cannot find git in PATH." #~ msgstr "PATH 中沒有找到 git" #~ 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 "Cannot move to top of working directory:" #~ msgstr "無法移動到工作根目錄:" #~ msgid "Cannot parse Git version string:" #~ msgstr "無法解析 Git 的版本信息:" #~ msgid "Cannot resolve %s as a commit." #~ msgstr "無法解析 %s 為提交." #~ msgid "Cannot use funny .git directory:" #~ msgstr "無法使用 .git 目錄:" #~ msgid "Cannot write shortcut:" #~ msgstr "無法修改快捷方式:" #~ msgid "Change Font" #~ msgstr "更改字體" #~ msgid "Checked out '%s'." #~ msgstr "'%s' 已被 checkout" #~ msgid "Clone Type:" #~ msgstr "克隆類型:" #~ msgid "Clone failed." #~ msgstr "克隆失敗." #~ msgid "Cloning from %s" #~ msgstr "從 %s 克隆" #~ msgid "Commit %s appears to be corrupt" #~ msgstr "提交 %s 似乎已損壞" #~ msgid "Commit failed: %s" #~ msgstr "提交失敗:%s" #~ msgid "Commit@@noun" #~ msgstr "提交(commit)" #~ msgid "Compress Database" #~ msgstr "壓縮數據庫" #~ msgid "Compressing the object database" #~ msgstr "壓縮對象數據庫" #~ msgid "Copied Or Moved Here By:" #~ msgstr "由複製或移動至此:" #~ msgid "Copying objects" #~ msgstr "複製 objects" #~ msgid "Counting objects" #~ msgstr "清點對象" #~ msgid "Create Desktop Icon" #~ msgstr "創建桌面圖標" #~ msgid "Created commit: %s" #~ msgstr "建立了一個新的修訂版提交:%s" #~ msgid "Creating working directory" #~ msgstr "創建工作目錄" #~ msgid "Current Branch:" #~ msgstr "當前分支:" #~ msgid "Database Statistics" #~ msgstr "數據庫統計信息" #~ msgid "Decrease Font Size" #~ msgstr "縮小字體" #~ msgid "Delete Local Branch" #~ msgstr "刪除本地分支" #~ msgid "Delete Only If" #~ msgstr "刪除僅當" #~ msgid "Delete Only If Merged Into" #~ msgstr "僅在合併後刪除" #~ msgid "Delete selected branch?" #~ msgstr "要移除選取的分支嗎?" #~ msgid "Destination Repository" #~ msgstr "目標版本庫" #~ msgid "Detach From Local Branch" #~ msgstr "從本地分支脫離" #~ msgid "Diff/Console Font" #~ msgstr "Diff/控制終端字體" #~ msgid "Directory %s already exists." #~ msgstr "目錄 %s 已經存在." #~ msgid "Disk space used by loose objects" #~ msgstr "鬆散對象所使用的磁盤空間" #~ msgid "Disk space used by packed objects" #~ msgstr "壓縮對象所使用的磁盤空間" #~ msgid "Do Nothing" #~ msgstr "不做操作" #~ msgid "Enter Git Repository" #~ msgstr "請輸入 Git 版本倉庫的路徑" #, fuzzy #~ msgid "Error %s" #~ msgstr "錯誤:%s" #~ msgid "Error loading commit data for amend:" #~ msgstr "為修正裝載提交數據出錯:" #~ msgid "Error: Command Failed" #~ msgstr "錯誤: 命令失敗" #~ msgid "Error: Stash exists" #~ msgstr "錯誤:珍藏項目已存在" #~ msgid "Errors: %s" #~ msgstr "錯誤:%s" #~ msgid "Exit code: %s" #~ msgstr "結束狀態碼:%s" #~ msgid "Failed to completely save options:" #~ msgstr "無法完全保存選項:" #~ msgid "Failed to configure origin" #~ msgstr "無法配置 origin" #~ msgid "Failed to create repository %s:" #~ msgstr "無法創建版本庫 %s:" #~ msgid "" #~ "Failed to delete branches:\n" #~ "%s" #~ msgstr "" #~ "無法刪除分支:\n" #~ "%s" #~ msgid "Failed to open repository %s:" #~ msgstr "無法打開版本庫 %s:" #~ msgid "Failed to rename '%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 "Failed to stage selected hunk." #~ msgstr "無法緩存所選代碼段." #~ msgid "Failed to unstage selected hunk." #~ msgstr "無法將選擇的代碼段從緩存中刪除." #~ msgid "Failed to update '%s'." #~ msgstr "無法更新 '%s'." #~ msgid "Fast Forward Only " #~ msgstr "只允許快速前移式的合併" #~ msgid "Fetch from" #~ msgstr "從..獲取(fetch)" #~ msgid "Fetching new changes from %s" #~ msgstr "從 %s 處獲取新的改動" #~ msgid "File level merge required." #~ msgstr "需要文件級合併." #~ msgid "Font Example" #~ msgstr "字體樣例" #~ msgid "Font Family" #~ msgstr "字體族" #~ msgid "Force overwrite existing branch (may discard changes)" #~ msgstr "強制覆蓋已有的分支 (可能會丟失改動)" #~ msgid "From Repository" #~ msgstr "從版本庫" #~ msgid "Full Copy (Slower, Redundant Backup)" #~ msgstr "全部複製 (較慢, 做備份)" #~ msgid "GPG-signed" #~ msgstr "已簽署 GPG 簽章" #~ msgid "Garbage files" #~ msgstr "垃圾文件" #~ msgid "Git Gui" #~ msgstr "Git Gui" #~ msgid "Git Repository (subproject)" #~ msgstr "Git 版本庫 (子項目)" #~ msgid "Git directory not found:" #~ 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 "Hardlinks are unavailable. Falling back to copying." #~ msgstr "硬連接不可用. 使用複製." #~ msgid "Hide Details.." #~ msgstr "隱藏詳細資訊……" #~ msgid "In File:" #~ msgstr "在文件:" #~ msgid "Increase Font Size" #~ msgstr "放大字體" #~ msgid "Index" #~ msgstr "修訂版提交準備區域" #~ msgid "Initial Commit Message:" #~ msgstr "初始的提交描述:" #~ msgid "Initial file checkout failed." #~ msgstr "初始的文件checkout失敗" #~ msgid "Invalid GIT_COMMITTER_IDENT:" #~ msgstr "無效的 GIT_COMMITTER_IDENT" #~ msgid "Invalid date from Git: %s" #~ msgstr "無效的日期: %s" #~ msgid "Invalid font specified in %s:" #~ msgstr "%s 中指定的字體無效:" #~ msgid "KiB" #~ msgstr "KiB" #~ 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 "" #~ "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 "" #~ "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 "Linking objects" #~ msgstr "鏈接 objects" #~ msgid "Loading annotation..." #~ msgstr "裝載標註..." #~ msgid "Loading copy/move tracking annotations..." #~ msgstr "裝載複製/移動跟蹤標註..." #~ msgid "Loading original location annotations..." #~ msgstr "裝載原始位置標註..." #~ msgid "Local Branches" #~ msgstr "本地分支" #~ msgid "Local Merge..." #~ msgstr "本地合併..." #~ msgid "Location %s already exists." #~ msgstr "位置 %s 已經存在." #~ msgid "Main Font" #~ msgstr "主要字體" #~ msgid "Match Tracking Branch Name" #~ msgstr "匹配跟蹤分支名字" #~ msgid "Match Tracking Branches" #~ msgstr "匹配跟蹤分支" #~ msgid "Merge completed successfully." #~ msgstr "合併成功完成." #~ msgid "Merge strategy '%s' not supported." #~ msgstr "合併策略 '%s' 不支持." #~ msgid "Merged Into:" #~ msgstr "合併到" #, fuzzy #~ msgid "Merging %s and %s..." #~ msgstr "合併 %s 和 %s" #~ msgid "Modified, not staged" #~ msgstr "修改但未緩存" #~ msgid "New Branch Name Template" #~ msgstr "新建分支命名模板" #~ msgid "New Commit" #~ msgstr "新建提交" #~ msgid "New Name:" #~ msgstr "新名字:" #~ 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 "No default branch obtained." #~ msgstr "沒有獲取缺省分支" #~ 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 "No files selected for checkout from HEAD." #~ msgstr "沒有選取任何需要自 HEAD 取出的檔案" #~ msgid "No working directory" #~ msgstr "沒有工作目錄" #~ msgid "Number of loose objects" #~ msgstr "鬆散對象的數量" #~ msgid "Number of packed objects" #~ msgstr "壓縮對象數量" #~ msgid "Number of packs" #~ msgstr "壓縮包數量" #~ msgid "On Debian-based systems try: sudo apt-get install python-pyinotify" #~ msgstr "於基於 Debian 的系統中嘗試於終端機下執行:sudo apt-get install python-pyinotify" #~ 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 "Options" #~ msgstr "選項..." #~ msgid "Original File:" #~ msgstr "原始文件:" #~ msgid "Originally By:" #~ msgstr "最初由:" #~ msgid "" #~ "Output:\n" #~ "%s" #~ msgstr "" #~ "命令輸出:\n" #~ "%s" #~ msgid "Output: %s" #~ msgstr "輸出:%s" #~ msgid "PATCH %(current)d/%(count)d" #~ msgstr "正在套用 %(current)d/%(count)d 修正" #~ msgid "Packed objects waiting for pruning" #~ msgstr "壓縮對象等待清理" #~ msgid "Path to git repository" #~ msgstr "Git 版本倉庫的路徑" #~ msgid "Please select one or more branches to delete." #~ msgstr "請選擇某個或多個分支來刪除" #~ msgid "Please supply a branch name." #~ msgstr "請提供分支名字." #~ msgid "Portions staged for commit" #~ 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 "Preferences..." #~ msgstr "首選項..." #~ msgid "Process Diff Hunk" #~ msgstr "處理內容差異區域" #~ msgid "Process Selection" #~ msgstr "處理選取的項目" #~ msgid "Prune Tracking Branches During Fetch" #~ msgstr "獲取時清除跟蹤分支" #~ msgid "Pruning tracking branches deleted from %s" #~ msgstr "清除" #~ msgid "Push Branches" #~ msgstr "上傳分支" #~ msgid "Push to" #~ msgstr "上傳到(push)" #~ msgid "Pushing %s %s to %s" #~ msgstr "上傳 %s %s 到 %s" #~ msgid "Reading %s..." #~ msgstr "讀取 %s..." #, fuzzy #~ msgid "Ready to commit." #~ msgstr "緩存為提交" #~ msgid "Ready." #~ msgstr "就緒" #, fuzzy #~ msgid "Rebase Branch" #~ msgstr "更改分支名:" #, fuzzy #~ msgid "Rebase..." #~ msgstr "復位(Reset)..." #~ msgid "" #~ "Recovering deleted branches is difficult.\n" #~ "\n" #~ "Delete the selected branches?" #~ msgstr "" #~ "恢復被刪除的分支非常困難.\n" #~ "\n" #~ "是否要刪除所選分支?" #~ msgid "" #~ "Recovering deleted branches is difficult. \n" #~ "\n" #~ " Delete the selected branches?" #~ msgstr "" #~ "恢復被刪除的分支非常困難.\n" #~ "\n" #~ "是否要刪除所選分支?" #~ msgid "Refreshing file status..." #~ msgstr "更新文件狀態..." #, fuzzy #~ msgid "Remote Branches" #~ msgstr "遠端分支名" #~ msgid "Remote:" #~ msgstr "Remote:" #~ msgid "Remove selected paths from the staging area" #~ msgstr "將選取的路徑自修訂版提交準備區域中移除" #~ msgid "Rename remote?" #~ msgstr "要重新命名遠端版控庫嗎?" #~ msgid "Repository" #~ msgstr "版本庫(repository)" #~ msgid "Requires merge resolution" #~ msgstr "需要解決合併衝突" #~ msgid "Rescan" #~ msgstr "重新掃瞄" #~ msgid "Reset Branch Head" #~ msgstr "重設分支 Head" #~ msgid "Reset Hard" #~ msgstr "硬式重設" #~ msgid "Reset Merge" #~ msgstr "合併式重設" #~ msgid "Reset Soft" #~ msgstr "軟式重設" #~ msgid "Reset Worktree" #~ msgstr "重設工作目錄樹" #~ 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 "Reset hard?" #~ msgstr "要進行硬式重設嗎?" #~ msgid "Reset merge?" #~ msgstr "要進行合併式重設嗎?" #~ msgid "Reset soft?" #~ msgstr "要進行軟式重設嗎?" #~ msgid "Reset worktree?" #~ msgstr "要重設工作目錄樹嗎?" #~ msgid "Revert Uncommitted Changes..." #~ msgstr "撤銷尚未建立修訂版提交的內容變動" #~ msgid "Revert changes in these %i files?" #~ msgstr "撤銷這些 (%i個) 文件的改動?" #~ msgid "Select File" #~ msgstr "選取檔案" #~ msgid "Select Repository..." #~ msgstr "選擇版控庫……" #~ msgid "Select file from \"%s\"" #~ msgstr "於「%s」中選取檔案" #~ msgid "Select manually..." #~ msgstr "手動選取……" #~ msgid "Shared (Fastest, Not Recommended, No Backup)" #~ msgstr "共享方式 (最快, 不推薦, 不做備份)" #~ msgid "Shared only available for local repository." #~ msgstr "共享方式僅當是本地版本庫時有效." #~ msgid "Show Details..." #~ msgstr "顯示詳細資訊……" #~ msgid "Show Less Context" #~ msgstr "顯示更少上下文" #~ msgid "Show More Context" #~ msgstr "顯示更多上下文" #~ msgid "Show icon? (if available)" #~ msgstr "要顯示圖示嗎(如果有)?" #~ msgid "Source Branches" #~ msgstr "源端分支:" #~ msgid "Stage Hunk For Commit" #~ msgstr "緩存修改塊為提交" #~ msgid "Staged Changes (Will Commit)" #~ msgstr "已緩存的改動 (將被提交)" #~ msgid "Staged for commit, missing" #~ msgstr "緩存為提交, 不存在" #~ msgid "Staged for removal" #~ msgstr "緩存為刪除" #~ msgid "Staged for removal, still present" #~ msgstr "緩存為刪除, 但仍存在" #~ msgid "Staging Area" #~ msgstr "新修訂版準備區域" #~ msgid "Staging area (index) is already locked." #~ msgstr "緩存區域 (index) 已被鎖定." #~ msgid "Standard (Fast, Semi-Redundant, Hardlinks)" #~ msgstr "標準方式 (快速, 部分備份, 作硬連接)" #~ msgid "Standard only available for local repository." #~ msgstr "標準方式僅當是本地版本庫時有效." #~ msgid "Starting gitk... please wait..." #~ msgstr "啟動 gitk... 請等待..." #~ msgid "Staying on branch '%s'." #~ msgstr "停留在分支 '%s'." #~ msgid "Success" #~ msgstr "成功" #~ msgid "Summary:" #~ msgstr "總結:" #~ msgid "The 'main' branch has not been initialized." #~ msgstr "'main'分支尚未初始化." #~ msgid "The branch will be reset using \"git reset --hard %s\"" #~ msgstr "這個分支將會被用「git reset --hard %s」命令重設" #~ msgid "The branch will be reset using \"git reset --merge %s\"" #~ msgstr "這個分支將會被用「git reset --merge %s」命令重設" #~ msgid "The following branches are not completely merged into %s:" #~ msgstr "下列分支沒有完全被合併到 %s:" #~ msgid "" #~ "The following branches are not completely merged into %s:\n" #~ "\n" #~ " - %s" #~ msgstr "" #~ "下列分支沒有被全部合併到 %s 中:\n" #~ "\n" #~ " - %s" #~ msgid "The worktree will be reset using \"git reset --keep %s\"" #~ msgstr "工作目錄樹將被用「git reset --keep %s」命令重設" #~ 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 "This Detached Checkout" #~ msgstr "該脫節的Checkout" #~ msgid "" #~ "This PyQt4 does not include QtWebKit.\n" #~ "The keyboard shortcuts feature is unavailable." #~ msgstr "" #~ "此 PyQt4 並未包含 QtWebKit。\n" #~ "不支援顯示軟體的鍵盤快捷鍵列表。翻譯者注:" #~ msgid "" #~ "This is example text.\n" #~ "If you like this text, it can be your font." #~ msgstr "" #~ "這是樣例文本.\n" #~ "如果你喜歡, 你可以設置該字體." #~ 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 "Tracking branch %s is not a branch in the remote repository." #~ msgstr "跟蹤分支 %s 並不是遠端版本庫中的一個分支" #~ msgid "Transfer Options" #~ msgstr "傳輸選項" #~ msgid "Unable to copy object: %s" #~ msgstr "無法複製 object: %s" #~ msgid "Unable to copy objects/info/alternates: %s" #~ msgstr "無法複製 objects/info/alternates: %s" #~ msgid "Unable to display %s" #~ msgstr "無法顯示 %s" #~ msgid "Unable to hardlink object: %s" #~ msgstr "無法硬鏈接 object: %s" #~ msgid "Unable to obtain your identity:" #~ msgstr "無法獲知你的身份:" #~ msgid "" #~ "Unable to start gitk:\n" #~ "\n" #~ "%s does not exist" #~ msgstr "" #~ "無法啟動 gitk:\n" #~ "\n" #~ "%s 不存在" #~ msgid "Unable to unlock the index." #~ msgstr "無法解鎖緩存 (index)" #~ msgid "" #~ "Unknown file state %s detected.\n" #~ "\n" #~ "File %s cannot be committed by this program.\n" #~ msgstr "" #~ "檢測到未知文件狀態 %s.\n" #~ "\n" #~ "文件 %s 無法由該程序提交.\n" #~ msgid "Unlock Index" #~ msgstr "解鎖 Index" #~ 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 "Unstage Hunk From Commit" #~ msgstr "從提交中撤除修改塊" #~ msgid "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui." #~ msgstr "更新 Git 緩存(Index)失敗, 重新掃瞄將自動開始以重新同步 git-gui." #~ msgid "Updating working directory to '%s'..." #~ msgstr "更新工作目錄到 '%s'..." #~ msgid "Updating..." #~ msgstr "正在更新……" #~ msgid "Use thin pack (for slow network connections)" #~ msgstr "使用 thin pack (適用於低速網絡連接)" #~ msgid "Verify Database" #~ msgstr "驗證數據庫" #~ msgid "Verifying the object database with fsck-objects" #~ msgstr "使用 fsck-objects 驗證對象數據庫" #~ msgid "Visualize %s's History" #~ msgstr "圖示 %s 分支的歷史" #~ msgid "Working... please wait..." #~ msgstr "工作中... 請等待..." #~ 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 "" #~ "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 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 "You must correct the above errors before committing." #~ msgstr "你必須在提交前修正上述錯誤." #~ msgid "[Up To Parent]" #~ msgstr "[上層目錄]" #, fuzzy #~ msgid "buckets" #~ msgstr "水桶??" #~ msgid "commit-tree failed:" #~ msgstr "commit-tree 失敗:" #~ msgid "fatal: Cannot resolve %s" #~ msgstr "致命錯誤: 無法解決 %s" #~ msgid "" #~ "file notification: disabled\n" #~ "Note: install pywin32 to enable.\n" #~ msgstr "" #~ "inotify 檔案變更通知:停用\n" #~ "注意:安裝 pywin32 以啟用此功能。\n" #~ msgid "files" #~ msgstr "文件" #, fuzzy #~ msgid "files reset" #~ msgstr "文件" #~ msgid "git clone returned exit code %s" #~ msgstr "git clone 命令傳回了 %s 錯誤狀態碼" #~ msgid "git tag returned exit code %s" #~ msgstr "git tag 命令傳回了 %s 錯誤狀態碼" #~ msgid "git-gui - a graphical user interface for Git." #~ msgstr "git-gui - Git 的圖形化用戶界面" #~ msgid "git-gui: fatal error" #~ msgstr "git-gui: 致命錯誤" #~ msgid "inotify enabled." #~ msgstr "inotify 已啟用。" #~ msgid "" #~ "inotify: disabled\n" #~ "Note: install python-pyinotify to enable inotify.\n" #~ msgstr "" #~ "inotify:停用\n" #~ "注意:安裝 python-pyinotify 軟體包以啟用 inotify 檔案變更通知功能。\n" #~ msgid "lines annotated" #~ msgstr "標註行" #~ msgid "objects" #~ msgstr "objects" #~ msgid "pt." #~ msgstr "磅" #~ msgid "push %s" #~ msgstr "上傳 %s" #~ msgid "remote prune %s" #~ msgstr "清除遠端 %s" #~ msgid "unknown" #~ msgstr "未知使用者" #~ msgid "update-ref failed:" #~ msgstr "update-ref 失敗:" #~ msgid "warning" #~ msgstr "警告" #~ msgid "warning: Tcl does not support encoding '%s'." #~ msgstr "警告: Tcl 不支持編碼方式 '%s'." #~ msgid "write-tree failed:" #~ msgstr "write-tree 失敗:" git-cola-4.6.1/cola/icons.py000066400000000000000000000233271457126473700156530ustar00rootroot00000000000000"""The only file where icon filenames are mentioned""" import os from qtpy import QtGui from qtpy import QtWidgets from . import core from . import decorators from . import qtcompat from . import resources from .compat import ustr from .i18n import N_ KNOWN_FILE_MIME_TYPES = [ ('text', 'file-code.svg'), ('image', 'file-media.svg'), ('octet', 'file-binary.svg'), ] KNOWN_FILE_EXTENSIONS = { '.bash': 'file-code.svg', '.c': 'file-code.svg', '.cpp': 'file-code.svg', '.css': 'file-code.svg', '.cxx': 'file-code.svg', '.h': 'file-code.svg', '.hpp': 'file-code.svg', '.hs': 'file-code.svg', '.html': 'file-code.svg', '.java': 'file-code.svg', '.js': 'file-code.svg', '.ksh': 'file-code.svg', '.lisp': 'file-code.svg', '.perl': 'file-code.svg', '.pl': 'file-code.svg', '.py': 'file-code.svg', '.rb': 'file-code.svg', '.rs': 'file-code.svg', '.sh': 'file-code.svg', '.zsh': 'file-code.svg', } def install(themes): for theme in themes: icon_dir = resources.icon_dir(theme) qtcompat.add_search_path('icons', icon_dir) def icon_themes(): return ( (N_('Default'), 'default'), (N_('Dark Theme'), 'dark'), (N_('Light Theme'), 'light'), ) def name_from_basename(basename): """Prefix the basename with "icons:" so that git-cola's icons are found "icons" is registered with the Qt resource system during install(). """ return 'icons:' + basename @decorators.memoize def from_name(name): """Return a QIcon from an absolute filename or "icons:basename.svg" name""" return QtGui.QIcon(name) def icon(basename): """Given a basename returns a QIcon from the corresponding cola icon""" return from_name(name_from_basename(basename)) def from_theme(name, fallback=None): """Grab an icon from the current theme with a fallback Support older versions of Qt checking for fromTheme's availability. """ if hasattr(QtGui.QIcon, 'fromTheme'): base, _ = os.path.splitext(name) if fallback: qicon = QtGui.QIcon.fromTheme(base, icon(fallback)) else: qicon = QtGui.QIcon.fromTheme(base) if not qicon.isNull(): return qicon return icon(fallback or name) def basename_from_filename(filename): """Returns an icon name based on the filename""" mimetype = core.guess_mimetype(filename) if mimetype is not None: mimetype = mimetype.lower() for filetype, icon_name in KNOWN_FILE_MIME_TYPES: if filetype in mimetype: return icon_name extension = os.path.splitext(filename)[1] return KNOWN_FILE_EXTENSIONS.get(extension.lower(), 'file-text.svg') def from_filename(filename): """Return a QIcon from a filename""" basename = basename_from_filename(filename) return from_name(name_from_basename(basename)) def mkicon(value, default=None): """Create an icon from a string value""" if value is None and default is not None: value = default() elif value and isinstance(value, (str, ustr)): value = QtGui.QIcon(value) return value def from_style(key): """Maintain a cache of standard icons and return cache entries.""" style = QtWidgets.QApplication.instance().style() return style.standardIcon(key) def status(filename, deleted, is_staged, untracked): """Status icon for a file""" if deleted: icon_name = 'circle-slash-red.svg' elif is_staged: icon_name = 'staged.svg' elif untracked: icon_name = 'question-plain.svg' else: icon_name = basename_from_filename(filename) return icon_name # Icons creators and SVG file references def three_bars(): """Three-bars icon""" return icon('three-bars.svg') def add(): """Add icon""" return from_theme('list-add', fallback='plus.svg') def alphabetical(): """Alphabetical icon""" return from_theme('view-sort', fallback='a-z-order.svg') def branch(): """Branch icon""" return icon('git-branch.svg') def check_name(): """Check mark icon name""" return name_from_basename('check.svg') def cherry_pick(): """Cherry-pick icon""" return icon('git-commit.svg') def circle_slash_red(): """A circle with a slash through it""" return icon('circle-slash-red.svg') def close(): """Close icon""" return icon('x.svg') def cola(): """Git Cola icon""" return icon('git-cola.svg') def commit(): """Commit icon""" return icon('document-save-symbolic.svg') def compare(): """Compare icon""" return icon('git-compare.svg') def configure(): """Configure icon""" return icon('gear.svg') def cut(): """Cut icon""" return from_theme('edit-cut', fallback='edit-cut.svg') def copy(): """Copy icon""" return from_theme('edit-copy', fallback='edit-copy.svg') def paste(): """Paste icon""" return from_theme('edit-paste', fallback='edit-paste.svg') def play(): """Play icon""" return icon('play.svg') def delete(): """Delete icon""" return from_theme('edit-delete', fallback='trashcan.svg') def default_app(): """Default app icon""" return icon('telescope.svg') def dot_name(): """Dot icon name""" return name_from_basename('primitive-dot.svg') def download(): """Download icon""" return icon('file-download.svg') def discard(): """Discard icon""" return from_theme('delete', fallback='trashcan.svg') # folder vs directory: directory is opaque, folder is just an outline # directory is used for the File Browser, where more contrast with the file # icons are needed. def folder(): """Folder icon""" return from_theme('folder', fallback='folder.svg') def directory(): """Directory icon""" return from_theme('folder', fallback='file-directory.svg') def diff(): """Diff icon""" return icon('diff.svg') def edit(): """Edit icon""" return from_theme('document-edit', fallback='pencil.svg') def ellipsis(): """Ellipsis icon""" return icon('ellipsis.svg') def external(): """External link icon""" return icon('link-external.svg') def file_code(): """Code file icon""" return icon('file-code.svg') def file_text(): """Text file icon""" return icon('file-text.svg') def file_zip(): """Zip file / tarball icon""" return icon('file-zip.svg') def fold(): """Fold icon""" return icon('fold.svg') def merge(): """Merge icon""" return icon('git-merge.svg') def modified(): """Modified icon""" return icon('modified.svg') def modified_name(): """Modified icon name""" return name_from_basename('modified.svg') def move_down(): """Move down icon""" return from_theme('go-next', fallback='arrow-down.svg') def move_up(): """Move up icon""" return from_theme('go-previous', fallback='arrow-up.svg') def new(): """Add new/add-to-list icon""" return from_theme('list-add', fallback='folder-new.svg') def ok(): """Ok/accept icon""" return from_theme('checkmark', fallback='check.svg') def open_directory(): """Open directory icon""" return from_theme('folder', fallback='folder.svg') def up(): """Previous icon""" return icon('arrow-up.svg') def down(): """Go to next item icon""" return icon('arrow-down.svg') def partial_name(): """Partial icon name""" return name_from_basename('partial.svg') def pull(): """Pull icon""" return icon('repo-pull.svg') def push(): """Push icon""" return icon('repo-push.svg') def question(): """Question icon""" return icon('question.svg') def remove(): """Remove icon""" return from_theme('list-remove', fallback='circle-slash.svg') def repo(): """Repository icon""" return icon('repo.svg') def reverse_chronological(): """Reverse chronological icon""" return icon('last-first-order.svg') def save(): """Save icon""" return from_theme('document-save', fallback='desktop-download.svg') def search(): """Search icon""" return from_theme('search', fallback='search.svg') def select_all(): """Select all icon""" return from_theme('edit-select-all', fallback='edit-select-all') def staged(): """Staged icon""" return icon('staged.svg') def staged_name(): """Staged icon name""" return name_from_basename('staged.svg') def star(): """Star icon""" return icon('star.svg') def sync(): """Sync/update icon""" return icon('sync.svg') def tag(): """Tag icon""" return icon('tag.svg') def terminal(): """Terminal icon""" return icon('terminal.svg') def undo(): """Undo icon""" return from_theme('edit-undo', fallback='edit-undo.svg') def redo(): """Redo icon""" return from_theme('edit-redo', fallback='edit-redo.svg') def style_dialog_apply(): """Apply icon from the current style""" return from_style(QtWidgets.QStyle.SP_DialogApplyButton) def style_dialog_discard(): """Discard icon for the current style""" return from_style(QtWidgets.QStyle.SP_DialogDiscardButton) def style_dialog_reset(): """Reset icon for the current style""" return from_style(QtWidgets.QStyle.SP_DialogResetButton) def unfold(): """Expand/unfold icon""" return icon('unfold.svg') def visualize(): """An eye icon to represent visualization""" return icon('eye.svg') def upstream_name(): """Upstream branch icon name""" return name_from_basename('upstream.svg') def zoom_fit_best(): """Zoom-to-fit icon""" return from_theme('zoom-fit-best', fallback='zoom-fit-best.svg') def zoom_in(): """Zoom-in icon""" return from_theme('zoom-in', fallback='zoom-in.svg') def zoom_out(): """Zoom-out icon""" return from_theme('zoom-out', fallback='zoom-out.svg') git-cola-4.6.1/cola/icons/000077500000000000000000000000001457126473700152725ustar00rootroot00000000000000git-cola-4.6.1/cola/icons/README.md000066400000000000000000000053521457126473700165560ustar00rootroot00000000000000# Git Cola Icons ## Guidelines 1. Size: 22x22px (the default action icon size of KDE and GNOME) 2. Margin: 1px (20x20px drawing area) 3. Colors: #000000 black, #ffffff white, #cc0000 red, #00dd26 green, #1961ff blue ## Copyright ### New icons The following icons are created/re-created by [Guo Yunhe](https://guoyunhe.me/): - a-z-order.svg - check.svg - circle-slash-red.svg - circle-slash.svg - desktop-download.svg - diff.svg ### Original icons The following icons are based on the based on the original .png icon designs for git-cola's File Browser by Uri Okrent. - staged.svg - modified.svg - partial.svg - upstream.svg Copyright (C) 2011 Uri Okrent Copyright (C) 2015-2024 David Aguilar License: MIT ### Git Logo Git Logo by [Jason Long](https://twitter.com/jasonlong) is licensed under the [Creative Commons Attribution 3.0 Unported License](https://creativecommons.org/licenses/by/3.0/). This license lets others distribute, remix, tweak, and build upon your work, even commercially, as long as they credit you for the original creation. This is the most accommodating of the CC licenses offered. Recommended for maximum dissemination and use of licensed materials. https://git-scm.com/downloads/logos git-cola.svg is based on the Git Logo. ### Octicons The following files are from Github's [octicons](https://github.com/github/octicons) icon set: - check.svg - circle-slash.svg - desktop-download.svg - diff.svg - ellipsis.svg - eye.svg - file-binary.svg - file-code.svg - file-directory.svg - file-media.svg - file-text.svg - file-zip.svg - fold.svg - gear.svg - git-branch.svg - git-compare.svg - git-merge.svg - link-external.svg - pencil.svg - play.svg - plus.svg - primitive-dot.svg - question.svg - question-plain.svg - repo-pull.svg - repo-push.svg - repo.svg - screen-full.svg - search.svg - star.svg - sync.svg - tag.svg - telescope.svg - terminal.svg - three-bars.svg - trashcan.svg - unfold.svg - x.svg Copyright (C) 2012-2015 GitHub License: [MIT](http://choosealicense.com/licenses/mit/) ### Gnome Adwaita Icons The following files are from the Gnome project's [Adwaita icon theme](https://github.com/GNOME/adwaita-icon-theme): - document-save-symbolic.svg Copyright (C) The Gnome Project License: [LGPL](https://github.com/GNOME/adwaita-icon-theme/blob/master/COPYING_LGPL) ### Gnome High Contrast Icons The following files are from the Gnome High Contrast Icon set: - zoom-fit-best.svg - zoom-in.svg - zoom-out.svg License: LGPL v2+ ### Google Material Icons (v2.2) The following files are by Google: - arrow-down.svg - arrow-up.svg - edit-copy.svg - edit-cut.svg - edit-paste.svg - edit-redo.svg - edit-select-all.svg - edit-undo.svg - file-download.svg License: [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0/) git-cola-4.6.1/cola/icons/a-z-order.svg000066400000000000000000000025071457126473700176170ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/arrow-down.svg000066400000000000000000000002531457126473700201120ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/arrow-up.svg000066400000000000000000000002521457126473700175660ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/check.svg000066400000000000000000000003151457126473700170670ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/circle-slash-red.svg000066400000000000000000000007501457126473700211360ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/circle-slash.svg000066400000000000000000000007511457126473700203670ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/000077500000000000000000000000001457126473700162135ustar00rootroot00000000000000git-cola-4.6.1/cola/icons/dark/README.md000066400000000000000000000041211457126473700174700ustar00rootroot00000000000000Git Cola Dark Icons -------------- All icons in this directory, besides color inversion, are unmodified original ones. All kudos and copyrights go to their respective authors ( see original readme below ). 2017 Filip Danilovic -------------------- Git Cola Icons -------------- The following icons are based on the based on the original .png icon designs for git-cola's File Browser by Uri Okrent. staged.svg modified.svg partial.svg upstream.svg Copyright (C) 2011 Uri Okrent Copyright (C) 2015-2024 David Aguilar License: MIT Git Logo -------- Git Logo by Jason Long is licensed under the Creative Commons Attribution 3.0 Unported License. http://git-scm.com/downloads/logos git-cola.svg is based on the original Git Logo. Octicons -------- The following files are from Github's [octicons](https://github.com/github/octicons) icon set: check.svg circle-slash.svg desktop-download.svg diff.svg ellipsis.svg eye.svg file-binary.svg file-code.svg file-directory.svg file-media.svg file-text.svg file-zip.svg fold.svg gear.svg git-branch.svg git-compare.svg git-merge.svg link-external.svg pencil.svg plus.svg primitive-dot.svg question.svg question-plain.svg repo-pull.svg repo-push.svg repo.svg screen-full.svg search.svg star.svg sync.svg tag.svg telescope.svg trashcan.svg unfold.svg x.svg Copyright (C) 2012-2015 GitHub License: [MIT](http://choosealicense.com/licenses/mit/) Gnome High Contrast Icons ------------------------- The following files are from the Gnome High Contrast Icon set: zoom-fit-best.svg zoom-in.svg zoom-out.svg License: LGPL v2+ Flaticon.com Icons ------------------ The following files are designed by Freepik from http://www.flaticons.com/ edit-undo.svg License: [Flatpik Basic License](http://cdn.flaticon.com/license/license.pdf) The following files are by Linh Pham from http://flaticons.com/ edit-copy.svg License: [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0/) Google Icons ------------ The following files are by Google: edit-select-all.svg file-download.svg License: [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0/) git-cola-4.6.1/cola/icons/dark/a-z-order.svg000066400000000000000000000025071457126473700205400ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/arrow-down.svg000066400000000000000000000002751457126473700210370ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/arrow-up.svg000066400000000000000000000002771457126473700205160ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/check.svg000066400000000000000000000003151457126473700200100ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/circle-slash-red.svg000066400000000000000000000007501457126473700220570ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/circle-slash.svg000066400000000000000000000007501457126473700213070ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/desktop-download.svg000066400000000000000000000003401457126473700222070ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/diff.svg000066400000000000000000000003741457126473700176500ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/document-save-symbolic.svg000066400000000000000000000020331457126473700233230ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/edit-copy.svg000066400000000000000000000006521457126473700206340ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/edit-cut.svg000066400000000000000000000025421457126473700204550ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/edit-paste.svg000066400000000000000000000012341457126473700207730ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/edit-redo.svg000066400000000000000000000006521457126473700206130ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/edit-select-all.svg000066400000000000000000000104211457126473700217020ustar00rootroot00000000000000 image/svg+xml git-cola-4.6.1/cola/icons/dark/edit-undo.svg000066400000000000000000000006711457126473700206300ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/ellipsis.svg000066400000000000000000000007171457126473700205650ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/eye.svg000066400000000000000000000010651457126473700175200ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/file-binary.svg000066400000000000000000000011121457126473700211300ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/file-code.svg000066400000000000000000000010271457126473700205630ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/file-directory.svg000066400000000000000000000006651457126473700216640ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/file-download.svg000066400000000000000000000011621457126473700214600ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/file-media.svg000066400000000000000000000006671457126473700207410ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/file-text.svg000066400000000000000000000007511457126473700206400ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/file-zip.svg000066400000000000000000000014341457126473700204550ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/fold.svg000066400000000000000000000012541457126473700176620ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/folder-new.svg000066400000000000000000000023521457126473700210000ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/folder.svg000066400000000000000000000013441457126473700202110ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/gear.svg000066400000000000000000000014571457126473700176610ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/git-branch.svg000066400000000000000000000030721457126473700207540ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/git-cola.ico000066400000000000000000013226261457126473700204220ustar00rootroot00000000000000 ( f ( @@ (B(00 %j   h.( 999 FFF!BBB:DDDDFFF3BBB333DDD"DDDqDDDCCDDDDDDDDDDDDDDDDCCDDDDDDD^KKKDDD"DDDDDEDDDDDI@Hv=J;K:L;K=JAGgCDDDDDCCDDDDIII333DDDDDEDDD?Ht8M4Q3Q3Q3Q3Q3Q3Q3Q5P9LAF^DDDDEFCCC[GGGDDEDDDAGh7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9LCFVDDDCCCUUUEEEDDEDDD=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4P@GoDDDDDDUUUEEEDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDCCCUUUFFFCCEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P?H|DDDDDDUUUFFFCCEDDDH}DDDCCC333CCCDDEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>H}DDDDDD333CCCDDEDDE;L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>H~DDDDDD333CCCDDEDDE;L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>H~DDDDDDUUUCCCDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>H~DDDDDDUUUCCCDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>H~DDDDDDUUUCCCDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDDUUUCCCDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDDUUU@@@DDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?IDDDDDDUUU@@@CCDDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?IDDDDDDUUU@@@CCDDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?IDDDDDDUUU@@@CCDDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?IDDDDDDUUU@@@CCDDDE;L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=HDDDDDDUUU@@@CCDDDE;L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDDUUU@@@CCDDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDCCCUUUFFFCCDDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDCCCUUUFFFDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDCCCUUUFFFDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDDUUUFFFDDEDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDDUUUFFFDDEDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDDIIIFFFDDEDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDDIIIFFFDDEDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDDIIIDDDDDEDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDDIIIDDDDDECCD:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDDIIIDDDDDECCD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDEEE999 DDDCEFCCD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDD999 DDDCEFCCD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDD999 DDDCDECDE9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=IDDDDDD999 DDDCDECDE9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=IDDDDDDMMM BBBCDECDE9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=IDDDDDDMMM BBBCDECDE9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=IDDDDDDMMM BBBCDECDE9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>JDDDDDDMMM BBBCDECDE:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>JDDDDDDMMM BBBCDECDE:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QGwCDEDDDDDDDDDDDDDDDDDDDDDCCCDDDDDEDDDDDDAF`9L3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QI3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;JDDDDDE@@@FFF,CDECDG8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4PCFSCCDHHH EEEDDD9N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QFI7Bc3P3P6Ds7?B~QX[7?C4J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?HxDDE@@@EEECDH4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDDCCD@@@BBB2CCEDEK7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4J7?B>FI7Cd3P3Q3P6D{7?Bw|~RY]7?C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9NDDDEEECCC5DDD>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDDCCD@@@FFF3CDECDJ7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5J7?B7?B5I3Q3Q3Q5E}7?Bw|~T[^7?C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAF`DEFEEEDDDCCD6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDDCCD@@@FFF3CDECDJ7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4L7?BY_c7@C5J3Q3Q3Q5E}7?Bw}U\`7?C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8MDDDDDDDDDZDDD=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDEDDE@@@FFF3CDEDEK8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4P8AIlqtOVZ7?D4I3Q3Q3Q6E~7?BX^b7?C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?I}DDDCCCjEEE%CCDCER5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;LDDEDDEIIIEEE4CDEDEL8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P5I4L3Q3Q3Q3Q6Ey9AEPWZ7?B5H3Q3Q3Q7B`PX`Y`c7?C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4PBFZDDEDDDKFFFDDECCD8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;LDDEDDEIIIEEE4CDEDEL7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3M8BR7?B7?C4J3Q3Q3Q4L7?B[ae7?B6Dx4L5I7@Cotw[ae7@C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6ODFQDDEDDDKFFF!DDEDDD:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDEDDEIIICCC5DEFDEL7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4K8@I>GKY`c7@C4J3Q3Q3Q6Er8@Cz7?B7?B7?BNUXZad7@C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q7NDFQCCDDDDmDDDGw;L4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LCCDDDEEEEDDDDEFCEO6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5F7?B7?B4J3Q3Q4L8AP9AC7?B6E{3Q3P5F7?Buz}\bf7?B5I3Q3Q3Q3O3O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5PAF`DDDDDD999 @@@DDDDDDCFV6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9LCDEDDEBBBFFF>DEFCEO6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6D{8@CCDECFP6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5E7?B7?B5F3Q3Q3Q3Q5Dv7?Bhnpqwy7?B5G3Q3Q5F7?Btz|\bf7?B4I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q@GmDDDCCCcFFFBDDECFX4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9LCDEDDE@@@EEE?CDECFP6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5H7?Bntv7?B4J3Q3Q3Q3Q5G7?B\cffln7?B4K3Q3Q5F7?Btz|\bf7?B5H3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QFI8BP3N3Q3Q3Q3Q5I7?B^dh7?B6G3Q3Q3Q6G7?Bsy{\cf7?B5H3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8NDDDDDDDDDmDDD:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QFI9AD6Dv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5H7?Bekn7?B6Dq3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?HvDDE@@@DDDAE[3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAGcDDEDDDDDD6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8B]NUY8AD6Dk3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4M9BP;CGw|~7?B4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5H7?Bkpt7?B7C^4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QI3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3M7?BX^b7@E4L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3N7C^7?Bz?FJ8AO3N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5H7?BY`cdkm7?B6Dn4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4PDEIDDDDDDDDD6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDDFFFBDDECET3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6Dp8@CELQ8AH4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P5E}7?BQX[KRV8@H4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5I8@C7?B7?B8@C5G3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4QBF_DDDGGGFFF DDEAF_3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAFaCCD333CCCyDDD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4N7?Dcil=EI8BR4N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4I8AI8ADCJN8AF4L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4N5F6F4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HxDDDCCCUUUDDDmDDD:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9LDDDDDD@@@ CDDCFW3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5G7?B;CF8BT3O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3N6Dq7?B;CFv{}8@C8BN5L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HwDDDDDDUUUKKKCDECFS3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PAEXCDE@@@EEEoDDD=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P7Ce9AC9AC8BU4N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4L7Ci7?B7?BMTWqwyzLSW7?B7?C6E3N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HwDDDDDDUUUDDDDDD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QJ6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDEDDEEEEFFF(CDECDG8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5H7?BX^bz7?B4N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3P?HtDDDEEEEEEFDEFCFS>H~BEQDDDDDDDDDDDDDDDDDDDDDDEI?Hu:K4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;LDDEDDEEEEAAA'CDECDH8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5I8@CHPT8@C6Dv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3P?GsDDDDDDDDDGDDECFR6O3Q3Q5P7N9L:L:L9N5O4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;LDDEDEFGGGDDD-CDEDEK8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4K8AH;CG?FJ8BS3O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q4Q?HyDDDDDDCCC=DEFCEN7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LCCDDDEHHH DDD-CDEDDI7M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4M8C[7?Bw}FMQ8AF4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q4Q?HyDDDDDDCCC=DEFCEN7O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LCCDCDDHHH FFF,CDEDDI7M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P6E7?B?GK;CF9AM4L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q4Q?HxDDDDDDFFF>DEFCEN7O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LCCDCDDHHH FFF,CDEDDI7M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4L7C^7?BFMQbhl7?B8C\3N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q4Q?HxDDDEEEFFF>DEFCEN7O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LDDECDF@@@FFF,CDEDDI8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P5J8BX7?B8@C[aeU\`7?B7?D5H3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q4Q?HxDDDCCCCCCEDDECEQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LDDECDFBBBFFF,CDEDDI8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4L6F7BT7?B7?B7?B7?B8AR6G4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q4Q?HxDDDCCCCCCEDDECEQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LDDECDFBBBAAA+CDECDH8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P4N4M3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q4Q>GwDDDDDDEEEFDDECEQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LDDECCDBBBAAA+CDECDH8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M4Q>GwDDDDDDEEEFDDECEQ6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KDDEDDEBBBAAA+DEFCDH8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD9M>GwDDDDDDEEEFDDECEQ6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KDDEDDEEEEBBB#DDFCDG8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDDBERDDDDDDCCCPCCDCET6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDDCEEIIIBBB#DDFDDG9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDDDDDDDDEEEQDDECET5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDDDEEIIIDDD"CEFDDG9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QBF[CCCEEE]DDDDDDDDDRDDECET5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDDDDE@@@DDD"CEFDDG9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q7O@GlDDDCCCEEE]DDDDDDSDDECFU5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDDCCD@@@FFF!DEFDDG8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDECCDEEEAAA+CCCCCCTDDECFU5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QHzDDEDDD"CCCWDDECFV6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;JDDDDDE@@@DDDCEFCDE9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PCDIDDDCCCnDDD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QIDDDGGGCCCBDO3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDDCCECCC@@@CDECDE:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q@HsDDEEEEDDD3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;JDDDDDEDDD@@@CDFCDE:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAGlCCDEEEDDD4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QGwCCDEEECDE4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q@@@DDEAFb3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QGwDDDDDDFFFCDEAEX4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDDDDFFF @@@CDFCCD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HxDDDDDDEEEDDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDCCEFFF @@@DDECCD:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HxDDDDDDEEEDDD>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QJBF^CDIDDDDDDDDDDDDBET?GqGwDDDEEECCCHDDECEN7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDCCCFFF GGGCCDCCD:L3Q3Q3Q3Q3Q3Q3Q3Q4Q>GwDDDEEEBBBIDDECEN7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDDDF999 GGGCCDCCD:L3Q3Q3Q3Q3Q3Q4Q>GwDDDEEEBBBIDDECEN7O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDDDF999 GGGCCDCCD:L3Q3Q3Q3Q4Q?HwDDDDDDBBBIDDECEN7O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDCCE999 @@@CCDCCD:L3Q3Q4Q?HwDDDDDDBBBIDDECEQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDCCE999 @@@DDECCD:L4Q?HwDDDDDDBBBIDDECEQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=IDDDCCE999 KKKCCDDDDAE\DDDCCCDDDVDDECFS6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDEUUUKKKCCDDDDDDDDDDVDDECET6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=HDDDDDDUUUKKKCCCjCCCWDDECET6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=HDDDCCD333DDDKDDECEQ6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QHDDDEEE@@@GGGCEFDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>HDDDDDDUUU@@@DDEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=HDDDDDD333@@@DDEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDD333@@@CCDDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDD333@@@CCDDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDEEE333@@@CCEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDEEE333CCCCCEDDD:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDEEE@@@CCCCCEDDD:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDD@@@CCCDDEDDD:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDD@@@CCCDDEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDD@@@GGGDDEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDD@@@GGGDDEDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=HDDDDDD@@@GGGCCDDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=HDDDDDD@@@KKKCCDDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=HDDDDDD@@@IIIDDEDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDD@@@IIIDDFDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDEEE@@@IIIDDFDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDEEE@@@;;; CCEDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDEEEUUU;;; CCEDDDIDDDCCC999 DDFDDD=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HxDDDDDD999 CCEDDD>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q@GoDDDDDD999 DDDDDD@Gl6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6NAE[DDDDDD@@@CCCDDDDDG=I5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6N?HxDDEDDECCCjEEE;CCCDDDCDE@Gm;K7N5O3P3P5O7MIBDSBBMYEEHCCET7M3Q3Q3Q3Q3Q3Q5O@GqDETEEHCBF\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q=JCFQDDHBE\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=ICERBFJ>BE\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>JCEQEEI?BE\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QH~?Gs=I9L4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LBEQ999 CCOj@Hm3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8MAE]CEUFFIbDDDICFQCCCCEQ7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LBDQFFF CCPo@Hn4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:MBEQEEECES5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;LCER@@@ CENo@Go4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4PBETGGGBBM]>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9MCFQ@@@ CERs?Hr4Q3Q3Q3Q3Q3Q3Q3Q3P4K3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9MBDOCEQ3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:MBEQ;;; DFSu?Gr4Q3Q3Q3Q3Q3Q3Q3Q;OFO_xCMi3O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?HtBBB6DFT9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9LBDQIIIACMjAGm3P3Q3Q3Q3Q3Q3Q3OBMjDNb3O3Q3Q3Q3Q3Q3Q3Q3Q3Q3QBEY@@@CCC_;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LBEQMMM CETz?Ht3P3Q3Q3Q3Q3Q3Q4OFOcFOa4O3Q3Q3Q3Q3Q3Q3Q3Q3QBESCCCL=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9MBEQDDDCFQn@Gn3P3Q3Q3Q3Q3Q3Q3OENcFOa3N3Q3Q3Q3Q3Q3Q3Q3QBEYIIICCC_;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KBEQFFF CET}?Hv3Q3Q3Q3Q3Q3Q3Q3QCQdkyGP`4N3Q3Q3Q3Q3Q3Q3Q?GuFFF7CDS9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8MCEQ@@@BDR?Iw3Q3Q3Q3Q3Q3Q3Q3Q4POXfGP\4MEPdGQ`4N3Q3Q3Q3Q3Q3Q9LCGSCDQ3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8KBEQKKKADQq@Go4Q3Q3Q3Q3Q3Q3Q3Q3Q4MjsV^m4N4OCNdIRb4M3Q3Q3Q3Q3Q4QBEU@@@EEHY?I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LCEPIIIBFT?Iz3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PKTbFO_4N3ODNfJSd3N3Q3Q3Q3Q3Q9LBEQEEECFS5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9NBDPGGGCGT>G{3Q3Q3Q3Q3Q3Q3Q3QIBFOUUUFFFBDQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8MCEQCCCDES>G|3Q3Q3Q3Q3Q3Q3Q3Q>NxIRa4M3OIRbJSb4N3Q3Q3Q3Q3QG~4Q3Q3Q3Q3Q3Q3Q3NIQaZbn>P3PDOhIQa4M3Q4NNV_JSa6N3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9NBEOFFFDES>I3Q3Q3Q3Q3Q3Q3Q3PDNaANv3ODOhJRa5N3QDOlEPd4N3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4O:K@FdBEWBEVBEY=G|9N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q7MBDPBBBBFS=I3Q3Q3Q3Q3Q3Q3Q3Q;NGP\iq~BNk3MDNiJRa5N3OFP`KTc?O3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P=HCESDFMqHHH UUUFFF EEE?BFUAFY8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q7NCEP@@@CFP>I3Q3Q3Q3Q3Q3Q3Q3Q3QFPlw~4L5MGPaBLj4ODNiJRa5M4O4K3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5O@FcAFSuFFFBDS;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8MCEPFFFBDR=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3QFPgBNk3P4ODNgAMq3PEQnJSa5M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PBF[CCGA333CEQ:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6NCEPDDDBDR=I3Q3Q3Q3Q3Q3Q3Q3P4L:M4N@P?O3Q4PBMn>P3PEPoJSa4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>ICFMn999 DER5N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6NBDPKKKCEPs?Hy3Q3Q3Q3Q3Q3Q3Q4NFPgMVb5KR\iz?P3Q3PAMt`ht6M3PEPnJSa4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6PDERۀBBEF?Hs3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:MCER@@@BFV3P3Q3Q3Q3Q3Q3Q5NIR`DM_?Pt{>O3Q3PCOpEPe3Q3PDOnKUc5M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3QO3Q3QCNjx4L3Q3PCOnLUc5L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAGbCCCBFR9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q7NCEUBEU6O3Q3Q3Q3Q3Q3QCRKTb4M3Q3Q4OGPcy@N3Q3OFP`?P3Q3Q4PDOoLUc5L3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3QBEUDDFf:J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QCEQCER4Q3Q3Q3Q3Q3Q3QFP]H~4Q3Q3Q3Q3Q3Q4MKSaKT`7M3Q3Q3Q9Npxbjv>P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q:LCDP@@@ CFFECFV5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PAHoBDR|DFT?H}4Q3Q3Q3Q3Q3Q6MNWcckxBQ4M8MNVdYap4N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q:KCFQFFF FFFCEPBGb5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PAGmBDP|CER?H{3Q3Q3Q3Q3Q3Q7NNVdyfm|4N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q:LDEPFFF DDI8DFOBDUDFPCCCgBFUBETBG]:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P?GlCERzCFU?I{3Q3Q3Q3Q3Q3Q4NISbEPk3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q:LBDRMMM CCH9CFV6O7N8L:L8M6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P@HmACTyCFT>H3Q3Q3Q3Q3Q3Q4ODOiEO_4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q:LCFQ;;; BBG2CFU5N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?GqCERAEQ>H}4Q3Q3Q3Q3Q3Q3Q=OJScEPl4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q:MCDO;;; AAF3CFU6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>GpDFSAES?I~3Q3Q3Q3Q3Q3Q3Q4P:OGSHSpGRw7L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q:LCDO;;; AAF3ADW6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q@GqBDPCET>H}3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv:LCDO@@@ EEJ4AEW5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q@GqBDS{CEW?Hu3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.DENCFR@@@DDH@BEX4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4P@FhAFSqBDQ{?Gr4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QI~4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4PAF[DDJOBEM]AFb5Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JBESUUUDDKKBEQCERBFXADSCFWCER>Hz6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4OAFZFFIMBGR]AGb5Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JBEUUUUDDGKAF_4P4Q5P7O4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5PAE[BBLMAFPfAFc4P3Q3Q3Q3Q3Q3Q3Q3Q3QHDGWEEKUBF`5Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEZDDKDCCMPCEPCFNXAFa5Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEWCCGABBLMAG_4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4OBF[BEEFEENNAG_4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4OCFYCFFEDDMOAG_4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5PBFXCFFEDDMVAE^4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5PBFXDGGD@@@DEI5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6PCEUBBB:EEKUBF`5Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBFWBBFBFFLTAF\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEWBBFBDDJSAF\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEUCCGADDJSAF\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEUDDD@FFIPAF\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6PBFWCCC9DGGOBFZ4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6OCEUDDD8EHHNBFZ4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6OCETDDD8BFFMBEZ4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBETFFF7BEEFCFX4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEUFFF7DDDHz@MYCCQ>H~5Q3Q3Q4Q=JDIc1@@P?I|4P3Q3Q3Q3Q4Q=JCI[*@@P?I}4P3Q3Q3Q3Q3Q3Q4Q=JAG_+<H3P3Q3Q3Q3Q3Q3Q3Q3Q3Q=J@F],<H3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JAG\/<I3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QH4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=KDIc1FFQ>I4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QI3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;IFF]7BBZ=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4P;K>J=HFaBBBZ>J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6O?GoFFF BIhe9K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:JAHcC@HX >J4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?IzBGih5N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;K?FdEFM]!EbFDKZ">J4Q3Q3QBYE[3Q3Q3Q3Q;K߀=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:JAHeG@G\$D])MMM >Hx4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KBIcM@F`(GuoFFF ?J4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KBFcMFM]!>J4Q3Q3Q3Q@XFYan\j@Wmz3Q3Q3Q=I@@@8L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KAHaGDKZ"Gw?Iv=I8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;L@FdTAG\/;J3Q3Q3Q3QJ\>SfqFYEZ3O3Q3Q3Q3Q3Q3Q=I@@@8L3Q3Q3Q3Q3Q6NAGh}@G`H:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LBHfUFFXI;I3Q3Q3Q}4P3Q`n=Sxv3Q?VJ^3Q3Q3Q3Q=I@@@8L3Q3Q3Q3Q;K=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QJ3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;J?Hy3Q3Q3QTdht3P3Q3QTceq3P3Q3Q3Q9SK]3Q3Q3Q3Q3Q=I@@@8L3Q3Q3Q3Q;JEES%CI[*9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?I|BBUI3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=J@JUDKZ"Fcb@F`P?HoGoZ8L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QD])BIf#;I4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=I@@@AGjBFc>@Gid7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>JEnk7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDUBBZ=I4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8M@Ekk@Iql8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IFFXDD^=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P?Gp?Hrn8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P>III[FFX=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9M@GN$=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P=I;ENII[=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;K>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P>I;ENII[>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9NBBI#=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>G=GRBBU>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QFm@Fjx?Hy:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?I~FFQEEb>I3P3Q3Q3Q3QJ3Q3Q3Q;JAEa?@Gol9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P?IBLUDD^>J3Q;JAEa?@Iql8L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?IBLUCNY@HlDIc1>Fp{7M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P>I|GGG?Hlq7M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?JFFQ?Hlq7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>I==I333?H{3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>Hz@@@;EN>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HCCC;EN>I3P3Q3Q3Q3Q3Q3Q3Q3Q4Q?HCCC==I>I4Q3Q3Q3Q3Q3Q3Q3P>I|CCC==I>H4Q3Q3Q3Q3Q4Q>IzGGG@@@>Gz5P3Q3Q5P?Hw;;; @@@AGlv?J>H@GloUUU????~?π?>|?(0` $333@@@;;N =H8N8N;K>Fa999 J4Q3Q3Q3Q3Q3Q;JGG\MMM =J3P3Q3Q3Q3Q3Q3Q3Q;JGG\MMM =J3P3Q3Q3Q3Q3Q3Q3Q3Q3QDj)CQ^:J3Q3QKa=W3Q3Q7M@@@;M3Q3Q3Q3Q3Q3Q3Q3Q3Q:L>Dj)@MY;K3Q3Q3QapAY3Q5PAHjR=IU9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;M=Im*@MY;K3Q3QAYQf{AY3Q9LFMf(FFF =I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9MCIs*FF];K3Q3Q3PUhbn3Q3Q:KUUUHyg5P3Q3Q3Q3Q3Q3Q3Q:MGGf?J3P3QK`QcRfguwMbQc3Q3Q3Q7MIII;J3Q3Q3Q8N=IU:L3Q3Q3Q3Q3Q3Q3Q3Q=KIt6O3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q;K7I[@MYJ999 =Gv5O3Q3Q3Q3Q3Q3Q3Q3Q3Q4QFd!8N3Q3Q3Q3Q3Q3Q3Q4Q;JFF] DDUHz:K:K8M3Q3Q3Q3Q3Q3Q3Q3QG|w6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;L77I@P`;K7O=G{O>F}x6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:K77IFFF BFj:>I|5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3QH}x5N3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q;J@@@ @@@=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;I@@@DDUIUUU????<?x?( @ Dj)99U 8N3Q3Q3Q3Q3Q3Q7MCQy@@`8L3QShdu7S9MBJ{;J3Q3Q3Q3Q3Q3Q3Q3Q7LCQyIIm:L3Q4O]ojyOcSh3Q;Jh@@@ 6N3Q3Q3Q3Q3Q3Q3Q3Q3Q9MIIm3Mf 9M3QYlq^pz3Q3Q;Jh@@@ 6N3Q3Q4Q9N8N4Q3Q3Q3Q3Q7L=Iy333:L3QF^uo~_r3Q3Q3Q;Jh@@@ 6N3Q4Q;JY/Mu(G2P3Q3U:U-I:X.Eʀ4LW0Q3Q3Q3U;W3OYn@[/K֣7Nu3Q8P̊7Nu4Q3V>XGTGf{Sj2P֡7Nx5P5O3Q3YCT6S寓(G(I-M6Pک7NƆ6N\8NR6Oؼ3Q3Q6U7W.Q/Q3Q3Q8Lq8Mg3Q3Q3V=V?[3W3Q4P4P3Q3XAZ@Z8X6MU8NK5P3Q3XBZFU8Xl@Wh?a?git-cola-4.6.1/cola/icons/dark/git-cola.svg000066400000000000000000000146231457126473700204410ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/git-commit.svg000066400000000000000000000005421457126473700210060ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/git-compare.svg000066400000000000000000000027571457126473700211560ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/git-merge.svg000066400000000000000000000027011457126473700206140ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/last-first-order.svg000066400000000000000000000112501457126473700221340ustar00rootroot00000000000000 image/svg+xml git-cola-4.6.1/cola/icons/dark/link-external.svg000066400000000000000000000006201457126473700215070ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/modified.svg000066400000000000000000000002341457126473700205130ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/partial.svg000066400000000000000000000002341457126473700203670ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/pencil.svg000066400000000000000000000006771457126473700202200ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/play.svg000066400000000000000000000011051457126473700176760ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/plus.svg000066400000000000000000000003001457126473700177100ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/primitive-dot.svg000066400000000000000000000003761457126473700215360ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/question-plain.svg000066400000000000000000000007261457126473700217110ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/question.svg000066400000000000000000000015641457126473700206110ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/repo-pull.svg000066400000000000000000000011431457126473700206520ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/repo-push.svg000066400000000000000000000010741457126473700206600ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/repo.svg000066400000000000000000000011031457126473700176740ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/screen-full.svg000066400000000000000000000011331457126473700211510ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/search.svg000066400000000000000000000012771457126473700202100ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/staged.svg000066400000000000000000000002321457126473700202000ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/star.svg000066400000000000000000000004101457126473700177000ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/sync.svg000066400000000000000000000013601457126473700177100ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/tag.svg000066400000000000000000000012301457126473700175030ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/telescope.svg000066400000000000000000000015041457126473700207170ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/terminal.svg000066400000000000000000000016051457126473700205510ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/three-bars.svg000066400000000000000000000013461457126473700207740ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/trashcan.svg000066400000000000000000000014471457126473700205450ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/unfold.svg000066400000000000000000000012321457126473700202210ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/upstream.svg000066400000000000000000000002411457126473700205710ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/x.svg000066400000000000000000000004711457126473700172050ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/zoom-fit-best.svg000066400000000000000000000015261457126473700214370ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/zoom-in.svg000066400000000000000000000022441457126473700203260ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/dark/zoom-out.svg000066400000000000000000000023121457126473700205230ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/desktop-download.svg000066400000000000000000000003401457126473700212660ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/diff.svg000066400000000000000000000003741457126473700167270ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/document-save-symbolic.svg000066400000000000000000000020071457126473700224030ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/edit-copy.svg000066400000000000000000000006351457126473700177140ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/edit-cut.svg000066400000000000000000000025251457126473700175350ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/edit-paste.svg000066400000000000000000000012171457126473700200530ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/edit-redo.svg000066400000000000000000000006351457126473700176730ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/edit-select-all.svg000066400000000000000000000022151457126473700207630ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/edit-undo.svg000066400000000000000000000006541457126473700177100ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/ellipsis.svg000066400000000000000000000004001457126473700176310ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/eye.svg000066400000000000000000000005341457126473700165770ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/file-binary.svg000066400000000000000000000005241457126473700202150ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/file-code.svg000066400000000000000000000010271457126473700176420ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/file-directory.svg000066400000000000000000000006651457126473700207430ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/file-download.svg000066400000000000000000000011621457126473700205370ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/file-media.svg000066400000000000000000000006671457126473700200200ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/file-text.svg000066400000000000000000000007511457126473700177170ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/file-zip.svg000066400000000000000000000014341457126473700175340ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/fold.svg000066400000000000000000000012541457126473700167410ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/folder-new.svg000066400000000000000000000023521457126473700200570ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/folder.svg000066400000000000000000000013441457126473700172700ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/gear.svg000066400000000000000000000014571457126473700167400ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/git-branch.svg000066400000000000000000000030721457126473700200330ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/git-cola.ico000066400000000000000000013226261457126473700175010ustar00rootroot00000000000000 ( f ( @@ (B(00 %j   h.( 999 FFF!BBB:DDDDFFF3BBB333DDD"DDDqDDDCCDDDDDDDDDDDDDDDDCCDDDDDDD^KKKDDD"DDDDDEDDDDDI@Hv=J;K:L;K=JAGgCDDDDDCCDDDDIII333DDDDDEDDD?Ht8M4Q3Q3Q3Q3Q3Q3Q3Q5P9LAF^DDDDEFCCC[GGGDDEDDDAGh7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9LCFVDDDCCCUUUEEEDDEDDD=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4P@GoDDDDDDUUUEEEDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDCCCUUUFFFCCEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P?H|DDDDDDUUUFFFCCEDDDH}DDDCCC333CCCDDEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>H}DDDDDD333CCCDDEDDE;L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>H~DDDDDD333CCCDDEDDE;L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>H~DDDDDDUUUCCCDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>H~DDDDDDUUUCCCDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>H~DDDDDDUUUCCCDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDDUUUCCCDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDDUUU@@@DDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?IDDDDDDUUU@@@CCDDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?IDDDDDDUUU@@@CCDDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?IDDDDDDUUU@@@CCDDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?IDDDDDDUUU@@@CCDDDE;L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=HDDDDDDUUU@@@CCDDDE;L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDDUUU@@@CCDDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDCCCUUUFFFCCDDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDCCCUUUFFFDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDCCCUUUFFFDDEDDE:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDDUUUFFFDDEDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDDUUUFFFDDEDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDDIIIFFFDDEDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDDIIIFFFDDEDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDDIIIDDDDDEDDE:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDDIIIDDDDDECCD:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDDIIIDDDDDECCD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDEEE999 DDDCEFCCD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDD999 DDDCEFCCD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDD999 DDDCDECDE9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=IDDDDDD999 DDDCDECDE9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=IDDDDDDMMM BBBCDECDE9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=IDDDDDDMMM BBBCDECDE9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=IDDDDDDMMM BBBCDECDE9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>JDDDDDDMMM BBBCDECDE:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>JDDDDDDMMM BBBCDECDE:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QGwCDEDDDDDDDDDDDDDDDDDDDDDCCCDDDDDEDDDDDDAF`9L3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QI3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;JDDDDDE@@@FFF,CDECDG8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4PCFSCCDHHH EEEDDD9N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QFI7Bc3P3P6Ds7?B~QX[7?C4J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?HxDDE@@@EEECDH4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDDCCD@@@BBB2CCEDEK7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4J7?B>FI7Cd3P3Q3P6D{7?Bw|~RY]7?C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9NDDDEEECCC5DDD>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDDCCD@@@FFF3CDECDJ7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5J7?B7?B5I3Q3Q3Q5E}7?Bw|~T[^7?C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAF`DEFEEEDDDCCD6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDDCCD@@@FFF3CDECDJ7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4L7?BY_c7@C5J3Q3Q3Q5E}7?Bw}U\`7?C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8MDDDDDDDDDZDDD=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDEDDE@@@FFF3CDEDEK8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4P8AIlqtOVZ7?D4I3Q3Q3Q6E~7?BX^b7?C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?I}DDDCCCjEEE%CCDCER5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;LDDEDDEIIIEEE4CDEDEL8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P5I4L3Q3Q3Q3Q6Ey9AEPWZ7?B5H3Q3Q3Q7B`PX`Y`c7?C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4PBFZDDEDDDKFFFDDECCD8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;LDDEDDEIIIEEE4CDEDEL7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3M8BR7?B7?C4J3Q3Q3Q4L7?B[ae7?B6Dx4L5I7@Cotw[ae7@C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6ODFQDDEDDDKFFF!DDEDDD:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDEDDEIIICCC5DEFDEL7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4K8@I>GKY`c7@C4J3Q3Q3Q6Er8@Cz7?B7?B7?BNUXZad7@C5I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q7NDFQCCDDDDmDDDGw;L4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LCCDDDEEEEDDDDEFCEO6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5F7?B7?B4J3Q3Q4L8AP9AC7?B6E{3Q3P5F7?Buz}\bf7?B5I3Q3Q3Q3O3O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5PAF`DDDDDD999 @@@DDDDDDCFV6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9LCDEDDEBBBFFF>DEFCEO6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6D{8@CCDECFP6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5E7?B7?B5F3Q3Q3Q3Q5Dv7?Bhnpqwy7?B5G3Q3Q5F7?Btz|\bf7?B4I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q@GmDDDCCCcFFFBDDECFX4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9LCDEDDE@@@EEE?CDECFP6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5H7?Bntv7?B4J3Q3Q3Q3Q5G7?B\cffln7?B4K3Q3Q5F7?Btz|\bf7?B5H3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QFI8BP3N3Q3Q3Q3Q5I7?B^dh7?B6G3Q3Q3Q6G7?Bsy{\cf7?B5H3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8NDDDDDDDDDmDDD:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QFI9AD6Dv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5H7?Bekn7?B6Dq3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?HvDDE@@@DDDAE[3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAGcDDEDDDDDD6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8B]NUY8AD6Dk3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4M9BP;CGw|~7?B4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5H7?Bkpt7?B7C^4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QI3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3M7?BX^b7@E4L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3N7C^7?Bz?FJ8AO3N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5H7?BY`cdkm7?B6Dn4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4PDEIDDDDDDDDD6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDDFFFBDDECET3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6Dp8@CELQ8AH4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P5E}7?BQX[KRV8@H4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5I8@C7?B7?B8@C5G3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4QBF_DDDGGGFFF DDEAF_3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAFaCCD333CCCyDDD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4N7?Dcil=EI8BR4N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4I8AI8ADCJN8AF4L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4N5F6F4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HxDDDCCCUUUDDDmDDD:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9LDDDDDD@@@ CDDCFW3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5G7?B;CF8BT3O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3N6Dq7?B;CFv{}8@C8BN5L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HwDDDDDDUUUKKKCDECFS3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PAEXCDE@@@EEEoDDD=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P7Ce9AC9AC8BU4N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4L7Ci7?B7?BMTWqwyzLSW7?B7?C6E3N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HwDDDDDDUUUDDDDDD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QJ6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDEDDEEEEFFF(CDECDG8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5H7?BX^bz7?B4N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3P?HtDDDEEEEEEFDEFCFS>H~BEQDDDDDDDDDDDDDDDDDDDDDDEI?Hu:K4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;LDDEDDEEEEAAA'CDECDH8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5I8@CHPT8@C6Dv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q3Q3P?GsDDDDDDDDDGDDECFR6O3Q3Q5P7N9L:L:L9N5O4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;LDDEDEFGGGDDD-CDEDEK8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4K8AH;CG?FJ8BS3O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q3Q4Q?HyDDDDDDCCC=DEFCEN7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LCCDDDEHHH DDD-CDEDDI7M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4M8C[7?Bw}FMQ8AF4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q3Q4Q?HyDDDDDDCCC=DEFCEN7O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LCCDCDDHHH FFF,CDEDDI7M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P6E7?B?GK;CF9AM4L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q3Q4Q?HxDDDDDDFFF>DEFCEN7O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LCCDCDDHHH FFF,CDEDDI7M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4L7C^7?BFMQbhl7?B8C\3N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q3Q4Q?HxDDDEEEFFF>DEFCEN7O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LDDECDF@@@FFF,CDEDDI8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P5J8BX7?B8@C[aeU\`7?B7?D5H3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q3Q4Q?HxDDDCCCCCCEDDECEQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LDDECDFBBBFFF,CDEDDI8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4L6F7BT7?B7?B7?B7?B8AR6G4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q3Q4Q?HxDDDCCCCCCEDDECEQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LDDECDFBBBAAA+CDECDH8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P4N4M3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M3Q4Q>GwDDDDDDEEEFDDECEQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LDDECCDBBBAAA+CDECDH8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD8M4Q>GwDDDDDDEEEFDDECEQ6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KDDEDDEBBBAAA+DEFCDH8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDD9M>GwDDDDDDEEEFDDECEQ6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KDDEDDEEEEBBB#DDFCDG8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDDBERDDDDDDCCCPCCDCET6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDDCEEIIIBBB#DDFDDG9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAE\CCCEEE]DDDDDDDDDEEEQDDECET5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDDDEEIIIDDD"CEFDDG9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QBF[CCCEEE]DDDDDDDDDRDDECET5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDDDDE@@@DDD"CEFDDG9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q7O@GlDDDCCCEEE]DDDDDDSDDECFU5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KDDDCCD@@@FFF!DEFDDG8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDECCDEEEAAA+CCCCCCTDDECFU5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QHzDDEDDD"CCCWDDECFV6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;JDDDDDE@@@DDDCEFCDE9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PCDIDDDCCCnDDD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QIDDDGGGCCCBDO3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KDDDCCECCC@@@CDECDE:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q@HsDDEEEEDDD3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;JDDDDDEDDD@@@CDFCDE:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAGlCCDEEEDDD4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QGwCCDEEECDE4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q@@@DDEAFb3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QGwDDDDDDFFFCDEAEX4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDDDDFFF @@@CDFCCD9L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HxDDDDDDEEEDDD8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDCCEFFF @@@DDECCD:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HxDDDDDDEEEDDD>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QJBF^CDIDDDDDDDDDDDDBET?GqGwDDDEEECCCHDDECEN7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDCCCFFF GGGCCDCCD:L3Q3Q3Q3Q3Q3Q3Q3Q4Q>GwDDDEEEBBBIDDECEN7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDDDF999 GGGCCDCCD:L3Q3Q3Q3Q3Q3Q4Q>GwDDDEEEBBBIDDECEN7O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDDDF999 GGGCCDCCD:L3Q3Q3Q3Q4Q?HwDDDDDDBBBIDDECEN7O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDCCE999 @@@CCDCCD:L3Q3Q4Q?HwDDDDDDBBBIDDECEQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JDDDCCE999 @@@DDECCD:L4Q?HwDDDDDDBBBIDDECEQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=IDDDCCE999 KKKCCDDDDAE\DDDCCCDDDVDDECFS6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=IDDDDDEUUUKKKCCDDDDDDDDDDVDDECET6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=HDDDDDDUUUKKKCCCjCCCWDDECET6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=HDDDCCD333DDDKDDECEQ6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QHDDDEEE@@@GGGCEFDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>HDDDDDDUUU@@@DDEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q=HDDDDDD333@@@DDEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDD333@@@CCDDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDDDD333@@@CCDDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>IDDDEEE333@@@CCEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDEEE333CCCCCEDDD:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDEEE@@@CCCCCEDDD:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDD@@@CCCDDEDDD:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDD@@@CCCDDEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDD@@@GGGDDEDDD;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDD@@@GGGDDEDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=HDDDDDD@@@GGGCCDDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=HDDDDDD@@@KKKCCDDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=HDDDDDD@@@IIIDDEDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDDDD@@@IIIDDFDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDEEE@@@IIIDDFDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDEEE@@@;;; CCEDDD;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDDEEEUUU;;; CCEDDDIDDDCCC999 DDFDDD=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HxDDDDDD999 CCEDDD>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q@GoDDDDDD999 DDDDDD@Gl6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6NAE[DDDDDD@@@CCCDDDDDG=I5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6N?HxDDEDDECCCjEEE;CCCDDDCDE@Gm;K7N5O3P3P5O7MIBDSBBMYEEHCCET7M3Q3Q3Q3Q3Q3Q5O@GqDETEEHCBF\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q=JCFQDDHBE\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=ICERBFJ>BE\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>JCEQEEI?BE\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QH~?Gs=I9L4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LBEQ999 CCOj@Hm3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8MAE]CEUFFIbDDDICFQCCCCEQ7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LBDQFFF CCPo@Hn4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:MBEQEEECES5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;LCER@@@ CENo@Go4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4PBETGGGBBM]>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9MCFQ@@@ CERs?Hr4Q3Q3Q3Q3Q3Q3Q3Q3P4K3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9MBDOCEQ3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:MBEQ;;; DFSu?Gr4Q3Q3Q3Q3Q3Q3Q3Q;OFO_xCMi3O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?HtBBB6DFT9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9LBDQIIIACMjAGm3P3Q3Q3Q3Q3Q3Q3OBMjDNb3O3Q3Q3Q3Q3Q3Q3Q3Q3Q3QBEY@@@CCC_;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LBEQMMM CETz?Ht3P3Q3Q3Q3Q3Q3Q4OFOcFOa4O3Q3Q3Q3Q3Q3Q3Q3Q3QBESCCCL=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9MBEQDDDCFQn@Gn3P3Q3Q3Q3Q3Q3Q3OENcFOa3N3Q3Q3Q3Q3Q3Q3Q3QBEYIIICCC_;K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KBEQFFF CET}?Hv3Q3Q3Q3Q3Q3Q3Q3QCQdkyGP`4N3Q3Q3Q3Q3Q3Q3Q?GuFFF7CDS9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8MCEQ@@@BDR?Iw3Q3Q3Q3Q3Q3Q3Q3Q4POXfGP\4MEPdGQ`4N3Q3Q3Q3Q3Q3Q9LCGSCDQ3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8KBEQKKKADQq@Go4Q3Q3Q3Q3Q3Q3Q3Q3Q4MjsV^m4N4OCNdIRb4M3Q3Q3Q3Q3Q4QBEU@@@EEHY?I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LCEPIIIBFT?Iz3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PKTbFO_4N3ODNfJSd3N3Q3Q3Q3Q3Q9LBEQEEECFS5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9NBDPGGGCGT>G{3Q3Q3Q3Q3Q3Q3Q3QIBFOUUUFFFBDQ6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8MCEQCCCDES>G|3Q3Q3Q3Q3Q3Q3Q3Q>NxIRa4M3OIRbJSb4N3Q3Q3Q3Q3QG~4Q3Q3Q3Q3Q3Q3Q3NIQaZbn>P3PDOhIQa4M3Q4NNV_JSa6N3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9NBEOFFFDES>I3Q3Q3Q3Q3Q3Q3Q3PDNaANv3ODOhJRa5N3QDOlEPd4N3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4O:K@FdBEWBEVBEY=G|9N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q7MBDPBBBBFS=I3Q3Q3Q3Q3Q3Q3Q3Q;NGP\iq~BNk3MDNiJRa5N3OFP`KTc?O3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P=HCESDFMqHHH UUUFFF EEE?BFUAFY8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q7NCEP@@@CFP>I3Q3Q3Q3Q3Q3Q3Q3Q3QFPlw~4L5MGPaBLj4ODNiJRa5M4O4K3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5O@FcAFSuFFFBDS;J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8MCEPFFFBDR=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3QFPgBNk3P4ODNgAMq3PEQnJSa5M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PBF[CCGA333CEQ:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6NCEPDDDBDR=I3Q3Q3Q3Q3Q3Q3Q3P4L:M4N@P?O3Q4PBMn>P3PEPoJSa4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>ICFMn999 DER5N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6NBDPKKKCEPs?Hy3Q3Q3Q3Q3Q3Q3Q4NFPgMVb5KR\iz?P3Q3PAMt`ht6M3PEPnJSa4M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6PDERۀBBEF?Hs3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:MCER@@@BFV3P3Q3Q3Q3Q3Q3Q5NIR`DM_?Pt{>O3Q3PCOpEPe3Q3PDOnKUc5M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3QO3Q3QCNjx4L3Q3PCOnLUc5L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3QAGbCCCBFR9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q7NCEUBEU6O3Q3Q3Q3Q3Q3QCRKTb4M3Q3Q4OGPcy@N3Q3OFP`?P3Q3Q4PDOoLUc5L3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q3Q3Q3QBEUDDFf:J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QCEQCER4Q3Q3Q3Q3Q3Q3QFP]H~4Q3Q3Q3Q3Q3Q4MKSaKT`7M3Q3Q3Q9Npxbjv>P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q3Q:LCDP@@@ CFFECFV5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PAHoBDR|DFT?H}4Q3Q3Q3Q3Q3Q6MNWcckxBQ4M8MNVdYap4N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q3Q:KCFQFFF FFFCEPBGb5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3PAGmBDP|CER?H{3Q3Q3Q3Q3Q3Q7NNVdyfm|4N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q3Q:LDEPFFF DDI8DFOBDUDFPCCCgBFUBETBG]:M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P?GlCERzCFU?I{3Q3Q3Q3Q3Q3Q4NISbEPk3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q3Q:LBDRMMM CCH9CFV6O7N8L:L8M6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P@HmACTyCFT>H3Q3Q3Q3Q3Q3Q4ODOiEO_4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q3Q:LCFQ;;; BBG2CFU5N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?GqCERAEQ>H}4Q3Q3Q3Q3Q3Q3Q=OJScEPl4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q3Q:MCDO;;; AAF3CFU6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>GpDFSAES?I~3Q3Q3Q3Q3Q3Q3Q4P:OGSHSpGRw7L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv3Q:LCDO;;; AAF3ADW6P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q@GqBDPCET>H}3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.?Hv:LCDO@@@ EEJ4AEW5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q@GqBDS{CEW?Hu3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9KEEEhCCC.DENCFR@@@DDH@BEX4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4P@FhAFSqBDQ{?Gr4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QI~4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4PAF[DDJOBEM]AFb5Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JBESUUUDDKKBEQCERBFXADSCFWCER>Hz6N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4OAFZFFIMBGR]AGb5Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JBEUUUUDDGKAF_4P4Q5P7O4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5PAE[BBLMAFPfAFc4P3Q3Q3Q3Q3Q3Q3Q3Q3QHDGWEEKUBF`5Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEZDDKDCCMPCEPCFNXAFa5Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEWCCGABBLMAG_4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4OBF[BEEFEENNAG_4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4OCFYCFFEDDMOAG_4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5PBFXCFFEDDMVAE^4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5PBFXDGGD@@@DEI5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6PCEUBBB:EEKUBF`5Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBFWBBFBFFLTAF\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEWBBFBDDJSAF\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEUCCGADDJSAF\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEUDDD@FFIPAF\5P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6PBFWCCC9DGGOBFZ4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6OCEUDDD8EHHNBFZ4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6OCETDDD8BFFMBEZ4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBETFFF7BEEFCFX4O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q5OBEUFFF7DDDHz@MYCCQ>H~5Q3Q3Q4Q=JDIc1@@P?I|4P3Q3Q3Q3Q4Q=JCI[*@@P?I}4P3Q3Q3Q3Q3Q3Q4Q=JAG_+<H3P3Q3Q3Q3Q3Q3Q3Q3Q3Q=J@F],<H3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=JAG\/<I3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QH4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=KDIc1FFQ>I4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QI3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;IFF]7BBZ=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4P;K>J=HFaBBBZ>J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q6O?GoFFF BIhe9K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:JAHcC@HX >J4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?IzBGih5N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;K?FdEFM]!EbFDKZ">J4Q3Q3QBYE[3Q3Q3Q3Q;K߀=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:JAHeG@G\$D])MMM >Hx4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KBIcM@F`(GuoFFF ?J4P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:KBFcMFM]!>J4Q3Q3Q3Q@XFYan\j@Wmz3Q3Q3Q=I@@@8L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;KAHaGDKZ"Gw?Iv=I8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;L@FdTAG\/;J3Q3Q3Q3QJ\>SfqFYEZ3O3Q3Q3Q3Q3Q3Q=I@@@8L3Q3Q3Q3Q3Q6NAGh}@G`H:K3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:LBHfUFFXI;I3Q3Q3Q}4P3Q`n=Sxv3Q?VJ^3Q3Q3Q3Q=I@@@8L3Q3Q3Q3Q;K=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QJ3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;J?Hy3Q3Q3QTdht3P3Q3QTceq3P3Q3Q3Q9SK]3Q3Q3Q3Q3Q=I@@@8L3Q3Q3Q3Q;JEES%CI[*9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q?I|BBUI3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=J@JUDKZ"Fcb@F`P?HoGoZ8L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QD])BIf#;I4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q=I@@@AGjBFc>@Gid7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>JEnk7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IDDUBBZ=I4Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q8M@Ekk@Iql8N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q>IFFXDD^=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P?Gp?Hrn8M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P>III[FFX=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9M@GN$=J3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P=I;ENII[=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;K>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P>I;ENII[>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9NBBI#=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>G=GRBBU>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3QFm@Fjx?Hy:L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?I~FFQEEb>I3P3Q3Q3Q3QJ3Q3Q3Q;JAEa?@Gol9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P?IBLUDD^>J3Q;JAEa?@Iql8L3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?IBLUCNY@HlDIc1>Fp{7M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3P>I|GGG?Hlq7M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?JFFQ?Hlq7N3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>I==I333?H{3P3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q>Hz@@@;EN>I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q?HCCC;EN>I3P3Q3Q3Q3Q3Q3Q3Q3Q4Q?HCCC==I>I4Q3Q3Q3Q3Q3Q3Q3P>I|CCC==I>H4Q3Q3Q3Q3Q4Q>IzGGG@@@>Gz5P3Q3Q5P?Hw;;; @@@AGlv?J>H@GloUUU????~?π?>|?(0` $333@@@;;N =H8N8N;K>Fa999 J4Q3Q3Q3Q3Q3Q;JGG\MMM =J3P3Q3Q3Q3Q3Q3Q3Q;JGG\MMM =J3P3Q3Q3Q3Q3Q3Q3Q3Q3QDj)CQ^:J3Q3QKa=W3Q3Q7M@@@;M3Q3Q3Q3Q3Q3Q3Q3Q3Q:L>Dj)@MY;K3Q3Q3QapAY3Q5PAHjR=IU9M3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;M=Im*@MY;K3Q3QAYQf{AY3Q9LFMf(FFF =I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q9MCIs*FF];K3Q3Q3PUhbn3Q3Q:KUUUHyg5P3Q3Q3Q3Q3Q3Q3Q:MGGf?J3P3QK`QcRfguwMbQc3Q3Q3Q7MIII;J3Q3Q3Q8N=IU:L3Q3Q3Q3Q3Q3Q3Q3Q=KIt6O3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q;K7I[@MYJ999 =Gv5O3Q3Q3Q3Q3Q3Q3Q3Q3Q4QFd!8N3Q3Q3Q3Q3Q3Q3Q4Q;JFF] DDUHz:K:K8M3Q3Q3Q3Q3Q3Q3Q3QG|w6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;L77I@P`;K7O=G{O>F}x6O3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q:K77IFFF BFj:>I|5O3Q3Q3Q3Q3Q3Q3Q3Q3Q3QH}x5N3Q3Q3Q3Q3Q3Q3Q3Q3Q4Q;J@@@ @@@=I3Q3Q3Q3Q3Q3Q3Q3Q3Q3Q;I@@@DDUIUUU????<?x?( @ Dj)99U 8N3Q3Q3Q3Q3Q3Q7MCQy@@`8L3QShdu7S9MBJ{;J3Q3Q3Q3Q3Q3Q3Q3Q7LCQyIIm:L3Q4O]ojyOcSh3Q;Jh@@@ 6N3Q3Q3Q3Q3Q3Q3Q3Q3Q9MIIm3Mf 9M3QYlq^pz3Q3Q;Jh@@@ 6N3Q3Q4Q9N8N4Q3Q3Q3Q3Q7L=Iy333:L3QF^uo~_r3Q3Q3Q;Jh@@@ 6N3Q4Q;JY/Mu(G2P3Q3U:U-I:X.Eʀ4LW0Q3Q3Q3U;W3OYn@[/K֣7Nu3Q8P̊7Nu4Q3V>XGTGf{Sj2P֡7Nx5P5O3Q3YCT6S寓(G(I-M6Pک7NƆ6N\8NR6Oؼ3Q3Q6U7W.Q/Q3Q3Q8Lq8Mg3Q3Q3V=V?[3W3Q4P4P3Q3XAZ@Z8X6MU8NK5P3Q3XBZFU8Xl@Wh?a?git-cola-4.6.1/cola/icons/git-cola.svg000066400000000000000000000146231457126473700175200ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/git-commit.svg000066400000000000000000000005471457126473700200720ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/git-compare.svg000066400000000000000000000027571457126473700202350ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/git-merge.svg000066400000000000000000000027011457126473700176730ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/last-first-order.svg000066400000000000000000000112501457126473700212130ustar00rootroot00000000000000 image/svg+xml git-cola-4.6.1/cola/icons/link-external.svg000066400000000000000000000006201457126473700205660ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/modified.svg000066400000000000000000000034441457126473700176000ustar00rootroot00000000000000 image/svg+xml git-cola-4.6.1/cola/icons/partial.svg000066400000000000000000000002341457126473700174460ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/pencil.svg000066400000000000000000000006771457126473700172770ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/play.svg000066400000000000000000000010731457126473700167610ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/plus.svg000066400000000000000000000003001457126473700167670ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/primitive-dot.svg000066400000000000000000000003761457126473700206150ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/question-plain.svg000066400000000000000000000007261457126473700207700ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/question.svg000066400000000000000000000015641457126473700176700ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/repo-pull.svg000066400000000000000000000011431457126473700177310ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/repo-push.svg000066400000000000000000000010741457126473700177370ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/repo.svg000066400000000000000000000011031457126473700167530ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/screen-full.svg000066400000000000000000000011331457126473700202300ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/search.svg000066400000000000000000000012771457126473700172670ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/staged.svg000066400000000000000000000002321457126473700172570ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/star.svg000066400000000000000000000004101457126473700167570ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/sync.svg000066400000000000000000000013601457126473700167670ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/tag.svg000066400000000000000000000012301457126473700165620ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/telescope.svg000066400000000000000000000015041457126473700177760ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/terminal.svg000066400000000000000000000015331457126473700176300ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/three-bars.svg000066400000000000000000000013251457126473700200500ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/trashcan.svg000066400000000000000000000014471457126473700176240ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/unfold.svg000066400000000000000000000012261457126473700173030ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/upstream.svg000066400000000000000000000005541457126473700176570ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/x.svg000066400000000000000000000030661457126473700162670ustar00rootroot00000000000000 image/svg+xml git-cola-4.6.1/cola/icons/zoom-fit-best.svg000066400000000000000000000015511457126473700205140ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/zoom-in.svg000066400000000000000000000022441457126473700174050ustar00rootroot00000000000000 git-cola-4.6.1/cola/icons/zoom-out.svg000066400000000000000000000023121457126473700176020ustar00rootroot00000000000000 git-cola-4.6.1/cola/inotify.py000066400000000000000000000042231457126473700162130ustar00rootroot00000000000000import ctypes import ctypes.util import errno import os # constant from Linux include/uapi/linux/limits.h NAME_MAX = 255 # constants from Linux include/uapi/linux/inotify.h IN_MODIFY = 0x00000002 IN_ATTRIB = 0x00000004 IN_CLOSE_WRITE = 0x00000008 IN_MOVED_FROM = 0x00000040 IN_MOVED_TO = 0x00000080 IN_CREATE = 0x00000100 IN_DELETE = 0x00000200 IN_Q_OVERFLOW = 0x00004000 IN_ONLYDIR = 0x01000000 IN_EXCL_UNLINK = 0x04000000 IN_ISDIR = 0x80000000 class inotify_event(ctypes.Structure): _fields_ = [ ('wd', ctypes.c_int), ('mask', ctypes.c_uint32), ('cookie', ctypes.c_uint32), ('len', ctypes.c_uint32), ] MAX_EVENT_SIZE = ctypes.sizeof(inotify_event) + NAME_MAX + 1 def _errcheck(result, func, arguments): if result >= 0: return result err = ctypes.get_errno() if err == errno.EINTR: return func(*arguments) raise OSError(err, os.strerror(err)) try: _libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True) _read = _libc.read init = _libc.inotify_init add_watch = _libc.inotify_add_watch rm_watch = _libc.inotify_rm_watch except AttributeError: raise ImportError('Could not load inotify functions from libc') _read.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_size_t] _read.errcheck = _errcheck init.argtypes = [] init.errcheck = _errcheck add_watch.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.c_uint32] add_watch.errcheck = _errcheck rm_watch.argtypes = [ctypes.c_int, ctypes.c_int] rm_watch.errcheck = _errcheck def read_events(inotify_fd, count=64): buf = ctypes.create_string_buffer(MAX_EVENT_SIZE * count) num = _read(inotify_fd, buf, ctypes.sizeof(buf)) addr = ctypes.addressof(buf) while num: assert num >= ctypes.sizeof(inotify_event) event = inotify_event.from_address(addr) addr += ctypes.sizeof(inotify_event) num -= ctypes.sizeof(inotify_event) if event.len: assert num >= event.len name = ctypes.string_at(addr) addr += event.len num -= event.len else: name = None yield event.wd, event.mask, event.cookie, name git-cola-4.6.1/cola/interaction.py000066400000000000000000000104171457126473700170530ustar00rootroot00000000000000import os import sys from . import core from .i18n import N_ class Interaction: """Prompts the user and answers questions""" VERBOSE = bool(os.getenv('GIT_COLA_VERBOSE')) @classmethod def command(cls, title, cmd, status, out, err): """Log a command and display error messages on failure""" cls.log_status(status, out, err) if status != 0: cls.command_error(title, cmd, status, out, err) @classmethod def command_error(cls, title, cmd, status, out, err): """Display an error message for a failed command""" core.print_stderr(title) core.print_stderr('-' * len(title)) core.print_stderr(cls.format_command_status(cmd, status)) core.print_stdout('') if out: core.print_stdout(out) if err: core.print_stderr(err) @staticmethod def format_command_status(cmd, status): return N_('"%(command)s" returned exit status %(status)d') % { 'command': cmd, 'status': status, } @staticmethod def format_out_err(out, err): """Format stdout and stderr into a single string""" details = out or '' if err: if details and not details.endswith('\n'): details += '\n' details += err return details @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'] = ('\n' + details) if details else '' scope['informative_text'] = ( ('\n' + informative_text) if informative_text else '' ) sys.stdout.write( """ %(title)s %(title_dashes)s %(message)s%(informative_text)s%(details)s\n""" % scope ) sys.stdout.flush() @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, cancel_text=None, ): cancel_text = cancel_text or 'Cancel' icon = icon or '?' cls.information(title, message=text, informative_text=informative_text) if default: prompt = '%s? [Y/n] ' % ok_text else: prompt = '%s? [y/N] ' % ok_text sys.stdout.write(prompt) sys.stdout.flush() answer = sys.stdin.readline().strip() if answer: result = answer.lower().startswith('y') else: result = default return result @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('# ' + title) cls.log('$ ' + core.list2cmdline(cmd)) status, out, err = core.run_command(cmd) cls.log_status(status, out, err) return status, out, err @classmethod def confirm_config_action(cls, _context, 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 + '\n') if out else '') + ((err + '\n') if err else '') cls.log(msg) cls.log('exit status %s' % status) @classmethod def log(cls, message): if cls.VERBOSE: core.print_stdout(message) @classmethod def save_as(cls, filename, title): if cls.confirm(title, 'Save as %s?' % filename, '', ok_text='Save'): return filename return None @staticmethod def async_command(title, command, runtask): pass @classmethod def choose_ref(cls, _context, title, button_text, default=None, icon=None): icon = icon or '?' cls.information(title, button_text) return sys.stdin.readline().strip() or default git-cola-4.6.1/cola/main.py000066400000000000000000000476451457126473700154750ustar00rootroot00000000000000"""Launcher and command line interface to git-cola""" import argparse import sys from . import app from . import cmds from . import compat from . import core def main(argv=None): app.initialize() if argv is None: argv = sys.argv[1:] # we're using argparse with subparsers, 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. help_commands = core.encode('--help-commands') args = [core.encode(arg) for arg in argv] if not argv or argv[0].startswith('-') and help_commands not in args: argv.insert(0, 'cola') elif help_commands in argv: argv.append('--help') args = parse_args(argv) return args.func(args) def parse_args(argv): parser = argparse.ArgumentParser() # Newer versions of argparse (Python 3.6+) emit an error message for # "--help-commands" unless we register the flag on the main parser. if compat.PY_VERSION >= (3, 6): add_help_options(parser) parser.set_defaults(func=lambda _: parser.print_help()) subparser = parser.add_subparsers(title='valid commands') add_cola_command(subparser) add_about_command(subparser) add_am_command(subparser) add_archive_command(subparser) add_branch_command(subparser) add_browse_command(subparser) add_clone_command(subparser) add_config_command(subparser) add_dag_command(subparser) add_diff_command(subparser) add_fetch_command(subparser) add_find_command(subparser) add_grep_command(subparser) add_merge_command(subparser) add_pull_command(subparser) add_push_command(subparser) add_rebase_command(subparser) add_recent_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(argv) def add_help_options(parser): """Add the --help-commands flag to the parser""" parser.add_argument( '--help-commands', default=False, action='store_true', help='show available sub-commands', ) def add_command(parent, name, description, func): parser = parent.add_parser(str(name), help=description) parser.set_defaults(func=func) app.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' ) add_help_options(parser) parser.add_argument( '--status-filter', '-s', metavar='', default='', help='status path filter' ) def add_about_command(parent): add_command(parent, 'about', 'about git-cola', cmd_about) def add_am_command(parent): parser = add_command(parent, 'am', 'apply patches using "git am"', cmd_am) parser.add_argument( 'patches', metavar='', nargs='*', help='patches to apply' ) def add_archive_command(parent): parser = add_command(parent, 'archive', 'save an archive', cmd_archive) parser.add_argument( 'ref', metavar='', nargs='?', default=None, help='commit 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) def add_clone_command(subparser): add_command(subparser, 'clone', 'clone repository', cmd_clone) 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( '--all', action='store_true', dest='show_all', help='visualize all branches', default=False, ) parser.add_argument( 'args', nargs=argparse.REMAINDER, metavar='', help='git log arguments' ) def add_diff_command(subparser): parser = add_command(subparser, 'diff', 'view diffs', cmd_diff) parser.add_argument( 'args', nargs=argparse.REMAINDER, metavar='', help='git diff arguments' ) def add_fetch_command(subparser): add_command(subparser, 'fetch', 'fetch remotes', cmd_fetch) def add_find_command(subparser): parser = add_command(subparser, 'find', 'find files', cmd_find) parser.add_argument('paths', nargs='*', metavar='', help='filter by path') 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): parser = add_command(subparser, 'merge', 'merge branches', cmd_merge) parser.add_argument( 'ref', nargs='?', metavar='', help='branch, tag, or commit to 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( '-v', '--verbose', default=False, action='store_true', help='display a diffstat of what changed upstream', ) parser.add_argument( '-q', '--quiet', default=False, action='store_true', help='be quiet. implies --no-stat', ) parser.add_argument( '-i', '--interactive', default=True, action='store_true', help=argparse.SUPPRESS ) parser.add_argument( '--autostash', default=False, action='store_true', help='automatically stash/stash pop before and after', ) parser.add_argument( '--fork-point', default=False, action='store_true', help="use 'merge-base --fork-point' to refine upstream", ) parser.add_argument( '--onto', default=None, metavar='', help='rebase onto given branch instead of upstream', ) parser.add_argument( '-p', '--preserve-merges', default=False, action='store_true', help='try to recreate merges instead of ignoring them', ) parser.add_argument( '-s', '--strategy', default=None, metavar='', help='use the given merge strategy', ) parser.add_argument( '--no-ff', default=False, action='store_true', help='cherry-pick all commits, even if unchanged', ) parser.add_argument( '-m', '--merge', default=False, action='store_true', help='use merging strategies to rebase', ) parser.add_argument( '-x', '--exec', default=None, help='add exec lines after each commit of ' 'the editable list', ) parser.add_argument( '-k', '--keep-empty', default=False, action='store_true', help='preserve empty commits during rebase', ) parser.add_argument( '-f', '--force-rebase', default=False, action='store_true', help='force rebase even if branch is up to date', ) parser.add_argument( '-X', '--strategy-option', default=None, metavar='', help='pass the argument through to the merge strategy', ) parser.add_argument( '--stat', default=False, action='store_true', help='display a diffstat of what changed upstream', ) parser.add_argument( '-n', '--no-stat', default=False, action='store_true', help='do not show diffstat of what changed upstream', ) parser.add_argument( '--verify', default=False, action='store_true', help='allow pre-rebase hook to run', ) parser.add_argument( '--rerere-autoupdate', default=False, action='store_true', help='allow rerere to update index with ' 'resolved conflicts', ) parser.add_argument( '--root', default=False, action='store_true', help='rebase all reachable commits up to the root(s)', ) parser.add_argument( '--autosquash', default=True, action='store_true', help='move commits that begin with ' 'squash!/fixup! under -i', ) parser.add_argument( '--no-autosquash', default=True, action='store_false', dest='autosquash', help='do not move commits that begin with ' 'squash!/fixup! under -i', ) parser.add_argument( '--committer-date-is-author-date', default=False, action='store_true', help="passed to 'git am' by 'git rebase'", ) parser.add_argument( '--ignore-date', default=False, action='store_true', help="passed to 'git am' by 'git rebase'", ) parser.add_argument( '--whitespace', default=False, action='store_true', help="passed to 'git apply' by 'git rebase'", ) parser.add_argument( '--ignore-whitespace', default=False, action='store_true', help="passed to 'git apply' by 'git rebase'", ) parser.add_argument( '--update-refs', default=False, action='store_true', help='update branches that point to commits that are being rebased', ) parser.add_argument( '-C', dest='context_lines', default=None, metavar='', help="passed to 'git apply' by 'git rebase'", ) actions = parser.add_argument_group('actions') actions.add_argument( '--continue', default=False, action='store_true', help='continue' ) actions.add_argument( '--abort', default=False, action='store_true', help='abort and check out the original branch', ) actions.add_argument( '--skip', default=False, action='store_true', help='skip current patch and continue', ) actions.add_argument( '--edit-todo', default=False, action='store_true', help='edit the todo list during an interactive rebase', ) parser.add_argument( 'upstream', nargs='?', default=None, metavar='', help='the upstream configured in branch..remote ' 'and branch..merge options will be used ' 'when is omitted; see git-rebase(1) ' 'for details. If you are currently not on any ' 'branch or if the current branch does not have ' 'a configured upstream, the rebase will abort', ) parser.add_argument( 'branch', nargs='?', default=None, metavar='', help='git rebase will perform an automatic ' '"git checkout " before doing anything ' 'else when is specified', ) def add_recent_command(subparser): add_command(subparser, 'recent', 'edit recent files', cmd_recent) 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='commit 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( '--builtin', action='store_true', default=False, help=argparse.SUPPRESS, ) parser.add_argument( '--brief', action='store_true', default=False, help='print the version number only', ) # entry points def cmd_cola(args): from .widgets.main import MainView status_filter = args.status_filter if status_filter: status_filter = core.abspath(status_filter) context = app.application_init(args) context.timer.start('view') view = MainView(context) if args.amend: cmds.do(cmds.AmendMode, context, amend=True) if status_filter: view.set_filter(core.relpath(status_filter)) context.timer.stop('view') if args.perf: context.timer.display('view') return app.application_run(context, view, start=start_cola, stop=app.default_stop) def start_cola(context, view): app.default_start(context, view) view.start(context) def cmd_about(args): from .widgets import about context = app.application_init(args) view = about.about_dialog(context) return app.application_start(context, view) def cmd_am(args): from .widgets.patch import new_apply_patches context = app.application_init(args) view = new_apply_patches(context, patches=args.patches) return app.application_start(context, view) def cmd_archive(args): from .widgets import archive context = app.application_init(args, update=True) if args.ref is None: args.ref = context.model.currentbranch view = archive.Archive(context, args.ref) return app.application_start(context, view) def cmd_branch(args): from .widgets.createbranch import create_new_branch context = app.application_init(args, update=True) view = create_new_branch(context) return app.application_start(context, view) def cmd_browse(args): from .widgets.browse import worktree_browser context = app.application_init(args) view = worktree_browser(context, show=False, update=False) return app.application_start(context, view) def cmd_clone(args): from .widgets import clone context = app.application_init(args) view = clone.clone(context) context.set_view(view) result = 0 if view.exec_() == view.Accepted else 1 app.default_stop(context, view) return result def cmd_config(args): from .widgets.prefs import preferences context = app.application_init(args) view = preferences(context) return app.application_start(context, view) def cmd_dag(args): from .widgets import dag context = app.application_init(args) # cola.main() uses parse_args(), unlike dag.main() which uses # parse_known_args(), thus we aren't able to automatically forward # all unknown arguments. Special-case support for "--all" since it's # used by the history viewer command on Windows. if args.show_all: args.args.insert(0, '--all') view = dag.git_dag(context, args=args, show=False) return app.application_start(context, view) def cmd_diff(args): from .difftool import diff_expression context = app.application_init(args) expr = core.list2cmdline(args.args) view = diff_expression(context, None, expr, create_widget=True) return app.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. from .widgets import remote context = app.application_init(args) context.model.update_status() view = remote.fetch(context) return app.application_start(context, view) def cmd_find(args): from .widgets import finder context = app.application_init(args) paths = core.list2cmdline(args.paths) view = finder.finder(context, paths=paths) return app.application_start(context, view) def cmd_grep(args): from .widgets import grep context = app.application_init(args) text = core.list2cmdline(args.args) view = grep.new_grep(context, text=text, parent=None) return app.application_start(context, view) def cmd_merge(args): from .widgets.merge import Merge context = app.application_init(args, update=True) view = Merge(context, parent=None, ref=args.ref) return app.application_start(context, view) def cmd_version(args): from . import version version.print_version(builtin=args.builtin, brief=args.brief) return 0 def cmd_pull(args): from .widgets import remote context = app.application_init(args, update=True) view = remote.pull(context) if args.rebase: view.set_rebase(True) return app.application_start(context, view) def cmd_push(args): from .widgets import remote context = app.application_init(args, update=True) view = remote.push(context) return app.application_start(context, view) def cmd_rebase(args): kwargs = { 'verbose': args.verbose, 'quiet': args.quiet, 'autostash': args.autostash, 'fork_point': args.fork_point, 'onto': args.onto, 'preserve_merges': args.preserve_merges, 'strategy': args.strategy, 'no_ff': args.no_ff, 'merge': args.merge, 'exec': getattr(args, 'exec', None), # python keyword 'keep_empty': args.keep_empty, 'force_rebase': args.force_rebase, 'strategy_option': args.strategy_option, 'stat': args.stat, 'no_stat': args.no_stat, 'verify': args.verify, 'rerere_autoupdate': args.rerere_autoupdate, 'root': args.root, 'autosquash': args.autosquash, 'committer_date_is_author_date': args.committer_date_is_author_date, 'ignore_date': args.ignore_date, 'whitespace': args.whitespace, 'ignore_whitespace': args.ignore_whitespace, 'C': args.context_lines, 'continue': getattr(args, 'continue', False), # python keyword 'abort': args.abort, 'skip': args.skip, 'edit_todo': args.edit_todo, 'update_refs': args.update_refs, 'upstream': args.upstream, 'branch': args.branch, } context = app.application_init(args) status, _, _ = cmds.do(cmds.Rebase, context, **kwargs) return status def cmd_recent(args): from .widgets import recent context = app.application_init(args) view = recent.browse_recent_files(context) return app.application_start(context, view) def cmd_remote(args): from .widgets import editremotes context = app.application_init(args) view = editremotes.editor(context, run=False) return app.application_start(context, view) def cmd_search(args): from .widgets.search import search context = app.application_init(args) view = search(context) return app.application_start(context, view) def cmd_stash(args): from .widgets import stash context = app.application_init(args) view = stash.view(context, show=False) return app.application_start(context, view) def cmd_tag(args): from .widgets.createtag import new_create_tag context = app.application_init(args) context.model.update_status() view = new_create_tag(context, name=args.name, ref=args.ref, sign=args.sign) return app.application_start(context, view) # Windows shortcut launch features: def shortcut_launch(): """Launch from a shortcut Prompt for the repository by default. """ argv = sys.argv[1:] if not argv: argv = ['cola', '--prompt'] return main(argv=argv) git-cola-4.6.1/cola/models/000077500000000000000000000000001457126473700154425ustar00rootroot00000000000000git-cola-4.6.1/cola/models/__init__.py000066400000000000000000000000001457126473700175410ustar00rootroot00000000000000git-cola-4.6.1/cola/models/browse.py000066400000000000000000000273011457126473700173200ustar00rootroot00000000000000import time from qtpy import QtGui from qtpy.QtCore import Qt from qtpy.QtCore import Signal from .. import gitcmds from .. import core from .. import icons from .. import utils from .. import qtutils from ..git import STDOUT from ..i18n import N_ class Columns: """Defines columns in the worktree browser""" NAME = 0 STATUS = 1 MESSAGE = 2 AUTHOR = 3 AGE = 4 ALL = (NAME, STATUS, MESSAGE, AUTHOR, AGE) ATTRS = ('name', 'status', 'message', 'author', 'age') TEXT = [] @classmethod def init(cls): cls.TEXT.extend( [N_('Name'), N_('Status'), N_('Message'), N_('Author'), N_('Age')] ) @classmethod def text_values(cls): if not cls.TEXT: cls.init() return cls.TEXT @classmethod def text(cls, column): try: value = cls.TEXT[column] except IndexError: # Defer translation until runtime cls.init() value = cls.TEXT[column] return value @classmethod def attr(cls, column): """Return the attribute for the column""" return cls.ATTRS[column] class GitRepoModel(QtGui.QStandardItemModel): """Provides an interface into a git repository for browsing purposes.""" restore = Signal() def __init__(self, context, parent): QtGui.QStandardItemModel.__init__(self, parent) self.setColumnCount(len(Columns.ALL)) self.context = context self.model = context.model self.entries = {} cfg = context.cfg self.turbo = cfg.get('cola.turbo', False) self.default_author = cfg.get('user.name', N_('Author')) self._interesting_paths = set() self._interesting_files = set() self._runtask = qtutils.RunTask(parent=parent) self.model.updated.connect(self.refresh, type=Qt.QueuedConnection) self.file_icon = icons.file_text() self.dir_icon = icons.directory() def mimeData(self, indexes): paths = qtutils.paths_from_indexes( self, indexes, item_type=GitRepoNameItem.TYPE ) return qtutils.mimedata_from_paths(self.context, paths) def mimeTypes(self): return qtutils.path_mimetypes() def clear(self): self.entries.clear() super().clear() def hasChildren(self, index): if index.isValid(): item = self.itemFromIndex(index) result = item.hasChildren() else: result = True return result def get(self, path, default=None): if not path: item = self.invisibleRootItem() else: item = self.entries.get(path, default) return item def create_row(self, path, create=True, is_dir=False): try: row = self.entries[path] except KeyError: if create: column = create_column row = self.entries[path] = [ column(c, path, is_dir) for c in Columns.ALL ] else: row = None return row def populate(self, item): self.populate_dir(item, item.path + '/') def add_directory(self, parent, path): """Add a directory entry to the model.""" # First, try returning an existing item current_item = self.get(path) if current_item is not None: return current_item[0] # Create model items row_items = self.create_row(path, is_dir=True) # Use a standard directory icon name_item = row_items[0] name_item.setIcon(self.dir_icon) parent.appendRow(row_items) return name_item def add_file(self, parent, path): """Add a file entry to the model.""" file_entry = self.get(path) if file_entry is not None: return file_entry # Create model items row_items = self.create_row(path) name_item = row_items[0] # Use a standard file icon for the name field name_item.setIcon(self.file_icon) # Add file paths at the end of the list parent.appendRow(row_items) return name_item def populate_dir(self, parent, path): """Populate a subtree""" context = self.context dirs, paths = gitcmds.listdir(context, path) # Insert directories before file paths for dirname in dirs: dir_parent = parent if '/' in dirname: dir_parent = self.add_parent_directories(parent, dirname) self.add_directory(dir_parent, dirname) self.update_entry(dirname) for filename in paths: file_parent = parent if '/' in filename: file_parent = self.add_parent_directories(parent, filename) self.add_file(file_parent, filename) self.update_entry(filename) def add_parent_directories(self, parent, dirname): """Ensure that all parent directory entries exist""" sub_parent = parent parent_dir = utils.dirname(dirname) for path in utils.pathset(parent_dir): sub_parent = self.add_directory(sub_parent, path) return sub_parent def path_is_interesting(self, path): """Return True if path has a status.""" return path in self._interesting_paths def get_paths(self, files=None): """Return paths of interest; e.g. paths with a status.""" if files is None: files = self.get_files() return utils.add_parents(files) def get_files(self): model = self.model return set(model.staged + model.unstaged) def refresh(self): old_files = self._interesting_files old_paths = self._interesting_paths new_files = self.get_files() new_paths = self.get_paths(files=new_files) if new_files != old_files or not old_paths: self.clear() self._initialize() self.restore.emit() # Existing items for path in sorted(new_paths.union(old_paths)): self.update_entry(path) self._interesting_files = new_files self._interesting_paths = new_paths def _initialize(self): self.setHorizontalHeaderLabels(Columns.text_values()) self.entries = {} self._interesting_files = files = self.get_files() self._interesting_paths = self.get_paths(files=files) root = self.invisibleRootItem() self.populate_dir(root, './') def update_entry(self, path): if self.turbo or path not in self.entries: return # entry doesn't currently exist context = self.context task = GitRepoInfoTask(context, path, self.default_author) task.connect(self.apply_data) self._runtask.start(task) def apply_data(self, data): entry = self.get(data[0]) if entry: entry[1].set_status(data[1]) entry[2].setText(data[2]) entry[3].setText(data[3]) entry[4].setText(data[4]) def create_column(col, path, is_dir): """Creates a StandardItem for use in a treeview cell.""" # GitRepoNameItem is the only one that returns a custom type() # and is used to infer selections. if col == Columns.NAME: item = GitRepoNameItem(path, is_dir) else: item = GitRepoItem(path) return item class GitRepoInfoTask(qtutils.Task): """Handles expensive git lookups for a path.""" def __init__(self, context, path, default_author): qtutils.Task.__init__(self) self.context = context self.path = path self._default_author = default_author self._data = {} def data(self, key): """Return git data for a path Supported keys are 'date', 'message', and 'author' """ git = self.context.git if not self._data: log_line = git.log( '-1', '--', self.path, no_color=True, pretty=r'format:%ar%x01%s%x01%an', _readonly=True, )[STDOUT] if 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._default_author return self._data[key] 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. """ try: st = core.stat(self.path) except OSError: return N_('%d minutes ago') % 0 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 = self.context.model unmerged = utils.add_parents(model.unmerged) modified = utils.add_parents(model.modified) staged = utils.add_parents(model.staged) untracked = utils.add_parents(model.untracked) upstream_changed = utils.add_parents(model.upstream_changed) path = self.path if path in unmerged: status = (icons.modified_name(), N_('Unmerged')) elif path in modified and self.path in staged: status = (icons.partial_name(), N_('Partially Staged')) elif path in modified: status = (icons.modified_name(), N_('Modified')) elif path in staged: status = (icons.staged_name(), N_('Staged')) elif path in upstream_changed: status = (icons.upstream_name(), N_('Changed Upstream')) elif path in untracked: status = (None, '?') else: status = (None, '') return status def task(self): """Perform expensive lookups and post corresponding events.""" data = ( self.path, self.status(), self.data('message'), self.data('author'), self.data('date'), ) return data 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, path): QtGui.QStandardItem.__init__(self) self.path = path self.cached = False self.setDragEnabled(False) self.setEditable(False) 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 = qtutils.standard_item_type_value(1) def __init__(self, path, is_dir): GitRepoItem.__init__(self, path) self.is_dir = is_dir self.setDragEnabled(True) self.setText(utils.basename(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 self.TYPE def hasChildren(self): return self.is_dir git-cola-4.6.1/cola/models/dag.py000066400000000000000000000214161457126473700165530ustar00rootroot00000000000000import json from .. import core from .. import utils from ..models import prefs # put summary at the end b/c it can contain # any number of funky characters, including the separator logfmt = r'format:%H%x01%P%x01%d%x01%an%x01%ad%x01%ae%x01%s' logsep = chr(0x01) class CommitFactory: root_generation = 0 commits = {} @classmethod def reset(cls): cls.commits.clear() cls.root_generation = 0 @classmethod def new(cls, oid=None, log_entry=None): if not oid and log_entry: oid = log_entry[:40] try: commit = cls.commits[oid] if log_entry and not commit.parsed: commit.parse(log_entry) cls.root_generation = max(commit.generation, cls.root_generation) except KeyError: commit = Commit(oid=oid, log_entry=log_entry) if not log_entry: cls.root_generation += 1 commit.generation = max(commit.generation, cls.root_generation) cls.commits[oid] = commit return commit class DAG: def __init__(self, ref, count): self.ref = ref self.count = count self.overrides = {} def set_ref(self, ref): changed = ref != self.ref if changed: self.ref = ref return changed def set_count(self, count): changed = count != self.count if changed: self.count = count return changed def set_arguments(self, args): if args is None: return if self.set_count(args.count): self.overrides['count'] = args.count if hasattr(args, 'args') and args.args: ref = core.list2cmdline(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: root_generation = 0 __slots__ = ( 'oid', 'summary', 'parents', 'children', 'branches', 'tags', 'author', 'authdate', 'email', 'generation', 'column', 'row', 'parsed', ) def __init__(self, oid=None, log_entry=None): self.oid = oid self.summary = None self.parents = [] self.children = [] self.tags = [] self.branches = [] self.email = None self.author = None self.authdate = None self.parsed = False self.generation = CommitFactory.root_generation self.column = None self.row = None if log_entry: self.parse(log_entry) def parse(self, log_entry, sep=logsep): self.oid = log_entry[:40] after_oid = log_entry[41:] details = after_oid.split(sep, 5) (parents, tags, author, authdate, email, summary) = details self.summary = summary if summary else '' self.author = author if author else '' self.authdate = authdate if authdate else '' self.email = email if email else '' if parents: generation = None for parent_oid in parents.split(' '): parent = CommitFactory.new(oid=parent_oid) 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(', '): self.add_label(tag) self.parsed = True return self def add_label(self, tag): """Add tag/branch labels from `git log --decorate ....`""" if tag.startswith('tag: '): tag = tag[5:] # strip off "tag: " leaving refs/tags/ if tag.startswith('refs/heads/'): branch = tag[11:] self.branches.append(branch) if tag.startswith('refs/'): # strip off refs/ leaving just tags/XXX remotes/XXX heads/XXX tag = tag[5:] if tag.endswith('/HEAD'): return # Git 2.4 Release Notes (draft) # ============================= # # Backward compatibility warning(s) # --------------------------------- # # This release has a few changes in the user-visible output from # Porcelain commands. These are not meant to be parsed by scripts, but # the users still may want to be aware of the changes: # # * Output from "git log --decorate" (and "%d" format specifier used in # the userformat "--format=" parameter "git log" family of # command takes) used to list "HEAD" just like other tips of branch # names, separated with a comma in between. E.g. # # $ git log --decorate -1 main # commit bdb0f6788fa5e3cacc4315e9ff318a27b2676ff4 (HEAD, main) # ... # # This release updates the output slightly when HEAD refers to the tip # of a branch whose name is also shown in the output. The above is # shown as: # # $ git log --decorate -1 main # commit bdb0f6788fa5e3cacc4315e9ff318a27b2676ff4 (HEAD -> main) # ... # # C.f. http://thread.gmane.org/gmane.linux.kernel/1931234 head_arrow = 'HEAD -> ' if tag.startswith(head_arrow): self.tags.append('HEAD') self.add_label(tag[len(head_arrow) :]) else: self.tags.append(tag) def __str__(self): return self.oid def data(self): return { 'oid': self.oid, 'summary': self.summary, 'author': self.author, 'authdate': self.authdate, 'parents': [p.oid for p in self.parents], 'tags': self.tags, } def __repr__(self): return json.dumps(self.data(), sort_keys=True, indent=4, default=list) 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: def __init__(self, context, params): self.context = context self.params = params self.git = context.git self.returncode = 0 self._proc = None self._objects = {} self._cmd = [ 'git', '-c', 'log.abbrevCommit=false', '-c', 'log.showSignature=false', 'log', '--topo-order', '--reverse', '--decorate=full', '--pretty=' + logfmt, ] self._cached = False """Indicates that all data has been read""" 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._proc.kill() self._proc = None self._cached = False self._topo_list = [] def get(self): """Generator function returns Commit objects found by the params""" if self._cached: idx = 0 while True: try: yield self._topo_list[idx] except IndexError: break idx += 1 return self.reset() ref_args = utils.shell_split(self.params.ref) cmd = ( self._cmd + ['-%d' % self.params.count] + ['--date=%s' % prefs.logdate(self.context)] + ref_args ) self._proc = core.start_command(cmd) while True: log_entry = core.readline(self._proc.stdout).rstrip() if not log_entry: self._cached = True self._proc.wait() self.returncode = self._proc.returncode self._proc = None break oid = log_entry[:40] try: yield self._objects[oid] except KeyError: commit = CommitFactory.new(log_entry=log_entry) self._objects[commit.oid] = commit self._topo_list.append(commit) yield commit return def __getitem__(self, oid): return self._objects[oid] def items(self): return list(self._objects.items()) git-cola-4.6.1/cola/models/main.py000066400000000000000000000453731457126473700167540ustar00rootroot00000000000000"""The central cola model""" import os from qtpy import QtCore from qtpy.QtCore import Signal from .. import core from .. import gitcmds from .. import gitcfg from .. import version from ..git import STDOUT from . import prefs def create(context): """Create the repository status model""" return MainModel(context) class MainModel(QtCore.QObject): """Repository status model""" # Refactor: split this class apart into separate DiffModel, CommitMessageModel, # StatusModel, and an DiffEditorState. # Signals about_to_update = Signal() previous_contents = Signal(list, list, list, list) commit_message_changed = Signal(object) diff_text_changed = Signal() diff_text_updated = Signal(str) # "diff_type" {text,image} represents the diff viewer mode. diff_type_changed = Signal(object) # "file_type" {text,image} represents the selected file type. file_type_changed = Signal(object) images_changed = Signal(object) mode_changed = Signal(str) submodules_changed = Signal() refs_updated = Signal() updated = Signal() worktree_changed = Signal() # States mode_none = 'none' # Default: nothing's happened, do nothing mode_worktree = 'worktree' # Comparing index to worktree mode_diffstat = 'diffstat' # Showing a diffstat mode_display = 'display' # Displaying arbitrary information mode_untracked = 'untracked' # Dealing with an untracked file mode_untracked_diff = 'untracked-diff' # Diffing an untracked file mode_index = 'index' # Comparing index to last commit mode_amend = 'amend' # Amending a commit mode_diff = 'diff' # Diffing against an arbitrary commit # Modes where we can checkout files from the $head modes_undoable = {mode_amend, mode_diff, mode_index, mode_worktree} # Modes where we can partially stage files modes_partially_stageable = { mode_amend, mode_diff, mode_worktree, mode_untracked_diff, } # Modes where we can partially unstage files modes_unstageable = {mode_amend, mode_diff, 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, context, cwd=None): """Interface to the main repository status""" super().__init__() self.context = context self.git = context.git self.cfg = context.cfg self.selection = context.selection self.initialized = False self.annex = False self.lfs = False self.head = 'HEAD' self.diff_text = '' self.diff_type = Types.TEXT self.file_type = Types.TEXT self.mode = self.mode_none self.filename = None self.is_cherry_picking = False self.is_merging = False self.is_rebasing = False self.is_applying_patch = False self.currentbranch = '' self.directory = '' self.project = '' self.remotes = [] self.filter_paths = None self.images = [] self.commitmsg = '' # current commit message self._auto_commitmsg = '' # e.g. .git/MERGE_MSG self._prev_commitmsg = '' # saved here when clobbered by .git/MERGE_MSG self.modified = [] # modified, staged, untracked, unmerged paths self.staged = [] self.untracked = [] self.unmerged = [] self.upstream_changed = [] # paths that've changed upstream self.staged_deleted = set() self.unstaged_deleted = set() self.submodules = set() self.submodules_list = None # lazy loaded self.error = None # The last error message. self.ref_sort = 0 # (0: version, 1:reverse-chrono) self.local_branches = [] self.remote_branches = [] self.tags = [] if cwd: self.set_worktree(cwd) def is_diff_mode(self): """Are we in diff mode?""" return self.mode == self.mode_diff def is_unstageable(self): """Are we in a mode that supports "unstage" actions?""" return self.mode in self.modes_unstageable def is_amend_mode(self): """Are we amending a commit?""" return self.mode == self.mode_amend def is_undoable(self): """Can we checkout from the current branch or head ref?""" return self.mode in self.modes_undoable def is_partially_stageable(self): """Whether partial staging should be allowed.""" return self.mode in self.modes_partially_stageable def is_stageable(self): """Whether staging should be allowed.""" return self.is_partially_stageable() or self.mode == self.mode_untracked def all_branches(self): return self.local_branches + self.remote_branches def set_worktree(self, worktree): last_worktree = self.git.paths.worktree self.git.set_worktree(worktree) is_valid = self.git.is_valid() if is_valid: reset = last_worktree is None or last_worktree != worktree cwd = self.git.getcwd() self.project = os.path.basename(cwd) self.set_directory(cwd) core.chdir(cwd) self.update_config(reset=reset) # Detect the "git init" scenario by checking for branches. # If no branches exist then we cannot use "git rev-parse" yet. err = None refs = self.git.git_path('refs', 'heads') if core.exists(refs) and core.listdir(refs): # "git rev-parse" exits with a non-zero exit status when the # safe.directory protection is active. status, _, err = self.git.rev_parse('HEAD') is_valid = status == 0 if is_valid: self.error = None self.worktree_changed.emit() else: self.error = err return is_valid def is_git_lfs_enabled(self): """Return True if `git lfs install` has been run We check for the existence of the "lfs" object-storea, and one of the "git lfs install"-provided hooks. This allows us to detect when "git lfs uninstall" has been run. """ lfs_filter = self.cfg.get('filter.lfs.clean', default=False) lfs_dir = lfs_filter and self.git.git_path('lfs') lfs_hook = lfs_filter and self.cfg.hooks_path('post-merge') return ( lfs_filter and lfs_dir and core.exists(lfs_dir) and lfs_hook and core.exists(lfs_hook) ) def set_commitmsg(self, msg, notify=True): self.commitmsg = msg if notify: self.commit_message_changed.emit(msg) def save_commitmsg(self, msg=None): if msg is None: msg = self.commitmsg path = self.git.git_path('GIT_COLA_MSG') try: if not msg.endswith('\n'): msg += '\n' core.write(path, msg) except OSError: pass return path def set_diff_text(self, txt): """Update the text displayed in the diff editor""" changed = txt != self.diff_text self.diff_text = txt self.diff_text_updated.emit(txt) if changed: self.diff_text_changed.emit() def set_diff_type(self, diff_type): # text, image """Set the diff type to either text or image""" changed = diff_type != self.diff_type self.diff_type = diff_type if changed: self.diff_type_changed.emit(diff_type) def set_file_type(self, file_type): # text, image """Set the file type to either text or image""" changed = file_type != self.file_type self.file_type = file_type if changed: self.file_type_changed.emit(file_type) def set_images(self, images): """Update the images shown in the preview pane""" self.images = images self.images_changed.emit(images) def set_directory(self, path): self.directory = path def set_mode(self, mode, head=None): """Set the current editing mode (worktree, index, amending, ...)""" # Do not allow going into index or worktree mode when amending. if self.is_amend_mode() and mode != self.mode_none: return # We cannot amend in the middle of git cherry-pick, git am or git merge. if ( self.is_cherry_picking or self.is_merging or self.is_applying_patch ) and mode == self.mode_amend: mode = self.mode # Stay in diff mode until explicitly reset. if self.mode == self.mode_diff and mode != self.mode_none: mode = self.mode_diff head = head or self.head else: # If we are amending then we'll use "HEAD^", otherwise use the specified # head or "HEAD" if head has not been specified. if mode == self.mode_amend: head = 'HEAD^' elif not head: head = 'HEAD' self.head = head self.mode = mode self.mode_changed.emit(mode) def update_path_filter(self, filter_paths): self.filter_paths = filter_paths self.update_file_status() def emit_about_to_update(self): self.previous_contents.emit( self.staged, self.unmerged, self.modified, self.untracked ) self.about_to_update.emit() def emit_updated(self): self.updated.emit() def update_file_status(self, update_index=False): """Update modified/staged files status""" self.emit_about_to_update() self.update_files(update_index=update_index, emit=True) def update_file_merge_status(self): """Update modified/staged files and Merge/Rebase/Cherry-pick status""" self.emit_about_to_update() self._update_merge_rebase_status() self.update_file_status() def update_status(self, update_index=False, reset=False): # Give observers a chance to respond self.emit_about_to_update() self.initialized = True self._update_merge_rebase_status() self._update_files(update_index=update_index) self._update_remotes() self._update_branches_and_tags() self._update_commitmsg() self.update_config() if reset: self.update_submodules_list() self.emit_updated() def update_config(self, emit=False, reset=False): if reset: self.cfg.reset() self.annex = self.cfg.is_annex() self.lfs = self.is_git_lfs_enabled() if emit: self.emit_updated() def update_files(self, update_index=False, emit=False): self._update_files(update_index=update_index) if emit: self.emit_updated() def _update_files(self, update_index=False): context = self.context display_untracked = prefs.display_untracked(context) state = gitcmds.worktree_state( context, head=self.head, update_index=update_index, display_untracked=display_untracked, paths=self.filter_paths, ) self.staged = state.get('staged', []) self.modified = state.get('modified', []) self.unmerged = state.get('unmerged', []) self.untracked = state.get('untracked', []) self.upstream_changed = state.get('upstream_changed', []) self.staged_deleted = state.get('staged_deleted', set()) self.unstaged_deleted = state.get('unstaged_deleted', set()) self.submodules = state.get('submodules', set()) selection = self.selection if self.is_empty(): selection.reset() else: selection.update(self) if selection.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 is_empty_repository(self): return not self.local_branches def _update_remotes(self): self.remotes = gitcfg.get_remotes(self.cfg) def _update_branches_and_tags(self): context = self.context sort_types = ( 'version:refname', '-committerdate', ) sort_key = sort_types[self.ref_sort] local_branches, remote_branches, tags = gitcmds.all_refs( context, split=True, sort_key=sort_key ) self.local_branches = local_branches self.remote_branches = remote_branches self.tags = tags # Set these early since they are used to calculate 'upstream_changed'. self.currentbranch = gitcmds.current_branch(self.context) self.refs_updated.emit() def _update_merge_rebase_status(self): cherry_pick_head = self.git.git_path('CHERRY_PICK_HEAD') merge_head = self.git.git_path('MERGE_HEAD') rebase_merge = self.git.git_path('rebase-merge') rebase_apply = self.git.git_path('rebase-apply', 'applying') self.is_cherry_picking = cherry_pick_head and core.exists(cherry_pick_head) self.is_merging = merge_head and core.exists(merge_head) self.is_rebasing = rebase_merge and core.exists(rebase_merge) self.is_applying_patch = rebase_apply and core.exists(rebase_apply) if self.mode == self.mode_amend and ( self.is_merging or self.is_cherry_picking or self.is_applying_patch ): self.set_mode(self.mode_none) def _update_commitmsg(self): """Check for merge message files and update the commit message The message is cleared when the merge completes. """ if self.is_amend_mode(): return # Check if there's a message file in .git/ context = self.context merge_msg_path = gitcmds.merge_message_path(context) if merge_msg_path: msg = gitcmds.read_merge_commit_message(context, merge_msg_path) if msg != self._auto_commitmsg: self._auto_commitmsg = msg self._prev_commitmsg = self.commitmsg self.set_commitmsg(msg) elif self._auto_commitmsg and self._auto_commitmsg == self.commitmsg: self._auto_commitmsg = '' self.set_commitmsg(self._prev_commitmsg) def update_submodules_list(self): self.submodules_list = gitcmds.list_submodule(self.context) self.submodules_changed.emit() def update_remotes(self): self._update_remotes() self.update_refs() def update_refs(self): """Update tag and branch names""" self.emit_about_to_update() self._update_branches_and_tags() self.emit_updated() def delete_branch(self, branch): status, out, err = self.git.branch(branch, D=True) self.update_refs() return status, out, err def rename_branch(self, branch, new_branch): status, out, err = self.git.branch(branch, new_branch, M=True) self.update_refs() return status, out, err def remote_url(self, name, action): push = action == 'PUSH' return gitcmds.remote_url(self.context, name, push=push) def fetch(self, remote, **opts): result = run_remote_action(self.context, self.git.fetch, remote, **opts) self.update_refs() return result def push(self, remote, remote_branch='', local_branch='', **opts): # Swap the branches in push mode (reverse of fetch) opts.update({ 'local_branch': remote_branch, 'remote_branch': local_branch, }) result = run_remote_action( self.context, self.git.push, remote, push=True, **opts ) self.update_refs() return result def pull(self, remote, **opts): result = run_remote_action( self.context, self.git.pull, remote, pull=True, **opts ) # Pull can result in merge conflicts self.update_refs() self.update_files(update_index=False, emit=True) return result 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 is_commit_published(self): """Return True if the latest commit exists in any remote branch""" return bool(self.git.branch(r=True, contains='HEAD')[STDOUT]) def untrack_paths(self, paths): context = self.context status, out, err = gitcmds.untrack_paths(context, paths) self.update_file_status() return status, out, err def getcwd(self): """If we've chosen a directory then use it, otherwise use current""" if self.directory: return self.directory return core.getcwd() def cycle_ref_sort(self): """Choose the next ref sort type (version, reverse-chronological)""" self.set_ref_sort(self.ref_sort + 1) def set_ref_sort(self, raw_value): value = raw_value % 2 # Currently two sort types if value == self.ref_sort: return self.ref_sort = value self.update_refs() class Types: """File types (used for image diff modes)""" IMAGE = 'image' TEXT = 'text' def remote_args( context, remote, local_branch='', remote_branch='', ff_only=False, force=False, no_ff=False, tags=False, rebase=False, pull=False, push=False, set_upstream=False, prune=False, ): """Return arguments for git fetch/push/pull""" args = [remote] what = refspec_arg(local_branch, remote_branch, pull, push) if what: args.append(what) kwargs = { 'verbose': True, } if pull: if rebase: kwargs['rebase'] = True elif ff_only: kwargs['ff_only'] = True elif no_ff: kwargs['no_ff'] = True elif force: if push and version.check_git(context, 'force-with-lease'): kwargs['force_with_lease'] = True else: kwargs['force'] = True if push and set_upstream: kwargs['set_upstream'] = True if tags: kwargs['tags'] = True if prune: kwargs['prune'] = True return (args, kwargs) def refspec(src, dst, push=False): if push and src == dst: spec = src else: spec = f'{src}:{dst}' return spec def refspec_arg(local_branch, remote_branch, pull, push): """Return the refspec for a fetch or pull command""" if not pull and local_branch and remote_branch: what = refspec(remote_branch, local_branch, push=push) else: what = local_branch or remote_branch or None return what def run_remote_action(context, action, remote, **kwargs): args, kwargs = remote_args(context, remote, **kwargs) return action(*args, **kwargs) git-cola-4.6.1/cola/models/prefs.py000066400000000000000000000246451457126473700171460ustar00rootroot00000000000000import sys from qtpy import QtCore from qtpy.QtCore import Signal from .. import core from .. import hidpi from .. import utils from ..cmd import Command AUTOCOMPLETE_PATHS = 'cola.autocompletepaths' AUTOTEMPLATE = 'cola.autoloadcommittemplate' BACKGROUND_EDITOR = 'cola.backgroundeditor' BLAME_VIEWER = 'cola.blameviewer' BLOCK_CURSOR = 'cola.blockcursor' BOLD_HEADERS = 'cola.boldheaders' CHECK_CONFLICTS = 'cola.checkconflicts' CHECK_PUBLISHED_COMMITS = 'cola.checkpublishedcommits' COMMENT_CHAR = 'core.commentchar' COMMIT_CLEANUP = 'commit.cleanup' DIFFCONTEXT = 'gui.diffcontext' DIFFTOOL = 'diff.tool' DISPLAY_UNTRACKED = 'gui.displayuntracked' EDITOR = 'gui.editor' ENABLE_GRAVATAR = 'cola.gravatar' EXPANDTAB = 'cola.expandtab' FONTDIFF = 'cola.fontdiff' HIDPI = 'cola.hidpi' HISTORY_BROWSER = 'gui.historybrowser' ICON_THEME = 'cola.icontheme' LINEBREAK = 'cola.linebreak' LOGDATE = 'cola.logdate' MAXRECENT = 'cola.maxrecent' MERGE_DIFFSTAT = 'merge.diffstat' MERGE_KEEPBACKUP = 'merge.keepbackup' MERGE_SUMMARY = 'merge.summary' MERGE_VERBOSITY = 'merge.verbosity' MERGETOOL = 'merge.tool' MOUSE_ZOOM = 'cola.mousezoom' PATCHES_DIRECTORY = 'cola.patchesdirectory' RESIZE_BROWSER_COLUMNS = 'cola.resizebrowsercolumns' SAFE_MODE = 'cola.safemode' SAVEWINDOWSETTINGS = 'cola.savewindowsettings' SHOW_PATH = 'cola.showpath' SORT_BOOKMARKS = 'cola.sortbookmarks' SPELL_CHECK = 'cola.spellcheck' STATUS_INDENT = 'cola.statusindent' STATUS_SHOW_TOTALS = 'cola.statusshowtotals' THEME = 'cola.theme' TABWIDTH = 'cola.tabwidth' TEXTWIDTH = 'cola.textwidth' USER_EMAIL = 'user.email' USER_NAME = 'user.name' class DateFormat: DEFAULT = 'default' RELATIVE = 'relative' LOCAL = 'local' ISO = 'iso8601' ISO_STRICT = 'iso8601-strict' RFC = 'rfc2822' SHORT = 'short' RAW = 'raw' HUMAN = 'human' UNIX = 'unix' def date_formats(): """Return valid values for git config cola.logdate""" return [ DateFormat.DEFAULT, DateFormat.RELATIVE, DateFormat.LOCAL, DateFormat.ISO, DateFormat.ISO_STRICT, DateFormat.RFC, DateFormat.SHORT, DateFormat.RAW, DateFormat.HUMAN, DateFormat.UNIX, ] def commit_cleanup_modes(): """Return valid values for the git config commit.cleanup""" return [ 'default', 'whitespace', 'strip', 'scissors', 'verbatim', ] class Defaults: """Read-only class for holding defaults that get overridden""" # These should match Git's defaults for git-defined values. autotemplate = False blame_viewer = 'git gui blame' block_cursor = True bold_headers = False check_conflicts = True check_published_commits = True comment_char = '#' commit_cleanup = 'default' display_untracked = True diff_context = 5 difftool = 'xxdiff' editor = 'gvim' enable_gravatar = True expandtab = False history_browser = 'gitk' icon_theme = 'default' linebreak = True maxrecent = 8 mergetool = difftool merge_diffstat = True merge_keep_backup = True merge_summary = True merge_verbosity = 2 mouse_zoom = True resize_browser_columns = False save_window_settings = True safe_mode = False autocomplete_paths = True show_path = True sort_bookmarks = True spellcheck = False tabwidth = 8 textwidth = 72 theme = 'default' hidpi = hidpi.Option.AUTO patches_directory = 'patches' status_indent = False status_show_totals = False logdate = DateFormat.DEFAULT def blame_viewer(context): """Return the configured "blame" viewer""" default = Defaults.blame_viewer return context.cfg.get(BLAME_VIEWER, default=default) def block_cursor(context): """Should we display a block cursor in diff editors?""" return context.cfg.get(BLOCK_CURSOR, default=Defaults.block_cursor) def bold_headers(context): """Should we bold the Status column headers?""" return context.cfg.get(BOLD_HEADERS, default=Defaults.bold_headers) def check_conflicts(context): """Should we check for merge conflict markers in unmerged files?""" return context.cfg.get(CHECK_CONFLICTS, default=Defaults.check_conflicts) def check_published_commits(context): """Should we check for published commits when amending?""" return context.cfg.get( CHECK_PUBLISHED_COMMITS, default=Defaults.check_published_commits ) def display_untracked(context): """Should we display untracked files?""" return context.cfg.get(DISPLAY_UNTRACKED, default=Defaults.display_untracked) def editor(context): """Return the configured editor""" app = context.cfg.get(EDITOR, default=fallback_editor()) return _remap_editor(app) def background_editor(context): """Return the configured non-blocking background editor""" app = context.cfg.get(BACKGROUND_EDITOR, default=editor(context)) return _remap_editor(app) def fallback_editor(): """Return a fallback editor for cases where one is not configured GIT_VISUAL and VISUAL are consulted before GIT_EDITOR and EDITOR to allow configuring a visual editor for Git Cola using $GIT_VISUAL and an alternative editor for the Git CLI. """ editor_variables = ( 'GIT_VISUAL', 'VISUAL', 'GIT_EDITOR', 'EDITOR', ) for env in editor_variables: env_editor = core.getenv(env) if env_editor: return env_editor return Defaults.editor def _remap_editor(app): """Remap a configured editor into a visual editor name""" # We do this for vim users because this configuration is convenient for new users. return { 'vim': 'gvim -f', 'nvim': 'nvim-qt --nofork', }.get(app, app) def comment_char(context): """Return the configured git commit comment character""" return context.cfg.get(COMMENT_CHAR, default=Defaults.comment_char) def commit_cleanup(context): """Return the configured git commit cleanup mode""" return context.cfg.get(COMMIT_CLEANUP, default=Defaults.commit_cleanup) def enable_gravatar(context): """Is gravatar enabled?""" return context.cfg.get(ENABLE_GRAVATAR, default=Defaults.enable_gravatar) def default_history_browser(): """Return the default history browser (e.g. git-dag, gitk)""" if utils.is_win32(): # On Windows, a sensible default is "python git-cola dag" # which is different than `gitk` below, but is preferred # because we don't have to guess paths. git_cola = sys.argv[0].replace('\\', '/') python = sys.executable.replace('\\', '/') cwd = core.getcwd().replace('\\', '/') argv = [python, git_cola, 'dag', '--repo', cwd] argv = core.prep_for_subprocess(argv) default = core.list2cmdline(argv) else: # The `gitk` script can be launched as-is on unix default = Defaults.history_browser return default def history_browser(context): """Return the configured history browser""" default = default_history_browser() return context.cfg.get(HISTORY_BROWSER, default=default) def linebreak(context): """Should we word-wrap lines in the commit message editor?""" return context.cfg.get(LINEBREAK, default=Defaults.linebreak) def logdate(context): """Return the configured log date format""" return context.cfg.get(LOGDATE, default=Defaults.logdate) def maxrecent(context): """Return the configured maximum number of Recent Repositories""" value = Defaults.maxrecent if context: value = context.cfg.get(MAXRECENT, default=value) return value def mouse_zoom(context): """Should we zoom text when using Ctrl + MouseWheel scroll""" return context.cfg.get(MOUSE_ZOOM, default=Defaults.mouse_zoom) def spellcheck(context): """Should we spellcheck commit messages?""" return context.cfg.get(SPELL_CHECK, default=Defaults.spellcheck) def expandtab(context): """Should we expand tabs in commit messages?""" return context.cfg.get(EXPANDTAB, default=Defaults.expandtab) def patches_directory(context): """Return the patches output directory""" return context.cfg.get(PATCHES_DIRECTORY, default=Defaults.patches_directory) def sort_bookmarks(context): """Should we sort bookmarks by name?""" return context.cfg.get(SORT_BOOKMARKS, default=Defaults.sort_bookmarks) def tabwidth(context): """Return the configured tab width in the commit message editor""" return context.cfg.get(TABWIDTH, default=Defaults.tabwidth) def textwidth(context): """Return the configured text width for word wrapping commit messages""" return context.cfg.get(TEXTWIDTH, default=Defaults.textwidth) def status_indent(context): """Should we indent items in the status widget?""" return context.cfg.get(STATUS_INDENT, default=Defaults.status_indent) def status_show_totals(context): """Should we display count totals in the status widget headers?""" return context.cfg.get(STATUS_SHOW_TOTALS, default=Defaults.status_show_totals) class PreferencesModel(QtCore.QObject): """Interact with repo-local and user-global git config preferences""" config_updated = Signal(str, str, object) def __init__(self, context): super().__init__() self.context = context self.config = context.cfg def set_config(self, source, config, value): """Set a configuration value""" if source == 'local': self.config.set_repo(config, value) else: self.config.set_user(config, value) self.config_updated.emit(source, config, value) def get_config(self, source, config): """Get a configured value""" if source == 'local': value = self.config.get_repo(config) else: value = self.config.get(config) return value class SetConfig(Command): """Store a gitconfig value""" UNDOABLE = True def __init__(self, model, source, config, value): self.source = source self.config = config self.value = value self.old_value = None self.model = model def do(self): """Modify the model and store the updated configuration""" self.old_value = self.model.get_config(self.source, self.config) self.model.set_config(self.source, self.config, self.value) def undo(self): """Restore the configuration change to its original value""" if self.old_value is None: return self.model.set_config(self.source, self.config, self.old_value) git-cola-4.6.1/cola/models/selection.py000066400000000000000000000071641457126473700200110ustar00rootroot00000000000000"""Provides a selection model to handle selection.""" import collections from qtpy import QtCore from qtpy.QtCore import Signal State = collections.namedtuple('State', 'staged unmerged modified untracked') def create(): """Create a SelectionModel""" return SelectionModel() def pick(selection): """Choose the first list from stage, unmerged, modified, untracked""" if selection.staged: files = selection.staged elif selection.unmerged: files = selection.unmerged elif selection.modified: files = selection.modified elif selection.untracked: files = selection.untracked else: files = [] return files def union(selection): """Return the union of all selected items in a sorted list""" values = set( selection.staged + selection.unmerged + selection.modified + selection.untracked ) return list(sorted(values)) def _filter(values, remove): """Filter a list in-place by removing items""" remove_set = set(remove) values_copy = list(values) last = len(values_copy) - 1 for idx, value in enumerate(reversed(values)): if value not in remove_set: values.pop(last - idx) class SelectionModel(QtCore.QObject): """Provides information about selected file paths.""" selection_changed = Signal() # 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): super().__init__() self.staged = [] self.unmerged = [] self.modified = [] self.untracked = [] self.line_number = None def reset(self, emit=False): self.staged = [] self.unmerged = [] self.modified = [] self.untracked = [] self.line_number = None if emit: self.selection_changed.emit() 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.selection_changed.emit() 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.selection_changed.emit() def selection(self): return State(self.staged, self.unmerged, self.modified, self.untracked) def single_selection(self): """Scan across staged, modified, etc. and return a single item.""" staged = None modified = None unmerged = None untracked = None if self.staged: staged = self.staged[0] elif self.modified: modified = self.modified[0] elif self.unmerged: unmerged = self.unmerged[0] elif self.untracked: untracked = self.untracked[0] return State(staged, unmerged, modified, untracked) def filename(self): paths = [path for path in self.single_selection() if path is not None] if paths: filename = paths[0] else: filename = None return filename def group(self): """A list of selected files in various states of being""" return pick(self.selection()) def union(self): """Return the union of all selected items in a sorted list""" return union(self) git-cola-4.6.1/cola/models/stash.py000066400000000000000000000167301457126473700171450ustar00rootroot00000000000000import re from .. import cmds from .. import core from .. import gitcmds from .. import utils from ..i18n import N_ from ..git import STDOUT from ..interaction import Interaction class StashModel: def __init__(self, context): self.context = context self.git = context.git self.model = model = context.model if not model.initialized: model.update_status() def stash_list(self, *args): return self.git.stash('list', *args)[STDOUT].splitlines() def is_staged(self): return bool(self.model.staged) def is_changed(self): model = self.model return bool(model.modified or model.staged) def stash_info(self, revids=False, names=False): """Parses "git stash list" and returns a list of stashes.""" stashes = self.stash_list(r'--format=%gd/%aD/%gs') split_stashes = [s.split('/', 2) for s in stashes if s] stashes = [f'{s[0]}: {s[2]}' for s in split_stashes] revids = [s[0] for s in split_stashes] author_dates = [s[1] for s in split_stashes] names = [s[2] for s in split_stashes] return stashes, revids, author_dates, names def stash_diff(self, rev): git = self.git diffstat = git.stash('show', rev)[STDOUT] diff = git.stash('show', '-p', '--no-ext-diff', rev)[STDOUT] return diffstat + '\n\n' + diff class ApplyStash(cmds.ContextCommand): def __init__(self, context, stash_index, index, pop): super().__init__(context) self.stash_ref = 'refs/' + stash_index self.index = index self.pop = pop def do(self): ref = self.stash_ref pop = self.pop if pop: action = 'pop' else: action = 'apply' if self.index: args = [action, '--index', ref] else: args = [action, ref] status, out, err = self.git.stash(*args) if status == 0: Interaction.log_status(status, out, err) else: title = N_('Error') cmdargs = core.list2cmdline(args) Interaction.command_error(title, 'git stash ' + cmdargs, status, out, err) self.model.update_status() class DropStash(cmds.ContextCommand): def __init__(self, context, stash_index): super().__init__(context) self.stash_ref = 'refs/' + stash_index def do(self): git = self.git status, out, err = git.stash('drop', self.stash_ref) if status == 0: Interaction.log_status(status, out, err) match = re.search(r'\((.*)\)', out) if match: return match.group(1) return '' title = N_('Error') Interaction.command_error( title, 'git stash drop ' + self.stash_ref, status, out, err ) return '' class SaveStash(cmds.ContextCommand): def __init__(self, context, stash_name, keep_index): super().__init__(context) self.stash_name = stash_name self.keep_index = keep_index def do(self): if self.keep_index: args = ['push', '--keep-index', '-m', self.stash_name] else: args = ['push', '-m', self.stash_name] status, out, err = self.git.stash(*args) if status == 0: Interaction.log_status(status, out, err) else: title = N_('Error') cmdargs = core.list2cmdline(args) Interaction.command_error(title, 'git stash ' + cmdargs, status, out, err) self.model.update_status() class RenameStash(cmds.ContextCommand): """Rename the stash""" def __init__(self, context, stash_index, stash_name): super().__init__(context) self.context = context self.stash_index = stash_index self.stash_name = stash_name def do(self): # Drop the stash first and get the returned ref ref = DropStash(self.context, self.stash_index).do() # Store the stash with a new name if ref: args = ['store', '-m', self.stash_name, ref] status, out, err = self.git.stash(*args) if status == 0: Interaction.log_status(status, out, err) else: title = N_('Error') cmdargs = core.list2cmdline(args) Interaction.command_error( title, 'git stash ' + cmdargs, status, out, err ) else: title = N_('Error Renaming Stash') msg = N_('"git stash drop" did not return a ref to rename.') Interaction.critical(title, message=msg) self.model.update_status() class StashIndex(cmds.ContextCommand): """Stash the index away""" def __init__(self, context, stash_name): super().__init__(context) self.stash_name = stash_name def do(self): # Manually create a stash representing the index state context = self.context git = self.git name = self.stash_name branch = gitcmds.current_branch(context) head = gitcmds.rev_parse(context, 'HEAD') message = f'On {branch}: {name}' # Get the message used for the "index" commit status, out, err = git.rev_list('HEAD', '--', oneline=True, n=1) if status != 0: stash_error('rev-list', status, out, err) return head_msg = out.strip() # Create a commit representing the index status, out, err = git.write_tree() if status != 0: stash_error('write-tree', status, out, err) return index_tree = out.strip() status, out, err = git.commit_tree( '-m', f'index on {branch}: {head_msg}', '-p', head, index_tree ) if status != 0: stash_error('commit-tree', status, out, err) return index_commit = out.strip() # Create a commit representing the worktree status, out, err = git.commit_tree( '-p', head, '-p', index_commit, '-m', message, index_tree ) if status != 0: stash_error('commit-tree', status, out, err) return worktree_commit = out.strip() # Record the stash entry status, out, err = git.update_ref( '-m', message, 'refs/stash', worktree_commit, create_reflog=True ) if status != 0: stash_error('update-ref', status, out, err) return # Sync the worktree with the post-stash state. We've created the # stash ref, so now we have to remove the staged changes from the # worktree. We do this by applying a reverse diff of the staged # changes. The diff from stash->HEAD is a reverse diff of the stash. patch = utils.tmp_filename('stash') with core.xopen(patch, mode='wb') as patch_fd: status, out, err = git.diff_tree( 'refs/stash', 'HEAD', '--', binary=True, _stdout=patch_fd ) if status != 0: stash_error('diff-tree', status, out, err) return # Apply the patch status, out, err = git.apply(patch) core.unlink(patch) ok = status == 0 if ok: # Finally, clear the index we just stashed git.reset() else: stash_error('apply', status, out, err) self.model.update_status() def stash_error(cmd, status, out, err): title = N_('Error creating stash') Interaction.command_error(title, cmd, status, out, err) git-cola-4.6.1/cola/polib.py000066400000000000000000001653101457126473700156440ustar00rootroot00000000000000# # License: MIT (see extras/polib/LICENSE file provided) # vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: """ **polib** allows you to manipulate, create, modify gettext files (pot, po and mo files). You can load existing files, iterate through it's entries, add, modify entries, comments or metadata, etc. or create new po files from scratch. **polib** provides a simple and pythonic API via the :func:`~polib.pofile` and :func:`~polib.mofile` convenience functions. """ import array import codecs import os import re import struct import sys import textwrap import io from . import compat __author__ = 'David Jean Louis ' __version__ = '1.1.1' __all__ = [ 'pofile', 'POFile', 'POEntry', 'mofile', 'MOFile', 'MOEntry', 'default_encoding', 'escape', 'unescape', 'detect_encoding', ] # the default encoding to use when encoding cannot be detected default_encoding = 'utf-8' # python 2/3 compatibility helpers {{{ PY3 = True text_type = str def b(s): return s.encode('utf-8') def u(s): return s # }}} # _pofile_or_mofile {{{ def _pofile_or_mofile(f, filetype, **kwargs): """ Internal function used by :func:`polib.pofile` and :func:`polib.mofile` to honor the DRY concept. """ # get the file encoding enc = kwargs.get('encoding') if enc is None: enc = detect_encoding(f, filetype == 'mofile') # parse the file kls = _POFileParser if filetype == 'pofile' else _MOFileParser parser = kls( f, encoding=enc, check_for_duplicates=kwargs.get('check_for_duplicates', False), klass=kwargs.get('klass'), ) instance = parser.parse() instance.wrapwidth = kwargs.get('wrapwidth', 78) return instance # }}} # _is_file {{{ def _is_file(filename_or_contents): """ Safely returns the value of os.path.exists(filename_or_contents). Arguments: ``filename_or_contents`` either a filename, or a string holding the contents of some file. In the latter case, this function will always return False. """ try: return os.path.isfile(filename_or_contents) except (TypeError, ValueError, UnicodeEncodeError): return False # }}} # function pofile() {{{ def pofile(pofile, **kwargs): """ Convenience function that parses the po or pot file ``pofile`` and returns a :class:`~polib.POFile` instance. Arguments: ``pofile`` string, full or relative path to the po/pot file or its content (data). ``wrapwidth`` integer, the wrap width, only useful when the ``-w`` option was passed to xgettext (optional, default: ``78``). ``encoding`` string, the encoding to use (e.g. "utf-8") (default: ``None``, the encoding will be auto-detected). ``check_for_duplicates`` whether to check for duplicate entries when adding entries to the file (optional, default: ``False``). ``klass`` class which is used to instantiate the return value (optional, default: ``None``, the return value with be a :class:`~polib.POFile` instance). """ return _pofile_or_mofile(pofile, 'pofile', **kwargs) # }}} # function mofile() {{{ def mofile(mofile, **kwargs): """ Convenience function that parses the mo file ``mofile`` and returns a :class:`~polib.MOFile` instance. Arguments: ``mofile`` string, full or relative path to the mo file or its content (string or bytes). ``wrapwidth`` integer, the wrap width, only useful when the ``-w`` option was passed to xgettext to generate the po file that was used to format the mo file (optional, default: ``78``). ``encoding`` string, the encoding to use (e.g. "utf-8") (default: ``None``, the encoding will be auto-detected). ``check_for_duplicates`` whether to check for duplicate entries when adding entries to the file (optional, default: ``False``). ``klass`` class which is used to instantiate the return value (optional, default: ``None``, the return value with be a :class:`~polib.POFile` instance). """ return _pofile_or_mofile(mofile, 'mofile', **kwargs) # }}} # function detect_encoding() {{{ def detect_encoding(file, binary_mode=False): """ Try to detect the encoding used by the ``file``. The ``file`` argument can be a PO or MO file path or a string containing the contents of the file. If the encoding cannot be detected, the function will return the value of ``default_encoding``. Arguments: ``file`` string, full or relative path to the po/mo file or its content. ``binary_mode`` boolean, set this to True if ``file`` is a mo file. """ PATTERN = r'"?Content-Type:.+? charset=([\w_\-:\.]+)' rxt = re.compile(u(PATTERN)) rxb = re.compile(b(PATTERN)) def charset_exists(charset): """Check whether ``charset`` is valid or not.""" try: codecs.lookup(charset) except LookupError: return False return True if not _is_file(file): try: match = rxt.search(file) except TypeError: match = rxb.search(file) if match: enc = match.group(1).strip() if not isinstance(enc, text_type): enc = enc.decode('utf-8') if charset_exists(enc): return enc else: # For PY3, always treat as binary if binary_mode or PY3: mode = 'rb' rx = rxb else: mode = 'r' rx = rxt f = open(file, mode) for line in f.readlines(): match = rx.search(line) if match: f.close() enc = match.group(1).strip() if not isinstance(enc, text_type): enc = enc.decode('utf-8') if charset_exists(enc): return enc f.close() return default_encoding # }}} # function escape() {{{ def escape(st): """ Escapes the characters ``\\\\``, ``\\t``, ``\\n``, ``\\r`` and ``"`` in the given string ``st`` and returns it. """ return ( st.replace('\\', r'\\') .replace('\t', r'\t') .replace('\r', r'\r') .replace('\n', r'\n') .replace('"', r'\"') ) # }}} # function unescape() {{{ def unescape(st): """ Unescapes the characters ``\\\\``, ``\\t``, ``\\n``, ``\\r`` and ``"`` in the given string ``st`` and returns it. """ def unescape_repl(m): m = m.group(1) if m == 'n': return '\n' if m == 't': return '\t' if m == 'r': return '\r' if m == '\\': return '\\' return m # handles escaped double quote return re.sub(r'\\(\\|n|t|r|")', unescape_repl, st) # }}} # function natural_sort() {{{ def natural_sort(lst): """ Sort naturally the given list. Credits: http://stackoverflow.com/a/4836734 """ def convert(text): return int(text) if text.isdigit() else text.lower() def alphanum_key(key): return [convert(c) for c in re.split('([0-9]+)', key)] return sorted(lst, key=alphanum_key) # }}} # class _BaseFile {{{ class _BaseFile(list): """ Common base class for the :class:`~polib.POFile` and :class:`~polib.MOFile` classes. This class should **not** be instantiated directly. """ def __init__(self, *_args, **kwargs): """ Constructor, accepts the following keyword arguments: ``pofile`` string, the path to the po or mo file, or its content as a string. ``wrapwidth`` integer, the wrap width, only useful when the ``-w`` option was passed to xgettext (optional, default: ``78``). ``encoding`` string, the encoding to use, defaults to ``default_encoding`` global variable (optional). ``check_for_duplicates`` whether to check for duplicate entries when adding entries to the file, (optional, default: ``False``). """ list.__init__(self) # the opened file handle pofile = kwargs.get('pofile', None) if pofile and _is_file(pofile): self.fpath = pofile else: self.fpath = kwargs.get('fpath') # the width at which lines should be wrapped self.wrapwidth = kwargs.get('wrapwidth', 78) # the file encoding self.encoding = kwargs.get('encoding', default_encoding) # whether to check for duplicate entries or not self.check_for_duplicates = kwargs.get('check_for_duplicates', False) # header self.header = '' # both po and mo files have metadata self.metadata = {} self.metadata_is_fuzzy = 0 def __unicode__(self): """ Returns the unicode representation of the file. """ ret = [] entries = [self.metadata_as_entry()] + [e for e in self if not e.obsolete] for entry in entries: ret.append(entry.__unicode__(self.wrapwidth)) for entry in self.obsolete_entries(): ret.append(entry.__unicode__(self.wrapwidth)) ret = u('\n').join(ret) return ret if PY3: def __str__(self): return self.__unicode__() else: def __str__(self): """ Returns the string representation of the file. """ return compat.ustr(self).encode(self.encoding) def __contains__(self, entry): """ Overridden ``list`` method to implement the membership test (in and not in). The method considers that an entry is in the file if it finds an entry that has the same msgid (the test is **case sensitive**) and the same msgctxt (or none for both entries). Argument: ``entry`` an instance of :class:`~polib._BaseEntry`. """ return self.find(entry.msgid, by='msgid', msgctxt=entry.msgctxt) is not None def __eq__(self, other): return str(self) == str(other) def __hash__(self): return hash(str(self)) def append(self, entry): """ Overridden method to check for duplicates entries, if a user tries to add an entry that is already in the file, the method will raise a ``ValueError`` exception. Argument: ``entry`` an instance of :class:`~polib._BaseEntry`. """ # check_for_duplicates may not be defined (yet) when unpickling. # But if pickling, we never want to check for duplicates anyway. if getattr(self, 'check_for_duplicates', False) and entry in self: raise ValueError('Entry "%s" already exists' % entry.msgid) super().append(entry) def insert(self, index, entry): """ Overridden method to check for duplicates entries, if a user tries to add an entry that is already in the file, the method will raise a ``ValueError`` exception. Arguments: ``index`` index at which the entry should be inserted. ``entry`` an instance of :class:`~polib._BaseEntry`. """ if self.check_for_duplicates and entry in self: raise ValueError('Entry "%s" already exists' % entry.msgid) super().insert(index, entry) def metadata_as_entry(self): """ Returns the file metadata as a :class:`~polib.POFile` instance. """ e = POEntry(msgid='') mdata = self.ordered_metadata() if mdata: strs = [] for name, value in mdata: # Strip whitespace off each line in a multi-line entry strs.append(f'{name}: {value}') e.msgstr = '\n'.join(strs) + '\n' if self.metadata_is_fuzzy: e.flags.append('fuzzy') return e def save(self, fpath=None, repr_method='__unicode__', newline=None): """ Saves the po file to ``fpath``. If it is an existing file and no ``fpath`` is provided, then the existing file is rewritten with the modified data. Keyword arguments: ``fpath`` string, full or relative path to the file. ``repr_method`` string, the method to use for output. ``newline`` string, controls how universal newlines works """ if self.fpath is None and fpath is None: raise OSError('You must provide a file path to save() method') contents = getattr(self, repr_method)() if fpath is None: fpath = self.fpath if repr_method == 'to_binary': fhandle = open(fpath, 'wb') else: fhandle = open(fpath, 'w', encoding=self.encoding, newline=newline) if not isinstance(contents, text_type): contents = contents.decode(self.encoding) fhandle.write(contents) fhandle.close() # set the file path if not set if self.fpath is None and fpath: self.fpath = fpath def find(self, st, by='msgid', include_obsolete_entries=False, msgctxt=False): """ Find the entry which msgid (or property identified by the ``by`` argument) matches the string ``st``. Keyword arguments: ``st`` string, the string to search for. ``by`` string, the property to use for comparison (default: ``msgid``). ``include_obsolete_entries`` boolean, whether to also search in entries that are obsolete. ``msgctxt`` string, allows specifying a specific message context for the search. """ if include_obsolete_entries: entries = self[:] else: entries = [e for e in self if not e.obsolete] matches = [] for e in entries: if getattr(e, by) == st: if msgctxt is not False and e.msgctxt != msgctxt: continue matches.append(e) if len(matches) == 1: return matches[0] elif len(matches) > 1: if not msgctxt: # find the entry with no msgctx e = None for m in matches: if not m.msgctxt: e = m if e: return e # fallback to the first entry found return matches[0] return None def ordered_metadata(self): """ Convenience method that returns an ordered version of the metadata dictionary. The return value is list of tuples (metadata name, metadata_value). """ # copy the dict first metadata = self.metadata.copy() data_order = [ 'Project-Id-Version', 'Report-Msgid-Bugs-To', 'POT-Creation-Date', 'PO-Revision-Date', 'Last-Translator', 'Language-Team', 'Language', 'MIME-Version', 'Content-Type', 'Content-Transfer-Encoding', 'Plural-Forms', ] ordered_data = [] for data in data_order: try: value = metadata.pop(data) ordered_data.append((data, value)) except KeyError: pass # the rest of the metadata will be alphabetically ordered since there # are no specs for this AFAIK for data in natural_sort(metadata.keys()): value = metadata[data] ordered_data.append((data, value)) return ordered_data def to_binary(self): """ Return the binary representation of the file. """ offsets = [] entries = self.translated_entries() # the keys are sorted in the .mo file def cmp(_self, other): # msgfmt compares entries with msgctxt if it exists self_msgid = _self.msgctxt or _self.msgid other_msgid = other.msgctxt or other.msgid if self_msgid > other_msgid: return 1 elif self_msgid < other_msgid: return -1 else: return 0 # add metadata entry entries.sort(key=lambda o: o.msgid_with_context.encode('utf-8')) mentry = self.metadata_as_entry() entries = [mentry] + entries entries_len = len(entries) ids, strs = b(''), b('') for e in entries: # For each string, we need size and file offset. Each string is # NUL terminated; the NUL does not count into the size. msgid = b('') if e.msgctxt: # Contexts are stored by storing the concatenation of the # context, a byte, and the original string msgid = self._encode(e.msgctxt + '\4') if e.msgid_plural: msgstr = [] for index in sorted(e.msgstr_plural.keys()): msgstr.append(e.msgstr_plural[index]) msgid += self._encode(e.msgid + '\0' + e.msgid_plural) msgstr = self._encode('\0'.join(msgstr)) else: msgid += self._encode(e.msgid) msgstr = self._encode(e.msgstr) offsets.append((len(ids), len(msgid), len(strs), len(msgstr))) ids += msgid + b('\0') strs += msgstr + b('\0') # The header is 7 32-bit unsigned integers. keystart = 7 * 4 + 16 * entries_len # and the values start after the keys valuestart = keystart + len(ids) koffsets = [] voffsets = [] # The string table first has the list of keys, then the list of values. # Each entry has first the size of the string, then the file offset. for o1, l1, o2, l2 in offsets: koffsets += [l1, o1 + keystart] voffsets += [l2, o2 + valuestart] offsets = koffsets + voffsets output = struct.pack( 'Iiiiiii', # Magic number MOFile.MAGIC, # Version 0, # number of entries entries_len, # start of key index 7 * 4, # start of value index 7 * 4 + entries_len * 8, # size and offset of hash table, we don't use hash tables 0, keystart, ) if PY3 and sys.version_info.minor > 1: # python 3.2 or newer output += array.array('i', offsets).tobytes() else: output += array.array('i', offsets).tostring() output += ids output += strs return output def _encode(self, mixed): """ Encodes the given ``mixed`` argument with the file encoding if and only if it's an unicode string and returns the encoded string. """ if isinstance(mixed, text_type): mixed = mixed.encode(self.encoding) return mixed # }}} # class POFile {{{ class POFile(_BaseFile): """ Po (or Pot) file reader/writer. This class inherits the :class:`~polib._BaseFile` class and, by extension, the python ``list`` type. """ def __unicode__(self): """ Returns the unicode representation of the po file. """ ret, headers = '', self.header.split('\n') for header in headers: if not header: ret += '#\n' elif header[:1] in [',', ':']: ret += '#%s\n' % header else: ret += '# %s\n' % header if not isinstance(ret, text_type): ret = ret.decode(self.encoding) return ret + _BaseFile.__unicode__(self) def save_as_mofile(self, fpath): """ Saves the binary representation of the file to given ``fpath``. Keyword argument: ``fpath`` string, full or relative path to the mo file. """ _BaseFile.save(self, fpath, 'to_binary') def percent_translated(self): """ Convenience method that returns the percentage of translated messages. """ total = len([e for e in self if not e.obsolete]) if total == 0: return 100 translated = len(self.translated_entries()) return int(translated * 100 / float(total)) def translated_entries(self): """ Convenience method that returns the list of translated entries. """ return [e for e in self if e.translated()] def untranslated_entries(self): """ Convenience method that returns the list of untranslated entries. """ return [ e for e in self if not e.translated() and not e.obsolete and not e.fuzzy ] def fuzzy_entries(self): """ Convenience method that returns the list of fuzzy entries. """ return [e for e in self if e.fuzzy and not e.obsolete] def obsolete_entries(self): """ Convenience method that returns the list of obsolete entries. """ return [e for e in self if e.obsolete] def merge(self, refpot): """ Convenience method that merges the current pofile with the pot file provided. It behaves exactly as the gettext msgmerge utility: * comments of this file will be preserved, but extracted comments and occurrences will be discarded; * any translations or comments in the file will be discarded, however, dot comments and file positions will be preserved; * the fuzzy flags are preserved. Keyword argument: ``refpot`` object POFile, the reference catalog. """ # Store entries in dict/set for faster access self_entries = {entry.msgid_with_context: entry for entry in self} refpot_msgids = {entry.msgid_with_context for entry in refpot} # Merge entries that are in the refpot for entry in refpot: e = self_entries.get(entry.msgid_with_context) if e is None: e = POEntry() self.append(e) e.merge(entry) # ok, now we must "obsolete" entries that are not in the refpot anymore for entry in self: if entry.msgid_with_context not in refpot_msgids: entry.obsolete = True # }}} # class MOFile {{{ class MOFile(_BaseFile): """ Mo file reader/writer. This class inherits the :class:`~polib._BaseFile` class and, by extension, the python ``list`` type. """ MAGIC = 0x950412DE MAGIC_SWAPPED = 0xDE120495 def __init__(self, *args, **kwargs): """ Constructor, accepts all keywords arguments accepted by :class:`~polib._BaseFile` class. """ _BaseFile.__init__(self, *args, **kwargs) self.magic_number = None self.version = 0 def save_as_pofile(self, fpath): """ Saves the mofile as a pofile to ``fpath``. Keyword argument: ``fpath`` string, full or relative path to the file. """ _BaseFile.save(self, fpath) def save(self, fpath=None): """ Saves the mofile to ``fpath``. Keyword argument: ``fpath`` string, full or relative path to the file. """ _BaseFile.save(self, fpath, 'to_binary') def percent_translated(self): """ Convenience method to keep the same interface with POFile instances. """ return 100 def translated_entries(self): """ Convenience method to keep the same interface with POFile instances. """ return self def untranslated_entries(self): """ Convenience method to keep the same interface with POFile instances. """ return [] def fuzzy_entries(self): """ Convenience method to keep the same interface with POFile instances. """ return [] def obsolete_entries(self): """ Convenience method to keep the same interface with POFile instances. """ return [] # }}} # class _BaseEntry {{{ class _BaseEntry: """ Base class for :class:`~polib.POEntry` and :class:`~polib.MOEntry` classes. This class should **not** be instantiated directly. """ def __init__(self, *_args, **kwargs): """ Constructor, accepts the following keyword arguments: ``msgid`` string, the entry msgid. ``msgstr`` string, the entry msgstr. ``msgid_plural`` string, the entry msgid_plural. ``msgstr_plural`` dict, the entry msgstr_plural lines. ``msgctxt`` string, the entry context (msgctxt). ``obsolete`` bool, whether the entry is "obsolete" or not. ``encoding`` string, the encoding to use, defaults to ``default_encoding`` global variable (optional). """ self.msgid = kwargs.get('msgid', '') self.msgstr = kwargs.get('msgstr', '') self.msgid_plural = kwargs.get('msgid_plural', '') self.msgstr_plural = kwargs.get('msgstr_plural', {}) self.msgctxt = kwargs.get('msgctxt', None) self.obsolete = kwargs.get('obsolete', False) self.encoding = kwargs.get('encoding', default_encoding) def __unicode__(self, wrapwidth=78): """ Returns the unicode representation of the entry. """ if self.obsolete: delflag = '#~ ' else: delflag = '' ret = [] # write the msgctxt if any if self.msgctxt is not None: ret += self._str_field('msgctxt', delflag, '', self.msgctxt, wrapwidth) # write the msgid ret += self._str_field('msgid', delflag, '', self.msgid, wrapwidth) # write the msgid_plural if any if self.msgid_plural: ret += self._str_field( 'msgid_plural', delflag, '', self.msgid_plural, wrapwidth ) if self.msgstr_plural: # write the msgstr_plural if any msgstrs = self.msgstr_plural keys = list(msgstrs) keys.sort() for index in keys: msgstr = msgstrs[index] plural_index = '[%s]' % index ret += self._str_field( 'msgstr', delflag, plural_index, msgstr, wrapwidth ) else: # otherwise write the msgstr ret += self._str_field('msgstr', delflag, '', self.msgstr, wrapwidth) ret.append('') ret = u('\n').join(ret) return ret if PY3: def __str__(self): return self.__unicode__() else: def __str__(self): """ Returns the string representation of the entry. """ return compat.ustr(self).encode(self.encoding) def __eq__(self, other): return str(self) == str(other) def __hash__(self): return hash(str(self)) def _str_field(self, fieldname, delflag, plural_index, field, wrapwidth=78): lines = field.splitlines(True) if len(lines) > 1: lines = [''] + lines # start with initial empty line else: escaped_field = escape(field) specialchars_count = 0 for c in ['\\', '\n', '\r', '\t', '"']: specialchars_count += field.count(c) # comparison must take into account fieldname length + one space # + 2 quotes (eg. msgid "") flength = len(fieldname) + 3 if plural_index: flength += len(plural_index) real_wrapwidth = wrapwidth - flength + specialchars_count if wrapwidth > 0 and len(field) > real_wrapwidth: # Wrap the line but take field name into account lines = [''] + [ unescape(item) for item in textwrap.wrap( escaped_field, wrapwidth - 2, # 2 for quotes "" drop_whitespace=False, break_long_words=False, ) ] else: lines = [field] if fieldname.startswith('previous_'): # quick and dirty trick to get the real field name fieldname = fieldname[9:] ret = [f'{delflag}{fieldname}{plural_index} "{escape(lines.pop(0))}"'] for line in lines: ret.append(f'{delflag}"{escape(line)}"') return ret @property def msgid_with_context(self): if self.msgctxt: return '{}{}{}'.format(self.msgctxt, '\x04', self.msgid) return self.msgid # }}} # class POEntry {{{ class POEntry(_BaseEntry): """ Represents a po file entry. """ def __init__(self, *args, **kwargs): """ Constructor, accepts the following keyword arguments: ``comment`` string, the entry comment. ``tcomment`` string, the entry translator comment. ``occurrences`` list, the entry occurrences. ``flags`` list, the entry flags. ``previous_msgctxt`` string, the entry previous context. ``previous_msgid`` string, the entry previous msgid. ``previous_msgid_plural`` string, the entry previous msgid_plural. ``linenum`` integer, the line number of the entry """ _BaseEntry.__init__(self, *args, **kwargs) self.comment = kwargs.get('comment', '') self.tcomment = kwargs.get('tcomment', '') self.occurrences = kwargs.get('occurrences', []) self.flags = kwargs.get('flags', []) self.previous_msgctxt = kwargs.get('previous_msgctxt', None) self.previous_msgid = kwargs.get('previous_msgid', None) self.previous_msgid_plural = kwargs.get('previous_msgid_plural', None) self.linenum = kwargs.get('linenum', None) def __unicode__(self, wrapwidth=78): """ Returns the unicode representation of the entry. """ ret = [] # comments first, if any (with text wrapping as xgettext does) if self.obsolete: comments = [('tcomment', '# ')] else: comments = [('comment', '#. '), ('tcomment', '# ')] for c in comments: val = getattr(self, c[0]) if val: for comment in val.split('\n'): if len(comment) + len(c[1]) > wrapwidth > 0: ret += textwrap.wrap( comment, wrapwidth, initial_indent=c[1], subsequent_indent=c[1], break_long_words=False, ) else: ret.append(f'{c[1]}{comment}') # occurrences (with text wrapping as xgettext does) if not self.obsolete and self.occurrences: filelist = [] for fpath, lineno in self.occurrences: if lineno: filelist.append(f'{fpath}:{lineno}') else: filelist.append(fpath) filestr = ' '.join(filelist) if len(filestr) + 3 > wrapwidth > 0: # textwrap split words that contain hyphen, this is not # what we want for filenames, so the dirty hack is to # temporally replace hyphens with a char that a file cannot # contain, like "*" ret += [ line.replace('*', '-') for line in textwrap.wrap( filestr.replace('-', '*'), wrapwidth, initial_indent='#: ', subsequent_indent='#: ', break_long_words=False, ) ] else: ret.append('#: ' + filestr) # flags (TODO: wrapping ?) if self.flags: ret.append('#, %s' % ', '.join(self.flags)) # previous context and previous msgid/msgid_plural fields = ['previous_msgctxt', 'previous_msgid', 'previous_msgid_plural'] if self.obsolete: prefix = '#~| ' else: prefix = '#| ' for f in fields: val = getattr(self, f) if val is not None: ret += self._str_field(f, prefix, '', val, wrapwidth) ret.append(_BaseEntry.__unicode__(self, wrapwidth)) ret = u('\n').join(ret) return ret def __cmp__(self, other): """ Called by comparison operations if rich comparison is not defined. """ # First: Obsolete test if self.obsolete != other.obsolete: if self.obsolete: return -1 else: return 1 # Work on a copy to protect original occ1 = sorted(self.occurrences[:]) occ2 = sorted(other.occurrences[:]) if occ1 > occ2: return 1 if occ1 < occ2: return -1 # Compare context msgctxt = self.msgctxt or '0' othermsgctxt = other.msgctxt or '0' if msgctxt > othermsgctxt: return 1 elif msgctxt < othermsgctxt: return -1 # Compare msgid_plural msgid_plural = self.msgid_plural or '0' othermsgid_plural = other.msgid_plural or '0' if msgid_plural > othermsgid_plural: return 1 elif msgid_plural < othermsgid_plural: return -1 # Compare msgstr_plural if self.msgstr_plural and isinstance(self.msgstr_plural, dict): msgstr_plural = list(self.msgstr_plural.values()) else: msgstr_plural = [] if other.msgstr_plural and isinstance(other.msgstr_plural, dict): othermsgstr_plural = list(other.msgstr_plural.values()) else: othermsgstr_plural = [] if msgstr_plural > othermsgstr_plural: return 1 elif msgstr_plural < othermsgstr_plural: return -1 # Compare msgid if self.msgid > other.msgid: return 1 elif self.msgid < other.msgid: return -1 # Compare msgstr if self.msgstr > other.msgstr: return 1 elif self.msgstr < other.msgstr: return -1 return 0 def __gt__(self, other): return self.__cmp__(other) > 0 def __lt__(self, other): return self.__cmp__(other) < 0 def __ge__(self, other): return self.__cmp__(other) >= 0 def __le__(self, other): return self.__cmp__(other) <= 0 def __eq__(self, other): return self.__cmp__(other) == 0 def __ne__(self, other): return self.__cmp__(other) != 0 def translated(self): """ Returns ``True`` if the entry has been translated or ``False`` otherwise. """ if self.obsolete or self.fuzzy: return False if self.msgstr != '': return True if self.msgstr_plural: for pos in self.msgstr_plural: if self.msgstr_plural[pos] == '': return False return True return False def merge(self, other): """ Merge the current entry with the given pot entry. """ self.msgid = other.msgid self.msgctxt = other.msgctxt self.occurrences = other.occurrences self.comment = other.comment fuzzy = self.fuzzy self.flags = other.flags[:] # clone flags if fuzzy: self.flags.append('fuzzy') self.msgid_plural = other.msgid_plural self.obsolete = other.obsolete self.previous_msgctxt = other.previous_msgctxt self.previous_msgid = other.previous_msgid self.previous_msgid_plural = other.previous_msgid_plural if other.msgstr_plural: for pos in other.msgstr_plural: try: # keep existing translation at pos if any self.msgstr_plural[pos] except KeyError: self.msgstr_plural[pos] = '' @property def fuzzy(self): return 'fuzzy' in self.flags def __hash__(self): return hash((self.msgid, self.msgstr)) # }}} # class MOEntry {{{ class MOEntry(_BaseEntry): """ Represents a mo file entry. """ def __init__(self, *args, **kwargs): """ Constructor, accepts the following keyword arguments, for consistency with :class:`~polib.POEntry`: ``comment`` ``tcomment`` ``occurrences`` ``flags`` ``previous_msgctxt`` ``previous_msgid`` ``previous_msgid_plural`` Note: even though these keyword arguments are accepted, they hold no real meaning in the context of MO files and are simply ignored. """ _BaseEntry.__init__(self, *args, **kwargs) self.comment = '' self.tcomment = '' self.occurrences = [] self.flags = [] self.previous_msgctxt = None self.previous_msgid = None self.previous_msgid_plural = None def __hash__(self): return hash((self.msgid, self.msgstr)) # }}} # class _POFileParser {{{ class _POFileParser: """ A finite state machine to parse efficiently and correctly po file format. """ def __init__(self, pofile, *_args, **kwargs): """ Constructor. Keyword arguments: ``pofile`` string, path to the po file or its content ``encoding`` string, the encoding to use, defaults to ``default_encoding`` global variable (optional). ``check_for_duplicates`` whether to check for duplicate entries when adding entries to the file (optional, default: ``False``). """ enc = kwargs.get('encoding', default_encoding) if _is_file(pofile): try: self.fhandle = open(pofile, encoding=enc) except LookupError: enc = default_encoding self.fhandle = open(pofile, encoding=enc) else: self.fhandle = pofile.splitlines() klass = kwargs.get('klass') if klass is None: klass = POFile self.instance = klass( pofile=pofile, encoding=enc, check_for_duplicates=kwargs.get('check_for_duplicates', False), ) self.transitions = {} self.current_line = 0 self.current_entry = POEntry(linenum=self.current_line) self.current_state = 'st' self.current_token = None # two memo flags used in handlers self.msgstr_index = 0 self.entry_obsolete = 0 # Configure the state machine, by adding transitions. # Signification of symbols: # * ST: Beginning of the file (start) # * HE: Header # * TC: a translation comment # * GC: a generated comment # * OC: a file/line occurrence # * FL: a flags line # * CT: a message context # * PC: a previous msgctxt # * PM: a previous msgid # * PP: a previous msgid_plural # * MI: a msgid # * MP: a msgid plural # * MS: a msgstr # * MX: a msgstr plural # * MC: a msgid or msgstr continuation line all = [ 'st', 'he', 'gc', 'oc', 'fl', 'ct', 'pc', 'pm', 'pp', 'tc', 'ms', 'mp', 'mx', 'mi', ] self.add('tc', ['st', 'he'], 'he') self.add( 'tc', ['gc', 'oc', 'fl', 'tc', 'pc', 'pm', 'pp', 'ms', 'mp', 'mx', 'mi'], 'tc', ) self.add('gc', all, 'gc') self.add('oc', all, 'oc') self.add('fl', all, 'fl') self.add('pc', all, 'pc') self.add('pm', all, 'pm') self.add('pp', all, 'pp') self.add( 'ct', ['st', 'he', 'gc', 'oc', 'fl', 'tc', 'pc', 'pm', 'pp', 'ms', 'mx'], 'ct', ) self.add( 'mi', ['st', 'he', 'gc', 'oc', 'fl', 'ct', 'tc', 'pc', 'pm', 'pp', 'ms', 'mx'], 'mi', ) self.add('mp', ['tc', 'gc', 'pc', 'pm', 'pp', 'mi'], 'mp') self.add('ms', ['mi', 'mp', 'tc'], 'ms') self.add('mx', ['mi', 'mx', 'mp', 'tc'], 'mx') self.add('mc', ['ct', 'mi', 'mp', 'ms', 'mx', 'pm', 'pp', 'pc'], 'mc') def parse(self): """ Run the state machine, parse the file line by line and call process() with the current matched symbol. """ keywords = { 'msgctxt': 'ct', 'msgid': 'mi', 'msgstr': 'ms', 'msgid_plural': 'mp', } prev_keywords = { 'msgid_plural': 'pp', 'msgid': 'pm', 'msgctxt': 'pc', } tokens = [] fpath = '%s ' % self.instance.fpath if self.instance.fpath else '' for line in self.fhandle: self.current_line += 1 if self.current_line == 1: BOM = codecs.BOM_UTF8.decode('utf-8') if line.startswith(BOM): line = line[len(BOM) :] line = line.strip() if line == '': continue tokens = line.split(None, 2) nb_tokens = len(tokens) if tokens[0] == '#~|': continue if tokens[0] == '#~' and nb_tokens > 1: line = line[3:].strip() tokens = tokens[1:] nb_tokens -= 1 self.entry_obsolete = 1 else: self.entry_obsolete = 0 # Take care of keywords like # msgid, msgid_plural, msgctxt & msgstr. if tokens[0] in keywords and nb_tokens > 1: line = line[len(tokens[0]) :].lstrip() if re.search(r'([^\\]|^)"', line[1:-1]): raise OSError( 'Syntax error in po file %s(line %s): ' 'unescaped double quote found' % (fpath, self.current_line) ) self.current_token = line self.process(keywords[tokens[0]]) continue self.current_token = line if tokens[0] == '#:': if nb_tokens <= 1: continue # we are on a occurrences line self.process('oc') elif line[:1] == '"': # we are on a continuation line if re.search(r'([^\\]|^)"', line[1:-1]): raise OSError( 'Syntax error in po file %s(line %s): ' 'unescaped double quote found' % (fpath, self.current_line) ) self.process('mc') elif line[:7] == 'msgstr[': # we are on a msgstr plural self.process('mx') elif tokens[0] == '#,': if nb_tokens <= 1: continue # we are on a flags line self.process('fl') elif tokens[0] == '#' or tokens[0].startswith('##'): if line == '#': line += ' ' # we are on a translator comment line self.process('tc') elif tokens[0] == '#.': if nb_tokens <= 1: continue # we are on a generated comment line self.process('gc') elif tokens[0] == '#|': if nb_tokens <= 1: raise OSError( 'Syntax error in po file %s(line %s)' % (fpath, self.current_line) ) # Remove the marker and any whitespace right after that. line = line[2:].lstrip() self.current_token = line if tokens[1].startswith('"'): # Continuation of previous metadata. self.process('mc') continue if nb_tokens == 2: # Invalid continuation line. raise OSError( 'Syntax error in po file %s(line %s): ' 'invalid continuation line' % (fpath, self.current_line) ) # we are on a "previous translation" comment line, if tokens[1] not in prev_keywords: # Unknown keyword in previous translation comment. raise OSError( 'Syntax error in po file %s(line %s): ' 'unknown keyword %s' % (fpath, self.current_line, tokens[1]) ) # Remove the keyword and any whitespace # between it and the starting quote. line = line[len(tokens[1]) :].lstrip() self.current_token = line self.process(prev_keywords[tokens[1]]) else: raise OSError( f'Syntax error in po file {fpath}(line {self.current_line})' ) if self.current_entry and len(tokens) > 0 and not tokens[0].startswith('#'): # since entries are added when another entry is found, we must add # the last entry here (only if there are lines). Trailing comments # are ignored self.instance.append(self.current_entry) # before returning the instance, check if there's metadata and if # so extract it in a dict metadataentry = self.instance.find('') if metadataentry: # metadata found # remove the entry self.instance.remove(metadataentry) self.instance.metadata_is_fuzzy = metadataentry.flags key = None for msg in metadataentry.msgstr.splitlines(): try: key, val = msg.split(':', 1) self.instance.metadata[key] = val.strip() except (ValueError, KeyError): if key is not None: self.instance.metadata[key] += '\n' + msg.strip() # close opened file if not isinstance(self.fhandle, list): # must be file self.fhandle.close() return self.instance def add(self, symbol, states, next_state): """ Add a transition to the state machine. Keywords arguments: ``symbol`` string, the matched token (two chars symbol). ``states`` list, a list of states (two chars symbols). ``next_state`` the next state the fsm will have after the action. """ for state in states: action = getattr(self, 'handle_%s' % next_state) self.transitions[(symbol, state)] = (action, next_state) def process(self, symbol): """ Process the transition corresponding to the current state and the symbol provided. Keywords arguments: ``symbol`` string, the matched token (two chars symbol). ``linenum`` integer, the current line number of the parsed file. """ try: (action, state) = self.transitions[(symbol, self.current_state)] if action(): self.current_state = state except Exception: fpath = '%s ' % self.instance.fpath if self.instance.fpath else '' if hasattr(self.fhandle, 'close'): self.fhandle.close() raise OSError(f'Syntax error in po file {fpath}(line {self.current_line})') # state handlers def handle_he(self): """Handle a header comment.""" if self.instance.header != '': self.instance.header += '\n' self.instance.header += self.current_token[2:] return 1 def handle_tc(self): """Handle a translator comment.""" if self.current_state in ['mc', 'ms', 'mx']: self.instance.append(self.current_entry) self.current_entry = POEntry(linenum=self.current_line) if self.current_entry.tcomment != '': self.current_entry.tcomment += '\n' tcomment = self.current_token.lstrip('#') if tcomment.startswith(' '): tcomment = tcomment[1:] self.current_entry.tcomment += tcomment return True def handle_gc(self): """Handle a generated comment.""" if self.current_state in ['mc', 'ms', 'mx']: self.instance.append(self.current_entry) self.current_entry = POEntry(linenum=self.current_line) if self.current_entry.comment != '': self.current_entry.comment += '\n' self.current_entry.comment += self.current_token[3:] return True def handle_oc(self): """Handle a file:num occurrence.""" if self.current_state in ['mc', 'ms', 'mx']: self.instance.append(self.current_entry) self.current_entry = POEntry(linenum=self.current_line) occurrences = self.current_token[3:].split() for occurrence in occurrences: if occurrence != '': try: fil, line = occurrence.rsplit(':', 1) if not line.isdigit(): fil = occurrence line = '' self.current_entry.occurrences.append((fil, line)) except (ValueError, AttributeError): self.current_entry.occurrences.append((occurrence, '')) return True def handle_fl(self): """Handle a flags line.""" if self.current_state in ['mc', 'ms', 'mx']: self.instance.append(self.current_entry) self.current_entry = POEntry(linenum=self.current_line) self.current_entry.flags += [ c.strip() for c in self.current_token[3:].split(',') ] return True def handle_pp(self): """Handle a previous msgid_plural line.""" if self.current_state in ['mc', 'ms', 'mx']: self.instance.append(self.current_entry) self.current_entry = POEntry(linenum=self.current_line) self.current_entry.previous_msgid_plural = unescape(self.current_token[1:-1]) return True def handle_pm(self): """Handle a previous msgid line.""" if self.current_state in ['mc', 'ms', 'mx']: self.instance.append(self.current_entry) self.current_entry = POEntry(linenum=self.current_line) self.current_entry.previous_msgid = unescape(self.current_token[1:-1]) return True def handle_pc(self): """Handle a previous msgctxt line.""" if self.current_state in ['mc', 'ms', 'mx']: self.instance.append(self.current_entry) self.current_entry = POEntry(linenum=self.current_line) self.current_entry.previous_msgctxt = unescape(self.current_token[1:-1]) return True def handle_ct(self): """Handle a msgctxt.""" if self.current_state in ['mc', 'ms', 'mx']: self.instance.append(self.current_entry) self.current_entry = POEntry(linenum=self.current_line) self.current_entry.msgctxt = unescape(self.current_token[1:-1]) return True def handle_mi(self): """Handle a msgid.""" if self.current_state in ['mc', 'ms', 'mx']: self.instance.append(self.current_entry) self.current_entry = POEntry(linenum=self.current_line) self.current_entry.obsolete = self.entry_obsolete self.current_entry.msgid = unescape(self.current_token[1:-1]) return True def handle_mp(self): """Handle a msgid plural.""" self.current_entry.msgid_plural = unescape(self.current_token[1:-1]) return True def handle_ms(self): """Handle a msgstr.""" self.current_entry.msgstr = unescape(self.current_token[1:-1]) return True def handle_mx(self): """Handle a msgstr plural.""" index = self.current_token[7] value = self.current_token[self.current_token.find('"') + 1 : -1] self.current_entry.msgstr_plural[int(index)] = unescape(value) self.msgstr_index = int(index) return True def handle_mc(self): """Handle a msgid or msgstr continuation line.""" token = unescape(self.current_token[1:-1]) if self.current_state == 'ct': self.current_entry.msgctxt += token elif self.current_state == 'mi': self.current_entry.msgid += token elif self.current_state == 'mp': self.current_entry.msgid_plural += token elif self.current_state == 'ms': self.current_entry.msgstr += token elif self.current_state == 'mx': self.current_entry.msgstr_plural[self.msgstr_index] += token elif self.current_state == 'pp': self.current_entry.previous_msgid_plural += token elif self.current_state == 'pm': self.current_entry.previous_msgid += token elif self.current_state == 'pc': self.current_entry.previous_msgctxt += token # don't change the current state return False # }}} # class _MOFileParser {{{ class _MOFileParser: """ A class to parse binary mo files. """ def __init__(self, mofile, *_args, **kwargs): """ Constructor. Keyword arguments: ``mofile`` string, path to the mo file or its content ``encoding`` string, the encoding to use, defaults to ``default_encoding`` global variable (optional). ``check_for_duplicates`` whether to check for duplicate entries when adding entries to the file (optional, default: ``False``). """ if _is_file(mofile): self.fhandle = open(mofile, 'rb') else: self.fhandle = io.BytesIO(mofile) klass = kwargs.get('klass') if klass is None: klass = MOFile self.instance = klass( fpath=mofile, encoding=kwargs.get('encoding', default_encoding), check_for_duplicates=kwargs.get('check_for_duplicates', False), ) def __del__(self): """ Make sure the file is closed, this prevents warnings on unclosed file when running tests with python >= 3.2. """ if self.fhandle and hasattr(self.fhandle, 'close'): self.fhandle.close() def parse(self): """ Build the instance with the file handle provided in the constructor. """ # parse magic number magic_number = self._readbinary('> 16 not in (0, 1): raise OSError('Invalid mo file, unexpected major revision number') self.instance.version = version # original strings and translation strings hash table offset msgids_hash_offset, msgstrs_hash_offset = self._readbinary(ii, 8) # move to msgid hash table and read length and offset of msgids self.fhandle.seek(msgids_hash_offset) msgids_index = [] for i in range(numofstrings): msgids_index.append(self._readbinary(ii, 8)) # move to msgstr hash table and read length and offset of msgstrs self.fhandle.seek(msgstrs_hash_offset) msgstrs_index = [] for i in range(numofstrings): msgstrs_index.append(self._readbinary(ii, 8)) # build entries encoding = self.instance.encoding for i in range(numofstrings): self.fhandle.seek(msgids_index[i][1]) msgid = self.fhandle.read(msgids_index[i][0]) self.fhandle.seek(msgstrs_index[i][1]) msgstr = self.fhandle.read(msgstrs_index[i][0]) if i == 0 and not msgid: # metadata raw_metadata, metadata = msgstr.split(b('\n')), {} for line in raw_metadata: tokens = line.split(b(':'), 1) if tokens[0] != b(''): try: k = tokens[0].decode(encoding) v = tokens[1].decode(encoding) metadata[k] = v.strip() except IndexError: metadata[k] = u('') self.instance.metadata = metadata continue # test if we have a plural entry msgid_tokens = msgid.split(b('\0')) if len(msgid_tokens) > 1: entry = self._build_entry( msgid=msgid_tokens[0], msgid_plural=msgid_tokens[1], msgstr_plural=dict(enumerate(msgstr.split(b('\x00')))), ) else: entry = self._build_entry(msgid=msgid, msgstr=msgstr) self.instance.append(entry) # close opened file self.fhandle.close() return self.instance def _build_entry(self, msgid, msgstr=None, msgid_plural=None, msgstr_plural=None): msgctxt_msgid = msgid.split(b('\x04')) encoding = self.instance.encoding if len(msgctxt_msgid) > 1: kwargs = { 'msgctxt': msgctxt_msgid[0].decode(encoding), 'msgid': msgctxt_msgid[1].decode(encoding), } else: kwargs = {'msgid': msgid.decode(encoding)} if msgstr: kwargs['msgstr'] = msgstr.decode(encoding) if msgid_plural: kwargs['msgid_plural'] = msgid_plural.decode(encoding) if msgstr_plural: for k in msgstr_plural: msgstr_plural[k] = msgstr_plural[k].decode(encoding) kwargs['msgstr_plural'] = msgstr_plural return MOEntry(**kwargs) def _readbinary(self, fmt, numbytes): """ Private method that unpack n bytes of data using format . It returns a tuple or a mixed value if the tuple length is 1. """ content = self.fhandle.read(numbytes) tup = struct.unpack(fmt, content) if len(tup) == 1: return tup[0] return tup # }}} git-cola-4.6.1/cola/qtcompat.py000066400000000000000000000031731457126473700163650ustar00rootroot00000000000000from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt try: from qtpy import PYQT4 except ImportError: PYQT4 = False from . import hotkeys def patch(obj, attr, value): if not hasattr(obj, attr): setattr(obj, attr, value) def install(): patch(QtWidgets.QGraphicsItem, 'mapRectToScene', _map_rect_to_scene) patch(QtGui.QKeySequence, 'Preferences', hotkeys.PREFERENCES) 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 = QtWidgets.QMainWindow.AllowNestedDocks tabbed = QtWidgets.QMainWindow.AllowTabbedDocks animated = QtWidgets.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) def wheel_translation(event): """Return the (Tx, Ty) translation delta for a pan""" if PYQT4: tx = event.delta() ty = 0.0 if event.orientation() == Qt.Vertical: (tx, ty) = (ty, tx) else: angle = event.angleDelta() tx = angle.x() ty = angle.y() return (tx, ty) def wheel_delta(event): """Return a single wheel delta""" if PYQT4: delta = event.delta() else: angle = event.angleDelta() x = angle.x() y = angle.y() if abs(x) > abs(y): delta = x else: delta = y return delta git-cola-4.6.1/cola/qtutils.py000066400000000000000000001151571457126473700162500ustar00rootroot00000000000000"""Miscellaneous Qt utility functions.""" import os from qtpy import compat from qtpy import QtGui from qtpy import QtCore from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from . import core from . import hotkeys from . import icons from . import utils from .i18n import N_ from .compat import int_types from .compat import ustr from .models import prefs from .widgets import defs STRETCH = object() SKIPPED = object() def active_window(): """Return the active window for the current application""" return QtWidgets.QApplication.activeWindow() def current_palette(): """Return the QPalette for the current application""" return QtWidgets.QApplication.instance().palette() def connect_action(action, func): """Connect an action to a function""" action.triggered[bool].connect(lambda x: func(), type=Qt.QueuedConnection) def connect_action_bool(action, func): """Connect a triggered(bool) action to a function""" action.triggered[bool].connect(func, type=Qt.QueuedConnection) def connect_button(button, func): """Connect a button to a function""" # Some versions of Qt send the `bool` argument to the clicked callback, # and some do not. The lambda consumes all callback-provided arguments. button.clicked.connect(lambda *args, **kwargs: func(), type=Qt.QueuedConnection) def connect_checkbox(widget, func): """Connect a checkbox to a function taking bool""" widget.clicked.connect( lambda *args, **kwargs: func(get(checkbox)), type=Qt.QueuedConnection ) def connect_released(button, func): """Connect a button to a function""" button.released.connect(func, type=Qt.QueuedConnection) def button_action(button, action): """Make a button trigger an action""" connect_button(button, action.trigger) def connect_toggle(toggle, func): """Connect a toggle button to a function""" toggle.toggled.connect(func, type=Qt.QueuedConnection) def disconnect(signal): """Disconnect signal from all slots""" try: signal.disconnect() except TypeError: # allow unconnected slots pass def get(widget, default=None): """Query a widget for its python value""" if hasattr(widget, 'isChecked'): value = widget.isChecked() elif hasattr(widget, 'value'): value = widget.value() elif hasattr(widget, 'text'): value = widget.text() elif hasattr(widget, 'toPlainText'): value = widget.toPlainText() elif hasattr(widget, 'sizes'): value = widget.sizes() elif hasattr(widget, 'date'): value = widget.date().toString(Qt.ISODate) else: value = default return value def hbox(margin, spacing, *items): """Create an HBoxLayout with the specified sizes and items""" return box(QtWidgets.QHBoxLayout, margin, spacing, *items) def vbox(margin, spacing, *items): """Create a VBoxLayout with the specified sizes and items""" return box(QtWidgets.QVBoxLayout, margin, spacing, *items) def buttongroup(*items): """Create a QButtonGroup for the specified items""" group = QtWidgets.QButtonGroup() for i in items: group.addButton(i) return group def set_margin(layout, margin): """Set the content margins for a layout""" layout.setContentsMargins(margin, margin, margin, margin) def box(cls, margin, spacing, *items): """Create a QBoxLayout with the specified sizes and items""" stretch = STRETCH skipped = SKIPPED layout = cls() layout.setSpacing(spacing) set_margin(layout, margin) for i in items: if isinstance(i, QtWidgets.QWidget): layout.addWidget(i) elif isinstance( i, ( QtWidgets.QHBoxLayout, QtWidgets.QVBoxLayout, QtWidgets.QFormLayout, QtWidgets.QLayout, ), ): layout.addLayout(i) elif i is stretch: layout.addStretch() elif i is skipped: continue elif isinstance(i, int_types): layout.addSpacing(i) return layout def form(margin, spacing, *widgets): """Create a QFormLayout with the specified sizes and items""" layout = QtWidgets.QFormLayout() layout.setSpacing(spacing) layout.setFieldGrowthPolicy(QtWidgets.QFormLayout.ExpandingFieldsGrow) set_margin(layout, margin) for idx, (name, widget) in enumerate(widgets): if isinstance(name, (str, ustr)): layout.addRow(name, widget) else: layout.setWidget(idx, QtWidgets.QFormLayout.LabelRole, name) layout.setWidget(idx, QtWidgets.QFormLayout.FieldRole, widget) return layout def grid(margin, spacing, *widgets): """Create a QGridLayout with the specified sizes and items""" layout = QtWidgets.QGridLayout() layout.setSpacing(spacing) set_margin(layout, margin) for row in widgets: item = row[0] if isinstance(item, QtWidgets.QWidget): layout.addWidget(*row) elif isinstance(item, QtWidgets.QLayoutItem): layout.addItem(*row) return layout def splitter(orientation, *widgets): """Create a splitter over the specified widgets :param orientation: Qt.Horizontal or Qt.Vertical """ layout = QtWidgets.QSplitter() layout.setOrientation(orientation) layout.setHandleWidth(defs.handle_width) layout.setChildrenCollapsible(True) for idx, widget in enumerate(widgets): layout.addWidget(widget) layout.setStretchFactor(idx, 1) # Workaround for Qt not setting the WA_Hover property for QSplitter # Cf. https://bugreports.qt.io/browse/QTBUG-13768 layout.handle(1).setAttribute(Qt.WA_Hover) return layout def label(text=None, align=None, fmt=None, selectable=True): """Create a QLabel with the specified properties""" widget = QtWidgets.QLabel() if align is not None: widget.setAlignment(align) if fmt is not None: widget.setTextFormat(fmt) if selectable: widget.setTextInteractionFlags(Qt.TextBrowserInteraction) widget.setOpenExternalLinks(True) if text: widget.setText(text) return widget class ComboBox(QtWidgets.QComboBox): """Custom read-only combo box with a convenient API""" def __init__(self, items=None, editable=False, parent=None, transform=None): super().__init__(parent) self.setEditable(editable) self.transform = transform self.item_data = [] if items: self.addItems(items) self.item_data.extend(items) def set_index(self, idx): idx = utils.clamp(idx, 0, self.count() - 1) self.setCurrentIndex(idx) def add_item(self, text, data): self.addItem(text) self.item_data.append(data) def current_data(self): return self.item_data[self.currentIndex()] def set_value(self, value): if self.transform: value = self.transform(value) try: index = self.item_data.index(value) except ValueError: index = 0 self.setCurrentIndex(index) def combo(items, editable=False, tooltip='', parent=None): """Create a readonly (by default) combo box from a list of items""" combobox = ComboBox(editable=editable, items=items, parent=parent) if tooltip: combobox.setToolTip(tooltip) return combobox def combo_mapped(data, editable=False, transform=None, parent=None): """Create a readonly (by default) combo box from a list of items""" widget = ComboBox(editable=editable, transform=transform, parent=parent) for k, v in data: widget.add_item(k, v) return widget def textbrowser(text=None): """Create a QTextBrowser for the specified text""" widget = QtWidgets.QTextBrowser() widget.setOpenExternalLinks(True) if text: widget.setText(text) return widget def link(url, text, palette=None): if palette is None: palette = QtGui.QPalette() color = palette.color(QtGui.QPalette.WindowText) rgb_color = f'rgb({color.red()}, {color.green()}, {color.blue()})' scope = {'rgb': rgb_color, 'text': text, 'url': url} return ( """ %(text)s """ % scope ) def add_completer(widget, items): """Add simple completion to a widget""" completer = QtWidgets.QCompleter(items, widget) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setCompletionMode(QtWidgets.QCompleter.InlineCompletion) widget.setCompleter(completer) def prompt(msg, title=None, text='', parent=None): """Presents the user with an input widget and returns the input.""" if title is None: title = msg if parent is None: parent = active_window() result = QtWidgets.QInputDialog.getText( parent, title, msg, QtWidgets.QLineEdit.Normal, text ) return (result[0], result[1]) def prompt_n(msg, inputs): """Presents the user with N input widgets and returns the results""" dialog = QtWidgets.QDialog(active_window()) dialog.setWindowModality(Qt.WindowModal) dialog.setWindowTitle(msg) long_value = msg for k, v in inputs: if len(k + v) > len(long_value): long_value = k + v min_width = min(720, text_width(dialog.font(), long_value) + 100) dialog.setMinimumWidth(min_width) ok_b = ok_button(msg, enabled=False) close_b = close_button() form_widgets = [] def get_values(): return [pair[1].text().strip() for pair in form_widgets] for name, value in inputs: lineedit = QtWidgets.QLineEdit() # Enable the OK button only when all fields have been populated lineedit.textChanged.connect( lambda x: ok_b.setEnabled(all(get_values())), type=Qt.QueuedConnection ) if value: lineedit.setText(value) form_widgets.append((name, lineedit)) # layouts form_layout = form(defs.no_margin, defs.button_spacing, *form_widgets) button_layout = hbox(defs.no_margin, defs.button_spacing, STRETCH, close_b, ok_b) main_layout = vbox(defs.margin, defs.button_spacing, form_layout, button_layout) dialog.setLayout(main_layout) # connections connect_button(ok_b, dialog.accept) connect_button(close_b, dialog.reject) accepted = dialog.exec_() == QtWidgets.QDialog.Accepted text = get_values() success = accepted and all(text) return (success, text) def standard_item_type_value(value): """Return a custom UserType for use in QTreeWidgetItem.type() overrides""" return custom_item_type_value(QtGui.QStandardItem, value) def graphics_item_type_value(value): """Return a custom UserType for use in QGraphicsItem.type() overrides""" return custom_item_type_value(QtWidgets.QGraphicsItem, value) def custom_item_type_value(cls, value): """Return a custom cls.UserType for use in cls.type() overrides""" user_type = enum_value(cls.UserType) return user_type + value def enum_value(value): """Qt6 has enums with an inner '.value' attribute.""" if hasattr(value, 'value'): value = value.value return value class TreeWidgetItem(QtWidgets.QTreeWidgetItem): TYPE = standard_item_type_value(101) def __init__(self, path, icon, deleted): QtWidgets.QTreeWidgetItem.__init__(self) self.path = path self.deleted = deleted self.setIcon(0, icons.from_name(icon)) self.setText(0, path) def type(self): return self.TYPE def paths_from_indexes(model, indexes, item_type=TreeWidgetItem.TYPE, item_filter=None): """Return paths from a list of QStandardItemModel indexes""" items = [model.itemFromIndex(i) for i in indexes] return paths_from_items(items, item_type=item_type, item_filter=item_filter) def _true_filter(_value): return True def paths_from_items(items, item_type=TreeWidgetItem.TYPE, item_filter=None): """Return a list of paths from a list of items""" if item_filter is None: item_filter = _true_filter return [i.path for i in items if i.type() == item_type and item_filter(i)] def tree_selection(tree_item, items): """Returns an array of model items that correspond to the selected QTreeWidgetItem children""" selected = [] count = min(tree_item.childCount(), len(items)) for idx in range(count): if tree_item.child(idx).isSelected(): selected.append(items[idx]) return selected def tree_selection_items(tree_item): """Returns selected widget items""" selected = [] for idx in range(tree_item.childCount()): child = tree_item.child(idx) if child.isSelected(): selected.append(child) return selected def selected_item(list_widget, items): """Returns the model item that corresponds to the selected QListWidget row.""" 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): item = items[row] else: item = None return item def selected_items(list_widget, items): """Returns an array of model items that correspond to the selected QListWidget rows.""" item_count = len(items) selected = [] for widget_item in list_widget.selectedItems(): row = list_widget.row(widget_item) if row < item_count: selected.append(items[row]) return selected def open_file(title, directory=None): """Creates an Open File dialog and returns a filename.""" result = compat.getopenfilename( parent=active_window(), caption=title, basedir=directory ) return result[0] def open_files(title, directory=None, filters=''): """Creates an Open File dialog and returns a list of filenames.""" result = compat.getopenfilenames( parent=active_window(), caption=title, basedir=directory, filters=filters ) return result[0] def _enum_value(value): """Resolve Qt6 enum values""" if hasattr(value, 'value'): return value.value return value def opendir_dialog(caption, path): """Prompts for a directory path""" options = QtWidgets.QFileDialog.Option( _enum_value(QtWidgets.QFileDialog.Directory) | _enum_value(QtWidgets.QFileDialog.DontResolveSymlinks) | _enum_value(QtWidgets.QFileDialog.ReadOnly) | _enum_value(QtWidgets.QFileDialog.ShowDirsOnly) ) return compat.getexistingdirectory( parent=active_window(), caption=caption, basedir=path, options=options ) def save_as(filename, title='Save As...'): """Creates a Save File dialog and returns a filename.""" result = compat.getsavefilename( parent=active_window(), caption=title, basedir=filename ) return result[0] def existing_file(directory, title='Append...'): """Creates a Save File dialog and returns a filename.""" result = compat.getopenfilename( parent=active_window(), caption=title, basedir=directory ) return result[0] def copy_path(filename, absolute=True): """Copy a filename to the clipboard""" if filename is None: return if absolute: filename = core.abspath(filename) set_clipboard(filename) def set_clipboard(text): """Sets the copy/paste buffer to text.""" if not text: return clipboard = QtWidgets.QApplication.clipboard() clipboard.setText(text, QtGui.QClipboard.Clipboard) if not utils.is_darwin() and not utils.is_win32(): clipboard.setText(text, QtGui.QClipboard.Selection) persist_clipboard() def persist_clipboard(): """Persist the clipboard X11 stores only a reference to the clipboard data. Send a clipboard event to force a copy of the clipboard to occur. This ensures that the clipboard is present after git-cola exits. Otherwise, the reference is destroyed on exit. C.f. https://stackoverflow.com/questions/2007103/how-can-i-disable-clear-of-clipboard-on-exit-of-pyqt4-application """ # noqa clipboard = QtWidgets.QApplication.clipboard() event = QtCore.QEvent(QtCore.QEvent.Clipboard) QtWidgets.QApplication.sendEvent(clipboard, event) def add_action_bool(widget, text, func, checked, *shortcuts): tip = text action = _add_action(widget, text, tip, func, connect_action_bool, *shortcuts) action.setCheckable(True) action.setChecked(checked) return action def add_action(widget, text, func, *shortcuts): """Create a QAction and bind it to the `func` callback and hotkeys""" tip = text return _add_action(widget, text, tip, func, connect_action, *shortcuts) def add_action_with_icon(widget, icon, text, func, *shortcuts): """Create a QAction using a custom icon bound to the `func` callback and hotkeys""" tip = text action = _add_action(widget, text, tip, func, connect_action, *shortcuts) action.setIcon(icon) return action def add_action_with_tooltip(widget, text, tip, func, *shortcuts): """Create an action with a tooltip""" return _add_action(widget, text, tip, func, connect_action, *shortcuts) def menu_separator(widget, text=''): """Return a QAction whose isSeparator() returns true. Used in context menus""" action = QtWidgets.QAction(text, widget) action.setSeparator(True) return action def _add_action(widget, text, tip, func, connect, *shortcuts): action = QtWidgets.QAction(text, widget) if hasattr(action, 'setIconVisibleInMenu'): action.setIconVisibleInMenu(True) if tip: action.setStatusTip(tip) connect(action, func) if shortcuts: action.setShortcuts(shortcuts) if hasattr(Qt, 'WidgetWithChildrenShortcut'): action.setShortcutContext(Qt.WidgetWithChildrenShortcut) widget.addAction(action) return action def set_selected_item(widget, idx): """Sets the currently selected item to the item at index idx.""" if isinstance(widget, QtWidgets.QTreeWidget): item = widget.topLevelItem(idx) if item: item.setSelected(True) widget.setCurrentItem(item) def add_items(widget, items): """Adds items to a widget.""" for item in items: if item is None: continue 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 create_treeitem(filename, staged=False, deleted=False, untracked=False): """Given a filename, return a TreeWidgetItem for a status widget "staged", "deleted, and "untracked" control which icon is used. """ icon_name = icons.status(filename, deleted, staged, untracked) icon = icons.name_from_basename(icon_name) return TreeWidgetItem(filename, icon, deleted=deleted) def add_close_action(widget): """Adds close action and shortcuts to a widget.""" return add_action(widget, N_('Close...'), widget.close, hotkeys.CLOSE, hotkeys.QUIT) def app(): """Return the current application""" return QtWidgets.QApplication.instance() def desktop_size(): rect = app().primaryScreen().geometry() return (rect.width(), rect.height()) def center_on_screen(widget): """Move widget to the center of the default screen""" width, height = desktop_size() center_x = width // 2 center_y = height // 2 widget.move(center_x - widget.width() // 2, center_y - widget.height() // 2) def default_size(parent, width, height, use_parent_height=True): """Return the parent's size, or the provided defaults""" if parent is not None: width = parent.width() if use_parent_height: height = parent.height() return (width, height) def default_monospace_font(): if utils.is_darwin(): family = 'Monaco' elif utils.is_win32(): family = 'Courier' else: family = 'Monospace' mfont = QtGui.QFont() mfont.setFamily(family) return mfont def diff_font_str(context): cfg = context.cfg font_str = cfg.get(prefs.FONTDIFF) if not font_str: font_str = default_monospace_font().toString() return font_str def diff_font(context): return font_from_string(diff_font_str(context)) def font_from_string(string): qfont = QtGui.QFont() qfont.fromString(string) return qfont def create_button( text='', layout=None, tooltip=None, icon=None, enabled=True, default=False ): """Create a button, set its title, and add it to the parent.""" button = QtWidgets.QPushButton() button.setCursor(Qt.PointingHandCursor) button.setFocusPolicy(Qt.NoFocus) if text: button.setText(' ' + text) if icon is not None: button.setIcon(icon) button.setIconSize(QtCore.QSize(defs.small_icon, defs.small_icon)) if tooltip is not None: button.setToolTip(tooltip) if layout is not None: layout.addWidget(button) if not enabled: button.setEnabled(False) if default: button.setDefault(True) return button def tool_button(): """Create a flat border-less button""" button = QtWidgets.QToolButton() button.setPopupMode(QtWidgets.QToolButton.InstantPopup) button.setCursor(Qt.PointingHandCursor) button.setFocusPolicy(Qt.NoFocus) # Highlight colors palette = QtGui.QPalette() highlight = palette.color(QtGui.QPalette.Highlight) highlight_rgb = rgb_css(highlight) button.setStyleSheet( """ /* No borders */ QToolButton { border: none; background-color: none; } /* Hide the menu indicator */ QToolButton::menu-indicator { image: none; } QToolButton:hover { border: %(border)spx solid %(highlight_rgb)s; } """ % { 'border': defs.border, 'highlight_rgb': highlight_rgb, } ) return button def create_action_button(tooltip=None, icon=None, visible=None): """Create a small tool button for use in dock title widgets""" button = tool_button() if tooltip is not None: button.setToolTip(tooltip) if icon is not None: button.setIcon(icon) button.setIconSize(QtCore.QSize(defs.small_icon, defs.small_icon)) if visible is not None: button.setVisible(visible) return button def ok_button(text, default=True, enabled=True, icon=None): if icon is None: icon = icons.ok() return create_button(text=text, icon=icon, default=default, enabled=enabled) def close_button(text=None, icon=None): text = text or N_('Close') icon = icons.mkicon(icon, icons.close) return create_button(text=text, icon=icon) def edit_button(enabled=True, default=False): return create_button( text=N_('Edit'), icon=icons.edit(), enabled=enabled, default=default ) def refresh_button(enabled=True, default=False): return create_button( text=N_('Refresh'), icon=icons.sync(), enabled=enabled, default=default ) def checkbox(text='', tooltip='', checked=None): """Create a checkbox""" return _checkbox(QtWidgets.QCheckBox, text, tooltip, checked) def radio(text='', tooltip='', checked=None): """Create a radio button""" return _checkbox(QtWidgets.QRadioButton, text, tooltip, checked) def _checkbox(cls, text, tooltip, checked): """Create a widget and apply properties""" widget = cls() if text: widget.setText(text) if tooltip: widget.setToolTip(tooltip) if checked is not None: widget.setChecked(checked) return widget class DockTitleBarWidget(QtWidgets.QFrame): def __init__(self, parent, title, stretch=True): QtWidgets.QFrame.__init__(self, parent) self.setAutoFillBackground(True) self.label = qlabel = QtWidgets.QLabel(title, self) qfont = qlabel.font() qfont.setBold(True) qlabel.setFont(qfont) qlabel.setCursor(Qt.OpenHandCursor) self.close_button = create_action_button( tooltip=N_('Close'), icon=icons.close() ) self.toggle_button = create_action_button( tooltip=N_('Detach'), icon=icons.external() ) self.corner_layout = hbox(defs.no_margin, defs.spacing) self.title_layout = hbox(defs.no_margin, defs.button_spacing, qlabel) if stretch: separator = STRETCH else: separator = SKIPPED self.main_layout = hbox( defs.small_margin, defs.titlebar_spacing, self.title_layout, separator, self.corner_layout, self.toggle_button, 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_title_widget(self, widget): """Add widgets to the title area""" self.title_layout.addWidget(widget) def add_corner_widget(self, widget): """Add widgets to the corner area""" 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(name, title, parent, stretch=True, widget=None, func=None): """Create a dock widget and set it up accordingly.""" dock = QtWidgets.QDockWidget(parent) dock.setWindowTitle(title) dock.setObjectName(name) titlebar = DockTitleBarWidget(dock, title, stretch=stretch) dock.setTitleBarWidget(titlebar) dock.setAutoFillBackground(True) if hasattr(parent, 'dockwidgets'): parent.dockwidgets.append(dock) if func: widget = func(dock) if widget: dock.setWidget(widget) return dock def hide_dock(widget): widget.toggleViewAction().setChecked(False) widget.hide() def create_menu(title, parent): """Create a menu and set its title.""" qmenu = DebouncingMenu(title, parent) return qmenu class DebouncingMenu(QtWidgets.QMenu): """Menu that debounces mouse release action i.e. stops it if occurred right after menu creation. Disables annoying behaviour when RMB is pressed to show menu, cursor is moved accidentally 1 px onto newly created menu and released causing to execute menu action """ threshold_ms = 400 def __init__(self, title, parent): QtWidgets.QMenu.__init__(self, title, parent) self.created_at = utils.epoch_millis() if hasattr(self, 'setToolTipsVisible'): self.setToolTipsVisible(True) def mouseReleaseEvent(self, event): threshold = DebouncingMenu.threshold_ms if (utils.epoch_millis() - self.created_at) > threshold: QtWidgets.QMenu.mouseReleaseEvent(self, event) def add_menu(title, parent): """Create a menu and set its title.""" menu = create_menu(title, parent) if hasattr(parent, 'addMenu'): parent.addMenu(menu) else: parent.addAction(menu.menuAction()) return menu def create_toolbutton(text=None, layout=None, tooltip=None, icon=None): button = tool_button() if icon is not None: button.setIcon(icon) button.setIconSize(QtCore.QSize(defs.default_icon, defs.default_icon)) if text is not None: button.setText(' ' + text) button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) if tooltip is not None: button.setToolTip(tooltip) if layout is not None: layout.addWidget(button) return button def create_toolbutton_with_callback(callback, text, icon, tooltip, layout=None): """Create a tool button that runs the specified callback""" toolbutton = create_toolbutton(text=text, layout=layout, tooltip=tooltip, icon=icon) connect_button(toolbutton, callback) return toolbutton def mimedata_from_paths(context, paths, include_urls=True): """Return mime data with a list of absolute path URLs Set `include_urls` to False to prevent URLs from being included in the mime data. This is useful in some terminals that do not gracefully handle multiple URLs being included in the payload. This allows the mime data to contain just plain a plain text value that we are able to format ourselves. Older versions of gnome-terminal expected a UTF-16 encoding, but that behavior is no longer needed. """ # noqa abspaths = [core.abspath(path) for path in paths] paths_text = core.list2cmdline(abspaths) # The text/x-moz-list format is always included by Qt, and doing # mimedata.removeFormat('text/x-moz-url') has no effect. # http://www.qtcentre.org/threads/44643-Dragging-text-uri-list-Qt-inserts-garbage # # Older versions of gnome-terminal expect UTF-16 encoded text, but other terminals, # e.g. terminator, expect UTF-8, so use cola.dragencoding to override the default. # NOTE: text/x-moz-url does not seem to be used/needed by modern versions of # gnome-terminal, kitty, and terminator. mimedata = QtCore.QMimeData() mimedata.setText(paths_text) if include_urls: urls = [QtCore.QUrl.fromLocalFile(path) for path in abspaths] encoding = context.cfg.get('cola.dragencoding', 'utf-16') encoded_text = core.encode(paths_text, encoding=encoding) mimedata.setUrls(urls) mimedata.setData('text/x-moz-url', encoded_text) return mimedata def path_mimetypes(include_urls=True): """Return a list of mime types that we generate""" mime_types = [ 'text/plain', 'text/plain;charset=utf-8', ] if include_urls: mime_types.append('text/uri-list') mime_types.append('text/x-moz-url') return mime_types class BlockSignals: """Context manager for blocking a signals on a widget""" def __init__(self, *widgets): self.widgets = widgets self.values = [] def __enter__(self): """Block Qt signals for all of the captured widgets""" self.values = [widget.blockSignals(True) for widget in self.widgets] return self def __exit__(self, exc_type, exc_val, exc_tb): """Restore Qt signals when we exit the scope""" for widget, value in zip(self.widgets, self.values): widget.blockSignals(value) class Channel(QtCore.QObject): finished = Signal(object) result = Signal(object) class Task(QtCore.QRunnable): """Run a task in the background and return the result using a Channel""" def __init__(self): QtCore.QRunnable.__init__(self) self.channel = Channel() self.result = None # Python's garbage collector will try to double-free the task # once it's finished so disable the Qt auto-deletion. self.setAutoDelete(False) def run(self): self.result = self.task() self.channel.result.emit(self.result) self.channel.finished.emit(self) def task(self): """Perform a long-running task""" return () def connect(self, handler): self.channel.result.connect(handler, type=Qt.QueuedConnection) class SimpleTask(Task): """Run a simple callable as a task""" def __init__(self, func, *args, **kwargs): Task.__init__(self) self.func = func self.args = args self.kwargs = kwargs def task(self): return self.func(*self.args, **self.kwargs) class RunTask(QtCore.QObject): """Runs QRunnable instances and transfers control when they finish""" def __init__(self, parent=None): QtCore.QObject.__init__(self, parent) self.tasks = [] self.task_details = {} self.threadpool = QtCore.QThreadPool.globalInstance() self.result_func = None def start(self, task, progress=None, finish=None, result=None): """Start the task and register a callback""" self.result_func = result if progress is not None: if hasattr(progress, 'start'): progress.start() # prevents garbage collection bugs in certain PyQt4 versions self.tasks.append(task) task_id = id(task) self.task_details[task_id] = (progress, finish, result) task.channel.finished.connect(self.finish, type=Qt.QueuedConnection) self.threadpool.start(task) def finish(self, task): """The task has finished. Run the finish and result callbacks""" task_id = id(task) try: self.tasks.remove(task) except ValueError: pass try: progress, finish, result = self.task_details[task_id] del self.task_details[task_id] except KeyError: finish = progress = result = None if progress is not None: if hasattr(progress, 'stop'): progress.stop() progress.hide() if result is not None: result(task.result) if finish is not None: finish(task) def wait(self): """Wait until all tasks have finished processing""" self.threadpool.waitForDone() # Syntax highlighting def rgb(red, green, blue): """Create a QColor from r, g, b arguments""" color = QtGui.QColor() color.setRgb(red, green, blue) return color def rgba(red, green, blue, alpha=255): """Create a QColor with alpha from r, g, b, a arguments""" color = rgb(red, green, blue) color.setAlpha(alpha) return color def rgb_triple(args): """Create a QColor from an argument with an [r, g, b] triple""" return rgb(*args) def rgb_css(color): """Convert a QColor into an rgb #abcdef CSS string""" return '#%s' % rgb_hex(color) def rgb_hex(color): """Convert a QColor into a hex aabbcc string""" return f'{color.red():02x}{color.green():02x}{color.blue():02x}' def clamp_color(value): """Clamp an integer value between 0 and 255""" return min(255, max(value, 0)) def css_color(value): """Convert a #abcdef hex string into a QColor""" if value.startswith('#'): value = value[1:] try: red = clamp_color(int(value[:2], base=16)) # ab except ValueError: red = 255 try: green = clamp_color(int(value[2:4], base=16)) # cd except ValueError: green = 255 try: blue = clamp_color(int(value[4:6], base=16)) # ef except ValueError: blue = 255 return rgb(red, green, blue) def hsl(hue, saturation, lightness): """Return a QColor from an hue, saturation and lightness""" return QtGui.QColor.fromHslF( utils.clamp(hue, 0.0, 1.0), utils.clamp(saturation, 0.0, 1.0), utils.clamp(lightness, 0.0, 1.0), ) def hsl_css(hue, saturation, lightness): """Convert HSL values to a CSS #abcdef color string""" return rgb_css(hsl(hue, saturation, lightness)) def make_format(foreground=None, background=None, bold=False): """Create a QTextFormat from the provided foreground, background and bold values""" fmt = QtGui.QTextCharFormat() if foreground: fmt.setForeground(foreground) if background: fmt.setBackground(background) if bold: fmt.setFontWeight(QtGui.QFont.Bold) return fmt class ImageFormats: def __init__(self): # returns a list of QByteArray objects formats_qba = QtGui.QImageReader.supportedImageFormats() # portability: python3 data() returns bytes, python2 returns str decode = core.decode formats = [decode(x.data()) for x in formats_qba] self.extensions = {'.' + fmt for fmt in formats} def ok(self, filename): _, ext = os.path.splitext(filename) return ext.lower() in self.extensions def set_scrollbar_values(widget, hscroll_value, vscroll_value): """Set scrollbars to the specified values""" hscroll = widget.horizontalScrollBar() if hscroll and hscroll_value is not None: hscroll.setValue(hscroll_value) vscroll = widget.verticalScrollBar() if vscroll and vscroll_value is not None: vscroll.setValue(vscroll_value) def get_scrollbar_values(widget): """Return the current (hscroll, vscroll) scrollbar values for a widget""" hscroll = widget.horizontalScrollBar() if hscroll: hscroll_value = get(hscroll) else: hscroll_value = None vscroll = widget.verticalScrollBar() if vscroll: vscroll_value = get(vscroll) else: vscroll_value = None return (hscroll_value, vscroll_value) def scroll_to_item(widget, item): """Scroll to an item while retaining the horizontal scroll position""" hscroll = None hscrollbar = widget.horizontalScrollBar() if hscrollbar: hscroll = get(hscrollbar) widget.scrollToItem(item) if hscroll is not None: hscrollbar.setValue(hscroll) def select_item(widget, item): """Scroll to and make a QTreeWidget item selected and current""" scroll_to_item(widget, item) widget.setCurrentItem(item) item.setSelected(True) def get_selected_values(widget, top_level_idx, values): """Map the selected items under the top-level item to the values list""" # Get the top-level item item = widget.topLevelItem(top_level_idx) return tree_selection(item, values) def get_selected_items(widget, idx): """Return the selected items under the top-level item""" item = widget.topLevelItem(idx) return tree_selection_items(item) def add_menu_actions(menu, menu_actions): """Add actions to a menu, treating None as a separator""" current_actions = menu.actions() if current_actions: first_action = current_actions[0] else: first_action = None menu.addSeparator() for action in menu_actions: if action is None: action = menu_separator(menu) menu.insertAction(first_action, action) def fontmetrics_width(metrics, text): """Get the width in pixels of specified text Calls QFontMetrics.horizontalAdvance() when available. QFontMetricswidth() is deprecated. Qt 5.11 added horizontalAdvance(). """ if hasattr(metrics, 'horizontalAdvance'): return metrics.horizontalAdvance(text) return metrics.width(text) def text_width(font, text): """Get the width in pixels for the QFont and text""" metrics = QtGui.QFontMetrics(font) return fontmetrics_width(metrics, text) def text_size(font, text): """Return the width in pixels for the specified text :param font_or_widget: The QFont or widget providing the font to use. :param text: The text to measure. """ metrics = QtGui.QFontMetrics(font) return (fontmetrics_width(metrics, text), metrics.height()) git-cola-4.6.1/cola/resources.py000066400000000000000000000124731457126473700165520ustar00rootroot00000000000000"""Functions for finding cola resources""" import os from os.path import dirname import webbrowser from . import core from . import compat # Default git-cola icon theme _default_icon_theme = 'light' _resources = core.abspath(core.realpath(__file__)) _package = os.path.dirname(_resources) if _package.endswith(os.path.join('site-packages', 'cola')): # Unix release tree # __file__ = '$prefix/lib/pythonX.Y/site-packages/cola/__file__.py' # _package = '$prefix/lib/pythonX.Y/site-packages/cola' _prefix = dirname(dirname(dirname(dirname(_package)))) elif _package.endswith(os.path.join('pkgs', 'cola')): # Windows release tree # __file__ = $installdir/pkgs/cola _prefix = dirname(dirname(_package)) else: # this is the source tree # __file__ = '$prefix/cola/__file__.py' _prefix = dirname(_package) def get_prefix(): """Return the installation prefix""" return _prefix def prefix(*args): """Return a path relative to cola's installation prefix""" return os.path.join(get_prefix(), *args) def command(name): """Return a command from the bin/ directory""" if compat.WIN32: # Check for "${name}.exe" on Windows. exe_path = prefix('bin', '%s.exe' % name) scripts_exe_path = prefix('Scripts', '%s.exe' % name) scripts_path = prefix('Scripts', name) path = prefix('bin', name) if core.exists(exe_path): result = exe_path elif core.exists(scripts_exe_path): result = scripts_exe_path elif core.exists(scripts_path): result = scripts_path else: result = path else: result = prefix('bin', name) return result def doc(*args): """Return a path relative to cola's /usr/share/doc/ directory""" return share('doc', 'git-cola', *args) def i18n(*args): """Return a path relative to cola's i18n locale directory, e.g. cola/i18n""" return package_data('i18n', *args) def html_docs(): """Return the path to the cola html documentation.""" # html/index.html only exists after the install-docs target is run. # Fallback to the source tree and lastly git-cola.rst. paths_to_try = (('html', 'index.html'), ('_build', 'html', 'index.html')) for paths in paths_to_try: docdir = doc(*paths) if core.exists(docdir): return docdir return doc('git-cola.rst') def show_html_docs(): """Open the HTML documentation in a browser""" url = html_docs() webbrowser.open_new_tab('file://' + url) def share(*args): """Return a path relative to cola's /usr/share/ directory""" return prefix('share', *args) def package_data(*args): """Return a path relative to cola's Python modules""" return os.path.join(_package, *args) def package_command(*args): """Return a path relative to cola's private bin/ directory""" return package_data('bin', *args) def icon_dir(theme): """Return the icons directory for the specified theme This returns the ``icons`` directory inside the ``cola`` Python package. When theme is defined then it will return a subdirectory of the icons/ directory, e.g. "dark" for the dark icon theme. When theme is set to an absolute directory path, that directory will be returned, which effectively makes git-cola use those icons. """ if not theme or theme == _default_icon_theme: icons = package_data('icons') else: theme_dir = package_data('icons', theme) if os.path.isabs(theme) and os.path.isdir(theme): icons = theme elif os.path.isdir(theme_dir): icons = theme_dir else: icons = package_data('icons') return icons def xdg_config_home(*args): """Return the XDG_CONFIG_HOME configuration directory, eg. ~/.config""" config = core.getenv( 'XDG_CONFIG_HOME', os.path.join(core.expanduser('~'), '.config') ) return os.path.join(config, *args) def xdg_data_home(*args): """Return the XDG_DATA_HOME configuration directory, e.g. ~/.local/share""" config = core.getenv( 'XDG_DATA_HOME', os.path.join(core.expanduser('~'), '.local', 'share') ) return os.path.join(config, *args) def xdg_data_dirs(): """Return the current set of XDG data directories Returns the values from $XDG_DATA_DIRS when defined in the environment. If $XDG_DATA_DIRS is either not set or empty, a value equal to /usr/local/share:/usr/share is used. """ paths = [] xdg_data_home_dir = xdg_data_home() if os.path.isdir(xdg_data_home_dir): paths.append(xdg_data_home_dir) xdg_data_dirs_env = core.getenv('XDG_DATA_DIRS', '') if not xdg_data_dirs_env: xdg_data_dirs_env = '/usr/local/share:/usr/share' paths.extend(path for path in xdg_data_dirs_env.split(':') if os.path.isdir(path)) return paths def find_first(subpath, paths, validate=os.path.isfile): """Return the first `subpath` found in the specified directory paths""" if os.path.isabs(subpath): return subpath for path in paths: candidate = os.path.join(path, subpath) if validate(candidate): return candidate # Nothing was found so return None. return None def config_home(*args): """Return git-cola's configuration directory, e.g. ~/.config/git-cola""" return xdg_config_home('git-cola', *args) git-cola-4.6.1/cola/sequenceeditor.py000066400000000000000000000667671457126473700175760ustar00rootroot00000000000000import sys import re from argparse import ArgumentParser from functools import partial from cola import app # prints a message if Qt cannot be found from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from cola import core from cola import difftool from cola import gitcmds from cola import hotkeys from cola import icons from cola import qtutils from cola import utils from cola.i18n import N_ from cola.models import dag from cola.models import prefs from cola.widgets import defs from cola.widgets import filelist from cola.widgets import diff from cola.widgets import standard from cola.widgets import text PICK = 'pick' REWORD = 'reword' EDIT = 'edit' FIXUP = 'fixup' SQUASH = 'squash' UPDATE_REF = 'update-ref' EXEC = 'exec' COMMANDS = ( PICK, REWORD, EDIT, FIXUP, SQUASH, ) COMMAND_IDX = {cmd_: idx_ for idx_, cmd_ in enumerate(COMMANDS)} ABBREV = { 'p': PICK, 'r': REWORD, 'e': EDIT, 'f': FIXUP, 's': SQUASH, 'x': EXEC, 'u': UPDATE_REF, } def main(): """Start a git-cola-sequence-editor session""" args = parse_args() context = app.application_init(args) view = new_window(context, args.filename) app.application_run(context, view, start=view.start, stop=stop) return view.status def stop(context, _view): """All done, cleanup""" context.view.stop() context.runtask.wait() def parse_args(): parser = ArgumentParser() parser.add_argument( 'filename', metavar='', help='git-rebase-todo file to edit' ) app.add_common_arguments(parser) return parser.parse_args() def new_window(context, filename): window = MainWindow(context) editor = Editor(context, filename, parent=window) window.set_editor(editor) return window def unabbrev(cmd): """Expand shorthand commands into their full name""" return ABBREV.get(cmd, cmd) class MainWindow(standard.MainWindow): """The main git-cola application window""" def __init__(self, context, parent=None): super().__init__(parent) self.context = context self.status = 1 # If the user closes the window without confirmation it's considered cancelled. self.cancelled = True self.editor = None default_title = '%s - git cola sequence editor' % core.getcwd() title = core.getenv('GIT_COLA_SEQ_EDITOR_TITLE', default_title) self.setWindowTitle(title) self.show_help_action = qtutils.add_action( self, N_('Show Help'), partial(show_help, context), hotkeys.QUESTION ) self.menubar = QtWidgets.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) self.init_state(context.settings, self.init_window_size) def init_window_size(self): """Set the window size on the first initial view""" if utils.is_darwin(): width, height = qtutils.desktop_size() self.resize(width, height) else: self.showMaximized() def set_editor(self, editor): self.editor = editor self.setCentralWidget(editor) editor.cancel.connect(self.close) editor.rebase.connect(self.rebase) editor.setFocus() def start(self, _context, _view): """Start background tasks""" self.editor.start() def stop(self): """Stop background tasks""" self.editor.stop() def rebase(self): """Exit the editor and initiate a rebase""" self.status = self.editor.save() self.close() class Editor(QtWidgets.QWidget): cancel = Signal() rebase = Signal() def __init__(self, context, filename, parent=None): super().__init__(parent) self.widget_version = 1 self.context = context self.filename = filename self.comment_char = comment_char = prefs.comment_char(context) self.diff = diff.DiffWidget(context, self) self.tree = RebaseTreeWidget(context, comment_char, self) self.filewidget = filelist.FileWidget(context, self, remarks=True) self.setFocusProxy(self.tree) self.rebase_button = qtutils.create_button( text=core.getenv('GIT_COLA_SEQ_EDITOR_ACTION', N_('Rebase')), tooltip=N_('Accept changes and rebase\nShortcut: Ctrl+Enter'), icon=icons.ok(), default=True, ) self.extdiff_button = qtutils.create_button( text=N_('Launch Diff Tool'), tooltip=N_('Launch external diff tool\nShortcut: Ctrl+D'), ) self.extdiff_button.setEnabled(False) self.help_button = qtutils.create_button( text=N_('Help'), tooltip=N_('Show help\nShortcut: ?'), icon=icons.question() ) self.cancel_button = qtutils.create_button( text=N_('Cancel'), tooltip=N_('Cancel rebase\nShortcut: Ctrl+Q'), icon=icons.close(), ) top = qtutils.splitter(Qt.Horizontal, self.tree, self.filewidget) top.setSizes([75, 25]) main_split = qtutils.splitter(Qt.Vertical, top, self.diff) main_split.setSizes([25, 75]) controls_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.cancel_button, qtutils.STRETCH, self.help_button, self.extdiff_button, self.rebase_button, ) layout = qtutils.vbox(defs.no_margin, defs.spacing, main_split, controls_layout) self.setLayout(layout) self.action_rebase = qtutils.add_action( self, N_('Rebase'), self.rebase.emit, hotkeys.CTRL_RETURN, hotkeys.CTRL_ENTER, ) self.tree.commits_selected.connect(self.commits_selected) self.tree.commits_selected.connect(self.filewidget.commits_selected) self.tree.commits_selected.connect(self.diff.commits_selected) self.tree.external_diff.connect(self.external_diff) self.filewidget.files_selected.connect(self.diff.files_selected) self.filewidget.remark_toggled.connect(self.remark_toggled_for_files) # `git` calls are expensive. When user toggles a remark of all commits touching # selected paths the GUI freezes for a while on a big enough sequence. This # cache is used (commit ID to paths tuple) to minimize calls to git. self.oid_to_paths = {} self.task = None # A task fills the cache in the background. self.running = False # This flag stops it. qtutils.connect_button(self.rebase_button, self.rebase.emit) qtutils.connect_button(self.extdiff_button, self.external_diff) qtutils.connect_button(self.help_button, partial(show_help, context)) qtutils.connect_button(self.cancel_button, self.cancel.emit) def start(self): insns = core.read(self.filename) self.parse_sequencer_instructions(insns) # Assume that the tree is filled at this point. self.running = True self.task = qtutils.SimpleTask(self.calculate_oid_to_paths) self.context.runtask.start(self.task) def stop(self): self.running = False # signal callbacks def commits_selected(self, commits): self.extdiff_button.setEnabled(bool(commits)) def remark_toggled_for_files(self, remark, filenames): filenames = set(filenames) items = self.tree.items() touching_items = [] for item in items: if not item.is_commit(): continue oid = item.oid paths = self.paths_touched_by_oid(oid) if filenames.intersection(paths): touching_items.append(item) self.tree.toggle_remark_of_items(remark, touching_items) def external_diff(self): items = self.tree.selected_items() if not items: return item = items[0] difftool.diff_expression(self.context, self, item.oid + '^!', hide_expr=True) # helpers def paths_touched_by_oid(self, oid): try: return self.oid_to_paths[oid] except KeyError: pass paths = gitcmds.changed_files(self.context, oid) self.oid_to_paths[oid] = paths return paths def calculate_oid_to_paths(self): """Fills the oid_to_paths cache in the background""" for item in self.tree.items(): if not self.running: return self.paths_touched_by_oid(item.oid) def parse_sequencer_instructions(self, insns): idx = 1 re_comment_char = re.escape(self.comment_char) exec_rgx = re.compile(r'^\s*(%s)?\s*(x|exec)\s+(.+)$' % re_comment_char) update_ref_rgx = re.compile( r'^\s*(%s)?\s*(u|update-ref)\s+(.+)$' % re_comment_char ) # The upper bound of 40 below must match git.OID_LENGTH. # We'll have to update this to the new hash length when that happens. pick_rgx = re.compile( ( r'^\s*(%s)?\s*' + r'(p|pick|r|reword|e|edit|f|fixup|s|squash)' + r'\s+([0-9a-f]{7,40})' + r'\s+(.+)$' ) % re_comment_char ) for line in insns.splitlines(): match = pick_rgx.match(line) if match: enabled = match.group(1) is None command = unabbrev(match.group(2)) oid = match.group(3) summary = match.group(4) self.tree.add_item(idx, enabled, command, oid=oid, summary=summary) idx += 1 continue match = exec_rgx.match(line) if match: enabled = match.group(1) is None command = unabbrev(match.group(2)) cmdexec = match.group(3) self.tree.add_item(idx, enabled, command, cmdexec=cmdexec) idx += 1 continue match = update_ref_rgx.match(line) if match: enabled = match.group(1) is None command = unabbrev(match.group(2)) branch = match.group(3) self.tree.add_item(idx, enabled, command, branch=branch) idx += 1 continue self.tree.decorate(self.tree.items()) self.tree.refit() self.tree.select_first() def save(self, string=None): """Save the instruction sheet""" if string is None: lines = [item.value() for item in self.tree.items()] # sequencer instructions string = '\n'.join(lines) + '\n' try: core.write(self.filename, string) status = 0 except (OSError, ValueError) as exc: msg, details = utils.format_exception(exc) sys.stderr.write(msg + '\n\n' + details) status = 128 return status class RebaseTreeWidget(standard.DraggableTreeWidget): commits_selected = Signal(object) external_diff = Signal() move_rows = Signal(object, object) def __init__(self, context, comment_char, parent): super().__init__(parent=parent) self.context = context self.comment_char = comment_char # header self.setHeaderLabels([ N_('#'), N_('Enabled'), N_('Command'), N_('SHA-1'), N_('Remarks'), N_('Summary'), ]) self.header().setStretchLastSection(True) self.setColumnCount(6) self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) # actions self.copy_oid_action = qtutils.add_action( self, N_('Copy SHA-1'), self.copy_oid, QtGui.QKeySequence.Copy ) self.external_diff_action = qtutils.add_action( self, N_('Launch Diff Tool'), self.external_diff.emit, hotkeys.DIFF ) self.toggle_enabled_action = qtutils.add_action( self, N_('Toggle Enabled'), self.toggle_enabled, hotkeys.PRIMARY_ACTION ) self.action_pick = qtutils.add_action( self, N_('Pick'), lambda: self.set_selected_to(PICK), *hotkeys.REBASE_PICK ) self.action_reword = qtutils.add_action( self, N_('Reword'), lambda: self.set_selected_to(REWORD), *hotkeys.REBASE_REWORD, ) self.action_edit = qtutils.add_action( self, N_('Edit'), lambda: self.set_selected_to(EDIT), *hotkeys.REBASE_EDIT ) self.action_fixup = qtutils.add_action( self, N_('Fixup'), lambda: self.set_selected_to(FIXUP), *hotkeys.REBASE_FIXUP, ) self.action_squash = qtutils.add_action( self, N_('Squash'), lambda: self.set_selected_to(SQUASH), *hotkeys.REBASE_SQUASH, ) self.action_shift_down = qtutils.add_action( self, N_('Shift Down'), self.shift_down, hotkeys.MOVE_DOWN_TERTIARY ) self.action_shift_up = qtutils.add_action( self, N_('Shift Up'), self.shift_up, hotkeys.MOVE_UP_TERTIARY ) self.toggle_remark_actions = tuple( qtutils.add_action( self, r, lambda remark=r: self.toggle_remark(remark), hotkeys.hotkey(Qt.CTRL | getattr(Qt, 'Key_' + r)), ) for r in map(str, range(10)) ) self.itemChanged.connect(self.item_changed) self.itemSelectionChanged.connect(self.selection_changed) self.move_rows.connect(self.move) self.items_moved.connect(self.decorate) def add_item( self, idx, enabled, command, oid='', summary='', cmdexec='', branch='' ): comment_char = self.comment_char item = RebaseTreeWidgetItem( idx, enabled, command, oid=oid, summary=summary, cmdexec=cmdexec, branch=branch, comment_char=comment_char, parent=self, ) self.invisibleRootItem().addChild(item) def decorate(self, items): for item in items: item.decorate(self) def refit(self): """Resize columns to fit content""" for i in range(RebaseTreeWidgetItem.COLUMN_COUNT - 1): self.resizeColumnToContents(i) def item_changed(self, item, column): """Validate item ordering when toggling their enabled state""" if column == item.ENABLED_COLUMN: self.validate() def validate(self): invalid_first_choice = {FIXUP, SQUASH} for item in self.items(): if item.is_enabled() and item.is_commit(): if item.command in invalid_first_choice: item.reset_command(PICK) break def set_selected_to(self, command): for i in self.selected_items(): i.reset_command(command) self.validate() def set_command(self, item, command): item.reset_command(command) self.validate() def copy_oid(self): item = self.selected_item() if item is None: return clipboard = item.oid or item.cmdexec qtutils.set_clipboard(clipboard) def selection_changed(self): item = self.selected_item() if item is None or not item.is_commit(): return context = self.context oid = item.oid params = dag.DAG(oid, 2) repo = dag.RepoReader(context, params) commits = [] for commit in repo.get(): commits.append(commit) if commits: commits = commits[-1:] self.commits_selected.emit(commits) def toggle_enabled(self): """Toggle the enabled state of each selected item""" items = self.selected_items() enable = should_enable(items, lambda item: item.is_enabled()) for item in items: if enable: needs_update = not item.is_enabled() else: needs_update = item.is_enabled() if needs_update: item.set_enabled(enable) 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): sel_items = self.selected_items() all_items = self.items() sel_idx = sorted([all_items.index(item) for item in sel_items]) if not sel_idx: return idx = sel_idx[0] + 1 if not ( idx > len(all_items) - len(sel_items) or all_items[sel_idx[-1]] is all_items[-1] ): self.move_rows.emit(sel_idx, idx) def shift_up(self): sel_items = self.selected_items() all_items = self.items() sel_idx = sorted([all_items.index(item) for item in sel_items]) if not sel_idx: return idx = sel_idx[0] - 1 if idx >= 0: self.move_rows.emit(sel_idx, idx) def toggle_remark(self, remark): """Toggle remarks for all selected items""" items = self.selected_items() self.toggle_remark_of_items(remark, items) def toggle_remark_of_items(self, remark, items): """Toggle remarks for the selected items""" enable = should_enable(items, lambda item: remark in item.remarks) for item in items: needs_update = enable ^ (remark in item.remarks) if needs_update: if enable: item.add_remark(remark) else: item.remove_remark(remark) def move(self, src_idxs, dst_idx): moved_items = [] src_base = sorted(src_idxs)[0] for idx in reversed(sorted(src_idxs)): item = self.invisibleRootItem().takeChild(idx) moved_items.insert(0, [dst_idx + (idx - src_base), item]) for item in moved_items: self.invisibleRootItem().insertChild(item[0], item[1]) self.setCurrentItem(item[1]) if moved_items: moved_items = [item[1] for item in moved_items] # If we've moved to the top then we need to re-decorate all items. # Otherwise, we can decorate just the new items. if dst_idx == 0: self.decorate(self.items()) else: self.decorate(moved_items) for item in moved_items: item.setSelected(True) self.validate() # Qt events def dropEvent(self, event): super().dropEvent(event) self.validate() def contextMenuEvent(self, event): items = self.selected_items() menu = qtutils.create_menu(N_('Actions'), 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_oid_action) self.copy_oid_action.setDisabled(len(items) > 1) menu.addAction(self.external_diff_action) self.external_diff_action.setDisabled(len(items) > 1) menu.addSeparator() menu_toggle_remark = menu.addMenu(N_('Toggle Remark')) for action in self.toggle_remark_actions: menu_toggle_remark.addAction(action) menu.exec_(self.mapToGlobal(event.pos())) def should_enable(items, predicate): """Calculate whether items should be toggled on or off. If all items are enabled then return False. If all items are disabled then return True. If more items are enabled then return True, otherwise return False. """ count = len(items) enabled = sum(predicate(item) for item in items) disabled = len(items) - enabled enable = count > enabled >= disabled or disabled == count return enable class ComboBox(QtWidgets.QComboBox): validate = Signal() class RebaseTreeWidgetItem(QtWidgets.QTreeWidgetItem): """A single data row in the rebase tree widget""" NUMBER_COLUMN = 0 ENABLED_COLUMN = 1 COMMAND_COLUMN = 2 COMMIT_COLUMN = 3 REMARKS_COLUMN = 4 SUMMARY_COLUMN = 5 COLUMN_COUNT = 6 OID_LENGTH = 7 COLORS = { '0': ('white', 'darkred'), '1': ('black', 'salmon'), '2': ('black', 'sandybrown'), '3': ('black', 'yellow'), '4': ('black', 'yellowgreen'), '5': ('white', 'forestgreen'), '6': ('white', 'dodgerblue'), '7': ('white', 'royalblue'), '8': ('white', 'slateblue'), '9': ('black', 'rosybrown'), } def __init__( self, idx, enabled, command, oid='', summary='', cmdexec='', branch='', comment_char='#', remarks=(), parent=None, ): QtWidgets.QTreeWidgetItem.__init__(self, parent) self.combo = None self.command = command self.idx = idx self.oid = oid self.summary = summary self.cmdexec = cmdexec self.branch = branch self.comment_char = comment_char self.remarks = remarks self.remarks_label = None self._parent = parent # if core.abbrev is set to a higher value then we will notice by # simply tracking the longest oid we've seen oid_len = self.OID_LENGTH self.__class__.OID_LENGTH = max(len(oid), oid_len) self.setText(self.NUMBER_COLUMN, '%02d' % idx) self.set_enabled(enabled) # checkbox on 1 # combo box on 2 if self.is_exec(): self.setText(self.COMMIT_COLUMN, '') self.setText(self.SUMMARY_COLUMN, cmdexec) elif self.is_update_ref(): self.setText(self.COMMIT_COLUMN, '') self.setText(self.SUMMARY_COLUMN, branch) else: self.setText(self.COMMIT_COLUMN, oid) self.setText(self.SUMMARY_COLUMN, summary) self.set_remarks(remarks) flags = self.flags() | Qt.ItemIsUserCheckable flags = flags | Qt.ItemIsDragEnabled flags = flags & ~Qt.ItemIsDropEnabled self.setFlags(flags) def __eq__(self, other): return self is other def __hash__(self): return self.oid def copy(self): return self.__class__( self.idx, self.is_enabled(), self.command, oid=self.oid, summary=self.summary, cmdexec=self.cmdexec, branch=self.branch, comment_char=self.comment_char, remarks=self.remarks, ) def decorate(self, parent): if self.is_exec(): items = [EXEC] idx = 0 elif self.is_update_ref(): items = [UPDATE_REF] idx = 0 else: items = COMMANDS idx = COMMAND_IDX[self.command] combo = self.combo = ComboBox() combo.setEditable(False) combo.addItems(items) combo.setCurrentIndex(idx) combo.setEnabled(self.is_commit()) signal = combo.currentIndexChanged signal.connect(lambda x: self.set_command_and_validate(combo)) combo.validate.connect(parent.validate) parent.setItemWidget(self, self.COMMAND_COLUMN, combo) self.remarks_label = remarks_label = QtWidgets.QLabel() parent.setItemWidget(self, self.REMARKS_COLUMN, remarks_label) self.update_remarks() def is_exec(self): return self.command == EXEC def is_update_ref(self): return self.command == UPDATE_REF def is_commit(self): return bool( not (self.is_exec() or self.is_update_ref()) and self.oid and self.summary ) def value(self): """Return the serialized representation of an item""" if self.is_enabled(): comment = '' else: comment = self.comment_char + ' ' if self.is_exec(): return f'{comment}{self.command} {self.cmdexec}' if self.is_update_ref(): return f'{comment}{self.command} {self.branch}' return f'{comment}{self.command} {self.oid} {self.summary}' def is_enabled(self): """Is the item enabled?""" return self.checkState(self.ENABLED_COLUMN) == Qt.Checked def set_enabled(self, enabled): """Enable the item by checking its enabled checkbox""" self.setCheckState(self.ENABLED_COLUMN, enabled and Qt.Checked or Qt.Unchecked) def toggle_enabled(self): """Toggle the enabled state of the item""" self.set_enabled(not self.is_enabled()) def add_remark(self, remark): """Add a remark to the item""" self.set_remarks(tuple(sorted(set(self.remarks + (remark,))))) def remove_remark(self, remark): """Remove a remark from the item""" self.set_remarks(tuple(r for r in self.remarks if r != remark)) def set_remarks(self, remarks): """Set the remarks and update the remark display""" if remarks == self.remarks: return self.remarks = remarks self.update_remarks() self._parent.resizeColumnToContents(self.REMARKS_COLUMN) def update_remarks(self): """Update the remarks label display to match the current remarks""" label = self.remarks_label if label is None: return label_text = '' for remark in self.remarks: fg_color, bg_color = self.COLORS[remark] label_text += f"""  {remark} """ label.setText(label_text) def set_command(self, command): """Set the item to a different command, no-op for exec items""" if self.is_exec(): return self.command = command def refresh(self): """Update the view to match the updated state""" if self.is_commit(): command = self.command self.combo.setCurrentIndex(COMMAND_IDX[command]) def reset_command(self, command): """Set and refresh the item in one shot""" self.set_command(command) self.refresh() def set_command_and_validate(self, combo): """Set the command and validate the command order""" command = COMMANDS[combo.currentIndex()] self.set_command(command) self.combo.validate.emit() def show_help(context): 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 exec = run command (the rest of the line) using shell update-ref = update branches that point to commits 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 difftool """ ) title = N_('Help - git-cola-sequence-editor') return text.text_dialog(context, help_text, title) git-cola-4.6.1/cola/settings.py000066400000000000000000000312601457126473700163730ustar00rootroot00000000000000"""Save settings, bookmarks, etc.""" import json import os import sys from . import core from . import display from . import git from . import resources def mkdict(obj): """Transform None and non-dicts into dicts""" if isinstance(obj, dict): value = obj else: value = {} return value def mklist(obj): """Transform None and non-lists into lists""" if isinstance(obj, list): value = obj elif isinstance(obj, tuple): value = list(obj) else: value = [] return value def read_json(path): try: with core.open_read(path) as f: return mkdict(json.load(f)) except (ValueError, TypeError, OSError): # bad path or json return {} def write_json(values, path): """Write the specified values dict to a JSON file at the specified path""" try: parent = os.path.dirname(path) if not core.isdir(parent): core.makedirs(parent) with core.open_write(path) as fp: json.dump(values, fp, indent=4) except (ValueError, TypeError, OSError): sys.stderr.write('git-cola: error writing "%s"\n' % path) return False return True def rename_path(old, new): """Rename a filename. Catch exceptions and return False on error.""" try: core.rename(old, new) except OSError: sys.stderr.write(f'git-cola: error renaming "{old}" to "{new}"\n') return False return True def remove_path(path): """Remove a filename. Report errors to stderr.""" try: core.remove(path) except OSError: sys.stderr.write('git-cola: error removing "%s"\n' % path) class Settings: config_path = 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'])) copy_formats = property(lambda self: mklist(self.values['copy_formats'])) def __init__(self, verify=git.is_git_worktree): """Load existing settings if they exist""" self.values = { 'bookmarks': [], 'gui_state': {}, 'recent': [], 'copy_formats': [], } self.verify = verify def remove_missing_bookmarks(self): """Remove "favorites" bookmarks that no longer exist""" missing_bookmarks = [] for bookmark in self.bookmarks: if not self.verify(bookmark['path']): missing_bookmarks.append(bookmark) for bookmark in missing_bookmarks: try: self.bookmarks.remove(bookmark) except ValueError: pass def remove_missing_recent(self): """Remove "recent" repositories that no longer exist""" missing_recent = [] for recent in self.recent: if not self.verify(recent['path']): missing_recent.append(recent) for recent in missing_recent: try: self.recent.remove(recent) except ValueError: pass def add_bookmark(self, path, name): """Adds a bookmark to the saved settings""" bookmark = {'path': display.normalize_path(path), 'name': name} if bookmark not in self.bookmarks: self.bookmarks.append(bookmark) def remove_bookmark(self, path, name): """Remove a bookmark""" bookmark = {'path': display.normalize_path(path), 'name': name} try: self.bookmarks.remove(bookmark) except ValueError: pass def rename_bookmark(self, path, name, new_name): return rename_entry(self.bookmarks, path, name, new_name) def add_recent(self, path, max_recent): normalize = display.normalize_path path = normalize(path) try: index = [normalize(recent['path']) for recent in self.recent].index(path) entry = self.recent.pop(index) except (IndexError, ValueError): entry = { 'name': os.path.basename(path), 'path': path, } self.recent.insert(0, entry) if len(self.recent) > max_recent: self.recent.pop() def remove_recent(self, path): """Removes an item from the recent items list""" normalize = display.normalize_path path = normalize(path) try: index = [normalize(recent.get('path', '')) for recent in self.recent].index( path ) except ValueError: return try: self.recent.pop(index) except IndexError: return def rename_recent(self, path, name, new_name): return rename_entry(self.recent, path, name, new_name) def path(self): return self.config_path def save(self): """Write settings robustly to avoid losing data during a forced shutdown. To save robustly we take these steps: * Write the new settings to a .tmp file. * Rename the current settings to a .bak file. * Rename the new settings from .tmp to the settings file. * Flush the data to disk * Delete the .bak file. Cf. https://github.com/git-cola/git-cola/issues/1241 """ path = self.path() path_tmp = path + '.tmp' path_bak = path + '.bak' # Write the new settings to the .tmp file. if not write_json(self.values, path_tmp): return # Rename the current settings to a .bak file. if core.exists(path) and not rename_path(path, path_bak): return # Rename the new settings from .tmp to the settings file. if not rename_path(path_tmp, path): return # Flush the data to disk. core.sync() # Delete the .bak file. if core.exists(path_bak): remove_path(path_bak) def load(self, path=None): """Load settings robustly. Attempt to load settings from the .bak file if it exists since it indicates that the program terminated before the data was flushed to disk. This can happen when a machine is force-shutdown, for example. This follows the strategy outlined in issue #1241. If the .bak file exists we use it, otherwise we fallback to the actual path or the .tmp path as a final last-ditch attempt to recover settings. """ path = self.path() path_bak = path + '.bak' path_tmp = path + '.tmp' if core.exists(path_bak): self.values.update(self.asdict(path=path_bak)) elif core.exists(path): self.values.update(self.asdict(path=path)) elif core.exists(path_tmp): # This is potentially dangerous, but it's guarded by the fact that the # file must be valid JSON in order otherwise the reader will return an # empty string, thus making this a no-op. self.values.update(self.asdict(path=path_tmp)) else: # This is either a new installation or the settings were lost. pass # We could try to remove the .bak and .tmp files, but it's better to set save() # handle that the next time it succeeds. self.upgrade_settings() return True @staticmethod def read(verify=git.is_git_worktree): """Load settings from disk""" settings = Settings(verify=verify) settings.load() return settings def upgrade_settings(self): """Upgrade git-cola settings""" # Upgrade bookmarks to the new dict-based bookmarks format. normalize = display.normalize_path if self.bookmarks and not isinstance(self.bookmarks[0], dict): bookmarks = [ {'name': os.path.basename(path), 'path': normalize(path)} for path in self.bookmarks ] self.values['bookmarks'] = bookmarks if self.recent and not isinstance(self.recent[0], dict): recent = [ {'name': os.path.basename(path), 'path': normalize(path)} for path in self.recent ] self.values['recent'] = recent def asdict(self, path=None): if not path: path = self.path() if core.exists(path): return read_json(path) # We couldn't find ~/.config/git-cola, try ~/.cola values = {} path = os.path.join(core.expanduser('~'), '.cola') if core.exists(path): json_values = read_json(path) for key in self.values: try: values[key] = json_values[key] except KeyError: pass # Ensure that all stored bookmarks use normalized paths ("/" only). normalize = display.normalize_path for entry in values.get('bookmarks', []): entry['path'] = normalize(entry['path']) for entry in values.get('recent', []): entry['path'] = normalize(entry['path']) 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 saved state for a gui""" return self.get_gui_state_by_name(gui.name()) def get_gui_state_by_name(self, gui_name): """Returns the saved state for a gui by name""" try: state = mkdict(self.gui_state[gui_name]) except KeyError: state = self.gui_state[gui_name] = {} return state def rename_entry(entries, path, name, new_name): normalize = display.normalize_path path = normalize(path) entry = {'name': name, 'path': path} try: index = entries.index(entry) except ValueError: return False if all(item['name'] != new_name for item in entries): entries[index]['name'] = new_name result = True else: result = False return result class Session(Settings): """Store per-session settings XDG sessions are created by the QApplication::commitData() callback. These sessions are stored once, and loaded once. They are deleted once loaded. The behavior of path() is such that it forgets its session path() and behaves like a return Settings object after the session has been loaded once. Once the session is loaded, it is removed and further calls to save() will save to the usual $XDG_CONFIG_HOME/git-cola/settings location. """ _sessions_dir = resources.config_home('sessions') repo = property(lambda self: self.values['local']) def __init__(self, session_id, repo=None): Settings.__init__(self) self.session_id = session_id self.values.update({'local': repo}) self.expired = False def session_path(self): """The session-specific session file""" return os.path.join(self._sessions_dir, self.session_id) def path(self): base_path = super().path() if self.expired: path = base_path else: path = self.session_path() if not os.path.exists(path): path = base_path return path def load(self, path=None): """Load the session and expire it for future loads The session should be loaded only once. We remove the session file when it's loaded, and set the session to be expired. This results in future calls to load() and save() using the default Settings path rather than the session-specific path. The use case for sessions is when the user logs out with apps running. We will restore their state, and if they then shutdown, it'll be just like a normal shutdown and settings will be stored to ~/.config/git-cola/settings instead of the session path. This is accomplished by "expiring" the session after it has been loaded initially. """ result = super().load(path=path) # This is the initial load, so expire the session and remove the # session state file. Future calls will be equivalent to # Settings.load(). if not self.expired: self.expired = True path = self.session_path() if core.exists(path): try: os.unlink(path) except (OSError, ValueError): pass return True return False return result def update(self): """Reload settings from the base settings path""" # This method does not expire the session. path = super().path() return super().load(path=path) git-cola-4.6.1/cola/spellcheck.py000066400000000000000000000060721457126473700166530ustar00rootroot00000000000000import codecs import collections import os from . import resources __copyright__ = """ 2012 Peter Norvig (http://norvig.com/spell-correct.html) 2013-2018 David Aguilar """ 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 {e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in words} def known(word, words): return {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: def __init__( self, words='dict/words', propernames='dict/propernames', ): data_dirs = resources.xdg_data_dirs() self.dictwords = resources.find_first(words, data_dirs) self.propernames = resources.find_first(propernames, data_dirs) self.words = collections.defaultdict(lambda: 1) self.extra_words = set() self.dictionary = None self.initialized = False def set_dictionary(self, dictionary): self.dictionary = dictionary 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): """Read dictionary words""" paths = [] words = self.dictwords propernames = self.propernames cfg_dictionary = self.dictionary if words and os.path.exists(words): paths.append((words, True)) if propernames and os.path.exists(propernames): paths.append((propernames, False)) if cfg_dictionary and os.path.exists(cfg_dictionary): paths.append((cfg_dictionary, False)) for path, title in paths: try: with codecs.open( path, 'r', encoding='utf-8', errors='ignore' ) as words_file: for line in words_file: word = line.rstrip() yield word if title: yield word.title() except OSError: pass git-cola-4.6.1/cola/textwrap.py000066400000000000000000000217741457126473700164220ustar00rootroot00000000000000"""Text wrapping and filling""" import re from .compat import ustr # Copyright (C) 1999-2001 Gregory P. Ward. # Copyright (C) 2002, 2003 Python Software Foundation. # Copyright (C) 2013-2024 David Aguilar # Written by Greg Ward # Simplified for git-cola by David Aguilar class TextWrapper: """ 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: false) Allow breaking hyphenated words. If true, wrapping will occur preferably on whitespace and right after the hyphenated 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=False, 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, ustr): 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 = list(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; i.e. 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 = list(reversed(chunks)) 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 (i.e. no lines started yet). if self.drop_whitespace and is_blank(chunks[-1]) and lines: chunks.pop() linebreak = False while chunks: length = self.chunklen(chunks[-1]) # Can at least squeeze this chunk onto the current line. if cur_len + length <= width: cur_line.append(chunks.pop()) cur_len += length # Nope, this line is full. else: linebreak = True 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()) # Avoid whitespace at the beginning of split lines if ( linebreak and self.drop_whitespace and cur_line and is_blank(cur_line[0]) ): cur_line.pop(0) # If the last chunk on this line is all a space, drop it. if self.drop_whitespace and cur_line and is_blank(cur_line[-1]): cur_line.pop() # 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, break_on_hyphens=False): """Wrap long lines to the specified limit""" lines = [] # Acked-by:, Signed-off-by:, Helped-by:, etc. special_tag_rgx = re.compile( r'^(' r'((' r'Acked-by|' r"Ack'd-by|" r'Based-on-patch-by|' r'Cheered-on-by|' r'Co-authored-by|' r'Comments-by|' r'Confirmed-by|' r'Contributions-by|' r'Debugged-by|' r'Discovered-by|' r'Explained-by|' r'Backtraced-by|' r'Helped-by|' r'Liked-by|' r'Link|' r'Improved-by|' r'Inspired-by|' r'Initial-patch-by|' r'Noticed-by|' r'Original-patch-by|' r'Originally-by|' r'Mentored-by|' r'Patch-by|' r'Proposed-by|' r'References|' r'Related-to|' r'Reported-by|' r'Requested-by|' r'Reviewed-by|' r'See-also|' r'Signed-off-by|' r'Signed-Off-by|' r'Spotted-by|' r'Suggested-by|' r'Tested-by|' r'Tested-on-([a-zA-Z-_]+)-by|' r'With-suggestions-by' r'):)' r'|([Cc]\.\s*[Ff]\.\s+)' r')' ) wrapper = TextWrapper( width=limit, tabwidth=tabwidth, break_on_hyphens=break_on_hyphens, drop_whitespace=True, ) for line in text.split('\n'): if special_tag_rgx.match(line): lines.append(line) else: lines.append(wrapper.fill(line)) return '\n'.join(lines) def is_blank(string): return string and not string.strip(' ') git-cola-4.6.1/cola/themes.py000066400000000000000000000617551457126473700160340ustar00rootroot00000000000000"""Themes generators""" import os try: import AppKit except ImportError: AppKit = None from qtpy import QtGui from .i18n import N_ from .widgets import defs from . import core from . import icons from . import qtutils from . import resources from . import utils class EStylesheet: DEFAULT = 1 FLAT = 2 CUSTOM = 3 # Files located in ~/.config/git-cola/themes/*.qss class Theme: def __init__( self, name, title, is_dark, style_sheet=EStylesheet.DEFAULT, main_color=None, macos_appearance=None, ): self.name = name self.title = title self.is_dark = is_dark self.is_palette_dark = None self.style_sheet = style_sheet self.main_color = main_color self.macos_appearance = macos_appearance self.disabled_text_color = None self.text_color = None self.highlight_color = None self.background_color = None self.palette = None def build_style_sheet(self, app_palette): if self.style_sheet == EStylesheet.CUSTOM: return self.style_sheet_custom(app_palette) if self.style_sheet == EStylesheet.FLAT: return self.style_sheet_flat() window = app_palette.color(QtGui.QPalette.Window) self.is_palette_dark = window.lightnessF() < 0.5 return style_sheet_default(app_palette) def build_palette(self, app_palette): QPalette = QtGui.QPalette palette_dark = app_palette.color(QPalette.Base).lightnessF() < 0.5 if self.is_palette_dark is None: self.is_palette_dark = palette_dark if palette_dark and self.is_dark: self.palette = app_palette return app_palette if not palette_dark and not self.is_dark: self.palette = app_palette return app_palette if self.is_dark: background = '#202025' else: background = '#edeef3' bg_color = qtutils.css_color(background) txt_color = qtutils.css_color('#777777') palette = QPalette(bg_color) palette.setColor(QPalette.Base, bg_color) palette.setColor(QPalette.Disabled, QPalette.Text, txt_color) self.background_color = background self.palette = palette return palette def style_sheet_flat(self): main_color = self.main_color color = qtutils.css_color(main_color) color_rgb = qtutils.rgb_css(color) self.is_palette_dark = self.is_dark if self.is_dark: background = '#2e2f30' field = '#383a3c' grayed = '#06080a' button_text = '#000000' field_text = '#d0d0d0' darker = qtutils.hsl_css( color.hslHueF(), color.hslSaturationF() * 0.3, color.lightnessF() * 1.3 ) lighter = qtutils.hsl_css( color.hslHueF(), color.hslSaturationF() * 0.7, color.lightnessF() * 0.6 ) focus = qtutils.hsl_css( color.hslHueF(), color.hslSaturationF() * 0.7, color.lightnessF() * 0.7 ) else: background = '#edeef3' field = '#ffffff' grayed = '#a2a2b0' button_text = '#ffffff' field_text = '#000000' darker = qtutils.hsl_css( color.hslHueF(), color.hslSaturationF(), color.lightnessF() * 0.4 ) lighter = qtutils.hsl_css(color.hslHueF(), color.hslSaturationF(), 0.92) focus = color_rgb self.disabled_text_color = grayed self.text_color = field_text self.highlight_color = lighter self.background_color = background return """ /* regular widgets */ * {{ background-color: {background}; color: {field_text}; selection-background-color: {lighter}; alternate-background-color: {field}; selection-color: {field_text}; show-decoration-selected: 1; spacing: 2px; }} /* Focused widths get a thin border */ QTreeView:focus, QListView:focus, QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus {{ border-width: 1px; border-style: solid; border-color: {focus}; }} QWidget:disabled {{ border-color: {grayed}; color: {grayed}; }} QDockWidget > QFrame {{ margin: 0px 0px 0px 0px; }} QPlainTextEdit, QLineEdit, QTextEdit, QAbstractItemView, QAbstractSpinBox {{ background-color: {field}; border-color: {grayed}; border-style: solid; border-width: 1px; }} QAbstractItemView::item:selected {{ background-color: {lighter}; }} QAbstractItemView::item:hover {{ background-color: {lighter}; }} QLabel {{ color: {darker}; background-color: transparent; }} DockTitleBarWidget {{ padding-bottom: 4px; }} /* buttons */ QPushButton[flat="false"] {{ background-color: {button}; color: {button_text}; border-radius: 2px; border-width: 0; margin-bottom: 1px; min-width: 55px; padding: 4px 5px; }} QPushButton[flat="true"], QToolButton {{ background-color: transparent; border-radius: 0px; }} QPushButton[flat="true"] {{ margin-bottom: 10px; }} QPushButton:hover, QToolButton:hover {{ background-color: {darker}; }} QPushButton[flat="false"]:pressed, QToolButton:pressed {{ background-color: {darker}; margin: 1px 1px 2px 1px; }} QPushButton:disabled {{ background-color: {grayed}; color: {field}; padding-left: 5px; padding-top: 5px; }} QPushButton[flat="true"]:disabled {{ background-color: transparent; }} /*menus*/ QMenuBar {{ background-color: {background}; color: {field_text}; border-width: 0; padding: 1px; }} QMenuBar::item {{ background: transparent; }} QMenuBar::item:selected {{ background: {button}; }} QMenuBar::item:pressed {{ background: {button}; }} QMenu {{ background-color: {field}; }} QMenu::separator {{ background: {background}; height: 1px; }} /* combo box */ QComboBox {{ background-color: {field}; border-color: {grayed}; border-style: solid; color: {field_text}; border-radius: 0px; border-width: 1px; margin-bottom: 1px; padding: 0 5px; }} QComboBox::drop-down {{ border-color: {field_text} {field} {field} {field}; border-style: solid; subcontrol-position: right; border-width: 4px 3px 0 3px; height: 0; margin-right: 5px; width: 0; }} QComboBox::drop-down:hover {{ border-color: {button} {field} {field} {field}; }} QComboBox:item {{ background-color: {button}; color: {button_text}; border-width: 0; height: 22px; }} QComboBox:item:selected {{ background-color: {darker}; color: {button_text}; }} QComboBox:item:checked {{ background-color: {darker}; color: {button_text}; }} /* MainWindow separator */ QMainWindow::separator {{ width: {separator}px; height: {separator}px; }} QMainWindow::separator:hover {{ background: {focus}; }} /* scroll bar */ QScrollBar {{ background-color: {field}; border: 0; }} QScrollBar::handle {{ background: {background} }} QScrollBar::handle:hover {{ background: {button} }} QScrollBar:horizontal {{ margin: 0 11px 0 11px; height: 10px; }} QScrollBar:vertical {{ margin: 11px 0 11px 0; width: 10px; }} QScrollBar::add-line, QScrollBar::sub-line {{ background: {background}; subcontrol-origin: margin; }} QScrollBar::sub-line:horizontal {{ /*required by a buggy Qt version*/ subcontrol-position: left; }} QScrollBar::add-line:hover, QScrollBar::sub-line:hover {{ background: {button}; }} QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {{ width: 10px; }} QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {{ height: 10px; }} QScrollBar:left-arrow, QScrollBar::right-arrow, QScrollBar::up-arrow, QScrollBar::down-arrow {{ border-style: solid; height: 0; width: 0; }} QScrollBar:right-arrow {{ border-color: {background} {background} {background} {darker}; border-width: 3px 0 3px 4px; }} QScrollBar:left-arrow {{ border-color: {background} {darker} {background} {background}; border-width: 3px 4px 3px 0; }} QScrollBar:up-arrow {{ border-color: {background} {background} {darker} {background}; border-width: 0 3px 4px 3px; }} QScrollBar:down-arrow {{ border-color: {darker} {background} {background} {background}; border-width: 4px 3px 0 3px; }} QScrollBar:right-arrow:hover {{ border-color: {button} {button} {button} {darker}; }} QScrollBar:left-arrow:hover {{ border-color: {button} {darker} {button} {button}; }} QScrollBar:up-arrow:hover {{ border-color: {button} {button} {darker} {button}; }} QScrollBar:down-arrow:hover {{ border-color: {darker} {button} {button} {button}; }} /* tab bar (stacked & docked widgets) */ QTabBar::tab {{ background: transparent; border-color: {darker}; border-width: 1px; margin: 1px; padding: 3px 5px; }} QTabBar::tab:selected {{ background: {grayed}; }} /* check box */ QCheckBox {{ spacing: 8px; margin: 4px; background-color: transparent; }} QCheckBox::indicator {{ background-color: {field}; border-color: {darker}; border-style: solid; subcontrol-position: left; border-width: 1px; height: 13px; width: 13px; }} QCheckBox::indicator:unchecked:hover {{ background-color: {button}; }} QCheckBox::indicator:unchecked:pressed {{ background-color: {darker}; }} QCheckBox::indicator:checked {{ background-color: {darker}; }} QCheckBox::indicator:checked:hover {{ background-color: {button}; }} QCheckBox::indicator:checked:pressed {{ background-color: {field}; }} /* radio checkbox */ QRadioButton {{ spacing: 8px; margin: 4px; }} QRadioButton::indicator {{ height: 0.75em; width: 0.75em; }} /* progress bar */ QProgressBar {{ background-color: {field}; border: 1px solid {darker}; }} QProgressBar::chunk {{ background-color: {button}; width: 1px; }} /* spin box */ QAbstractSpinBox::up-button, QAbstractSpinBox::down-button {{ background-color: transparent; }} QAbstractSpinBox::up-arrow, QAbstractSpinBox::down-arrow {{ border-style: solid; height: 0; width: 0; }} QAbstractSpinBox::up-arrow {{ border-color: {field} {field} {darker} {field}; border-width: 0 3px 4px 3px; }} QAbstractSpinBox::up-arrow:hover {{ border-color: {field} {field} {button} {field}; border-width: 0 3px 4px 3px; }} QAbstractSpinBox::down-arrow {{ border-color: {darker} {field} {field} {field}; border-width: 4px 3px 0 3px; }} QAbstractSpinBox::down-arrow:hover {{ border-color: {button} {field} {field} {field}; border-width: 4px 3px 0 3px; }} /* dialogs */ QDialog > QFrame {{ margin: 2px 2px 2px 2px; }} /* headers */ QHeaderView {{ color: {field_text}; border-style: solid; border-width: 0 0 1px 0; border-color: {grayed}; }} QHeaderView::section {{ border-style: solid; border-right: 1px solid {grayed}; background-color: {background}; color: {field_text}; padding-left: 4px; }} /* headers */ QHeaderView {{ color: {field_text}; border-style: solid; border-width: 0 0 1px 0; border-color: {grayed}; }} QHeaderView::section {{ border-style: solid; border-right: 1px solid {grayed}; background-color: {background}; color: {field_text}; padding-left: 4px; }} """.format( background=background, field=field, button=color_rgb, darker=darker, lighter=lighter, grayed=grayed, button_text=button_text, field_text=field_text, separator=defs.separator, focus=focus, ) def style_sheet_custom(self, app_palette): """Get custom style sheet. File name is saved in variable self.name. If user has deleted file, use default style""" # check if path exists filename = resources.config_home('themes', self.name + '.qss') if not core.exists(filename): return style_sheet_default(app_palette) try: return core.read(filename) except OSError as err: core.print_stderr(f'warning: unable to read custom theme {filename}: {err}') return style_sheet_default(app_palette) def get_palette(self): """Get a QPalette for the current theme""" if self.palette is None: palette = qtutils.current_palette() else: palette = self.palette return palette def highlight_color_rgb(self): """Return an rgb(r,g,b) CSS color value for the selection highlight""" if self.highlight_color: highlight_rgb = self.highlight_color elif self.main_color: highlight_rgb = qtutils.rgb_css( qtutils.css_color(self.main_color).lighter() ) else: palette = self.get_palette() color = palette.color(QtGui.QPalette.Highlight) highlight_rgb = qtutils.rgb_css(color) return highlight_rgb def selection_color(self): """Return a color suitable for selections""" highlight = qtutils.css_color(self.highlight_color_rgb()) if highlight.lightnessF() > 0.7: # Avoid clamping light colors to white. color = highlight else: color = highlight.lighter() return color def text_colors_rgb(self): """Return a pair of rgb(r,g,b) CSS color values for text and selected text""" if self.text_color: text_rgb = self.text_color highlight_text_rgb = self.text_color else: palette = self.get_palette() color = palette.text().color() text_rgb = qtutils.rgb_css(color) color = palette.highlightedText().color() highlight_text_rgb = qtutils.rgb_css(color) return text_rgb, highlight_text_rgb def disabled_text_color_rgb(self): """Return an rgb(r,g,b) CSS color value for the disabled text""" if self.disabled_text_color: disabled_text_rgb = self.disabled_text_color else: palette = self.get_palette() color = palette.color(QtGui.QPalette.Disabled, QtGui.QPalette.Text) disabled_text_rgb = qtutils.rgb_css(color) return disabled_text_rgb def background_color_rgb(self): """Return an rgb(r,g,b) CSS color value for the window background""" if self.background_color: background_color = self.background_color else: palette = self.get_palette() window = palette.color(QtGui.QPalette.Base) background_color = qtutils.rgb_css(window) return background_color def style_sheet_default(palette): highlight = palette.color(QtGui.QPalette.Highlight) shadow = palette.color(QtGui.QPalette.Shadow) base = palette.color(QtGui.QPalette.Base) highlight_rgb = qtutils.rgb_css(highlight) shadow_rgb = qtutils.rgb_css(shadow) base_rgb = qtutils.rgb_css(base) return """ QCheckBox::indicator {{ width: {checkbox_size}px; height: {checkbox_size}px; }} QCheckBox::indicator::unchecked {{ border: {checkbox_border}px solid {shadow_rgb}; background: {base_rgb}; }} QCheckBox::indicator::checked {{ image: url({checkbox_icon}); border: {checkbox_border}px solid {shadow_rgb}; background: {base_rgb}; }} QRadioButton::indicator {{ width: {radio_size}px; height: {radio_size}px; }} QRadioButton::indicator::unchecked {{ border: {radio_border}px solid {shadow_rgb}; border-radius: {radio_radius}px; background: {base_rgb}; }} QRadioButton::indicator::checked {{ image: url({radio_icon}); border: {radio_border}px solid {shadow_rgb}; border-radius: {radio_radius}px; background: {base_rgb}; }} QSplitter::handle:hover {{ background: {highlight_rgb}; }} QMainWindow::separator {{ background: none; width: {separator}px; height: {separator}px; }} QMainWindow::separator:hover {{ background: {highlight_rgb}; }} """.format( separator=defs.separator, highlight_rgb=highlight_rgb, shadow_rgb=shadow_rgb, base_rgb=base_rgb, checkbox_border=defs.border, checkbox_icon=icons.check_name(), checkbox_size=defs.checkbox, radio_border=defs.radio_border, radio_icon=icons.dot_name(), radio_radius=defs.radio // 2, radio_size=defs.radio, ) def get_all_themes(): themes = [ Theme( 'default', N_('Default'), False, style_sheet=EStylesheet.DEFAULT, main_color=None, ), ] if utils.is_darwin(): themes.extend(get_macos_themes().values()) themes.extend([ Theme( 'flat-light-blue', N_('Flat light blue'), False, style_sheet=EStylesheet.FLAT, main_color='#5271cc', ), Theme( 'flat-light-red', N_('Flat light red'), False, style_sheet=EStylesheet.FLAT, main_color='#cc5452', ), Theme( 'flat-light-grey', N_('Flat light grey'), False, style_sheet=EStylesheet.FLAT, main_color='#707478', ), Theme( 'flat-light-green', N_('Flat light green'), False, style_sheet=EStylesheet.FLAT, main_color='#42a65c', ), Theme( 'flat-dark-blue', N_('Flat dark blue'), True, style_sheet=EStylesheet.FLAT, main_color='#5271cc', ), Theme( 'flat-dark-red', N_('Flat dark red'), True, style_sheet=EStylesheet.FLAT, main_color='#cc5452', ), Theme( 'flat-dark-grey', N_('Flat dark grey'), True, style_sheet=EStylesheet.FLAT, main_color='#aaaaaa', ), Theme( 'flat-dark-green', N_('Flat dark green'), True, style_sheet=EStylesheet.FLAT, main_color='#42a65c', ), ]) # check if themes path exists in user folder path = resources.config_home('themes') if not os.path.isdir(path): return themes # Gather Qt .qss stylesheet themes try: filenames = core.listdir(path) except OSError: return themes for filename in filenames: name, ext = os.path.splitext(filename) if ext == '.qss': themes.append(Theme(name, N_(name), False, EStylesheet.CUSTOM, None)) return themes def apply_platform_theme(theme): """Apply platform-specific themes (e.g. dark mode on macOS)""" # https://developer.apple.com/documentation/appkit/nsappearancecustomization/choosing_a_specific_appearance_for_your_macos_app # https://github.com/git-cola/git-cola/issues/905#issuecomment-461118465 if utils.is_darwin(): if AppKit is None: return app = AppKit.NSApplication.sharedApplication() macos_themes = get_macos_themes() try: macos_appearance = macos_themes[theme].macos_appearance except KeyError: return if macos_appearance is None: return appearance = AppKit.NSAppearance.appearanceNamed_(macos_appearance) app.setAppearance_(appearance) def get_macos_themes(): """Get a mapping from theme names to macOS NSAppearanceName values""" themes = {} if AppKit is None: return themes def add_macos_theme(name, description, is_dark, attr): """Add an AppKit theme if it exists""" if hasattr(AppKit, attr): themes[name] = Theme( name, description, is_dark, macos_appearance=getattr(AppKit, attr) ) add_macos_theme( 'macos-aqua-light', N_('MacOS Aqua light'), False, 'NSAppearanceNameAqua' ) add_macos_theme( 'macos-aqua-dark', N_('MacOS Aqua dark'), True, 'NSAppearanceNameDarkAqua', ) add_macos_theme( 'macos-vibrant-light', N_('MacOS Vibrant light'), False, 'NSAppearanceNameVibrantLight', ) add_macos_theme( 'macos-vibrant-dark', N_('MacOS Vibrant dark'), True, 'NSAppearanceNameVibrantDark', ) return themes def options(themes=None): """Return a dictionary mapping display names to theme names""" if themes is None: themes = get_all_themes() return [(theme.title, theme.name) for theme in themes] def find_theme(name): themes = get_all_themes() for item in themes: if item.name == name: return item return themes[0] git-cola-4.6.1/cola/utils.py000066400000000000000000000252561457126473700157030ustar00rootroot00000000000000"""Miscellaneous utility functions""" import copy import os import random import re import shlex import sys import tempfile import time import traceback from . import core from . import compat random.seed(hash(time.time())) def asint(obj, default=0): """Make any value into an int, even if the cast fails""" try: value = int(obj) except (TypeError, ValueError): value = default return value def clamp(value, low, high): """Clamp a value to the specified range""" return min(high, max(low, value)) def epoch_millis(): return int(time.time() * 1000) def add_parents(paths): """Iterate over each item in the set and add its parent directories.""" all_paths = set() for path in paths: while '//' in path: path = path.replace('//', '/') all_paths.add(path) if '/' in path: parent_dir = dirname(path) while parent_dir: all_paths.add(parent_dir) parent_dir = dirname(parent_dir) return all_paths def format_exception(exc): """Format an exception object for display""" exc_type, exc_value, exc_tb = sys.exc_info() details = traceback.format_exception(exc_type, exc_value, exc_tb) details = '\n'.join(map(core.decode, details)) if hasattr(exc, 'msg'): msg = exc.msg else: msg = core.decode(repr(exc)) return (msg, details) def sublist(values, remove): """Subtracts list b from list a and returns the resulting list.""" # conceptually, c = a - b result = [] for item in values: if item not in remove: result.append(item) return result __grep_cache = {} def grep(pattern, items, squash=True): """Greps a list for items that match a pattern :param squash: If only one item matches, return just that item :returns: List of matching items """ isdict = isinstance(items, 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: result = matchdict elif squash and len(matched) == 1: result = matched[0] else: result = matched return result 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""" return path.strip('/').split('/', 1)[-1] def dirname(path, current_dir=''): """ 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 current_dir return path.rsplit('/', 1)[0] def splitpath(path): """Split paths using '/' regardless of platform""" return path.split('/') def split(name): """Split a path-like name. Returns tuple "(head, tail)" where "tail" is everything after the final slash. The "head" may be empty. This is the same as os.path.split() but only uses '/' as the delimiter. >>> split('a/b/c') ('a/b', 'c') >>> split('xyz') ('', 'xyz') """ return (dirname(name), basename(name)) def join(*paths): """Join paths using '/' regardless of platform >>> join('a', 'b', 'c') 'a/b/c' """ return '/'.join(paths) def normalize_slash(value): """Strip and normalize slashes in a string >>> normalize_slash('///Meow///Cat///') 'Meow/Cat' """ value = value.strip('/') new_value = value.replace('//', '/') while new_value != value: value = new_value new_value = value.replace('//', '/') return value def pathjoin(paths): """Join a list of paths using '/' regardless of platform >>> pathjoin(['a', 'b', 'c']) 'a/b/c' """ return join(*paths) def pathset(path): """Return all of the path components for the specified path >>> pathset('foo/bar/baz') == ['foo', 'foo/bar', 'foo/bar/baz'] True """ result = [] parts = splitpath(path) prefix = '' for part in parts: result.append(prefix + part) prefix += part + '/' return result def select_directory(paths): """Return the first directory in a list of paths""" if not paths: return core.getcwd() for path in paths: if core.isdir(path): return path return os.path.dirname(paths[0]) or core.getcwd() 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 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_py2(value): """Python2 requires bytes inputs to shlex.split(). Returns [unicode]""" try: result = shlex.split(core.encode(value)) except ValueError: result = core.encode(value).strip().split() # Decode to Unicode strings return [core.decode(arg) for arg in result] def _shell_split_py3(value): """Python3 requires Unicode inputs to shlex.split(). Convert to Unicode""" try: result = shlex.split(value) except ValueError: result = core.decode(value).strip().split() # Already Unicode return result def shell_split(value): if compat.PY2: # Encode before calling split() values = _shell_split_py2(value) else: # Python3 does not need the encode/decode dance values = _shell_split_py3(value) return values def tmp_filename(label, suffix=''): label = 'git-cola-' + label.replace('/', '-').replace('\\', '-') with tempfile.NamedTemporaryFile( prefix=label + '-', suffix=suffix, delete=False ) as handle: return handle.name def is_linux(): """Is this a Linux machine?""" return sys.platform.startswith('linux') def is_debian(): """Is this a Debian/Linux machine?""" return os.path.exists('/usr/bin/apt-get') def is_darwin(): """Is this a macOS machine?""" return sys.platform == 'darwin' def is_win32(): """Return True on win32""" return sys.platform in {'win32', 'cygwin'} def launch_default_app(paths): """Execute the default application on the specified paths""" if is_win32(): for path in paths: if hasattr(os, 'startfile'): os.startfile(path) return if is_darwin(): launcher = 'open' else: launcher = 'xdg-open' core.fork([launcher] + paths) def expandpath(path): """Expand ~user/ and environment $variables""" path = os.path.expandvars(path) if path.startswith('~'): path = os.path.expanduser(path) return path class Group: """Operate on a collection of objects as a single unit""" def __init__(self, *members): self._members = members def __getattr__(self, name): """Return a function that relays calls to the group""" def relay(*args, **kwargs): for member in self._members: method = getattr(member, name) method(*args, **kwargs) setattr(self, name, relay) return relay class Proxy: """Wrap an object and override attributes""" def __init__(self, obj, **overrides): self._obj = obj for k, v in overrides.items(): setattr(self, k, v) def __getattr__(self, name): return getattr(self._obj, name) def slice_func(input_items, map_func): """Slice input_items and call `map_func` 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. # 4K pages x 32 MAX_ARG_PAGES max_arg_len = (32 * 4096) // 4 # allow plenty of space for the environment max_filename_len = 256 size = max_arg_len // max_filename_len status = 0 outs = [] errs = [] items = copy.copy(input_items) while items: stat, out, err = map_func(items[:size]) if stat < 0: status = min(stat, status) else: status = max(stat, status) outs.append(out) errs.append(err) items = items[size:] return (status, '\n'.join(outs), '\n'.join(errs)) class Sequence: def __init__(self, sequence): self.sequence = sequence def index(self, item, default=-1): try: idx = self.sequence.index(item) except ValueError: idx = default return idx def __getitem__(self, idx): return self.sequence[idx] def catch_runtime_error(func, *args, **kwargs): """Run the function safely. Catch RuntimeError to avoid tracebacks during application shutdown. """ # Signals and callbacks can sometimes get triggered during application shutdown. # This can happen when exiting while background tasks are still processing. # Guard against this by making this operation a no-op. try: valid = True result = func(*args, **kwargs) except RuntimeError: valid = False result = None return (valid, result) git-cola-4.6.1/cola/version.py000066400000000000000000000075301457126473700162230ustar00rootroot00000000000000"""Provide git-cola's version number""" import os import sys from .git import STDOUT from .decorators import memoize from ._version import VERSION try: if sys.version_info < (3, 8): import importlib_metadata as metadata else: from importlib import metadata except (ImportError, OSError): metadata = None if __name__ == '__main__': srcdir = os.path.dirname(os.path.dirname(__file__)) sys.path.insert(1, srcdir) # 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.6', # new: git cat-file --filters --path= SHA1 # old: git cat-file --filters blob SHA1: 'cat-file-filters-path': '2.11.0', # git diff --submodule was introduced in 1.6.6 'diff-submodule': '1.6.6', # git check-ignore was introduced in 1.8.2, but did not follow the same # rules as git add and git status until 1.8.5 'check-ignore': '1.8.5', # git push --force-with-lease 'force-with-lease': '1.8.5', # git submodule update --recursive was introduced in 1.6.5 'submodule-update-recursive': '1.6.5', # git include.path pseudo-variable was introduced in 1.7.10. 'config-includes': '1.7.10', # git config --show-scope was introduced in 2.26.0 'config-show-scope': '2.26.0', # git config --show-origin was introduced in 2.8.0 'config-show-origin': '2.8.0', # git for-each-ref --sort=version:refname 'version-sort': '2.7.0', # Qt support for QT_AUTO_SCREEN_SCALE_FACTOR and QT_SCALE_FACTOR 'qt-hidpi-scale': '5.6.0', # git rev-parse --show-superproject-working-tree was added in 2.13.0 'show-superproject-working-tree': '2.13.0', # git rebase --update-refs was added in 2.38.0 'rebase-update-refs': '2.38.0', } def get(key): """Returns an entry from the known versions table""" return _versions.get(key) def version(): """Returns the current version""" pkg_version = VERSION if metadata is not None: try: pkg_version = metadata.version('git-cola') except (ImportError, OSError): pass return pkg_version def builtin_version(): """Returns the version recorded in cola/_version.py""" 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 check_git(context, key): """Checks if Git has a specific feature""" return check(key, git_version(context)) def version_to_list(value): """Convert a version string to a list of numbers or strings""" ver_list = [] for part in value.split('.'): try: number = int(part) except ValueError: number = part ver_list.append(number) return ver_list @memoize def git_version_str(context): """Returns the current GIT version""" git = context.git return git.version(_readonly=True)[STDOUT].strip() @memoize def git_version(context): """Returns the current GIT version""" parts = git_version_str(context).split() if parts and len(parts) >= 3: result = parts[2] else: # minimum supported version result = '1.6.3' return result def cola_version(): """A version string for consumption by humans""" suffix = version() return 'cola version %s' % suffix def print_version(builtin=False, brief=False): if builtin: msg = builtin_version() elif brief: msg = version() else: msg = cola_version() sys.stdout.write('%s\n' % msg) git-cola-4.6.1/cola/widgets/000077500000000000000000000000001457126473700156255ustar00rootroot00000000000000git-cola-4.6.1/cola/widgets/__init__.py000066400000000000000000000000001457126473700177240ustar00rootroot00000000000000git-cola-4.6.1/cola/widgets/about.py000066400000000000000000000436431457126473700173230ustar00rootroot00000000000000import platform import webbrowser import sys import qtpy from qtpy.QtCore import Qt from qtpy import QtGui from qtpy import QtWidgets from ..i18n import N_ from .. import core from .. import resources from .. import hotkeys from .. import icons from .. import qtutils from .. import version from . import defs def about_dialog(context): """Launches the Help -> About dialog""" view = AboutView(context, qtutils.active_window()) view.show() return view class ExpandingTabBar(QtWidgets.QTabBar): """A TabBar with tabs that expand to fill the empty space The setExpanding(True) method does not work in practice because it respects the OS style. We override the style by implementing tabSizeHint() so that we can specify the size explicitly. """ def tabSizeHint(self, tab_index): width = self.parent().width() // max(2, self.count()) - 1 size = super().tabSizeHint(tab_index) size.setWidth(width) return size class ExpandingTabWidget(QtWidgets.QTabWidget): def __init__(self, parent=None): super().__init__(parent) self.setTabBar(ExpandingTabBar(self)) def resizeEvent(self, event): """Forward resize events to the ExpandingTabBar""" # Qt does not resize the tab bar when the dialog is resized # so manually forward resize events to the tab bar. width = event.size().width() height = self.tabBar().height() self.tabBar().resize(width, height) return super().resizeEvent(event) class AboutView(QtWidgets.QDialog): """Provides the git-cola 'About' dialog""" def __init__(self, context, parent=None): QtWidgets.QDialog.__init__(self, parent) self.context = context self.setWindowTitle(N_('About git-cola')) self.setWindowModality(Qt.WindowModal) # Top-most large icon logo_pixmap = icons.cola().pixmap(defs.huge_icon, defs.large_icon) self.logo_label = QtWidgets.QLabel() self.logo_label.setPixmap(logo_pixmap) self.logo_label.setAlignment(Qt.AlignCenter) self.logo_text_label = QtWidgets.QLabel() self.logo_text_label.setText('Git Cola') self.logo_text_label.setAlignment(Qt.AlignLeft | Qt.AlignCenter) font = self.logo_text_label.font() font.setPointSize(defs.logo_text) self.logo_text_label.setFont(font) self.text = qtutils.textbrowser(text=copyright_text()) self.version = qtutils.textbrowser(text=version_text(context)) self.authors = qtutils.textbrowser(text=authors_text()) self.translators = qtutils.textbrowser(text=translators_text()) self.tabs = ExpandingTabWidget() self.tabs.addTab(self.text, N_('About')) self.tabs.addTab(self.version, N_('Version')) self.tabs.addTab(self.authors, N_('Authors')) self.tabs.addTab(self.translators, N_('Translators')) self.close_button = qtutils.close_button() self.close_button.setDefault(True) self.logo_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.logo_label, self.logo_text_label, qtutils.STRETCH, ) self.button_layout = qtutils.hbox( defs.spacing, defs.margin, qtutils.STRETCH, self.close_button ) self.main_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.logo_layout, self.tabs, self.button_layout, ) self.setLayout(self.main_layout) qtutils.connect_button(self.close_button, self.accept) self.resize(defs.scale(600), defs.scale(720)) def copyright_text(): return """ Git Cola: The highly caffeinated Git GUI Copyright (C) 2007-2024 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/. """ def version_text(context): git_version = version.git_version(context) cola_version = version.version() python_path = sys.executable python_version = sys.version qt_version = qtpy.QT_VERSION qtpy_version = qtpy.__version__ pyqt_api_name = qtpy.API_NAME if ( getattr(qtpy, 'PYQT6', False) or getattr(qtpy, 'PYQT5', False) or getattr(qtpy, 'PYQT4', False) ): pyqt_api_version = qtpy.PYQT_VERSION elif qtpy.PYSIDE: pyqt_api_version = qtpy.PYSIDE_VERSION else: pyqt_api_version = 'unknown' platform_version = platform.platform() scope = dict( cola_version=cola_version, git_version=git_version, platform_version=platform_version, pyqt_api_name=pyqt_api_name, pyqt_api_version=pyqt_api_version, python_path=python_path, python_version=python_version, qt_version=qt_version, qtpy_version=qtpy_version, ) return ( N_( """
Git Cola version %(cola_version)s
  • %(platform_version)s
  • Python (%(python_path)s) %(python_version)s
  • Git %(git_version)s
  • Qt %(qt_version)s
  • QtPy %(qtpy_version)s
  • %(pyqt_api_name)s %(pyqt_api_version)s
""" ) % scope ) def mailto(email, text, palette): return qtutils.link('mailto:%s' % email, text, palette) + '
' def render_authors(authors): """Render a list of author details into rich text html""" for x in authors: x.setdefault('email', '') entries = [ ( """

%(name)s
%(title)s
%(email)s

""" % author ) for author in authors ] return ''.join(entries) def contributors_text(authors, prelude='', epilogue=''): author_text = render_authors(authors) scope = dict(author_text=author_text, epilogue=epilogue, prelude=prelude) return ( """ %(prelude)s %(author_text)s %(epilogue)s """ % scope ) def authors_text(): palette = QtGui.QPalette() contact = N_('Email contributor') authors = ( # The names listed here are listed in the same order as # `git shortlog --summary --numbered --no-merges` # Please submit a pull request if you would like to include your # email address in the about screen. # See the `generate-about` script in the "todo" branch. # vim :read! ./todo/generate-about dict( name='David Aguilar', title=N_('Maintainer (since 2007) and developer'), email=mailto('davvid@gmail.com', contact, palette), ), dict(name='Daniel Harding', title=N_('Developer')), dict( name='V字龍(Vdragon)', title=N_('Developer'), email=mailto('Vdragon.Taiwan@gmail.com', contact, palette), ), dict(name='Efimov Vasily', title=N_('Developer')), dict(name='Guillaume de Bure', title=N_('Developer')), dict(name='Uri Okrent', title=N_('Developer')), dict(name='Javier Rodriguez Cuevas', title=N_('Developer')), dict(name='Alex Chernetz', title=N_('Developer')), dict(name='xhl', title=N_('Developer')), dict(name='Andreas Sommer', title=N_('Developer')), dict(name='Thomas Kluyver', title=N_('Developer')), dict(name='Minarto Margoliono', title=N_('Developer')), dict(name='Ville Skyttä', title=N_('Developer')), dict(name='Szymon Judasz', title=N_('Developer')), dict(name='jm4R', title=N_('Developer')), dict(name='Stanislaw Halik', title=N_('Developer')), dict(name='Igor Galarraga', title=N_('Developer')), dict(name='Virgil Dupras', title=N_('Developer')), dict(name='wsdfhjxc', title=N_('Developer')), dict(name='Barry Roberts', title=N_('Developer')), dict(name='林博仁(Buo-ren Lin)', title=N_('Developer')), dict(name='Guo Yunhe', title=N_('Developer')), dict(name='cclauss', title=N_('Developer')), dict(name='Stefan Naewe', title=N_('Developer')), dict(name='Victor Nepveu', title=N_('Developer')), dict(name='Pavel Rehak', title=N_('Developer')), dict(name='Benedict Lee', title=N_('Developer')), dict(name='Tim Brown', title=N_('Developer')), dict(name='Steffen Prohaska', title=N_('Developer')), dict(name='Filip Danilović', title=N_('Developer')), dict(name='NotSqrt', title=N_('Developer')), dict(name='Michael Geddes', title=N_('Developer')), dict(name='Rustam Safin', title=N_('Developer')), dict(name='Justin Lecher', title=N_('Developer')), dict(name='Alex Gulyás', title=N_('Developer')), dict(name='David Martínez Martí', title=N_('Developer')), dict(name='Hualiang Xie', title=N_('Developer')), dict(name='Kai Krakow', title=N_('Developer')), dict(name='Karl Bielefeldt', title=N_('Developer')), dict(name='Marco Costalba', title=N_('Developer')), dict(name='Michael Homer', title=N_('Developer')), dict(name='Sebastian Schuberth', title=N_('Developer')), dict(name='Sven Claussner', title=N_('Developer')), dict(name='Victor Gambier', title=N_('Developer')), dict(name='bsomers', title=N_('Developer')), dict(name='real', title=N_('Developer')), dict(name='v.paritskiy', title=N_('Developer')), dict(name='vanderkoort', title=N_('Developer')), dict(name='wm4', title=N_('Developer')), dict(name='Audrius Karabanovas', title=N_('Developer')), dict(name='Matthew E. Levine', title=N_('Developer')), dict(name='Matthias Mailänder', title=N_('Developer')), dict(name='Md. Mahbub Alam', title=N_('Developer')), dict(name='Jakub Szymański', title=N_('Developer')), dict(name='ochristi', title=N_('Developer')), dict(name='Miguel Boekhold', title=N_('Developer')), dict(name='MiguelBoekhold', title=N_('Developer')), dict(name='Mikhail Terekhov', title=N_('Developer')), dict(name='Jake Biesinger', title=N_('Developer')), dict(name='Iulian Udrea', title=N_('Developer')), dict(name='Paul Hildebrandt', title=N_('Developer')), dict(name='Paul Weingardt', title=N_('Developer')), dict(name='Paulo Fidalgo', title=N_('Developer')), dict(name='Ilya Tumaykin', title=N_('Developer')), dict(name='Petr Gladkikh', title=N_('Developer')), dict(name='Philip Stark', title=N_('Developer')), dict(name='Radek Postołowicz', title=N_('Developer')), dict(name='Rainer Müller', title=N_('Developer')), dict(name='Ricardo J. Barberis', title=N_('Developer')), dict(name='Rolando Espinoza', title=N_('Developer')), dict(name='George Vasilakos', title=N_('Developer')), dict(name="Samsul Ma'arif", title=N_('Developer')), dict(name='Sebastian Brass', title=N_('Developer')), dict(name='Arthur Coelho', title=N_('Developer')), dict(name='Simon Peeters', title=N_('Developer')), dict(name='Felipe Morales', title=N_('Developer')), dict(name='David Zumbrunnen', title=N_('Developer')), dict(name='David Schwörer', title=N_('Developer')), dict(name='Stephen', title=N_('Developer')), dict(name='Andrej', title=N_('Developer')), dict(name='Daniel Pavel', title=N_('Developer')), dict(name='Daniel King', title=N_('Developer')), dict(name='Daniel Haskin', title=N_('Developer')), dict(name='Clément Pit--Claudel', title=N_('Developer')), dict(name='Vaibhav Sagar', title=N_('Developer')), dict(name='Ved Vyas', title=N_('Developer')), dict(name='Adrien be', title=N_('Developer')), dict(name='Charles', title=N_('Developer')), dict(name='Boris W', title=N_('Developer')), dict(name='Ben Boeckel', title=N_('Developer')), dict(name='Voicu Hodrea', title=N_('Developer')), dict(name='Wesley Wong', title=N_('Developer')), dict(name='Wolfgang Ocker', title=N_('Developer')), dict(name='Zhang Han', title=N_('Developer')), dict(name='beauxq', title=N_('Developer')), dict(name='Jamie Pate', title=N_('Developer')), dict(name='Jean-Francois Dagenais', title=N_('Developer')), dict(name='Joachim Lusiardi', title=N_('Developer')), dict(name='0xflotus', title=N_('Developer')), dict(name='AJ Bagwell', title=N_('Developer')), dict(name='Barrett Lowe', title=N_('Developer')), dict(name='Karthik Manamcheri', title=N_('Developer')), dict(name='Kelvie Wong', title=N_('Developer')), dict(name='Kyle', title=N_('Developer')), dict(name='Maciej Filipiak', title=N_('Developer')), dict(name='Maicon D. Filippsen', title=N_('Developer')), dict(name='Markus Heidelberg', title=N_('Developer')), ) bug_url = 'https://github.com/git-cola/git-cola/issues' bug_link = qtutils.link(bug_url, bug_url) scope = dict(bug_link=bug_link) prelude = ( N_( """
Please use %(bug_link)s to report issues.
""" ) % scope ) return contributors_text(authors, prelude=prelude) def translators_text(): palette = QtGui.QPalette() contact = N_('Email contributor') translators = ( # See the `generate-about` script in the "todo" branch. # vim :read! ./Meta/generate-about --translators dict( name='V字龍(Vdragon)', title=N_('Traditional Chinese (Taiwan) translation'), email=mailto('Vdragon.Taiwan@gmail.com', contact, palette), ), dict(name='Pavel Rehak', title=N_('Czech translation')), dict(name='Zhang Han', title=N_('Simplified Chinese translation')), dict(name='Victorhck', title=N_('Spanish translation')), dict(name='Vitor Lobo', title=N_('Brazilian translation')), dict(name='Igor Kopach', title=N_('Ukranian translation')), dict(name='Łukasz Wojniłowicz', title=N_('Polish translation')), dict(name='Rafael Nascimento', title=N_('Brazilian translation')), dict(name='Barış ÇELİK', title=N_('Turkish translation')), dict(name='Minarto Margoliono', title=N_('Indonesian translation')), dict(name='Sven Claussner', title=N_('German translation')), dict(name='Shun Sakai', title=N_('Japanese translation')), dict(name='Vaiz', title=N_('Russian translation')), dict(name='adlgrbz', title=N_('Turkish translation')), dict(name='fu7mu4', title=N_('Japanese translation')), dict(name='Guo Yunhe', title=N_('Simplified Chinese translation')), dict(name="Samsul Ma'arif", title=N_('Indonesian translation')), dict(name='Gyuris Gellért', title=N_('Hungarian translation')), dict(name='Joachim Lusiardi', title=N_('German translation')), dict(name='Kai Krakow', title=N_('German translation')), dict(name='Louis Rousseau', title=N_('French translation')), dict(name='Mickael Albertus', title=N_('French translation')), dict( name='Peter Dave Hello', title=N_('Traditional Chinese (Taiwan) translation'), ), dict(name='Pilar Molina Lopez', title=N_('Spanish translation')), dict(name='Rafael Reuber', title=N_('Brazilian translation')), dict(name='Sabri Ünal', title=N_('Turkish translation')), dict(name='Balázs Meskó', title=N_('Translation')), dict(name='Zeioth', title=N_('Spanish translation')), dict(name='balping', title=N_('Hungarian translation')), dict(name='p-bo', title=N_('Czech translation')), dict( name='林博仁(Buo-ren Lin)', title=N_('Traditional Chinese (Taiwan) translation'), ), ) bug_url = 'https://github.com/git-cola/git-cola/issues' bug_link = qtutils.link(bug_url, bug_url) scope = dict(bug_link=bug_link) prelude = ( N_( """
Git Cola has been translated into different languages thanks to the help of the individuals listed below.

Translation is approximate. If you find a mistake, please let us know by opening an issue on Github:

%(bug_link)s


We invite you to participate in translation by adding or updating a translation and opening a pull request.


""" ) % scope ) return contributors_text(translators, prelude=prelude) def show_shortcuts(): hotkeys_html = resources.doc(N_('hotkeys.html')) try: from qtpy import QtWebEngineWidgets except (ImportError, qtpy.PythonQtError): # Redhat disabled QtWebKit in their Qt build but don't punish the users webbrowser.open_new_tab('file://' + hotkeys_html) return html = core.read(hotkeys_html) parent = qtutils.active_window() widget = QtWidgets.QDialog(parent) widget.setWindowModality(Qt.WindowModal) widget.setWindowTitle(N_('Shortcuts')) web = QtWebEngineWidgets.QWebEngineView() web.setHtml(html) layout = qtutils.hbox(defs.no_margin, defs.spacing, web) widget.setLayout(layout) widget.resize(800, min(parent.height(), 600)) qtutils.add_action( widget, N_('Close'), widget.accept, hotkeys.QUESTION, *hotkeys.ACCEPT ) widget.show() widget.exec_() git-cola-4.6.1/cola/widgets/action.py000066400000000000000000000077661457126473700174740ustar00rootroot00000000000000"""Actions widget""" from functools import partial from qtpy import QtCore from qtpy import QtWidgets from .. import cmds from .. import qtutils from ..i18n import N_ from ..widgets import defs from ..widgets import remote from ..widgets import stash from ..qtutils import create_button from ..qtutils import connect_button class QFlowLayoutWidget(QtWidgets.QFrame): _horizontal = QtWidgets.QBoxLayout.LeftToRight _vertical = QtWidgets.QBoxLayout.TopToBottom def __init__(self, parent): QtWidgets.QFrame.__init__(self, parent) self._direction = self._vertical self._layout = layout = QtWidgets.QBoxLayout(self._direction) layout.setSpacing(defs.spacing) qtutils.set_margin(layout, defs.margin) self.setLayout(layout) policy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum ) self.setSizePolicy(policy) self.setMinimumSize(QtCore.QSize(10, 10)) 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) def tooltip_button(text, layout, tooltip=''): """Convenience wrapper around qtutils.create_button()""" return create_button(text, layout=layout, tooltip=tooltip) class ActionButtons(QFlowLayoutWidget): def __init__(self, context, parent=None): QFlowLayoutWidget.__init__(self, parent) layout = self.layout() self.context = context self.stage_button = tooltip_button( N_('Stage'), layout, tooltip=N_('Stage changes using "git add"') ) self.unstage_button = tooltip_button( N_('Unstage'), layout, tooltip=N_('Unstage changes using "git reset"') ) self.refresh_button = tooltip_button(N_('Refresh'), layout) self.fetch_button = tooltip_button( N_('Fetch...'), layout, tooltip=N_('Fetch from one or more remotes using "git fetch"'), ) self.push_button = tooltip_button( N_('Push...'), layout, N_('Push to one or more remotes using "git push"') ) self.pull_button = tooltip_button( N_('Pull...'), layout, tooltip=N_('Integrate changes using "git pull"') ) self.stash_button = tooltip_button( N_('Stash...'), layout, tooltip=N_('Temporarily stash away uncommitted changes using "git stash"'), ) self.exit_diff_mode_button = tooltip_button( N_('Exit Diff'), layout, tooltip=N_('Exit Diff mode') ) self.exit_diff_mode_button.setVisible(False) self.aspect_ratio = 0.4 layout.addStretch() self.setMinimumHeight(30) # Add callbacks connect_button(self.refresh_button, cmds.run(cmds.Refresh, context)) connect_button(self.fetch_button, partial(remote.fetch, context)) connect_button(self.push_button, partial(remote.push, context)) connect_button(self.pull_button, partial(remote.pull, context)) connect_button(self.stash_button, partial(stash.view, context)) connect_button(self.stage_button, cmds.run(cmds.StageSelected, context)) connect_button(self.exit_diff_mode_button, cmds.run(cmds.ResetMode, context)) connect_button(self.unstage_button, self.unstage) def unstage(self): """Unstage selected files, or all files if no selection exists.""" context = self.context paths = context.selection.staged if not paths: cmds.do(cmds.UnstageAll, context) else: cmds.do(cmds.Unstage, context, paths) def set_mode(self, mode): """Respond to changes to the diff mode""" diff_mode = mode == self.context.model.mode_diff self.exit_diff_mode_button.setVisible(diff_mode) git-cola-4.6.1/cola/widgets/archive.py000066400000000000000000000202561457126473700176250ustar00rootroot00000000000000"""Git Archive dialog""" import os from qtpy import QtCore from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from ..git import STDOUT from ..i18n import N_ from ..interaction import Interaction from .. import cmds from .. import core from .. import icons from .. import qtutils from .text import LineEdit from .standard import Dialog from . import defs class ExpandableGroupBox(QtWidgets.QGroupBox): expanded = Signal(bool) def __init__(self, parent=None): QtWidgets.QGroupBox.__init__(self, parent) self.setFlat(True) self.is_expanded = True self.click_pos = None self.arrow_icon_size = defs.small_icon def set_expanded(self, expanded): if expanded == self.is_expanded: self.expanded.emit(expanded) return self.is_expanded = expanded for widget in self.findChildren(QtWidgets.QWidget): widget.setHidden(not expanded) self.expanded.emit(expanded) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: option = QtWidgets.QStyleOptionGroupBox() self.initStyleOption(option) icon_size = defs.small_icon button_area = QtCore.QRect(0, 0, icon_size, icon_size) offset = 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() QtWidgets.QGroupBox.mousePressEvent(self, event) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton and self.click_pos == event.pos(): self.set_expanded(not self.is_expanded) QtWidgets.QGroupBox.mouseReleaseEvent(self, event) def paintEvent(self, _event): painter = QtWidgets.QStylePainter(self) option = QtWidgets.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 = QtWidgets.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.is_expanded: painter.drawPrimitive(style.PE_IndicatorArrowDown, option) else: painter.drawPrimitive(style.PE_IndicatorArrowRight, option) def save_archive(context): oid = context.git.rev_parse('HEAD')[STDOUT] show_save_dialog(context, oid, parent=qtutils.active_window()) def show_save_dialog(context, oid, parent=None): shortoid = oid[:7] dlg = Archive(context, oid, shortoid, parent=parent) dlg.show() if dlg.exec_() != dlg.Accepted: return None return dlg class Archive(Dialog): def __init__(self, context, ref, shortref=None, parent=None): Dialog.__init__(self, parent=parent) self.context = context if parent is not None: self.setWindowModality(Qt.WindowModal) # input self.ref = ref if shortref is None: shortref = ref # outputs self.fmt = None filename = f'{os.path.basename(core.getcwd())}-{shortref}' self.prefix = filename + '/' self.filename = filename # widgets self.setWindowTitle(N_('Save Archive')) self.filetext = LineEdit() self.filetext.set_value(self.filename) self.browse = qtutils.create_toolbutton(icon=icons.file_zip()) stdout = context.git.archive('--list')[STDOUT] self.format_strings = stdout.rstrip().splitlines() self.format_combo = qtutils.combo(self.format_strings) self.close_button = qtutils.close_button() self.save_button = qtutils.create_button( text=N_('Save'), icon=icons.save(), default=True ) self.prefix_label = QtWidgets.QLabel() self.prefix_label.setText(N_('Prefix')) self.prefix_text = LineEdit() self.prefix_text.set_value(self.prefix) self.prefix_group = ExpandableGroupBox() self.prefix_group.setTitle(N_('Advanced')) # layouts self.filelayt = qtutils.hbox( defs.no_margin, defs.spacing, self.browse, self.filetext, self.format_combo ) self.prefixlayt = qtutils.hbox( defs.margin, defs.spacing, self.prefix_label, self.prefix_text ) self.prefix_group.setLayout(self.prefixlayt) self.prefix_group.set_expanded(False) self.btnlayt = qtutils.hbox( defs.no_margin, defs.spacing, qtutils.STRETCH, self.close_button, self.save_button, ) self.mainlayt = qtutils.vbox( defs.margin, defs.no_spacing, self.filelayt, self.prefix_group, qtutils.STRETCH, self.btnlayt, ) self.setLayout(self.mainlayt) # 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_format(idx) # connections self.filetext.textChanged.connect(self.filetext_changed) self.prefix_text.textChanged.connect(self.prefix_text_changed) self.format_combo.currentIndexChanged.connect(self.update_format) self.prefix_group.expanded.connect(self.prefix_group_expanded) self.accepted.connect(self.archive_saved) qtutils.connect_button(self.browse, self.choose_filename) qtutils.connect_button(self.close_button, self.reject) qtutils.connect_button(self.save_button, self.save_archive) self.init_size(parent=parent) def archive_saved(self): context = self.context ref = self.ref fmt = self.fmt prefix = self.prefix filename = self.filename cmds.do(cmds.Archive, context, ref, fmt, prefix, filename) Interaction.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') if not Interaction.confirm( title, msg, info_txt, ok_txt, default=False, icon=icons.save() ): return self.accept() def choose_filename(self): filename = qtutils.save_as(self.filename) if not filename: return self.filetext.setText(filename) self.update_format(self.format_combo.currentIndex()) def filetext_changed(self, filename): self.filename = filename self.save_button.setEnabled(bool(self.filename)) prefix = self.strip_exts(os.path.basename(self.filename)) + '/' self.prefix_text.setText(prefix) def prefix_text_changed(self, prefix): self.prefix = prefix 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_format(self, idx): self.fmt = self.format_strings[idx] text = self.strip_exts(self.filetext.text()) self.filename = f'{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-4.6.1/cola/widgets/bookmarks.py000066400000000000000000000431701457126473700201740ustar00rootroot00000000000000"""Provides widgets related to bookmarks""" import os from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from .. import cmds from .. import core from .. import git from .. import hotkeys from .. import icons from .. import qtutils from .. import utils from ..i18n import N_ from ..interaction import Interaction from ..models import prefs from ..widgets import defs from ..widgets import standard from ..widgets import switcher BOOKMARKS = 0 RECENT_REPOS = 1 def bookmark(context, parent): return BookmarksWidget(context, BOOKMARKS, parent=parent) def recent(context, parent): return BookmarksWidget(context, RECENT_REPOS, parent=parent) class BookmarksWidget(QtWidgets.QFrame): def __init__(self, context, style=BOOKMARKS, parent=None): QtWidgets.QFrame.__init__(self, parent) self.context = context self.style = style self.items = items = [] self.model = model = QtGui.QStandardItemModel() settings = context.settings builder = BuildItem(context) # bookmarks if self.style == BOOKMARKS: entries = settings.bookmarks # recent items elif self.style == RECENT_REPOS: entries = settings.recent for entry in entries: item = builder.get(entry['path'], entry['name']) items.append(item) model.appendRow(item) place_holder = N_('Search repositories by name...') self.quick_switcher = switcher.switcher_outer_view( context, model, place_holder=place_holder ) self.tree = BookmarksTreeView( context, style, self.set_items_to_models, parent=self ) self.add_button = qtutils.create_action_button( tooltip=N_('Add'), icon=icons.add() ) self.delete_button = qtutils.create_action_button( tooltip=N_('Delete'), icon=icons.remove() ) self.open_button = qtutils.create_action_button( tooltip=N_('Open'), icon=icons.repo() ) self.search_button = qtutils.create_action_button( tooltip=N_('Search'), icon=icons.search() ) self.button_group = utils.Group(self.delete_button, self.open_button) self.button_group.setEnabled(False) self.setFocusProxy(self.tree) if style == BOOKMARKS: self.setToolTip(N_('Favorite repositories')) elif style == RECENT_REPOS: self.setToolTip(N_('Recent repositories')) self.add_button.hide() self.button_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.search_button, self.open_button, self.add_button, self.delete_button, ) self.main_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.quick_switcher, self.tree ) self.setLayout(self.main_layout) self.corner_widget = QtWidgets.QWidget(self) self.corner_widget.setLayout(self.button_layout) titlebar = parent.titleBarWidget() titlebar.add_corner_widget(self.corner_widget) qtutils.connect_button(self.add_button, self.tree.add_bookmark) qtutils.connect_button(self.delete_button, self.tree.delete_bookmark) qtutils.connect_button(self.open_button, self.tree.open_repo) qtutils.connect_button(self.search_button, self.toggle_switcher_input_field) QtCore.QTimer.singleShot(0, self.reload_bookmarks) self.tree.toggle_switcher.connect(self.enable_switcher_input_field) # moving key has pressed while focusing on input field self.quick_switcher.filter_input.switcher_selection_move.connect( self.tree.keyPressEvent ) # escape key has pressed while focusing on input field self.quick_switcher.filter_input.switcher_escape.connect( self.close_switcher_input_field ) # some key except moving key has pressed while focusing on list view self.tree.switcher_text.connect(self.switcher_text_inputted) def reload_bookmarks(self): # Called once after the GUI is initialized tree = self.tree tree.refresh() model = tree.model() model.dataChanged.connect(tree.item_changed) selection = tree.selectionModel() selection.selectionChanged.connect(tree.item_selection_changed) tree.doubleClicked.connect(tree.tree_double_clicked) def tree_item_selection_changed(self): enabled = bool(self.tree.selected_item()) self.button_group.setEnabled(enabled) def connect_to(self, other): self.tree.default_changed.connect(other.tree.refresh) other.tree.default_changed.connect(self.tree.refresh) def set_items_to_models(self, items): model = self.model self.items.clear() model.clear() for item in items: self.items.append(item) model.appendRow(item) self.quick_switcher.proxy_model.setSourceModel(model) self.tree.setModel(self.quick_switcher.proxy_model) def toggle_switcher_input_field(self): visible = self.quick_switcher.filter_input.isVisible() self.enable_switcher_input_field(not visible) def close_switcher_input_field(self): self.enable_switcher_input_field(False) def enable_switcher_input_field(self, visible): filter_input = self.quick_switcher.filter_input filter_input.setVisible(visible) if not visible: filter_input.clear() def switcher_text_inputted(self, event): # default selection for first index first_proxy_idx = self.quick_switcher.proxy_model.index(0, 0) self.tree.setCurrentIndex(first_proxy_idx) self.quick_switcher.filter_input.keyPressEvent(event) def disable_rename(_path, _name, _new_name): return False class BookmarksTreeView(standard.TreeView): default_changed = Signal() toggle_switcher = Signal(bool) # this signal will be emitted when some key pressed while focusing on tree view switcher_text = Signal(QtGui.QKeyEvent) def __init__(self, context, style, set_model, parent=None): standard.TreeView.__init__(self, parent=parent) self.context = context self.style = style self.set_model = set_model self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) self.setHeaderHidden(True) # We make the items editable, but we don't want the double-click # behavior to trigger editing. Make it behave like Mac OS X's Finder. self.setEditTriggers(self.SelectedClicked) self.open_action = qtutils.add_action( self, N_('Open'), self.open_repo, hotkeys.OPEN ) self.accept_action = qtutils.add_action( self, N_('Accept'), self.accept_repo, *hotkeys.ACCEPT ) self.open_new_action = qtutils.add_action( self, N_('Open in New Window'), self.open_new_repo, hotkeys.NEW ) self.set_default_repo_action = qtutils.add_action( self, N_('Set Default Repository'), self.set_default_repo ) self.clear_default_repo_action = qtutils.add_action( self, N_('Clear Default Repository'), self.clear_default_repo ) self.rename_repo_action = qtutils.add_action( self, N_('Rename Repository'), self.rename_repo ) self.open_default_action = qtutils.add_action( self, cmds.OpenDefaultApp.name(), self.open_default, hotkeys.PRIMARY_ACTION ) self.launch_editor_action = qtutils.add_action( self, cmds.Edit.name(), self.launch_editor, hotkeys.EDIT ) self.launch_terminal_action = qtutils.add_action( self, cmds.LaunchTerminal.name(), self.launch_terminal, hotkeys.TERMINAL ) self.copy_action = qtutils.add_action(self, N_('Copy'), self.copy, hotkeys.COPY) self.delete_action = qtutils.add_action( self, N_('Delete'), self.delete_bookmark ) self.remove_missing_action = qtutils.add_action( self, N_('Prune Missing Entries'), self.remove_missing ) self.remove_missing_action.setToolTip( N_('Remove stale entries for repositories that no longer exist') ) self.action_group = utils.Group( self.open_action, self.open_new_action, self.copy_action, self.launch_editor_action, self.launch_terminal_action, self.open_default_action, self.rename_repo_action, self.delete_action, ) self.action_group.setEnabled(False) self.set_default_repo_action.setEnabled(False) self.clear_default_repo_action.setEnabled(False) # Connections if style == RECENT_REPOS: context.model.worktree_changed.connect( self.refresh, type=Qt.QueuedConnection ) def keyPressEvent(self, event): """ This will be hooked while focusing on this list view. Set input field invisible when escape key pressed. Move selection when move key like tab, UP etc pressed. Or open input field and simply act like text input to it. This is when some character key pressed while focusing on tree view, NOT input field. """ selection_moving_keys = switcher.moving_keys() pressed_key = event.key() if pressed_key == Qt.Key_Escape: self.toggle_switcher.emit(False) elif pressed_key in hotkeys.ACCEPT: self.accept_repo() elif pressed_key in selection_moving_keys: super().keyPressEvent(event) else: self.toggle_switcher.emit(True) self.switcher_text.emit(event) def refresh(self): context = self.context settings = context.settings builder = BuildItem(context) # bookmarks if self.style == BOOKMARKS: entries = settings.bookmarks # recent items elif self.style == RECENT_REPOS: entries = settings.recent items = [builder.get(entry['path'], entry['name']) for entry in entries] if self.style == BOOKMARKS and prefs.sort_bookmarks(context): items.sort(key=lambda x: x.name.lower()) self.set_model(items) def contextMenuEvent(self, event): menu = qtutils.create_menu(N_('Actions'), self) menu.addAction(self.open_action) menu.addAction(self.open_new_action) menu.addAction(self.open_default_action) menu.addSeparator() menu.addAction(self.copy_action) menu.addAction(self.launch_editor_action) menu.addAction(self.launch_terminal_action) menu.addSeparator() item = self.selected_item() is_default = bool(item and item.is_default) if is_default: menu.addAction(self.clear_default_repo_action) else: menu.addAction(self.set_default_repo_action) menu.addAction(self.rename_repo_action) menu.addSeparator() menu.addAction(self.delete_action) menu.addAction(self.remove_missing_action) menu.exec_(self.mapToGlobal(event.pos())) def item_selection_changed(self, selected, _deselected): item_idx = selected.indexes() if item_idx: item = self.model().itemFromIndex(item_idx[0]) enabled = bool(item) self.action_group.setEnabled(enabled) is_default = bool(item and item.is_default) self.set_default_repo_action.setEnabled(not is_default) self.clear_default_repo_action.setEnabled(is_default) def tree_double_clicked(self, _index): context = self.context item = self.selected_item() cmds.do(cmds.OpenRepo, context, item.path) self.toggle_switcher.emit(False) def selected_item(self): index = self.currentIndex() return self.model().itemFromIndex(index) def item_changed(self, _top_left, _bottom_right, _roles): item = self.selected_item() self.rename_entry(item, item.text()) def rename_entry(self, item, new_name): settings = self.context.settings if self.style == BOOKMARKS: rename = settings.rename_bookmark elif self.style == RECENT_REPOS: rename = settings.rename_recent else: rename = disable_rename if rename(item.path, item.name, new_name): settings.save() item.name = new_name else: item.setText(item.name) self.toggle_switcher.emit(False) def apply_func(self, func, *args, **kwargs): item = self.selected_item() if item: func(item, *args, **kwargs) def copy(self): self.apply_func(lambda item: qtutils.set_clipboard(item.path)) self.toggle_switcher.emit(False) def open_default(self): context = self.context self.apply_func(lambda item: cmds.do(cmds.OpenDefaultApp, context, [item.path])) self.toggle_switcher.emit(False) def set_default_repo(self): self.apply_func(self.set_default_item) self.toggle_switcher.emit(False) def set_default_item(self, item): context = self.context cmds.do(cmds.SetDefaultRepo, context, item.path) self.refresh() self.default_changed.emit() self.toggle_switcher.emit(False) def clear_default_repo(self): self.apply_func(self.clear_default_item) self.default_changed.emit() self.toggle_switcher.emit(False) def clear_default_item(self, _item): context = self.context cmds.do(cmds.SetDefaultRepo, context, None) self.refresh() self.toggle_switcher.emit(False) def rename_repo(self): index = self.currentIndex() self.edit(index) self.toggle_switcher.emit(False) def accept_repo(self): self.apply_func(self.accept_item) self.toggle_switcher.emit(False) def accept_item(self, _item): if self.state() & self.EditingState: current_index = self.currentIndex() widget = self.indexWidget(current_index) if widget: self.commitData(widget) self.closePersistentEditor(current_index) self.refresh() else: self.open_selected_repo() def open_repo(self): context = self.context self.apply_func(lambda item: cmds.do(cmds.OpenRepo, context, item.path)) def open_selected_repo(self): item = self.selected_item() context = self.context cmds.do(cmds.OpenRepo, context, item.path) self.toggle_switcher.emit(False) def open_new_repo(self): context = self.context self.apply_func(lambda item: cmds.do(cmds.OpenNewRepo, context, item.path)) self.toggle_switcher.emit(False) def launch_editor(self): context = self.context self.apply_func(lambda item: cmds.do(cmds.Edit, context, [item.path])) self.toggle_switcher.emit(False) def launch_terminal(self): context = self.context self.apply_func(lambda item: cmds.do(cmds.LaunchTerminal, context, item.path)) self.toggle_switcher.emit(False) def add_bookmark(self): normpath = utils.expandpath(core.getcwd()) name = os.path.basename(normpath) prompt = ( (N_('Name'), name), (N_('Path'), core.getcwd()), ) ok, values = qtutils.prompt_n(N_('Add Favorite'), prompt) if not ok: return name, path = values normpath = utils.expandpath(path) if git.is_git_worktree(normpath): settings = self.context.settings settings.load() settings.add_bookmark(normpath, name) settings.save() self.refresh() else: Interaction.critical(N_('Error'), N_('%s is not a Git repository.') % path) def delete_bookmark(self): """Removes a bookmark from the bookmarks list""" item = self.selected_item() context = self.context if not item: return if self.style == BOOKMARKS: cmd = cmds.RemoveBookmark elif self.style == RECENT_REPOS: cmd = cmds.RemoveRecent else: return ok, _, _, _ = cmds.do(cmd, context, item.path, item.name, icon=icons.discard()) if ok: self.refresh() self.toggle_switcher.emit(False) def remove_missing(self): """Remove missing entries from the favorites/recent file list""" settings = self.context.settings if self.style == BOOKMARKS: settings.remove_missing_bookmarks() elif self.style == RECENT_REPOS: settings.remove_missing_recent() self.refresh() class BuildItem: def __init__(self, context): self.star_icon = icons.star() self.folder_icon = icons.folder() cfg = context.cfg self.default_repo = cfg.get('cola.defaultrepo') def get(self, path, name): is_default = self.default_repo == path if is_default: icon = self.star_icon else: icon = self.folder_icon return BookmarksTreeItem(path, name, icon, is_default) class BookmarksTreeItem(switcher.SwitcherListItem): def __init__(self, path, name, icon, is_default): switcher.SwitcherListItem.__init__(self, name, icon=icon, name=name) self.path = path self.name = name self.is_default = is_default self.setIcon(icon) self.setText(name) self.setToolTip(path) self.setFlags(self.flags() | Qt.ItemIsEditable) git-cola-4.6.1/cola/widgets/branch.py000066400000000000000000000714161457126473700174450ustar00rootroot00000000000000"""Provides widgets related to branches""" from functools import partial from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from ..compat import uchr from ..git import STDOUT from ..i18n import N_ from ..interaction import Interaction from ..widgets import defs from ..widgets import standard from ..qtutils import get from .. import cmds from .. import gitcmds from .. import hotkeys from .. import icons from .. import qtutils from . import log from . import text def defer_func(parent, title, func, *args, **kwargs): """Return a QAction bound against a partial func with arguments""" return qtutils.add_action(parent, title, partial(func, *args, **kwargs)) def add_branch_to_menu(menu, branch, remote_branch, remote, upstream, func): """Add a remote branch to the context menu""" branch_remote, _ = gitcmds.parse_remote_branch(remote_branch) if branch_remote != remote: menu.addSeparator() action = defer_func(menu, remote_branch, func, branch, remote_branch) if remote_branch == upstream: action.setIcon(icons.star()) menu.addAction(action) return branch_remote class AsyncGitActionTask(qtutils.Task): """Run git action asynchronously""" def __init__(self, git_helper, action, args, kwarg, update_refs): qtutils.Task.__init__(self) self.git_helper = git_helper self.action = action self.args = args self.kwarg = kwarg self.update_refs = update_refs def task(self): """Runs action and captures the result""" git_action = getattr(self.git_helper, self.action) return git_action(*self.args, **self.kwarg) class BranchesWidget(QtWidgets.QFrame): """A widget for displaying and performing operations on branches""" def __init__(self, context, parent): QtWidgets.QFrame.__init__(self, parent) self.model = model = context.model tooltip = N_('Toggle the branches filter') icon = icons.ellipsis() self.filter_button = qtutils.create_action_button(tooltip=tooltip, icon=icon) self.order_icons = ( icons.alphabetical(), icons.reverse_chronological(), ) tooltip_order = N_( 'Set the sort order for branches and tags.\n' 'Toggle between date-based and version-name-based sorting.' ) icon = self.order_icon(model.ref_sort) self.sort_order_button = qtutils.create_action_button( tooltip=tooltip_order, icon=icon ) self.tree = BranchesTreeWidget(context, parent=self) self.filter_widget = BranchesFilterWidget(self.tree) self.filter_widget.hide() self.setFocusProxy(self.tree) self.setToolTip(N_('Branches')) self.main_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.filter_widget, self.tree ) self.setLayout(self.main_layout) self.toggle_action = qtutils.add_action( self, tooltip, self.toggle_filter, hotkeys.FILTER ) qtutils.connect_button(self.filter_button, self.toggle_filter) qtutils.connect_button( self.sort_order_button, cmds.run(cmds.CycleReferenceSort, context) ) model.refs_updated.connect(self.refresh, Qt.QueuedConnection) def toggle_filter(self): shown = not self.filter_widget.isVisible() self.filter_widget.setVisible(shown) if shown: self.filter_widget.setFocus() else: self.tree.setFocus() def order_icon(self, idx): return self.order_icons[idx % len(self.order_icons)] def refresh(self): icon = self.order_icon(self.model.ref_sort) self.sort_order_button.setIcon(icon) class BranchesTreeWidget(standard.TreeWidget): """A tree widget for displaying branches""" updated = Signal() def __init__(self, context, parent=None): standard.TreeWidget.__init__(self, parent) self.context = context self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) self.setHeaderHidden(True) self.setAlternatingRowColors(False) self.setColumnCount(1) self.setExpandsOnDoubleClick(False) self.current_branch = None self.tree_helper = BranchesTreeHelper(self) self.git_helper = GitHelper(context) self.runtask = qtutils.RunTask(parent=self) self._visible = False self._needs_refresh = False self._tree_states = None self.updated.connect(self.refresh, type=Qt.QueuedConnection) context.model.updated.connect(self.updated) # Expand items when they are clicked self.clicked.connect(self._toggle_expanded) # Checkout branch when double clicked self.doubleClicked.connect(self.checkout_action) def refresh(self): """Refresh the UI widgets to match the current state""" self._needs_refresh = True self._refresh() def _refresh(self): """Refresh the UI to match the updated state""" # There is no need to refresh the UI when this widget is inactive. if not self._visible: return model = self.context.model self.current_branch = model.currentbranch self._tree_states = self._save_tree_state() ellipsis = icons.ellipsis() local_tree = create_tree_entries(model.local_branches) local_tree.basename = N_('Local') local = create_toplevel_item(local_tree, icon=icons.branch(), ellipsis=ellipsis) remote_tree = create_tree_entries(model.remote_branches) remote_tree.basename = N_('Remote') remote = create_toplevel_item( remote_tree, icon=icons.branch(), ellipsis=ellipsis ) tags_tree = create_tree_entries(model.tags) tags_tree.basename = N_('Tags') tags = create_toplevel_item(tags_tree, icon=icons.tag(), ellipsis=ellipsis) self.clear() self.addTopLevelItems([local, remote, tags]) if self._tree_states: self._load_tree_state(self._tree_states) self._tree_states = None self._update_branches() def showEvent(self, event): """Defer updating widgets until the widget is visible""" if not self._visible: self._visible = True if self._needs_refresh: self.refresh() return super().showEvent(event) def _toggle_expanded(self, index): """Toggle expanded/collapsed state when items are clicked""" item = self.itemFromIndex(index) if item and item.childCount(): self.setExpanded(index, not self.isExpanded(index)) def contextMenuEvent(self, event): """Build and execute the context menu""" context = self.context selected = self.selected_item() if not selected: return # Only allow actions on leaf nodes that have a valid refname. if not selected.refname: return root = get_toplevel_item(selected) full_name = selected.refname menu = qtutils.create_menu(N_('Actions'), self) visualize_action = qtutils.add_action( menu, N_('Visualize'), self.visualize_branch_action ) visualize_action.setIcon(icons.visualize()) menu.addAction(visualize_action) menu.addSeparator() # all branches except current the current branch if full_name != self.current_branch: menu.addAction( qtutils.add_action(menu, N_('Checkout'), self.checkout_action) ) # remote branch if root.name == N_('Remote'): label = N_('Checkout as new branch') action = self.checkout_new_branch_action menu.addAction(qtutils.add_action(menu, label, action)) merge_menu_action = qtutils.add_action( menu, N_('Merge into current branch'), self.merge_action ) merge_menu_action.setIcon(icons.merge()) menu.addAction(merge_menu_action) # local and remote branch if root.name != N_('Tags'): # local branch if root.name == N_('Local'): remote = gitcmds.tracked_branch(context, full_name) if remote is not None: menu.addSeparator() pull_menu_action = qtutils.add_action( menu, N_('Pull'), self.pull_action ) pull_menu_action.setIcon(icons.pull()) menu.addAction(pull_menu_action) push_menu_action = qtutils.add_action( menu, N_('Push'), self.push_action ) push_menu_action.setIcon(icons.push()) menu.addAction(push_menu_action) rename_menu_action = qtutils.add_action( menu, N_('Rename Branch'), self.rename_action ) rename_menu_action.setIcon(icons.edit()) menu.addSeparator() menu.addAction(rename_menu_action) # not current branch if full_name != self.current_branch: delete_label = N_('Delete Branch') if root.name == N_('Remote'): delete_label = N_('Delete Remote Branch') delete_menu_action = qtutils.add_action( menu, delete_label, self.delete_action ) delete_menu_action.setIcon(icons.discard()) menu.addSeparator() menu.addAction(delete_menu_action) # manage upstream branches for local branches if root.name == N_('Local'): upstream_menu = menu.addMenu(N_('Set Upstream Branch')) upstream_menu.setIcon(icons.branch()) self.build_upstream_menu(upstream_menu) menu.exec_(self.mapToGlobal(event.pos())) def build_upstream_menu(self, menu): """Build the "Set Upstream Branch" sub-menu""" context = self.context model = context.model selected_branch = self.selected_refname() remote = None upstream = None branches = [] other_branches = [] if selected_branch: remote = gitcmds.upstream_remote(context, selected_branch) upstream = gitcmds.tracked_branch(context, branch=selected_branch) if not remote and 'origin' in model.remotes: remote = 'origin' if remote: prefix = remote + '/' for branch in model.remote_branches: if branch.startswith(prefix): branches.append(branch) else: other_branches.append(branch) else: # This can be a pretty big list, let's try to split it apart branch_remote = '' target = branches for branch in model.remote_branches: new_branch_remote, _ = gitcmds.parse_remote_branch(branch) if branch_remote and branch_remote != new_branch_remote: target = other_branches branch_remote = new_branch_remote target.append(branch) limit = 16 if not other_branches and len(branches) > limit: branches, other_branches = (branches[:limit], branches[limit:]) # Add an action for each remote branch current_remote = remote for branch in branches: current_remote = add_branch_to_menu( menu, selected_branch, branch, current_remote, upstream, self.set_upstream, ) # This list could be longer so we tuck it away in a sub-menu. # Selecting a branch from the non-default remote is less common. if other_branches: menu.addSeparator() sub_menu = menu.addMenu(N_('Other branches')) for branch in other_branches: current_remote = add_branch_to_menu( sub_menu, selected_branch, branch, current_remote, upstream, self.set_upstream, ) def set_upstream(self, branch, remote_branch): """Configure the upstream for a branch""" context = self.context remote, r_branch = gitcmds.parse_remote_branch(remote_branch) if remote and r_branch: cmds.do(cmds.SetUpstreamBranch, context, branch, remote, r_branch) def _save_tree_state(self): """Save the tree state into a dictionary""" states = {} for item in self.items(): states.update(self.tree_helper.save_state(item)) return states def _load_tree_state(self, states): """Restore expanded items after rebuilding UI widgets""" # Disable animations to eliminate redraw flicker. animated = self.isAnimated() self.setAnimated(False) for item in self.items(): self.tree_helper.load_state(item, states.get(item.name, {})) self.tree_helper.set_current_item() self.setAnimated(animated) def _update_branches(self): """Query branch details using a background task""" context = self.context current_branch = self.current_branch top_item = self.topLevelItem(0) item = find_by_refname(top_item, current_branch) if item is not None: expand_item_parents(item) item.setIcon(0, icons.star()) branch_details_task = BranchDetailsTask( context, current_branch, self.git_helper ) self.runtask.start( branch_details_task, finish=self._update_branches_finished ) def _update_branches_finished(self, task): """Update the UI with the branch details once the background task completes""" current_branch, tracked_branch, ahead, behind = task.result top_item = self.topLevelItem(0) item = find_by_refname(top_item, current_branch) if current_branch and tracked_branch and item is not None: status_str = '' if ahead > 0: status_str += f'{uchr(0x2191)}{ahead}' if behind > 0: status_str += f' {uchr(0x2193)}{behind}' if status_str: item.setText(0, f'{item.text(0)}\t{status_str}') def git_action_async( self, action, args, kwarg=None, update_refs=False, remote_messages=False ): """Execute a git action in a background task""" if kwarg is None: kwarg = {} task = AsyncGitActionTask(self.git_helper, action, args, kwarg, update_refs) progress = standard.progress( N_('Executing action %s') % action, N_('Updating'), self ) if remote_messages: result_handler = log.show_remote_messages(self.context, self) else: result_handler = None self.runtask.start( task, progress=progress, finish=self.git_action_completed, result=result_handler, ) def git_action_completed(self, task): """Update the with the results of an async git action""" status, out, err = task.result self.git_helper.show_result(task.action, status, out, err) if task.update_refs: self.context.model.update_refs() def push_action(self): """Push the selected branch to its upstream remote""" context = self.context branch = self.selected_refname() remote_branch = gitcmds.tracked_branch(context, branch) context.settings.load() push_settings = context.settings.get_gui_state_by_name('push') remote_messages = push_settings.get('remote_messages', False) if remote_branch: remote, branch_name = gitcmds.parse_remote_branch(remote_branch) if remote and branch_name: # we assume that user wants to "Push" the selected local # branch to a remote with same name self.git_action_async( 'push', [remote, branch_name], update_refs=True, remote_messages=remote_messages, ) def rename_action(self): """Rename the selected branch""" branch = self.selected_refname() new_branch, ok = qtutils.prompt( N_('Enter New Branch Name'), title=N_('Rename branch'), text=branch ) if ok and new_branch: self.git_action_async('rename', [branch, new_branch], update_refs=True) def pull_action(self): """Pull the selected branch into the current branch""" context = self.context branch = self.selected_refname() if not branch: return remote_branch = gitcmds.tracked_branch(context, branch) context.settings.load() pull_settings = context.settings.get_gui_state_by_name('pull') remote_messages = pull_settings.get('remote_messages', False) if remote_branch: remote, branch_name = gitcmds.parse_remote_branch(remote_branch) if remote and branch_name: self.git_action_async( 'pull', [remote, branch_name], update_refs=True, remote_messages=remote_messages, ) def delete_action(self): """Delete the selected branch""" branch = self.selected_refname() if not branch or branch == self.current_branch: return remote = False root = get_toplevel_item(self.selected_item()) if not root: return if root.name == N_('Remote'): remote = True if remote: remote, branch = gitcmds.parse_remote_branch(branch) if remote and branch: cmds.do(cmds.DeleteRemoteBranch, self.context, remote, branch) else: cmds.do(cmds.DeleteBranch, self.context, branch) def merge_action(self): """Merge the selected branch into the current branch""" branch = self.selected_refname() if branch and branch != self.current_branch: self.git_action_async('merge', [branch]) def checkout_action(self): """Checkout the selected branch""" branch = self.selected_refname() if branch and branch != self.current_branch: self.git_action_async('checkout', [branch], update_refs=True) def checkout_new_branch_action(self): """Checkout a new branch""" branch = self.selected_refname() if branch and branch != self.current_branch: _, new_branch = gitcmds.parse_remote_branch(branch) self.git_action_async( 'checkout', ['-b', new_branch, branch], update_refs=True ) def visualize_branch_action(self): """Visualize the selected branch""" branch = self.selected_refname() if branch: cmds.do(cmds.VisualizeRevision, self.context, branch) def selected_refname(self): return getattr(self.selected_item(), 'refname', None) class BranchDetailsTask(qtutils.Task): """Lookup branch details in a background task""" def __init__(self, context, current_branch, git_helper): super().__init__() self.context = context self.current_branch = current_branch self.git_helper = git_helper def task(self): """Query git for branch details""" tracked_branch = gitcmds.tracked_branch(self.context, self.current_branch) ahead = 0 behind = 0 if self.current_branch and tracked_branch: origin = tracked_branch + '..' + self.current_branch our_commits = self.git_helper.log(origin)[STDOUT] ahead = our_commits.count('\n') if our_commits: ahead += 1 origin = self.current_branch + '..' + tracked_branch their_commits = self.git_helper.log(origin)[STDOUT] behind = their_commits.count('\n') if their_commits: behind += 1 return self.current_branch, tracked_branch, ahead, behind class BranchTreeWidgetItem(QtWidgets.QTreeWidgetItem): def __init__(self, name, refname=None, icon=None): QtWidgets.QTreeWidgetItem.__init__(self) self.name = name self.refname = refname self.setText(0, name) self.setToolTip(0, name) if icon is not None: self.setIcon(0, icon) self.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) class TreeEntry: """Tree representation for the branches widget The branch widget UI displays the basename. For intermediate names, e.g. "xxx" in the "xxx/abc" and "xxx/def" branches, the 'refname' will be None. 'children' contains a list of TreeEntry, and is empty when refname is defined. """ def __init__(self, basename, refname, children): self.basename = basename self.refname = refname self.children = children def create_tree_entries(names): """Create a nested tree structure with a single root TreeEntry. When names == ['xxx/abc', 'xxx/def'] the result will be:: TreeEntry( basename=None, refname=None, children=[ TreeEntry( basename='xxx', refname=None, children=[ TreeEntry( basename='abc', refname='xxx/abc', children=[] ), TreeEntry( basename='def', refname='xxx/def', children=[] ) ] ) ] ) """ # Phase 1: build a nested dictionary representing the intermediate # names in the branches, e.g. {'xxx': {'abc': {}, 'def': {}}} tree_names = create_name_dict(names) # Loop over the names again, this time we'll create tree entries entries = {} root = TreeEntry(None, None, []) for item in names: cur_names = tree_names cur_entries = entries tree = root children = root.children for part in item.split('/'): if cur_names[part]: # This has children try: tree, _ = cur_entries[part] except KeyError: # New entry tree = TreeEntry(part, None, []) cur_entries[part] = (tree, {}) # Append onto the parent children list only once children.append(tree) else: # This is the actual branch tree = TreeEntry(part, item, []) children.append(tree) cur_entries[part] = (tree, {}) # Advance into the nested child list children = tree.children # Advance into the inner dict cur_names = cur_names[part] _, cur_entries = cur_entries[part] return root def create_name_dict(names): # Phase 1: build a nested dictionary representing the intermediate # names in the branches, e.g. {'xxx': {'abc': {}, 'def': {}}} tree_names = {} for item in names: part_names = tree_names for part in item.split('/'): # Descend into the inner names dict. part_names = part_names.setdefault(part, {}) return tree_names def create_toplevel_item(tree, icon=None, ellipsis=None): """Create a top-level BranchTreeWidgetItem and its children""" item = BranchTreeWidgetItem(tree.basename, icon=ellipsis) children = create_tree_items(tree.children, icon=icon, ellipsis=ellipsis) if children: item.addChildren(children) return item def create_tree_items(entries, icon=None, ellipsis=None): """Create children items for a tree item""" result = [] for tree in entries: item = BranchTreeWidgetItem(tree.basename, refname=tree.refname, icon=icon) children = create_tree_items(tree.children, icon=icon, ellipsis=ellipsis) if children: item.addChildren(children) if ellipsis is not None: item.setIcon(0, ellipsis) result.append(item) return result def expand_item_parents(item): """Expand tree parents from item""" parent = item.parent() while parent is not None: if not parent.isExpanded(): parent.setExpanded(True) parent = parent.parent() def find_by_refname(item, refname): """Find child by full name recursive""" result = None for i in range(item.childCount()): child = item.child(i) if child.refname and child.refname == refname: return child result = find_by_refname(child, refname) if result is not None: return result return result def get_toplevel_item(item): """Returns top-most item found by traversing up the specified item""" parents = [item] parent = item.parent() while parent is not None: parents.append(parent) parent = parent.parent() return parents[-1] class BranchesTreeHelper: """Save and restore the tree state""" def __init__(self, tree): self.tree = tree self.current_item = None def set_current_item(self): """Reset the current item""" if self.current_item is not None: self.tree.setCurrentItem(self.current_item) self.current_item = None def load_state(self, item, state): """Load expanded items from a dict""" if not state: return if state.get('expanded', False) and not item.isExpanded(): item.setExpanded(True) if state.get('selected', False) and not item.isSelected(): item.setSelected(True) self.current_item = item children_state = state.get('children', {}) if not children_state: return for i in range(item.childCount()): child = item.child(i) self.load_state(child, children_state.get(child.name, {})) def save_state(self, item): """Save the selected and expanded item state into a dict""" expanded = item.isExpanded() selected = item.isSelected() children = {} entry = { 'children': children, 'expanded': expanded, 'selected': selected, } result = {item.name: entry} for i in range(item.childCount()): child = item.child(i) children.update(self.save_state(child)) return result class GitHelper: def __init__(self, context): self.context = context self.git = context.git def log(self, origin): return self.git.log(origin, abbrev=7, pretty='format:%h', _readonly=True) def push(self, remote, branch): return self.git.push(remote, branch, verbose=True) def pull(self, remote, branch): return self.git.pull(remote, branch, no_ff=True, verbose=True) def merge(self, branch): return self.git.merge(branch, no_commit=True) def rename(self, branch, new_branch): return self.git.branch(branch, new_branch, m=True) def checkout(self, *args, **options): return self.git.checkout(*args, **options) @staticmethod def show_result(command, status, out, err): Interaction.log_status(status, out, err) if status != 0: Interaction.command_error(N_('Error'), command, status, out, err) class BranchesFilterWidget(QtWidgets.QWidget): def __init__(self, tree, parent=None): QtWidgets.QWidget.__init__(self, parent) self.tree = tree hint = N_('Filter branches...') self.text = text.LineEdit(parent=self, clear_button=True) self.text.setToolTip(hint) self.setFocusProxy(self.text) self._filter = None self.main_layout = qtutils.hbox(defs.no_margin, defs.spacing, self.text) self.setLayout(self.main_layout) self.text.textChanged.connect(self.apply_filter) self.tree.updated.connect(self.apply_filter, type=Qt.QueuedConnection) def apply_filter(self): value = get(self.text) if value == self._filter: return self._apply_bold(self._filter, False) self._filter = value if value: self._apply_bold(value, True) def _apply_bold(self, value, is_bold): match = Qt.MatchContains | Qt.MatchRecursive children = self.tree.findItems(value, match) for child in children: if child.childCount() == 0: font = child.font(0) font.setBold(is_bold) child.setFont(0, font) git-cola-4.6.1/cola/widgets/browse.py000066400000000000000000000661621457126473700175130ustar00rootroot00000000000000import shlex from qtpy.QtCore import Qt from qtpy.QtCore import Signal from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from ..models.browse import GitRepoModel from ..models.browse import GitRepoNameItem from ..models.selection import State from ..i18n import N_ from ..interaction import Interaction from .. import cmds from .. import core from .. import difftool from .. import gitcmds from .. import hotkeys from .. import icons from .. import utils from .. import qtutils from .selectcommits import select_commits from . import common from . import defs from . import standard def worktree_browser(context, parent=None, update=True, show=True): """Create a new worktree browser""" view = Browser(context, parent, update=update) if parent is None: context.browser_windows.append(view) view.closed.connect(context.browser_windows.remove) model = GitRepoModel(context, view.tree) view.set_model(model) if update: view.refresh() if show: view.show() return view def save_path(context, path, model): """Choose an output filename based on the selected path""" filename = qtutils.save_as(path) if filename: model.filename = filename cmds.do(SaveBlob, context, model) result = True else: result = False return result class Browser(standard.Widget): """A repository branch file browser. Browses files provided by GitRepoModel""" # Read-only mode property mode = property(lambda self: self.model.mode) def __init__(self, context, parent, update=True): standard.Widget.__init__(self, parent) self.tree = RepoTreeView(context, self) self.mainlayout = qtutils.hbox(defs.no_margin, defs.spacing, self.tree) self.setLayout(self.mainlayout) self.model = context.model self.model.updated.connect(self._updated_callback, type=Qt.QueuedConnection) if parent is None: qtutils.add_close_action(self) if update: self._updated_callback() self.init_state(context.settings, self.resize, 720, 420) def set_model(self, model): """Set the model""" self.tree.set_model(model) def refresh(self): """Refresh the model triggering view updates""" self.tree.refresh() def _updated_callback(self): branch = self.model.currentbranch curdir = core.getcwd() msg = N_('Repository: %s') % curdir msg += '\n' msg += N_('Branch: %s') % branch self.setToolTip(msg) scope = { 'project': self.model.project, 'branch': branch, } title = N_('%(project)s: %(branch)s - Browse') % scope 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, context, parent): standard.TreeView.__init__(self, parent) self.context = context self.selection = context.selection self.saved_selection = [] self.saved_current_path = None self.saved_open_folders = set() self.restoring_selection = False self._columns_sized = False self.setDragEnabled(True) self.setRootIsDecorated(False) self.setSortingEnabled(False) self.setSelectionMode(self.ExtendedSelection) # Observe model updates model = context.model model.about_to_update.connect(self.save_selection, type=Qt.QueuedConnection) model.updated.connect(self.update_actions, type=Qt.QueuedConnection) self.expanded.connect(self.index_expanded) self.collapsed.connect(lambda idx: self.size_columns()) self.collapsed.connect(self.index_collapsed) # Sync selection before the key press event changes the model index queued = Qt.QueuedConnection self.index_about_to_change.connect(self.sync_selection, type=queued) self.action_history = qtutils.add_action_with_tooltip( self, N_('View History...'), N_('View history for selected paths'), self.view_history, hotkeys.HISTORY, ) self.action_stage = qtutils.add_action_with_tooltip( self, cmds.StageOrUnstage.name(), N_('Stage/unstage selected paths for commit'), cmds.run(cmds.StageOrUnstage, context), hotkeys.STAGE_SELECTION, ) self.action_untrack = qtutils.add_action_with_tooltip( self, N_('Untrack Selected'), N_('Stop tracking paths'), self.untrack_selected, ) self.action_rename = qtutils.add_action_with_tooltip( self, N_('Rename'), N_('Rename selected paths'), self.rename_selected ) self.action_difftool = qtutils.add_action_with_tooltip( self, difftool.LaunchDifftool.name(), N_('Launch git-difftool on the current path'), cmds.run(difftool.LaunchDifftool, context), hotkeys.DIFF, ) self.action_difftool_predecessor = qtutils.add_action_with_tooltip( self, N_('Diff Against Predecessor...'), N_('Launch git-difftool against previous versions'), self.diff_predecessor, hotkeys.DIFF_SECONDARY, ) self.action_revert_unstaged = qtutils.add_action_with_tooltip( self, cmds.RevertUnstagedEdits.name(), N_('Revert unstaged changes to selected paths'), cmds.run(cmds.RevertUnstagedEdits, context), hotkeys.REVERT, hotkeys.REVERT_ALT, ) self.action_revert_uncommitted = qtutils.add_action_with_tooltip( self, cmds.RevertUncommittedEdits.name(), N_('Revert uncommitted changes to selected paths'), cmds.run(cmds.RevertUncommittedEdits, context), hotkeys.UNDO, ) self.action_editor = qtutils.add_action_with_tooltip( self, cmds.LaunchEditor.name(), N_('Edit selected paths'), cmds.run(cmds.LaunchEditor, context), hotkeys.EDIT, ) self.action_blame = qtutils.add_action_with_tooltip( self, cmds.BlamePaths.name(), N_('Blame selected paths'), cmds.run(cmds.BlamePaths, context), ) self.action_refresh = common.refresh_action(context, self) self.action_default_app = common.default_app_action( context, self, self.selected_paths ) self.action_parent_dir = common.parent_dir_action( context, self, self.selected_paths ) self.action_terminal = common.terminal_action( context, self, func=self.selected_paths ) self.x_width = qtutils.text_width(self.font(), 'x') self.size_columns(force=True) def index_expanded(self, index): """Update information about a directory as it is expanded.""" # Remember open folders so that we can restore them when refreshing item = self.name_item_from_index(index) self.saved_open_folders.add(item.path) self.size_columns() # update information about a directory as it is expanded if item.cached: return path = item.path model = self.model() model.populate(item) model.update_entry(path) for row in range(item.rowCount()): path = item.child(row, 0).path model.update_entry(path) item.cached = True def index_collapsed(self, index): item = self.name_item_from_index(index) self.saved_open_folders.remove(item.path) def refresh(self): self.model().refresh() def size_columns(self, force=False): """Set the column widths.""" cfg = self.context.cfg should_resize = cfg.get('cola.resizebrowsercolumns', default=False) if not force and not should_resize: return self.resizeColumnToContents(0) self.resizeColumnToContents(1) self.resizeColumnToContents(2) self.resizeColumnToContents(3) self.resizeColumnToContents(4) def sizeHintForColumn(self, column): x_width = self.x_width if column == 1: # Status size = x_width * 11 elif column == 2: # Summary size = x_width * 64 elif column == 3: # Author size = x_width * 18 elif column == 4: # Age size = x_width * 16 else: # Filename and others use the actual content size = super().sizeHintForColumn(column) return size def save_selection(self): selection = self.selected_paths() if selection: self.saved_selection = selection current = self.current_item() if current: self.saved_current_path = current.path def restore(self): selection = self.selectionModel() flags = selection.Select | selection.Rows self.restoring_selection = True # Restore opened folders model = self.model() for path in sorted(self.saved_open_folders): row = model.get(path) if not row: continue index = row[0].index() if index.isValid(): self.setExpanded(index, True) # Restore the current item. We do this first, otherwise # setCurrentIndex() can mess with the selection we set below current_index = None current_path = self.saved_current_path if current_path: row = model.get(current_path) if row: current_index = row[0].index() if current_index and current_index.isValid(): self.setCurrentIndex(current_index) # Restore selected items for path in self.saved_selection: row = model.get(path) if not row: continue index = row[0].index() if index.isValid(): self.scrollTo(index) selection.select(index, flags) self.restoring_selection = False # Resize the columns once when cola.resizebrowsercolumns is False. # This provides a good initial size since we will not be resizing # the columns during expand/collapse. if not self._columns_sized: self._columns_sized = True self.size_columns(force=True) self.update_diff() 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(selection=selection)) revertable = staged or modified self.action_editor.setEnabled(selected) self.action_history.setEnabled(selected) self.action_default_app.setEnabled(selected) self.action_parent_dir.setEnabled(selected) if self.action_terminal is not None: self.action_terminal.setEnabled(selected) self.action_stage.setEnabled(staged or unstaged) self.action_untrack.setEnabled(tracked) self.action_rename.setEnabled(tracked) self.action_difftool.setEnabled(staged or modified) self.action_difftool_predecessor.setEnabled(tracked) self.action_revert_unstaged.setEnabled(revertable) self.action_revert_uncommitted.setEnabled(revertable) def contextMenuEvent(self, event): """Create a context menu.""" self.update_actions() menu = qtutils.create_menu(N_('Actions'), self) menu.addAction(self.action_editor) menu.addAction(self.action_stage) menu.addSeparator() menu.addAction(self.action_history) menu.addAction(self.action_difftool) menu.addAction(self.action_difftool_predecessor) menu.addAction(self.action_blame) menu.addSeparator() menu.addAction(self.action_revert_unstaged) menu.addAction(self.action_revert_uncommitted) menu.addAction(self.action_untrack) menu.addAction(self.action_rename) menu.addSeparator() menu.addAction(self.action_default_app) menu.addAction(self.action_parent_dir) if self.action_terminal is not None: menu.addAction(self.action_terminal) menu.exec_(self.mapToGlobal(event.pos())) def mousePressEvent(self, event): """Synchronize the selection on mouse-press.""" result = QtWidgets.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 = self.context.model model_staged = utils.add_parents(model.staged) model_modified = utils.add_parents(model.modified) model_unmerged = utils.add_parents(model.unmerged) model_untracked = utils.add_parents(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. self.selection.set_selection(state) return paths def selectionChanged(self, old, new): """Override selectionChanged to update available actions.""" result = QtWidgets.QTreeView.selectionChanged(self, old, new) if not self.restoring_selection: self.update_actions() self.update_diff() return result def update_diff(self): context = self.context model = context.model paths = self.sync_selection() if paths and self.model().path_is_interesting(paths[0]): cached = paths[0] in model.staged cmds.do(cmds.Diff, context, paths[0], cached) def set_model(self, model): """Set the concrete QAbstractItemModel instance.""" self.setModel(model) model.restore.connect(self.restore, type=Qt.QueuedConnection) def name_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 paths_from_indexes(self, indexes): return qtutils.paths_from_indexes( self.model(), indexes, item_type=GitRepoNameItem.TYPE ) def selected_paths(self): """Return the selected paths.""" return self.paths_from_indexes(self.selectedIndexes()) def selected_staged_paths(self, selection=None): """Return selected staged paths.""" if selection is None: selection = self.selected_paths() model = self.context.model staged = utils.add_parents(model.staged) return [p for p in selection if p in staged] def selected_modified_paths(self, selection=None): """Return selected modified paths.""" if selection is None: selection = self.selected_paths() model = self.context.model modified = utils.add_parents(model.modified) return [p for p in selection if p in modified] def selected_unstaged_paths(self, selection=None): """Return selected unstaged paths.""" if selection is None: selection = self.selected_paths() model = self.context.model modified = utils.add_parents(model.modified) untracked = utils.add_parents(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 selection is None: selection = self.selected_paths() model = self.context.model staged = set(self.selected_staged_paths(selection=selection)) modified = set(self.selected_modified_paths(selection=selection)) untracked = utils.add_parents(model.untracked) tracked = staged.union(modified) return [p for p in selection if p not in untracked or p in tracked] def view_history(self): """Launch the configured history browser path-limited to entries.""" paths = self.selected_paths() cmds.do(cmds.VisualizePaths, self.context, paths) def untrack_selected(self): """Untrack selected paths.""" context = self.context cmds.do(cmds.Untrack, context, self.selected_tracked_paths()) def rename_selected(self): """Untrack selected paths.""" context = self.context cmds.do(cmds.Rename, context, self.selected_tracked_paths()) def diff_predecessor(self): """Diff paths against previous versions.""" context = self.context paths = self.selected_tracked_paths() args = ['--'] + paths revs, summaries = gitcmds.log_helper(context, all=False, extra_args=args) commits = select_commits( context, N_('Select Previous Version'), revs, summaries, multiselect=False ) if not commits: return commit = commits[0] difftool.difftool_launch(context, left=commit, paths=paths) def current_path(self): """Return the path for the current item.""" index = self.currentIndex() if not index.isValid(): return None return self.name_item_from_index(index).path class BrowseModel: """Context data used for browsing branches via git-ls-tree""" def __init__(self, ref, filename=None): self.ref = ref self.relpath = filename self.filename = filename class SaveBlob(cmds.ContextCommand): def __init__(self, context, model): super().__init__(context) self.browse_model = model def do(self): git = self.context.git model = self.browse_model ref = f'{model.ref}:{model.relpath}' with core.xopen(model.filename, 'wb') as fp: status, output, err = git.show(ref, _stdout=fp) out = '# git show {} >{}\n{}'.format( shlex.quote(ref), shlex.quote(model.filename), output, ) Interaction.command(N_('Error Saving File'), 'git show', status, out, err) if status != 0: return msg = N_('Saved "%(filename)s" from "%(ref)s" to "%(destination)s"') % { '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 BrowseBranch(standard.Dialog): @classmethod def browse(cls, context, ref): model = BrowseModel(ref) dlg = cls(context, model, parent=qtutils.active_window()) dlg_model = GitTreeModel(context, ref, dlg) dlg.setModel(dlg_model) dlg.setWindowTitle(N_('Browsing %s') % model.ref) dlg.show() dlg.raise_() if dlg.exec_() != dlg.Accepted: return None return dlg def __init__(self, context, model, parent=None): standard.Dialog.__init__(self, parent=parent) if parent is not None: self.setWindowModality(Qt.WindowModal) # updated for use by commands self.context = context self.model = model # widgets self.tree = GitTreeWidget(parent=self) self.close_button = qtutils.close_button() text = N_('Save') self.save = qtutils.create_button(text=text, enabled=False, default=True) # layouts self.btnlayt = qtutils.hbox( defs.margin, defs.spacing, self.close_button, qtutils.STRETCH, self.save ) self.layt = qtutils.vbox(defs.margin, defs.spacing, self.tree, self.btnlayt) self.setLayout(self.layt) # connections self.tree.path_chosen.connect(self.save_path) self.tree.selection_changed.connect( self.selection_changed, type=Qt.QueuedConnection ) qtutils.connect_button(self.close_button, self.close) qtutils.connect_button(self.save, self.save_blob) self.init_size(parent=parent) 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) if save_path(self.context, path, self.model): self.accept() def save_blob(self): """Save the currently selected file""" filenames = self.tree.selected_files() if not filenames: return self.save_path(filenames[0]) 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): selection_changed = Signal() path_chosen = Signal(object) def __init__(self, parent=None): standard.TreeView.__init__(self, parent) self.setHeaderHidden(True) self.doubleClicked.connect(self.double_clicked) def double_clicked(self, index): item = self.model().itemFromIndex(index) if item is None: return if item.is_dir: return self.path_chosen.emit(item.path) def selected_files(self): items = self.selected_items() return [i.path for i in items if not i.is_dir] def selectionChanged(self, old_selection, new_selection): QtWidgets.QTreeView.selectionChanged(self, old_selection, new_selection) self.selection_changed.emit() 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 = 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 = create_row(path, True) try: parent_path = parent.path except AttributeError: # root QStandardItem parent_path = '' # Insert directories before file paths try: row = self.dir_rows[parent_path] except KeyError: row = self.dir_rows[parent_path] = 0 parent.insertRow(row, row_items) self.dir_rows[parent_path] += 1 self.dir_entries[path] = row_items[0] return row_items[0] 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 def create_row(path, is_dir): """Return a list of items representing a row.""" return [GitTreeItem(path, is_dir)] class GitTreeModel(GitFileTreeModel): def __init__(self, context, ref, parent): GitFileTreeModel.__init__(self, parent) self.context = context self.ref = ref self._initialize() def _initialize(self): """Iterate over git-ls-tree and create GitTreeItems.""" git = self.context.git 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 tree view. 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: icon = icons.directory() else: icon = icons.file_text() self.setIcon(icon) git-cola-4.6.1/cola/widgets/cfgactions.py000066400000000000000000000246561457126473700203340ustar00rootroot00000000000000import os from qtpy import QtCore from qtpy import QtWidgets from qtpy.QtCore import Qt from .. import core from .. import gitcmds from .. import icons from .. import qtutils from ..i18n import N_ from ..interaction import Interaction from . import defs from . import completion from . import standard from .text import LineEdit def install(): Interaction.run_command = staticmethod(run_command) Interaction.confirm_config_action = staticmethod(confirm_config_action) def get_config_actions(context): cfg = context.cfg return cfg.get_guitool_names_and_shortcuts() def confirm_config_action(context, name, opts): dlg = ActionDialog(context, qtutils.active_window(), name, opts) dlg.show() if dlg.exec_() != QtWidgets.QDialog.Accepted: return False rev = dlg.revision() if rev: opts['revision'] = rev args = 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): """Text viewer that reads the output of a command synchronously""" # Keep us in scope otherwise PyQt kills the widget def __init__(self, title, parent=None): standard.Dialog.__init__(self, parent) self.setWindowTitle(title) if parent is not None: self.setWindowModality(Qt.ApplicationModal) # Construct the process self.proc = QtCore.QProcess(self) self.exitstatus = 0 self.out = '' self.err = '' self.command = [] # Create the text browser self.output_text = QtWidgets.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) # Create abort / close buttons # Start with abort disabled - will be enabled when the process is run. self.button_abort = qtutils.create_button(text=N_('Abort'), enabled=False) self.button_close = qtutils.close_button() # Put them in a horizontal layout at the bottom. self.button_box = QtWidgets.QDialogButtonBox(self) self.button_box.addButton( self.button_abort, QtWidgets.QDialogButtonBox.RejectRole ) self.button_box.addButton( self.button_close, QtWidgets.QDialogButtonBox.AcceptRole ) # Connect the signals to the process self.proc.readyReadStandardOutput.connect(self.read_stdout) self.proc.readyReadStandardError.connect(self.read_stderr) self.proc.finished.connect(self.proc_finished) self.proc.stateChanged.connect(self.proc_state_changed) qtutils.connect_button(self.button_abort, self.abort) qtutils.connect_button(self.button_close, self.close) self._layout = qtutils.vbox( defs.margin, defs.spacing, self.output_text, self.button_box ) self.setLayout(self._layout) self.resize(720, 420) def set_command(self, command): self.command = command def run(self): """Runs the process""" self.proc.start(self.command[0], self.command[1:]) def read_stdout(self): text = self.read_stream(self.proc.readAllStandardOutput) self.out += text def read_stderr(self): text = self.read_stream(self.proc.readAllStandardError) self.err += text def read_stream(self, func): data = func().data() text = core.decode(data) self.append_text(text) return 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 abort(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.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 Interaction.confirm( title, msg, info_text, ok_text, default=False, icon=icons.close() ): self.abort() event.accept() else: event.ignore() else: event.accept() return standard.Dialog.closeEvent(self, event) def proc_state_changed(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 proc_finished(self, status): self.exitstatus = status class ActionDialog(standard.Dialog): VALUES = {} def __init__(self, context, parent, name, opts): standard.Dialog.__init__(self, parent) self.context = context self.action_name = name self.opts = opts try: values = self.VALUES[name] except KeyError: values = self.VALUES[name] = {} self.setWindowModality(Qt.ApplicationModal) title = opts.get('title') if title: self.setWindowTitle(os.path.expandvars(title)) self.prompt = QtWidgets.QLabel() prompt = opts.get('prompt') if prompt: self.prompt.setText(os.path.expandvars(prompt)) self.argslabel = QtWidgets.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 = LineEdit() if self.opts.get('argprompt'): try: # Remember the previous value saved_value = values['argstxt'] self.argstxt.setText(saved_value) except KeyError: pass else: self.argslabel.setMinimumSize(10, 10) self.argstxt.setMinimumSize(10, 10) self.argstxt.hide() self.argslabel.hide() revs = ( (N_('Local Branch'), gitcmds.branch_list(context, remote=False)), (N_('Tracking Branch'), gitcmds.branch_list(context, remote=True)), (N_('Tag'), gitcmds.tag_list(context)), ) if 'revprompt' not in opts or opts.get('revprompt') is True: revprompt = N_('Revision') else: revprompt = opts.get('revprompt') self.revselect = RevisionSelector(context, self, revs) self.revselect.set_revision_label(revprompt) if not opts.get('revprompt'): self.revselect.hide() # Close/Run buttons self.closebtn = qtutils.close_button() self.runbtn = qtutils.create_button( text=N_('Run'), default=True, icon=icons.ok() ) self.argslayt = qtutils.hbox( defs.margin, defs.spacing, self.argslabel, self.argstxt ) self.btnlayt = qtutils.hbox( defs.margin, defs.spacing, qtutils.STRETCH, self.closebtn, self.runbtn ) self.layt = qtutils.vbox( defs.margin, defs.spacing, self.prompt, self.argslayt, self.revselect, self.btnlayt, ) self.setLayout(self.layt) self.argstxt.textChanged.connect(self._argstxt_changed) qtutils.connect_button(self.closebtn, self.reject) qtutils.connect_button(self.runbtn, self.accept) # Widen the dialog by default self.resize(666, self.height()) def revision(self): return self.revselect.revision() def args(self): return self.argstxt.text() def _argstxt_changed(self, value): """Store the argstxt value so that we can remember it between calls""" self.VALUES[self.action_name]['argstxt'] = value class RevisionSelector(QtWidgets.QWidget): def __init__(self, context, parent, revs): QtWidgets.QWidget.__init__(self, parent) self.context = context self._revs = revs self._revdict = dict(revs) self._rev_label = QtWidgets.QLabel(self) self._revision = completion.GitRefLineEdit(context, parent=self) # Create the radio buttons radio_btns = [] self._radio_btns = {} for label, rev_list in self._revs: radio = qtutils.radio(text=label) radio.setObjectName(label) qtutils.connect_button(radio, self._set_revision_list) radio_btns.append(radio) self._radio_btns[label] = radio radio_btns.append(qtutils.STRETCH) self._rev_list = QtWidgets.QListWidget() label, rev_list = self._revs[0] self._radio_btns[label].setChecked(True) qtutils.set_items(self._rev_list, rev_list) self._rev_layt = qtutils.hbox( defs.no_margin, defs.spacing, self._rev_label, self._revision ) self._radio_layt = qtutils.hbox(defs.margin, defs.spacing, *radio_btns) self._layt = qtutils.vbox( defs.no_margin, defs.spacing, self._rev_layt, self._radio_layt, self._rev_list, ) self.setLayout(self._layt) self._rev_list.itemSelectionChanged.connect(self.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 = self.sender().objectName() revs = self._revdict[sender] qtutils.set_items(self._rev_list, revs) def selection_changed(self): items = self._rev_list.selectedItems() if not items: return self._revision.setText(items[0].text()) git-cola-4.6.1/cola/widgets/clone.py000066400000000000000000000152171457126473700173050ustar00rootroot00000000000000import os from functools import partial from qtpy import QtCore from qtpy import QtWidgets from qtpy.QtCore import Qt from .. import cmds from .. import core from .. import icons from .. import utils from .. import qtutils from ..i18n import N_ from ..interaction import Interaction from ..qtutils import get from . import defs from . import standard from . import text def clone(context, spawn=True, show=True): """Clone a repository and spawn a new git-cola instance""" parent = qtutils.active_window() progress = standard.progress('', '', parent) return clone_repo(context, show, progress, task_finished, spawn) def clone_repo(context, show, progress, finish, spawn): """Clone a repository asynchronously with progress animation""" func = partial(start_clone_task, context, progress, finish, spawn) prompt = prompt_for_clone(context, show=show) prompt.result.connect(func) return prompt def prompt_for_clone(context, show=True): """Presents a GUI for cloning a repository""" view = Clone(context, parent=qtutils.active_window()) if show: view.show() return view def task_finished(task): """Report errors from the clone task if they exist""" cmd = task.cmd if cmd is None: return status = cmd.status out = cmd.out err = cmd.err title = N_('Error: could not clone "%s"') % cmd.url Interaction.command(title, 'git clone', status, out, err) def start_clone_task( context, progress, finish, spawn, url, destdir, submodules, shallow ): # Use a thread to update in the background runtask = context.runtask progress.set_details(N_('Clone Repository'), N_('Cloning repository at %s') % url) task = CloneTask(context, url, destdir, submodules, shallow, spawn) runtask.start(task, finish=finish, progress=progress) class CloneTask(qtutils.Task): """Clones a Git repository""" def __init__(self, context, url, destdir, submodules, shallow, spawn): qtutils.Task.__init__(self) self.context = context self.url = url self.destdir = destdir self.submodules = submodules self.shallow = shallow self.spawn = spawn self.cmd = None def task(self): """Runs the model action and captures the result""" self.cmd = cmds.do( cmds.Clone, self.context, self.url, self.destdir, self.submodules, self.shallow, spawn=self.spawn, ) return self.cmd class Clone(standard.Dialog): # Signal binding for returning the input data result = QtCore.Signal(object, object, bool, bool) def __init__(self, context, parent=None): standard.Dialog.__init__(self, parent=parent) self.context = context self.model = context.model self.setWindowTitle(N_('Clone Repository')) if parent is not None: self.setWindowModality(Qt.WindowModal) # Repository location self.url_label = QtWidgets.QLabel(N_('URL')) hint = 'git://git.example.com/repo.git' self.url = text.HintedLineEdit(context, hint, parent=self) self.url.setToolTip(N_('Path or URL to clone (Env. $VARS okay)')) # Initialize submodules self.submodules = qtutils.checkbox( text=N_('Inititalize submodules'), checked=False ) # Reduce commit history self.shallow = qtutils.checkbox( text=N_('Reduce commit history to minimum'), checked=False ) # Buttons self.ok_button = qtutils.create_button( text=N_('Clone'), icon=icons.ok(), default=True ) self.close_button = qtutils.close_button() # Form layout for inputs self.input_layout = qtutils.form( defs.no_margin, defs.button_spacing, (self.url_label, self.url) ) self.button_layout = qtutils.hbox( defs.margin, defs.spacing, self.submodules, defs.button_spacing, self.shallow, qtutils.STRETCH, self.close_button, self.ok_button, ) self.main_layout = qtutils.vbox( defs.margin, defs.spacing, self.input_layout, self.button_layout ) self.setLayout(self.main_layout) qtutils.connect_button(self.close_button, self.close) qtutils.connect_button(self.ok_button, self.prepare_to_clone) self.url.textChanged.connect(lambda x: self.update_actions()) self.init_state(context.settings, self.resize, 720, 200) self.update_actions() def update_actions(self): url = get(self.url).strip() enabled = bool(url) self.ok_button.setEnabled(enabled) def prepare_to_clone(self): """Grabs and validates the input data""" submodules = get(self.submodules) shallow = get(self.shallow) url = get(self.url) url = utils.expandpath(url) if not url: return # Pick a suitable basename by parsing the URL newurl = url.replace('\\', '/').rstrip('/') try: default = newurl.rsplit('/', 1)[-1] except IndexError: default = '' 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: Interaction.information( N_('Error Cloning'), N_('Could not parse Git URL: "%s"') % url ) Interaction.log(N_('Could not parse Git URL: "%s"') % url) return # 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, self.model.getcwd()) if not dirname: return 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(N_('Directory Exists'), msg) # Make sure the directory doesn't exist while core.exists(destdir): destdir = olddestdir + str(count) count += 1 # Return the input data and close the dialog self.result.emit(url, destdir, submodules, shallow) self.close() git-cola-4.6.1/cola/widgets/commitmsg.py000066400000000000000000000575731457126473700202170ustar00rootroot00000000000000from functools import partial from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from .. import actions from .. import cmds from .. import core from .. import gitcmds from .. import hotkeys from .. import icons from .. import textwrap from .. import qtutils from .. import spellcheck from ..interaction import Interaction from ..gitcmds import commit_message_path from ..i18n import N_ from ..models import dag from ..models import prefs from ..qtutils import get from ..utils import Group from . import defs from . import standard from .selectcommits import select_commits from .spellcheck import SpellCheckLineEdit, SpellCheckTextEdit from .text import anchor_mode class CommitMessageEditor(QtWidgets.QFrame): commit_finished = Signal(object) cursor_changed = Signal(int, int) down = Signal() up = Signal() def __init__(self, context, parent): QtWidgets.QFrame.__init__(self, parent) cfg = context.cfg self.context = context self.model = model = context.model self.spellcheck_initialized = False self.spellcheck = spellcheck.NorvigSpellCheck() self.spellcheck.set_dictionary(cfg.get('cola.dictionary', None)) self._linebreak = None self._textwidth = None self._tabwidth = None # Actions self.signoff_action = qtutils.add_action( self, cmds.SignOff.name(), cmds.run(cmds.SignOff, context), hotkeys.SIGNOFF ) self.signoff_action.setIcon(icons.style_dialog_apply()) self.signoff_action.setToolTip(N_('Sign off on this commit')) self.commit_action = qtutils.add_action( self, N_('Commit@@verb'), self.commit, hotkeys.APPLY ) self.commit_action.setIcon(icons.commit()) self.commit_action.setToolTip(N_('Commit staged changes')) self.clear_action = qtutils.add_action(self, N_('Clear...'), self.clear) self.launch_editor = actions.launch_editor_at_line(context, self) self.launch_difftool = actions.launch_difftool(context, self) self.move_up = actions.move_up(self) self.move_down = actions.move_down(self) # Menu actions self.menu_actions = menu_actions = [ self.signoff_action, self.commit_action, None, self.launch_editor, self.launch_difftool, None, self.move_up, self.move_down, None, ] # Widgets self.summary = CommitSummaryLineEdit(context, check=self.spellcheck) self.summary.setMinimumHeight(defs.tool_button_height) self.summary.menu_actions.extend(menu_actions) self.description = CommitMessageTextEdit( context, check=self.spellcheck, parent=self ) self.description.menu_actions.extend(menu_actions) commit_button_tooltip = N_('Commit staged changes\nShortcut: Ctrl+Enter') self.commit_button = qtutils.create_button( text=N_('Commit@@verb'), tooltip=commit_button_tooltip, icon=icons.commit() ) self.commit_group = Group(self.commit_action, self.commit_button) self.commit_progress_bar = standard.progress_bar( self, disable=(self.commit_button, self.summary, self.description), ) self.commit_progress_bar.setMaximumHeight(defs.small_icon) self.actions_menu = qtutils.create_menu(N_('Actions'), self) self.actions_button = qtutils.create_toolbutton( icon=icons.configure(), tooltip=N_('Actions...') ) self.actions_button.setMenu(self.actions_menu) 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.setIcon(icons.edit()) self.amend_action.setCheckable(True) self.amend_action.setShortcut(hotkeys.AMEND) self.amend_action.setShortcutContext(Qt.ApplicationShortcut) # Bypass hooks self.bypass_commit_hooks_action = self.actions_menu.addAction( N_('Bypass Commit Hooks') ) self.bypass_commit_hooks_action.setCheckable(True) self.bypass_commit_hooks_action.setChecked(False) # Sign commits self.sign_action = self.actions_menu.addAction(N_('Create Signed Commit')) self.sign_action.setCheckable(True) signcommits = cfg.get('cola.signcommits', default=False) self.sign_action.setChecked(signcommits) # Spell checker self.check_spelling_action = self.actions_menu.addAction(N_('Check Spelling')) self.check_spelling_action.setCheckable(True) spell_check = prefs.spellcheck(context) self.check_spelling_action.setChecked(spell_check) self.toggle_check_spelling(spell_check) # Line wrapping self.autowrap_action = self.actions_menu.addAction(N_('Auto-Wrap Lines')) self.autowrap_action.setCheckable(True) self.autowrap_action.setChecked(prefs.linebreak(context)) # Commit message self.actions_menu.addSeparator() self.load_commitmsg_menu = self.actions_menu.addMenu( N_('Load Previous Commit Message') ) self.load_commitmsg_menu.aboutToShow.connect(self.build_commitmsg_menu) self.fixup_commit_menu = self.actions_menu.addMenu(N_('Fixup Previous Commit')) self.fixup_commit_menu.aboutToShow.connect(self.build_fixup_menu) self.toplayout = qtutils.hbox( defs.no_margin, defs.spacing, self.actions_button, self.summary, self.commit_button, ) self.toplayout.setContentsMargins( defs.margin, defs.no_margin, defs.no_margin, defs.no_margin ) self.mainlayout = qtutils.vbox( defs.no_margin, defs.spacing, self.toplayout, self.description ) self.setLayout(self.mainlayout) qtutils.connect_button(self.commit_button, self.commit) # Broadcast the amend mode qtutils.connect_action_bool( self.amend_action, partial(cmds.run(cmds.AmendMode), context) ) qtutils.connect_action_bool( self.check_spelling_action, self.toggle_check_spelling ) # Handle the one-off auto-wrapping qtutils.connect_action_bool(self.autowrap_action, self.set_linebreak) self.summary.accepted.connect(self.focus_description) self.summary.down_pressed.connect(self.summary_cursor_down) self.model.commit_message_changed.connect( self.set_commit_message, type=Qt.QueuedConnection ) self.commit_finished.connect(self._commit_finished, type=Qt.QueuedConnection) self.summary.cursor_changed.connect(self.cursor_changed.emit) self.description.cursor_changed.connect( # description starts at line 2 lambda row, col: self.cursor_changed.emit(row + 2, col) ) self.summary.textChanged.connect(self.commit_summary_changed) self.description.textChanged.connect(self._commit_message_changed) self.description.leave.connect(self.focus_summary) self.commit_group.setEnabled(False) self.set_expandtab(prefs.expandtab(context)) self.set_tabwidth(prefs.tabwidth(context)) self.set_textwidth(prefs.textwidth(context)) self.set_linebreak(prefs.linebreak(context)) # Loading message commit_msg = '' commit_msg_path = commit_message_path(context) if commit_msg_path: commit_msg = core.read(commit_msg_path) model.set_commitmsg(commit_msg) # Allow tab to jump from the summary to the description self.setTabOrder(self.summary, self.description) self.setFont(qtutils.diff_font(context)) self.setFocusProxy(self.summary) cfg.user_config_changed.connect(self.config_changed) def config_changed(self, key, value): if key != prefs.SPELL_CHECK: return if get(self.check_spelling_action) == value: return self.check_spelling_action.setChecked(value) self.toggle_check_spelling(value) 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 summary_cursor_down(self): """Handle the down key in the summary field If the cursor is at the end of the line then focus the description. Otherwise, move the cursor to the end of the line so that a subsequence "down" press moves to the end of the line. """ self.focus_description() def commit_message(self, raw=True): """Return the commit message as a Unicode string""" summary = get(self.summary) if raw: description = get(self.description) else: description = self.formatted_description() if summary and description: return summary + '\n\n' + description if summary: return summary if description: return '\n\n' + description return '' def formatted_description(self): text = get(self.description) if not self._linebreak: return text return textwrap.word_wrap(text, self._tabwidth, self._textwidth) def commit_summary_changed(self): """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 = self.summary.value() if '\n' in value: summary, description = value.split('\n', 1) description = description.lstrip('\n') cur_description = get(self.description) if cur_description: description = description + '\n' + cur_description # this callback is triggered by changing `summary` # so disable signals for `summary` only. self.summary.set_value(summary, block=True) self.description.set_value(description) self._commit_message_changed() def _commit_message_changed(self, _value=None): """Update the model when values change""" message = self.commit_message() self.model.set_commitmsg(message, notify=False) self.refresh_palettes() self.update_actions() def clear(self): if not Interaction.confirm( N_('Clear commit message?'), N_('The commit message will be cleared.'), N_('This cannot be undone. Clear commit message?'), N_('Clear commit message'), default=True, icon=icons.discard(), ): return self.model.set_commitmsg('') def update_actions(self): commit_enabled = bool(get(self.summary)) self.commit_group.setEnabled(commit_enabled) def refresh_palettes(self): """Update the color palette for the hint text""" self.summary.hint.refresh() self.description.hint.refresh() def set_commit_message(self, message): """Set the commit message to match the observed model""" # Parse the "summary" and "description" fields lines = message.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 self.summary.set_value(summary, block=True) # Update description self.description.set_value(description, block=True) # Update text color self.refresh_palettes() # Focus the empty summary or description if focus_summary: self.summary.setFocus() elif focus_description: self.description.setFocus() else: self.summary.cursor_position.emit() self.update_actions() def set_expandtab(self, value): self.description.set_expandtab(value) 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) with qtutils.BlockSignals(self.autowrap_action): self.autowrap_action.setChecked(brk) 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 with qtutils.BlockSignals(self.amend_action): self.amend_action.setEnabled(can_amend) self.amend_action.setChecked(checked) def commit(self): """Attempt to create a commit from the index and commit message.""" context = self.context if not bool(get(self.summary)): # 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) # We either need to have something staged, or be merging. # If there was a merge conflict resolved, there may not be anything # to stage, but we still need to commit to complete the merge. if not (self.model.staged or self.model.is_merging): 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 Interaction.confirm( N_('Stage and commit?'), error_msg, informative_text, N_('Stage and Commit'), default=True, icon=icons.save(), ): return else: Interaction.information(N_('Nothing to commit'), error_msg) return cmds.do(cmds.StageModified, context) # Warn that amending published commits is generally bad amend = get(self.amend_action) check_published = prefs.check_published_commits(context) if ( amend and check_published and self.model.is_commit_published() and not Interaction.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=icons.save(), ) ): return no_verify = get(self.bypass_commit_hooks_action) sign = get(self.sign_action) self.bypass_commit_hooks_action.setChecked(False) task = qtutils.SimpleTask( cmds.run(cmds.Commit, context, amend, msg, sign, no_verify=no_verify) ) self.context.runtask.start( task, finish=self.commit_finished.emit, progress=self.commit_progress_bar, ) def _commit_finished(self, task): """Reset widget state on completion of the commit task""" title = N_('Commit failed') status, out, err = task.result Interaction.command(title, 'git commit', status, out, err) self.setFocus() 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.LoadCommitMessageFromOID, self.load_commitmsg_menu, self.choose_commit_message, ) def build_commits_menu(self, cmd, menu, chooser, prefix=''): context = self.context params = dag.DAG('HEAD', 6) commits = dag.RepoReader(context, params) menu_commits = [] for idx, commit in enumerate(commits.get()): menu_commits.insert(0, commit) if idx > 5: continue menu.clear() for commit in menu_commits: menu.addAction(prefix + commit.summary, cmds.run(cmd, context, commit.oid)) if len(commits) == 6: menu.addSeparator() menu.addAction(N_('More...'), chooser) def choose_commit(self, cmd): context = self.context revs, summaries = gitcmds.log_helper(context) oids = select_commits( context, N_('Select Commit'), revs, summaries, multiselect=False ) if not oids: return oid = oids[0] cmds.do(cmd, context, oid) def choose_commit_message(self): self.choose_commit(cmds.LoadCommitMessageFromOID) def choose_fixup_commit(self): self.choose_commit(cmds.LoadFixupMessage) def toggle_check_spelling(self, enabled): spell_check = self.spellcheck cfg = self.context.cfg if prefs.spellcheck(self.context) != enabled: cfg.set_user(prefs.SPELL_CHECK, enabled) if enabled and not self.spellcheck_initialized: # Add our name to the dictionary self.spellcheck_initialized = True user_name = cfg.get('user.name') if user_name: for part in user_name.split(): spell_check.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('.'): spell_check.add_word(elt) # git jargon spell_check.add_word('Acked') spell_check.add_word('Signed') spell_check.add_word('Closes') spell_check.add_word('Fixes') self.summary.highlighter.enable(enabled) self.description.highlighter.enable(enabled) class CommitSummaryLineEdit(SpellCheckLineEdit): """Text input field for the commit summary""" down_pressed = Signal() accepted = Signal() def __init__(self, context, check=None, parent=None): hint = N_('Commit summary') SpellCheckLineEdit.__init__(self, context, hint, check=check, parent=parent) self._comment_char = None self._refresh_config() self.textChanged.connect(self._update_summary_text, Qt.QueuedConnection) context.cfg.updated.connect(self._refresh_config, type=Qt.QueuedConnection) def _refresh_config(self): """Update comment char in response to config changes""" self._comment_char = prefs.comment_char(self.context) def _update_summary_text(self): """Prevent commit messages from starting with comment characters""" value = self.value() if self._comment_char and value.startswith(self._comment_char): cursor = self.textCursor() position = cursor.position() value = value.lstrip() if self._comment_char: value = value.lstrip(self._comment_char).lstrip() self.set_value(value, block=True) value = self.value() if position > 1: position = max(0, min(position - 1, len(value) - 1)) cursor.setPosition(position) self.setTextCursor(cursor) def keyPressEvent(self, event): """Allow "Enter" to focus into the extended description field""" event_key = event.key() if event_key in ( Qt.Key_Enter, Qt.Key_Return, ): self.accepted.emit() return SpellCheckLineEdit.keyPressEvent(self, event) class CommitMessageTextEdit(SpellCheckTextEdit): leave = Signal() def __init__(self, context, check=None, parent=None): hint = N_('Extended description...') SpellCheckTextEdit.__init__(self, context, hint, check=check, parent=parent) self.action_emit_leave = qtutils.add_action( self, 'Shift Tab', self.leave.emit, hotkeys.LEAVE ) 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(): self.set_cursor_position(0) else: self.leave.emit() event.accept() return text_before = 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 = self.toPlainText() text_after = all_text[position:] lines_after = text_after.count('\n') if lines_after == 0: select = event.modifiers() & Qt.ShiftModifier mode = anchor_mode(select) cursor.setPosition(len(all_text), mode) self.setTextCursor(cursor) event.accept() return SpellCheckTextEdit.keyPressEvent(self, event) def setFont(self, font): SpellCheckTextEdit.setFont(self, font) width, height = qtutils.text_size(font, 'MMMM') self.setMinimumSize(QtCore.QSize(width, height * 2)) git-cola-4.6.1/cola/widgets/common.py000066400000000000000000000046521457126473700174760ustar00rootroot00000000000000import functools from ..i18n import N_ from .. import cmds from .. import hotkeys from .. import icons from .. import qtutils from .. import utils def cmd_action(parent, cmd, context, func, *keys): """Wrap a standard Command object in a QAction This function assumes that :func:`func()` takes no arguments, that `cmd` has a :func:`name()` method, and that the `cmd` constructor takes a single argument, as returned by `func`. """ return qtutils.add_action( parent, cmd.name(), lambda: cmds.do(cmd, context, func()), *keys ) def default_app_action(context, parent, func): """Open paths with the OS-default app -> QAction""" action = cmd_action( parent, cmds.OpenDefaultApp, context, func, hotkeys.PRIMARY_ACTION ) action.setIcon(icons.default_app()) return action def edit_action(context, parent, *keys): """Launch an editor -> QAction""" action = qtutils.add_action_with_tooltip( parent, cmds.LaunchEditor.name(), N_('Edit selected paths'), cmds.run(cmds.LaunchEditor, context), hotkeys.EDIT, *keys ) action.setIcon(icons.edit()) return action def parent_dir_action(context, parent, func): """Open the parent directory of paths -> QAction""" hotkey = hotkeys.SECONDARY_ACTION action = cmd_action(parent, cmds.OpenParentDir, context, func, hotkey) action.setIcon(icons.folder()) return action def worktree_dir_action(context, parent, *keys): """Open the repository worktree -> QAction""" # lambda: None is a no-op. action = cmd_action(parent, cmds.OpenWorktree, context, lambda: None, *keys) action.setIcon(icons.folder()) return action def refresh_action(context, parent): """Refresh the repository state -> QAction""" return qtutils.add_action( parent, cmds.Refresh.name(), cmds.run(cmds.Refresh, context), hotkeys.REFRESH ) def terminal_action(context, parent, func=None, hotkey=None): """Launch a terminal -> QAction""" action = None if cmds.LaunchTerminal.is_available(context): if func is None: func = functools.partial(lambda: None) action = cmd_action( parent, cmds.LaunchTerminal, context, lambda: utils.select_directory(func()), ) action.setIcon(icons.terminal()) if hotkey is not None: action.setShortcut(hotkey) return action git-cola-4.6.1/cola/widgets/compare.py000066400000000000000000000214741457126473700176350ustar00rootroot00000000000000"""Provides dialogs for comparing branches and commits.""" from qtpy import QtWidgets from qtpy.QtCore import Qt from .. import difftool from .. import gitcmds from .. import icons from .. import qtutils from ..i18n import N_ from ..qtutils import connect_button from . import defs from . import standard class FileItem(QtWidgets.QTreeWidgetItem): def __init__(self, path, icon): QtWidgets.QTreeWidgetItem.__init__(self, [path]) self.path = path self.setIcon(0, icon) def compare_branches(context): """Launches a dialog for comparing a pair of branches""" view = CompareBranchesDialog(context, qtutils.active_window()) view.show() return view class CompareBranchesDialog(standard.Dialog): def __init__(self, context, parent): standard.Dialog.__init__(self, parent=parent) self.context = context self.BRANCH_POINT = N_('*** Branch Point ***') self.SANDBOX = N_('*** Sandbox ***') self.LOCAL = N_('Local') self.diff_arg = () self.use_sandbox = False self.start = None self.end = None self.setWindowTitle(N_('Branch Diff Viewer')) self.remote_branches = gitcmds.branch_list(context, remote=True) self.local_branches = gitcmds.branch_list(context, remote=False) self.top_widget = QtWidgets.QWidget() self.bottom_widget = QtWidgets.QWidget() self.left_combo = QtWidgets.QComboBox() self.left_combo.addItem(N_('Local')) self.left_combo.addItem(N_('Remote')) self.left_combo.setCurrentIndex(0) self.right_combo = QtWidgets.QComboBox() self.right_combo.addItem(N_('Local')) self.right_combo.addItem(N_('Remote')) self.right_combo.setCurrentIndex(1) self.left_list = QtWidgets.QListWidget() self.right_list = QtWidgets.QListWidget() Expanding = QtWidgets.QSizePolicy.Expanding Minimum = QtWidgets.QSizePolicy.Minimum self.button_spacer = QtWidgets.QSpacerItem(1, 1, Expanding, Minimum) self.button_compare = qtutils.create_button( text=N_('Compare'), icon=icons.diff() ) self.button_close = qtutils.close_button() self.diff_files = standard.TreeWidget() self.diff_files.headerItem().setText(0, N_('File Differences')) self.top_grid_layout = qtutils.grid( defs.no_margin, defs.spacing, (self.left_combo, 0, 0, 1, 1), (self.left_list, 1, 0, 1, 1), (self.right_combo, 0, 1, 1, 1), (self.right_list, 1, 1, 1, 1), ) self.top_widget.setLayout(self.top_grid_layout) self.bottom_grid_layout = qtutils.grid( defs.no_margin, defs.button_spacing, (self.diff_files, 0, 0, 1, 4), (self.button_spacer, 1, 0, 1, 1), (self.button_close, 1, 2, 1, 1), (self.button_compare, 1, 3, 1, 1), ) self.bottom_widget.setLayout(self.bottom_grid_layout) self.splitter = qtutils.splitter( Qt.Vertical, self.top_widget, self.bottom_widget ) self.main_layout = qtutils.vbox(defs.margin, defs.spacing, self.splitter) self.setLayout(self.main_layout) connect_button(self.button_close, self.accept) connect_button(self.button_compare, self.compare) self.diff_files.itemDoubleClicked.connect(lambda _: self.compare()) self.left_combo.currentIndexChanged.connect( lambda x: self.update_combo_boxes(left=True) ) self.right_combo.currentIndexChanged.connect( lambda x: self.update_combo_boxes(left=False) ) self.left_list.itemSelectionChanged.connect(self.update_diff_files) self.right_list.itemSelectionChanged.connect(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) item.setSelected(True) item = self.right_list.item(0) if item: self.right_list.setCurrentItem(item) item.setSelected(True) self.init_size(parent=parent) def selection(self): left_item = self.left_list.currentItem() if left_item and left_item.isSelected(): left_item = left_item.text() else: left_item = None right_item = self.right_list.currentItem() if right_item and right_item.isSelected(): right_item = right_item.text() else: right_item = None return (left_item, right_item) def update_diff_files(self): """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 context = self.context if len(self.diff_arg) == 1: files = gitcmds.diff_index_filenames(context, self.diff_arg[0]) else: files = gitcmds.diff_filenames(context, *self.diff_arg) self.set_diff_files(files) def set_diff_files(self, files): mk = FileItem icon = icons.file_code() 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]'""" context = self.context if branch == self.BRANCH_POINT: # Compare against the branch point so find the merge-base branch = gitcmds.current_branch(context) tracked_branch = gitcmds.tracked_branch(context) if tracked_branch: return gitcmds.merge_base(context, branch, tracked_branch) remote_branches = gitcmds.branch_list(context, remote=True) remote_branch = 'origin/%s' % branch if remote_branch in remote_branches: return gitcmds.merge_base(context, branch, remote_branch) if 'origin/main' in remote_branches: return gitcmds.merge_base(context, branch, 'origin/main') if 'origin/master' in remote_branches: return gitcmds.merge_base(context, branch, 'origin/master') return 'HEAD' # 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 = self.left_combo.currentText() widget = self.left_list else: which = 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) item.setSelected(True) def compare(self): """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: left = self.diff_arg[0] if len(self.diff_arg) > 1: right = self.diff_arg[1] else: right = None else: left, right = self.start, self.end context = self.context difftool.difftool_launch(context, left=left, right=right, paths=[filename]) git-cola-4.6.1/cola/widgets/completion.py000066400000000000000000000716671457126473700203710ustar00rootroot00000000000000import re import time from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from ..models import prefs from .. import core from .. import gitcmds from .. import icons from .. import qtutils from .. import utils from . import defs from .text import HintedLineEdit class ValidateRegex: def __init__(self, regex): self.regex = re.compile(regex) # regex to scrub def validate(self, string, idx): """Scrub and validate the user-supplied input""" state = QtGui.QValidator.Acceptable if self.regex.search(string): string = self.regex.sub('', string) # scrub matching bits idx = min(idx - 1, len(string)) return (state, string, idx) class RemoteValidator(QtGui.QValidator): """Prevent invalid remote names""" def __init__(self, parent=None): super().__init__(parent) self._validate = ValidateRegex(r'[ \t\\/]') def validate(self, string, idx): return self._validate.validate(string, idx) class BranchValidator(QtGui.QValidator): """Prevent invalid branch names""" def __init__(self, git, parent=None): super().__init__(parent) self._git = git self._validate = ValidateRegex(r'[ \t\\]') # forward-slash is okay def validate(self, string, idx): """Scrub and validate the user-supplied input""" state, string, idx = self._validate.validate(string, idx) if string: # Allow empty strings status, _, _ = self._git.check_ref_format(string, branch=True) if status != 0: # The intermediate string, when deleting characters, might # end in a name that is invalid to Git, but we must allow it # otherwise we won't be able to delete it using backspace. if string.endswith('/') or string.endswith('.'): state = self.Intermediate else: state = self.Invalid return (state, string, idx) def _is_case_sensitive(text): return bool([char for char in text if char.isupper()]) class CompletionLineEdit(HintedLineEdit): """A lineedit with advanced completion abilities""" activated = Signal() changed = Signal() cleared = Signal() enter = Signal() up = Signal() down = Signal() # Activation keys will cause a selected completion item to be chosen ACTIVATION_KEYS = (Qt.Key_Return, Qt.Key_Enter) # Navigation keys trigger signals that widgets can use for customization NAVIGATION_KEYS = { Qt.Key_Return: 'enter', Qt.Key_Enter: 'enter', Qt.Key_Up: 'up', Qt.Key_Down: 'down', } def __init__( self, context, model_factory, hint='', show_all_completions=False, parent=None ): HintedLineEdit.__init__(self, context, hint, parent=parent) # Tracks when the completion popup was active during key events self.context = context # The most recently selected completion item self._selection = None self._show_all_completions = show_all_completions # Create a completion model completion_model = model_factory(context, self) completer = Completer(completion_model, self) completer.setWidget(self) self._completer = completer self._completion_model = completion_model # The delegate highlights matching completion text in the popup widget self._delegate = HighlightDelegate(self) completer.popup().setItemDelegate(self._delegate) self.textChanged.connect(self._text_changed) self._completer.activated.connect(self.choose_completion) self._completion_model.updated.connect( self._completions_updated, type=Qt.QueuedConnection ) self.destroyed.connect(self.dispose) def __del__(self): self.dispose() def dispose(self, *args): self._completer.dispose() def completion_selection(self): """Return the last completion's selection""" return self._selection def complete(self): """Trigger the completion popup to appear and offer completions""" self._completer.complete() def refresh(self): """Refresh the completion model""" return self._completer.model().update() def popup(self): """Return the completer's popup""" return self._completer.popup() def _text_changed(self, full_text): match_text = self._last_word() self._do_text_changed(full_text, match_text) self.complete_last_word() def _do_text_changed(self, full_text, match_text): case_sensitive = _is_case_sensitive(match_text) if case_sensitive: self._completer.setCaseSensitivity(Qt.CaseSensitive) else: self._completer.setCaseSensitivity(Qt.CaseInsensitive) self._delegate.set_highlight_text(match_text, case_sensitive) self._completer.set_match_text(full_text, match_text, case_sensitive) def update_matches(self): text = self._last_word() case_sensitive = _is_case_sensitive(text) self._completer.setCompletionPrefix(text) self._completer.model().update_matches(case_sensitive) def choose_completion(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. """ 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 = core.list2cmdline(words) self.setText(text) self.changed.emit() self._do_text_changed(text, '') self.popup().hide() def _words(self): return utils.shell_split(self.value()) def _ends_with_whitespace(self): value = self.value() return value != value.rstrip() def _last_word(self): if self._ends_with_whitespace(): return '' words = self._words() if not words: return self.value() if not words[-1]: return '' return words[-1] def complete_last_word(self): self.update_matches() self.complete() def close_popup(self): """Close the completion popup""" self.popup().close() def _completions_updated(self): """Select the first completion item when completions are updated""" popup = self.popup() if self._completion_model.rowCount() == 0: popup.hide() return if not popup.isVisible(): if not self.hasFocus() or not self._show_all_completions: return self.select_first_completion() def select_first_completion(self): """Select the first item in the completion model""" idx = self._completion_model.index(0, 0) mode = ( QtCore.QItemSelectionModel.Rows | QtCore.QItemSelectionModel.SelectCurrent ) self.popup().selectionModel().setCurrentIndex(idx, mode) def selected_completion(self): """Return the selected completion item""" popup = self.popup() if not popup.isVisible(): return None model = popup.selectionModel() indexes = model.selectedIndexes() if not indexes: return None idx = indexes[0] item = self._completion_model.itemFromIndex(idx) if not item: return None return item.text() def select_completion(self): """Choose the selected completion option from the completion popup""" result = False visible = self.popup().isVisible() if visible: selection = self.selected_completion() if selection: self.choose_completion(selection) result = True return result def show_popup(self): """Display the completion popup""" self.refresh() x_val = self.x() y_val = self.y() + self.height() point = QtCore.QPoint(x_val, y_val) mapped = self.parent().mapToGlobal(point) popup = self.popup() popup.move(mapped.x(), mapped.y()) popup.show() # Qt overrides def event(self, event): """Override QWidget::event() for tab completion""" event_type = event.type() if ( event_type == QtCore.QEvent.KeyPress and event.key() == Qt.Key_Tab and self.select_completion() ): return True # Make sure the popup goes away during teardown if event_type == QtCore.QEvent.Close: self.close_popup() elif event_type == QtCore.QEvent.Hide: self.popup().hide() return super().event(event) def keyPressEvent(self, event): """Process completion and navigation events""" super().keyPressEvent(event) popup = self.popup() visible = popup.isVisible() # Hide the popup when the field becomes empty. is_empty = not self.value() if is_empty and event.modifiers() != Qt.ControlModifier: self.cleared.emit() if visible: popup.hide() # Activation keys select the completion when pressed and emit the # activated signal. Navigation keys have lower priority, and only # emit when it wasn't already handled as an activation event. key = event.key() if key in self.ACTIVATION_KEYS and visible: if self.select_completion(): self.activated.emit() return navigation = self.NAVIGATION_KEYS.get(key, None) if navigation: signal = getattr(self, navigation) signal.emit() return # Show the popup when Ctrl-Space is pressed. if ( not visible and key == Qt.Key_Space and event.modifiers() == Qt.ControlModifier ): self.show_popup() class GatherCompletionsThread(QtCore.QThread): items_gathered = Signal(object) def __init__(self, model): QtCore.QThread.__init__(self) self.model = model self.case_sensitive = False self.running = False def dispose(self): self.running = False utils.catch_runtime_error(self.wait) def run(self): text = None items = [] self.running = True # Loop when the matched text changes between the start and end time. # This happens when gather_matches() takes too long and the # model's match_text changes in-between. while self.running and text != self.model.match_text: text = self.model.match_text items = self.model.gather_matches(self.case_sensitive) if self.running and text is not None: self.items_gathered.emit(items) class HighlightDelegate(QtWidgets.QStyledItemDelegate): """A delegate used for auto-completion to give formatted completion""" def __init__(self, parent): QtWidgets.QStyledItemDelegate.__init__(self, parent) self.widget = parent self.highlight_text = '' self.case_sensitive = False self.doc = QtGui.QTextDocument() # older PyQt4 does not have setDocumentMargin if hasattr(self.doc, 'setDocumentMargin'): self.doc.setDocumentMargin(0) def set_highlight_text(self, text, case_sensitive): """Sets the text that will be made bold 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: QtWidgets.QStyledItemDelegate.paint(self, painter, option, index) return text = index.data() 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 params = QtWidgets.QStyleOptionViewItem(option) self.initStyleOption(params, index) params.text = '' style = QtWidgets.QApplication.style() style.drawControl(QtWidgets.QStyle.CE_ItemViewItem, params, painter) ctx = QtGui.QAbstractTextDocumentLayout.PaintContext() # Highlighting text if item is selected if params.state & QtWidgets.QStyle.State_Selected: color = params.palette.color( QtGui.QPalette.Active, QtGui.QPalette.HighlightedText ) ctx.palette.setColor(QtGui.QPalette.Text, color) # translate the painter to where the text is drawn item_text = QtWidgets.QStyle.SE_ItemViewItemText rect = style.subElementRect(item_text, params, self.widget) painter.save() start = rect.topLeft() + QtCore.QPoint(defs.margin, 0) painter.translate(start) # tell the text document to draw the html for us self.doc.documentLayout().draw(painter, ctx) painter.restore() def ref_sort_key(ref): """Sort key function that causes shorter refs to sort first, but alphabetizes refs of equal length (in order to make local branches sort before remote ones).""" return len(ref), ref class CompletionModel(QtGui.QStandardItemModel): updated = Signal() items_gathered = Signal(object) model_updated = Signal() def __init__(self, context, parent): QtGui.QStandardItemModel.__init__(self, parent) self.context = context self.match_text = '' self.full_text = '' self.case_sensitive = False self.update_thread = GatherCompletionsThread(self) self.update_thread.items_gathered.connect( self.apply_matches, type=Qt.QueuedConnection ) def update(self): case_sensitive = self.update_thread.case_sensitive self.update_matches(case_sensitive) def set_match_text(self, full_text, match_text, case_sensitive): self.full_text = full_text self.match_text = match_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): """Build widgets for all of the matching items""" if not match_tuple: # Results from background tasks may arrive after the widget # has been destroyed. utils.catch_runtime_error(self.set_items, []) return matched_refs, matched_paths, dirs = match_tuple QStandardItem = QtGui.QStandardItem dir_icon = icons.directory() git_icon = icons.cola() items = [] for ref in matched_refs: item = QStandardItem() item.setText(ref) item.setIcon(git_icon) items.append(item) from_filename = icons.from_filename for match in matched_paths: item = QStandardItem() item.setText(match) if match in dirs: item.setIcon(dir_icon) else: item.setIcon(from_filename(match)) items.append(item) # Results from background tasks can arrive after the widget has been destroyed. utils.catch_runtime_error(self.set_items, items) def set_items(self, items): """Clear the widget and add items to the model""" self.clear() self.invisibleRootItem().appendRows(items) self.updated.emit() def dispose(self): self.update_thread.dispose() def _identity(value): return value def _lower(value): return value.lower() def filter_matches(match_text, candidates, case_sensitive, sort_key=None): """Filter candidates and return the matches""" if case_sensitive: case_transform = _identity else: case_transform = _lower if match_text: match_text = case_transform(match_text) matches = [r for r in candidates if match_text in case_transform(r)] else: matches = list(candidates) if case_sensitive: if sort_key is None: matches.sort() else: matches.sort(key=sort_key) else: if sort_key is None: matches.sort(key=_lower) else: matches.sort(key=lambda x: sort_key(_lower(x))) return matches def filter_path_matches(match_text, file_list, case_sensitive): """Return matching completions from a list of candidate files""" files = set(file_list) files_and_dirs = utils.add_parents(files) dirs = files_and_dirs.difference(files) paths = filter_matches(match_text, files_and_dirs, case_sensitive) return (paths, dirs) class Completer(QtWidgets.QCompleter): def __init__(self, model, parent): QtWidgets.QCompleter.__init__(self, parent) self._model = model self.setCompletionMode(QtWidgets.QCompleter.UnfilteredPopupCompletion) self.setCaseSensitivity(Qt.CaseInsensitive) self.setFilterMode(QtCore.Qt.MatchContains) model.model_updated.connect(self.update, type=Qt.QueuedConnection) self.setModel(model) def update(self): self._model.update() def dispose(self): self._model.dispose() def set_match_text(self, full_text, match_text, case_sensitive): self._model.set_match_text(full_text, match_text, case_sensitive) class GitCompletionModel(CompletionModel): def __init__(self, context, parent): CompletionModel.__init__(self, context, parent) self.context = context context.model.updated.connect(self.model_updated, type=Qt.QueuedConnection) def gather_matches(self, case_sensitive): refs = filter_matches( self.match_text, self.matches(), case_sensitive, sort_key=ref_sort_key ) return (refs, (), set()) def matches(self): return [] class GitRefCompletionModel(GitCompletionModel): """Completer for branches and tags""" def __init__(self, context, parent): GitCompletionModel.__init__(self, context, parent) context.model.refs_updated.connect(self.model_updated, type=Qt.QueuedConnection) def matches(self): model = self.context.model return model.local_branches + model.remote_branches + model.tags def find_potential_branches(model): remotes = model.remotes remote_branches = model.remote_branches ambiguous = set() allnames = set(model.local_branches) potential = [] for remote_branch in remote_branches: branch = gitcmds.strip_remote(remotes, remote_branch) if branch in allnames or branch == remote_branch: ambiguous.add(branch) continue potential.append(branch) allnames.add(branch) potential_branches = [p for p in potential if p not in ambiguous] return potential_branches class GitCreateBranchCompletionModel(GitCompletionModel): """Completer for naming new branches""" def matches(self): model = self.context.model potential_branches = find_potential_branches(model) return model.local_branches + potential_branches + model.tags class GitCheckoutBranchCompletionModel(GitCompletionModel): """Completer for git checkout """ def matches(self): model = self.context.model potential_branches = find_potential_branches(model) return ( model.local_branches + potential_branches + model.remote_branches + model.tags ) class GitBranchCompletionModel(GitCompletionModel): """Completer for local branches""" def __init__(self, context, parent): GitCompletionModel.__init__(self, context, parent) def matches(self): model = self.context.model return model.local_branches class GitRemoteBranchCompletionModel(GitCompletionModel): """Completer for remote branches""" def __init__(self, context, parent): GitCompletionModel.__init__(self, context, parent) def matches(self): model = self.context.model return model.remote_branches class GitPathCompletionModel(GitCompletionModel): """Base class for path completion""" def __init__(self, context, parent): GitCompletionModel.__init__(self, context, parent) def candidate_paths(self): return [] def gather_matches(self, case_sensitive): paths, dirs = filter_path_matches( self.match_text, self.candidate_paths(), case_sensitive ) return ((), paths, dirs) class GitStatusFilterCompletionModel(GitPathCompletionModel): """Completer for modified files and folders for status filtering""" def __init__(self, context, parent): GitPathCompletionModel.__init__(self, context, parent) def candidate_paths(self): model = self.context.model return model.staged + model.unmerged + model.modified + model.untracked class GitTrackedCompletionModel(GitPathCompletionModel): """Completer for tracked files and folders""" def __init__(self, context, parent): GitPathCompletionModel.__init__(self, context, parent) self.model_updated.connect(self.gather_paths, type=Qt.QueuedConnection) self._paths = [] def gather_paths(self): context = self.context self._paths = gitcmds.tracked_files(context) def gather_matches(self, case_sensitive): if not self._paths: self.gather_paths() refs = [] paths, dirs = filter_path_matches(self.match_text, self._paths, case_sensitive) return (refs, paths, dirs) class GitLogCompletionModel(GitRefCompletionModel): """Completer for arguments suitable for git-log like commands""" def __init__(self, context, parent): GitRefCompletionModel.__init__(self, context, parent) self._paths = [] self._model = context.model self._runtask = qtutils.RunTask(parent=self) self._time = 0.0 # ensure that the first event runs a task. self.model_updated.connect( self._start_gathering_paths, type=Qt.QueuedConnection ) def matches(self): """Return candidate values for completion""" matches = super().matches() return [ '--all', '--all-match', '--author', '--after=two.days.ago', '--basic-regexp', '--before=two.days.ago', '--branches', '--committer', '--exclude', '--extended-regexp', '--find-object', '--first-parent', '--fixed-strings', '--full-diff', '--grep', '--invert-grep', '--merges', '--no-merges', '--not', '--perl-regexp', '--pickaxe-all', '--pickaxe-regex', '--regexp-ignore-case', '--tags', '-D', '-E', '-F', '-G', '-P', '-S', '@{upstream}', ] + matches def _start_gathering_paths(self): """Gather paths when the model changes""" # Debounce updates that land within 1 second of each other. if time.time() - self._time > 1.0: self._runtask.start(qtutils.SimpleTask(self.gather_paths)) self._time = time.time() def gather_paths(self): """Gather paths and store them in the model""" self._time = time.time() if self._model.cfg.get(prefs.AUTOCOMPLETE_PATHS, True): self._paths = gitcmds.tracked_files(self.context) else: self._paths = [] self._time = time.time() def gather_matches(self, case_sensitive): """Filter paths and refs to find matching entries""" if not self._paths: self.gather_paths() refs = filter_matches( self.match_text, self.matches(), case_sensitive, sort_key=ref_sort_key ) paths, dirs = filter_path_matches(self.match_text, self._paths, case_sensitive) has_doubledash = ( self.match_text == '--' or self.full_text.startswith('-- ') or ' -- ' in self.full_text ) if has_doubledash: refs = [] elif refs and paths: paths.insert(0, '--') return (refs, paths, dirs) def bind_lineedit(model, hint='', show_all_completions=False): """Create a line edit bound against a specific model""" class BoundLineEdit(CompletionLineEdit): def __init__(self, context, hint=hint, parent=None): CompletionLineEdit.__init__( self, context, model, hint=hint, show_all_completions=show_all_completions, parent=parent, ) self.context = context return BoundLineEdit # Concrete classes GitLogLineEdit = bind_lineedit(GitLogCompletionModel, hint='') GitRefLineEdit = bind_lineedit(GitRefCompletionModel, hint='') GitCheckoutBranchLineEdit = bind_lineedit( GitCheckoutBranchCompletionModel, hint='', show_all_completions=True, ) GitCreateBranchLineEdit = bind_lineedit(GitCreateBranchCompletionModel, hint='') GitBranchLineEdit = bind_lineedit(GitBranchCompletionModel, hint='') GitRemoteBranchLineEdit = bind_lineedit( GitRemoteBranchCompletionModel, hint='' ) GitStatusFilterLineEdit = bind_lineedit(GitStatusFilterCompletionModel, hint='') GitTrackedLineEdit = bind_lineedit(GitTrackedCompletionModel, hint='') class GitDialog(QtWidgets.QDialog): # The "lineedit" argument is provided by the derived class constructor. def __init__(self, lineedit, context, title, text, parent, icon=None): QtWidgets.QDialog.__init__(self, parent) self.context = context self.setWindowTitle(title) self.setWindowModality(Qt.WindowModal) self.setMinimumWidth(333) self.label = QtWidgets.QLabel() self.label.setText(title) self.lineedit = lineedit(context) self.ok_button = qtutils.ok_button(text, icon=icon, enabled=False) self.close_button = qtutils.close_button() self.button_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, qtutils.STRETCH, self.close_button, self.ok_button, ) self.main_layout = qtutils.vbox( defs.margin, defs.spacing, self.label, self.lineedit, self.button_layout ) self.setLayout(self.main_layout) self.lineedit.textChanged.connect(self.text_changed) self.lineedit.enter.connect(self.accept) qtutils.connect_button(self.ok_button, self.accept) qtutils.connect_button(self.close_button, self.reject) self.setFocusProxy(self.lineedit) self.lineedit.setFocus() def text(self): return 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, context, title, text, parent, default=None, icon=None): dlg = cls(context, title, text, parent, icon=icon) if default: dlg.set_text(default) dlg.show() QtCore.QTimer().singleShot(250, dlg.lineedit.show_popup) if dlg.exec_() == cls.Accepted: return dlg.text() return None class GitRefDialog(GitDialog): def __init__(self, context, title, text, parent, icon=None): GitDialog.__init__( self, GitRefLineEdit, context, title, text, parent, icon=icon ) class GitCheckoutBranchDialog(GitDialog): def __init__(self, context, title, text, parent, icon=None): GitDialog.__init__( self, GitCheckoutBranchLineEdit, context, title, text, parent, icon=icon ) class GitBranchDialog(GitDialog): def __init__(self, context, title, text, parent, icon=None): GitDialog.__init__( self, GitBranchLineEdit, context, title, text, parent, icon=icon ) class GitRemoteBranchDialog(GitDialog): def __init__(self, context, title, text, parent, icon=None): GitDialog.__init__( self, GitRemoteBranchLineEdit, context, title, text, parent, icon=icon ) git-cola-4.6.1/cola/widgets/createbranch.py000066400000000000000000000276201457126473700206270ustar00rootroot00000000000000from qtpy import QtWidgets from qtpy import QtCore from qtpy.QtCore import Qt from qtpy.QtCore import Signal from ..i18n import N_ from ..interaction import Interaction from ..qtutils import get from .. import gitcmds from .. import icons from .. import qtutils from . import defs from . import completion from . import standard def create_new_branch(context, revision=''): """Launches a dialog for creating a new branch""" view = CreateBranchDialog(context, parent=qtutils.active_window()) if revision: view.set_revision(revision) view.show() return view class CreateOpts: def __init__(self, context): self.context = context self.reset = False self.track = False self.fetch = True self.checkout = True self.revision = 'HEAD' self.branch = '' class CreateThread(QtCore.QThread): command = Signal(object, object, object) result = Signal(object) 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 context = self.opts.context git = context.git model = context.model results = [] status = 0 if track and '/' in revision: remote = revision.split('/', 1)[0] status, out, err = git.fetch(remote) self.command.emit(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.command.emit(status, out, err) results.append(('branch', status, out, err)) if status == 0 and checkout: status, out, err = git.checkout(branch) self.command.emit(status, out, err) results.append(('checkout', status, out, err)) model.update_status() self.result.emit(results) class CreateBranchDialog(standard.Dialog): """A dialog for creating branches.""" def __init__(self, context, parent=None): standard.Dialog.__init__(self, parent=parent) self.setWindowTitle(N_('Create Branch')) if parent is not None: self.setWindowModality(Qt.WindowModal) self.context = context self.model = context.model self.opts = CreateOpts(context) self.thread = CreateThread(self.opts, self) self.progress = None self.branch_name_label = QtWidgets.QLabel() self.branch_name_label.setText(N_('Branch Name')) self.branch_name = completion.GitCreateBranchLineEdit(context) self.branch_validator = completion.BranchValidator( context.git, parent=self.branch_name ) self.branch_name.setValidator(self.branch_validator) self.rev_label = QtWidgets.QLabel() self.rev_label.setText(N_('Starting Revision')) self.revision = completion.GitRefLineEdit(context) current = gitcmds.current_branch(context) if current: self.revision.setText(current) self.local_radio = qtutils.radio(text=N_('Local branch'), checked=True) self.remote_radio = qtutils.radio(text=N_('Tracking branch')) self.tag_radio = qtutils.radio(text=N_('Tag')) self.branch_list = QtWidgets.QListWidget() self.update_existing_label = QtWidgets.QLabel() self.update_existing_label.setText(N_('Update Existing Branch:')) self.no_update_radio = qtutils.radio(text=N_('No')) self.ffwd_only_radio = qtutils.radio(text=N_('Fast Forward Only'), checked=True) self.reset_radio = qtutils.radio(text=N_('Reset')) text = N_('Fetch Tracking Branch') self.fetch_checkbox = qtutils.checkbox(text=text, checked=True) text = N_('Checkout After Creation') self.checkout_checkbox = qtutils.checkbox(text=text, checked=True) icon = icons.branch() self.create_button = qtutils.create_button( text=N_('Create Branch'), icon=icon, default=True ) self.close_button = qtutils.close_button() self.options_checkbox_layout = qtutils.hbox( defs.margin, defs.spacing, self.fetch_checkbox, self.checkout_checkbox, qtutils.STRETCH, ) self.branch_name_layout = qtutils.hbox( defs.margin, defs.spacing, self.branch_name_label, self.branch_name ) self.rev_radio_group = qtutils.buttongroup( self.local_radio, self.remote_radio, self.tag_radio ) self.rev_radio_layout = qtutils.hbox( defs.margin, defs.spacing, self.local_radio, self.remote_radio, self.tag_radio, qtutils.STRETCH, ) self.rev_start_textinput_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.rev_label, defs.spacing, self.revision ) self.rev_start_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.rev_radio_layout, self.branch_list, self.rev_start_textinput_layout, ) self.options_radio_group = qtutils.buttongroup( self.no_update_radio, self.ffwd_only_radio, self.reset_radio ) self.options_radio_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.update_existing_label, self.no_update_radio, self.ffwd_only_radio, self.reset_radio, qtutils.STRETCH, ) self.buttons_layout = qtutils.hbox( defs.margin, defs.spacing, qtutils.STRETCH, self.close_button, self.create_button, ) self.main_layout = qtutils.vbox( defs.margin, defs.spacing, self.branch_name_layout, self.rev_start_layout, defs.button_spacing, self.options_radio_layout, self.options_checkbox_layout, self.buttons_layout, ) self.setLayout(self.main_layout) qtutils.add_close_action(self) qtutils.connect_button(self.close_button, self.close) qtutils.connect_button(self.create_button, self.create_branch) qtutils.connect_toggle(self.local_radio, self.display_model) qtutils.connect_toggle(self.remote_radio, self.display_model) qtutils.connect_toggle(self.tag_radio, self.display_model) branches = self.branch_list branches.itemSelectionChanged.connect(self.branch_item_changed) thread = self.thread thread.command.connect(Interaction.log_status, type=Qt.QueuedConnection) thread.result.connect(self.thread_result, type=Qt.QueuedConnection) self.init_size(settings=context.settings, parent=parent) self.display_model() def set_revision(self, revision): self.revision.setText(revision) def getopts(self): self.opts.revision = get(self.revision) self.opts.branch = get(self.branch_name) self.opts.checkout = get(self.checkout_checkbox) self.opts.reset = get(self.reset_radio) self.opts.fetch = get(self.fetch_checkbox) self.opts.track = get(self.remote_radio) def create_branch(self): """Creates a branch; called by the "Create Branch" button""" context = self.context self.getopts() revision = self.opts.revision branch = self.opts.branch no_update = get(self.no_update_radio) ffwd_only = get(self.ffwd_only_radio) existing_branches = gitcmds.branch_list(context) check_branch = False if not branch or not revision: Interaction.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 Interaction.critical(N_('Branch Exists'), msg) return # Whether we should prompt the user for lost commits commits = gitcmds.rev_list_range(context, revision, branch) check_branch = bool(commits) if check_branch: msg = N_('Resetting "%(branch)s" to "%(revision)s" will lose commits.') % { 'branch': branch, 'revision': revision, } if ffwd_only: Interaction.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) info_text = N_('Reset "%(branch)s" to "%(revision)s"?') % { 'branch': branch, 'revision': revision, } if not Interaction.confirm( N_('Reset Branch?'), '\n'.join(lines), info_text, N_('Reset Branch'), default=False, icon=icons.undo(), ): return title = N_('Create Branch') label = N_('Updating') self.progress = standard.progress(title, label, self) self.progress.show() self.thread.start() def thread_result(self, results): self.progress.hide() del self.progress for cmd, status, _, _ in results: if status != 0: Interaction.critical( N_('Error Creating Branch'), ( N_('"%(command)s" returned exit status "%(status)d"') % { 'command': 'git ' + cmd, 'status': status, } ), ) return 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 remote_branch = qtutils.selected_item(qlist, self.branch_sources()) if not remote_branch: return # Update the model with the selection self.revision.setText(remote_branch) # Set the branch field if we're branching from a remote branch. if not get(self.remote_radio): return branch = gitcmds.strip_remote(self.model.remotes, remote_branch) if branch == 'HEAD': return # Signal that we've clicked on a remote branch self.branch_name.set_value(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 get(self.local_radio): value = self.model.local_branches elif get(self.remote_radio): value = self.model.remote_branches elif get(self.tag_radio): value = self.model.tags else: value = [] return value def dispose(self): self.branch_name.dispose() self.revision.dispose() git-cola-4.6.1/cola/widgets/createtag.py000066400000000000000000000100101457126473700201260ustar00rootroot00000000000000from qtpy import QtWidgets from qtpy.QtCore import Qt from .. import cmds from .. import icons from .. import qtutils from ..i18n import N_ from ..qtutils import get from . import defs from . import completion from . import standard from . import text def new_create_tag(context, name='', ref='', sign=False, parent=None): """Entry point for external callers.""" opts = TagOptions(name, ref, sign) view = CreateTag(context, opts, parent=parent) return view def create_tag(context, name='', ref='', sign=False): """Entry point for external callers.""" view = new_create_tag( context, name=name, ref=ref, sign=sign, parent=qtutils.active_window(), ) view.show() view.raise_() return view class TagOptions: """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, context, opts, parent=None): standard.Dialog.__init__(self, parent=parent) self.context = context self.model = model = context.model self.opts = opts self.setWindowTitle(N_('Create Tag')) if parent is not None: self.setWindowModality(Qt.WindowModal) # Tag label self.tag_name_label = QtWidgets.QLabel(self) self.tag_name_label.setText(N_('Name')) self.tag_name = text.HintedLineEdit(context, N_('vX.Y.Z'), parent=self) self.tag_name.set_value(opts.name) self.tag_name.setToolTip(N_('Specifies the tag name')) qtutils.add_completer(self.tag_name, model.tags) # Sign Tag self.sign_label = QtWidgets.QLabel(self) self.sign_label.setText(N_('Sign Tag')) tooltip = N_('Whether to sign the tag (git tag -s)') self.sign_tag = qtutils.checkbox(checked=True, tooltip=tooltip) # Tag message self.tag_msg_label = QtWidgets.QLabel(self) self.tag_msg_label.setText(N_('Message')) self.tag_msg = text.HintedPlainTextEdit(context, N_('Tag message...'), self) self.tag_msg.setToolTip(N_('Specifies the tag message')) # Revision self.rev_label = QtWidgets.QLabel(self) self.rev_label.setText(N_('Revision')) self.revision = completion.GitRefLineEdit(context) self.revision.setText(self.opts.ref) self.revision.setToolTip(N_('Specifies the SHA-1 to tag')) # Buttons self.create_button = qtutils.create_button( text=N_('Create Tag'), icon=icons.tag(), default=True ) self.close_button = qtutils.close_button() # Form layout for inputs self.input_layout = qtutils.form( defs.margin, defs.spacing, (self.tag_name_label, self.tag_name), (self.tag_msg_label, self.tag_msg), (self.rev_label, self.revision), (self.sign_label, self.sign_tag), ) self.button_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, qtutils.STRETCH, self.close_button, self.create_button, ) self.main_layt = qtutils.vbox( defs.margin, defs.spacing, self.input_layout, self.button_layout ) self.setLayout(self.main_layt) qtutils.connect_button(self.close_button, self.close) qtutils.connect_button(self.create_button, self.create_tag) settings = context.settings self.init_state(settings, self.resize, defs.scale(720), defs.scale(210)) def create_tag(self): """Verifies inputs and emits a notifier tag message.""" context = self.context revision = get(self.revision) tag_name = get(self.tag_name) tag_msg = get(self.tag_msg) sign_tag = get(self.sign_tag) ok = cmds.do( cmds.Tag, context, tag_name, revision, sign=sign_tag, message=tag_msg ) if ok: self.close() git-cola-4.6.1/cola/widgets/dag.py000066400000000000000000002424251457126473700167430ustar00rootroot00000000000000import collections import itertools import math from functools import partial from qtpy.QtCore import Qt from qtpy.QtCore import Signal from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from ..compat import maxsize from ..i18n import N_ from ..models import dag from ..models import main from ..qtutils import get from .. import core from .. import cmds from .. import difftool from .. import gitcmds from .. import guicmds from .. import hotkeys from .. import icons from .. import qtcompat from .. import qtutils from .. import utils from . import archive from . import browse from . import completion from . import createbranch from . import createtag from . import defs from . import diff from . import filelist from . import standard def git_dag(context, args=None, existing_view=None, show=True): """Return a pre-populated git DAG widget.""" model = context.model branch = model.currentbranch # disambiguate between branch names and filenames by using '--' branch_doubledash = (branch + ' --') if branch else '' params = dag.DAG(branch_doubledash, 1000) params.set_arguments(args) if existing_view is None: view = GitDAG(context, params) else: view = existing_view view.set_params(params) if params.ref: view.display() if show: view.show() return view class FocusRedirectProxy: """Redirect actions from the main widget to child widgets""" def __init__(self, *widgets): """Provide proxied widgets; the default widget must be first""" self.widgets = widgets self.default = widgets[0] def __getattr__(self, name): return lambda *args, **kwargs: self._forward_action(name, *args, **kwargs) def _forward_action(self, name, *args, **kwargs): """Forward the captured action to the focused or default widget""" widget = QtWidgets.QApplication.focusWidget() if widget in self.widgets and hasattr(widget, name): func = getattr(widget, name) else: func = getattr(self.default, name) return func(*args, **kwargs) class ViewerMixin: """Implementations must provide selected_items()""" def __init__(self): self.context = None # provided by implementation self.selected = None self.clicked = None self.menu_actions = None # provided by implementation 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_oid(self): """Return the currently selected commit object ID""" item = self.selected_item() if item is None: result = None else: result = item.commit.oid return result def selected_oids(self): """Return the currently selected commit object IDs""" return [i.commit for i in self.selected_items()] def clicked_oid(self): """Return the clicked or selected commit object ID""" if self.clicked: return self.clicked.oid return self.selected_oid() def with_oid(self, func): """Run an operation with a commit object ID""" oid = self.clicked_oid() if oid: result = func(oid) else: result = None return result def with_selected_oid(self, func): """Run an operation with a commit object ID""" oid = self.selected_oid() if oid: result = func(oid) else: result = None return result def diff_selected_this(self): """Diff the selected commit against the clicked commit""" clicked_oid = self.clicked.oid selected_oid = self.selected.oid self.diff_commits.emit(selected_oid, clicked_oid) def diff_this_selected(self): """Diff the clicked commit against the selected commit""" clicked_oid = self.clicked.oid selected_oid = self.selected.oid self.diff_commits.emit(clicked_oid, selected_oid) def cherry_pick(self): """Cherry-pick a commit using git cherry-pick""" context = self.context self.with_oid(lambda oid: cmds.do(cmds.CherryPick, context, [oid])) def revert(self): """Revert a commit using git revert""" context = self.context self.with_oid(lambda oid: cmds.do(cmds.Revert, context, oid)) def copy_to_clipboard(self): """Copy the current commit object ID to the clipboard""" self.with_oid(qtutils.set_clipboard) def checkout_branch(self): """Checkout the clicked/selected branch""" branches = [] clicked = self.clicked selected = self.selected_item() if clicked: branches.extend(clicked.branches) if selected: branches.extend(selected.commit.branches) if not branches: return guicmds.checkout_branch(self.context, default=branches[0]) def create_branch(self): """Create a branch at the selected commit""" context = self.context create_new_branch = partial(createbranch.create_new_branch, context) self.with_oid(lambda oid: create_new_branch(revision=oid)) def create_tag(self): """Create a tag at the selected commit""" context = self.context self.with_oid(lambda oid: createtag.create_tag(context, ref=oid)) def create_tarball(self): """Create a tarball from the selected commit""" context = self.context self.with_oid(lambda oid: archive.show_save_dialog(context, oid, parent=self)) def show_diff(self): """Show the diff for the selected commit""" context = self.context self.with_oid( lambda oid: difftool.diff_expression( context, self, oid + '^!', hide_expr=False, focus_tree=True ) ) def show_dir_diff(self): """Show a full directory diff for the selected commit""" context = self.context self.with_oid( lambda oid: difftool.difftool_launch( context, left=oid, left_take_magic=True, dir_diff=True ) ) def rebase_to_commit(self): """Rebase the current branch to the selected commit""" context = self.context self.with_oid(lambda oid: cmds.do(cmds.Rebase, context, upstream=oid)) def reset_mixed(self): """Reset the repository using git reset --mixed""" context = self.context self.with_oid(lambda oid: cmds.do(cmds.ResetMixed, context, ref=oid)) def reset_keep(self): """Reset the repository using git reset --keep""" context = self.context self.with_oid(lambda oid: cmds.do(cmds.ResetKeep, context, ref=oid)) def reset_merge(self): """Reset the repository using git reset --merge""" context = self.context self.with_oid(lambda oid: cmds.do(cmds.ResetMerge, context, ref=oid)) def reset_soft(self): """Reset the repository using git reset --soft""" context = self.context self.with_oid(lambda oid: cmds.do(cmds.ResetSoft, context, ref=oid)) def reset_hard(self): """Reset the repository using git reset --hard""" context = self.context self.with_oid(lambda oid: cmds.do(cmds.ResetHard, context, ref=oid)) def restore_worktree(self): """Reset the worktree contents from the selected commit""" context = self.context self.with_oid(lambda oid: cmds.do(cmds.RestoreWorktree, context, ref=oid)) def checkout_detached(self): """Checkout a commit using an anonymous detached HEAD""" context = self.context self.with_oid(lambda oid: cmds.do(cmds.Checkout, context, [oid])) def save_blob_dialog(self): """Save a file blob from the selected commit""" context = self.context self.with_oid(lambda oid: browse.BrowseBranch.browse(context, oid)) def update_menu_actions(self, event): """Update menu actions to reflect the selection state""" selected_items = self.selected_items() selected_item = self.selected_item() 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_single_selection_or_clicked = bool(has_single_selection or commit) has_selection = bool(selected_items) can_diff = bool( commit and has_single_selection and selected_items and commit is not selected_items[0].commit ) has_branches = ( has_single_selection and selected_item and bool(selected_item.commit.branches) ) or (self.clicked and bool(self.clicked.branches)) 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['diff_commit'].setEnabled(has_single_selection_or_clicked) self.menu_actions['diff_commit_all'].setEnabled(has_single_selection_or_clicked) self.menu_actions['checkout_branch'].setEnabled(has_branches) self.menu_actions['checkout_detached'].setEnabled( has_single_selection_or_clicked ) self.menu_actions['cherry_pick'].setEnabled(has_single_selection_or_clicked) self.menu_actions['copy'].setEnabled(has_single_selection_or_clicked) self.menu_actions['create_branch'].setEnabled(has_single_selection_or_clicked) self.menu_actions['create_patch'].setEnabled(has_selection) self.menu_actions['create_tag'].setEnabled(has_single_selection_or_clicked) self.menu_actions['create_tarball'].setEnabled(has_single_selection_or_clicked) self.menu_actions['rebase_to_commit'].setEnabled( has_single_selection_or_clicked ) self.menu_actions['reset_mixed'].setEnabled(has_single_selection_or_clicked) self.menu_actions['reset_keep'].setEnabled(has_single_selection_or_clicked) self.menu_actions['reset_merge'].setEnabled(has_single_selection_or_clicked) self.menu_actions['reset_soft'].setEnabled(has_single_selection_or_clicked) self.menu_actions['reset_hard'].setEnabled(has_single_selection_or_clicked) self.menu_actions['restore_worktree'].setEnabled( has_single_selection_or_clicked ) self.menu_actions['revert'].setEnabled(has_single_selection_or_clicked) self.menu_actions['save_blob'].setEnabled(has_single_selection_or_clicked) def context_menu_event(self, event): """Build a context menu and execute it""" self.update_menu_actions(event) menu = qtutils.create_menu(N_('Actions'), self) menu.addAction(self.menu_actions['diff_this_selected']) menu.addAction(self.menu_actions['diff_selected_this']) menu.addAction(self.menu_actions['diff_commit']) menu.addAction(self.menu_actions['diff_commit_all']) menu.addSeparator() menu.addAction(self.menu_actions['checkout_branch']) menu.addAction(self.menu_actions['create_branch']) menu.addAction(self.menu_actions['create_tag']) menu.addAction(self.menu_actions['rebase_to_commit']) menu.addSeparator() menu.addAction(self.menu_actions['cherry_pick']) menu.addAction(self.menu_actions['revert']) menu.addAction(self.menu_actions['create_patch']) menu.addAction(self.menu_actions['create_tarball']) menu.addSeparator() reset_menu = menu.addMenu(N_('Reset')) reset_menu.addAction(self.menu_actions['reset_soft']) reset_menu.addAction(self.menu_actions['reset_mixed']) reset_menu.addAction(self.menu_actions['restore_worktree']) reset_menu.addSeparator() reset_menu.addAction(self.menu_actions['reset_keep']) reset_menu.addAction(self.menu_actions['reset_merge']) reset_menu.addAction(self.menu_actions['reset_hard']) menu.addAction(self.menu_actions['checkout_detached']) menu.addSeparator() menu.addAction(self.menu_actions['save_blob']) menu.addAction(self.menu_actions['copy']) menu.exec_(self.mapToGlobal(event.pos())) def set_icon(icon, action): """ "Set the icon for an action and return the action""" action.setIcon(icon) return action def viewer_actions(widget): """Return common actions across the tree and graph widgets""" return { 'diff_this_selected': set_icon( icons.compare(), qtutils.add_action( widget, N_('Diff this -> selected'), widget.proxy.diff_this_selected ), ), 'diff_selected_this': set_icon( icons.compare(), qtutils.add_action( widget, N_('Diff selected -> this'), widget.proxy.diff_selected_this ), ), 'create_branch': set_icon( icons.branch(), qtutils.add_action(widget, N_('Create Branch'), widget.proxy.create_branch), ), 'create_patch': set_icon( icons.save(), qtutils.add_action(widget, N_('Create Patch'), widget.proxy.create_patch), ), 'create_tag': set_icon( icons.tag(), qtutils.add_action(widget, N_('Create Tag'), widget.proxy.create_tag), ), 'create_tarball': set_icon( icons.file_zip(), qtutils.add_action( widget, N_('Save As Tarball/Zip...'), widget.proxy.create_tarball ), ), 'cherry_pick': set_icon( icons.cherry_pick(), qtutils.add_action(widget, N_('Cherry Pick'), widget.proxy.cherry_pick), ), 'revert': set_icon( icons.undo(), qtutils.add_action(widget, N_('Revert'), widget.proxy.revert) ), 'diff_commit': set_icon( icons.diff(), qtutils.add_action( widget, N_('Launch Diff Tool'), widget.proxy.show_diff, hotkeys.DIFF ), ), 'diff_commit_all': set_icon( icons.diff(), qtutils.add_action( widget, N_('Launch Directory Diff Tool'), widget.proxy.show_dir_diff, hotkeys.DIFF_SECONDARY, ), ), 'checkout_branch': set_icon( icons.branch(), qtutils.add_action( widget, N_('Checkout Branch'), widget.proxy.checkout_branch ), ), 'checkout_detached': qtutils.add_action( widget, N_('Checkout Detached HEAD'), widget.proxy.checkout_detached ), 'rebase_to_commit': set_icon( icons.play(), qtutils.add_action( widget, N_('Rebase to this commit'), widget.proxy.rebase_to_commit ), ), 'reset_soft': set_icon( icons.style_dialog_reset(), qtutils.add_action( widget, N_('Reset Branch (Soft)'), widget.proxy.reset_soft ), ), 'reset_mixed': set_icon( icons.style_dialog_reset(), qtutils.add_action( widget, N_('Reset Branch and Stage (Mixed)'), widget.proxy.reset_mixed ), ), 'reset_keep': set_icon( icons.style_dialog_reset(), qtutils.add_action( widget, N_('Restore Worktree and Reset All (Keep Unstaged Edits)'), widget.proxy.reset_keep, ), ), 'reset_merge': set_icon( icons.style_dialog_reset(), qtutils.add_action( widget, N_('Restore Worktree and Reset All (Merge)'), widget.proxy.reset_merge, ), ), 'reset_hard': set_icon( icons.style_dialog_reset(), qtutils.add_action( widget, N_('Restore Worktree and Reset All (Hard)'), widget.proxy.reset_hard, ), ), 'restore_worktree': set_icon( icons.edit(), qtutils.add_action( widget, N_('Restore Worktree'), widget.proxy.restore_worktree ), ), 'save_blob': set_icon( icons.save(), qtutils.add_action( widget, N_('Grab File...'), widget.proxy.save_blob_dialog ), ), 'copy': set_icon( icons.copy(), qtutils.add_action( widget, N_('Copy SHA-1'), widget.proxy.copy_to_clipboard, hotkeys.COPY_SHA1, ), ), } class GitDagLineEdit(completion.GitLogLineEdit): """The text input field for specifying "git log" options""" def __init__(self, context): super().__init__(context) self._action_filter_to_current_author = qtutils.add_action( self, N_('Commits authored by me'), self._filter_to_current_author ) self._action_pickaxe_search = qtutils.add_action( self, N_('Pickaxe search for changes containing text'), self._pickaxe_search ) self._action_grep_search = qtutils.add_action( self, N_('Search commit messages'), self._grep_search, ) self._action_no_merges = qtutils.add_action( self, N_('Ignore merge commits'), self._no_merges ) def contextMenuEvent(self, event): """Adds custom actions to the default context menu""" event_pos = event.pos() menu = self.createStandardContextMenu() menu.addSeparator() actions = menu.actions() first_action = actions[0] menu.insertAction(first_action, self._action_pickaxe_search) menu.insertAction(first_action, self._action_filter_to_current_author) menu.insertAction(first_action, self._action_grep_search) menu.insertAction(first_action, self._action_no_merges) menu.insertSeparator(first_action) menu.exec_(self.mapToGlobal(event_pos)) def insert(self, text): """Insert text at the beginning of the current text""" value = self.value() if value: text = f'{text} {value}' self.setText(text) self.close_popup() def _filter_to_current_author(self): """Filter to commits by the current author/user""" _, email = self.context.cfg.get_author() author_filter = '--author=' + email self.insert(author_filter) def _pickaxe_search(self): """Pickaxe search for changes containing text""" self.insert('-G"search"') start = len('-G"') length = len('search') self.setSelection(start, length) def _grep_search(self): """Pickaxe search for changes containing text""" self.insert('--grep="search"') start = len('--grep="') length = len('search') self.setSelection(start, length) def _no_merges(self): """Ignore merge commits""" self.insert('--no-merges') class CommitTreeWidgetItem(QtWidgets.QTreeWidgetItem): """Custom TreeWidgetItem used in to build the commit tree widget""" def __init__(self, commit, parent=None): QtWidgets.QTreeWidgetItem.__init__(self, parent) self.commit = commit self.setText(0, commit.summary) self.setText(1, commit.author) self.setText(2, commit.authdate) class CommitTreeWidget(standard.TreeWidget, ViewerMixin): """Display commits using a flat treewidget in "list" mode""" commits_selected = Signal(object) diff_commits = Signal(object, object) zoom_to_fit = Signal() def __init__(self, context, parent): standard.TreeWidget.__init__(self, parent) ViewerMixin.__init__(self) self.setSelectionMode(self.ExtendedSelection) self.setHeaderLabels([N_('Summary'), N_('Author'), N_('Date, Time')]) self.context = context self.oidmap = {} self.menu_actions = None self.selecting = False self.commits = [] self._adjust_columns = False self.action_up = qtutils.add_action( self, N_('Go Up'), self.go_up, hotkeys.MOVE_UP ) self.action_down = qtutils.add_action( self, N_('Go Down'), self.go_down, hotkeys.MOVE_DOWN ) self.zoom_to_fit_action = qtutils.add_action( self, N_('Zoom to Fit'), self.zoom_to_fit.emit, hotkeys.FIT ) self.itemSelectionChanged.connect(self.selection_changed) def export_state(self): """Export the widget's state""" # The base class method is intentionally overridden because we only # care about the details below for this sub-widget. state = {} state['column_widths'] = self.column_widths() return state def apply_state(self, state): """Apply the exported widget state""" try: column_widths = state['column_widths'] except (KeyError, ValueError): column_widths = None if column_widths: self.set_column_widths(column_widths) else: # Defer showing the columns until we are shown, and our true width # is known. Calling adjust_columns() here ends up with the wrong # answer because we have not yet been parented to the layout. # We set this flag that we process once during our initial # showEvent(). self._adjust_columns = True return True # Qt overrides def showEvent(self, event): """Override QWidget::showEvent() to size columns when we are shown""" if self._adjust_columns: self._adjust_columns = False width = self.width() two_thirds = (width * 2) // 3 one_sixth = width // 6 self.setColumnWidth(0, two_thirds) self.setColumnWidth(1, one_sixth) self.setColumnWidth(2, one_sixth) return standard.TreeWidget.showEvent(self, event) # ViewerMixin def go_up(self): """Select the item above the current item""" self.goto(self.itemAbove) def go_down(self): """Select the item below the current item""" self.goto(self.itemBelow) def goto(self, finder): """Move the selection using a finder strategy""" items = self.selected_items() item = items[0] if items else None if item is None: return found = finder(item) if found: self.select([found.commit.oid]) def selected_commit_range(self): """Return a range of selected commits""" selected_items = self.selected_items() if not selected_items: return None, None return selected_items[-1].commit.oid, selected_items[0].commit.oid def set_selecting(self, selecting): """Record the "are we selecting?" status""" self.selecting = selecting def selection_changed(self): """Respond to itemSelectionChanged notifications""" items = self.selected_items() if not items: self.set_selecting(True) self.commits_selected.emit([]) self.set_selecting(False) return self.set_selecting(True) self.commits_selected.emit(sort_by_generation([i.commit for i in items])) self.set_selecting(False) def select_commits(self, commits): """Select commits that were selected by the sibling tree/graph widget""" if self.selecting: return with qtutils.BlockSignals(self): self.select([commit.oid for commit in commits]) def select(self, oids): """Mark items as selected""" self.clearSelection() if not oids: return for oid in oids: try: item = self.oidmap[oid] except KeyError: continue self.scrollToItem(item) item.setSelected(True) def clear(self): """Clear the tree""" QtWidgets.QTreeWidget.clear(self) self.oidmap.clear() self.commits = [] def add_commits(self, commits): """Add commits to the tree""" self.commits.extend(commits) items = [] for c in reversed(commits): item = CommitTreeWidgetItem(c) items.append(item) self.oidmap[c.oid] = item for tag in c.tags: self.oidmap[tag] = item self.insertTopLevelItems(0, items) def create_patch(self): """Export a patch from the selected items""" items = self.selectedItems() if not items: return context = self.context oids = [item.commit.oid for item in reversed(items)] all_oids = [c.oid for c in self.commits] cmds.do(cmds.FormatPatch, context, oids, all_oids) # Qt overrides def contextMenuEvent(self, event): """Create a custom context menu and execute it""" self.context_menu_event(event) def mousePressEvent(self, event): """Intercept the right-click event to retain selection state""" item = self.itemAt(event.pos()) if item is None: self.clicked = None else: self.clicked = item.commit if event.button() == Qt.RightButton: event.accept() return QtWidgets.QTreeWidget.mousePressEvent(self, event) class GitDAG(standard.MainWindow): """The git-dag widget.""" commits_selected = Signal(object) def __init__(self, context, params, parent=None): super().__init__(parent) self.setMinimumSize(420, 420) # change when widgets are added/removed self.widget_version = 2 self.context = context self.params = params self.model = context.model self.commits = {} self.commit_list = [] self.selection = [] self.old_refs = set() self.old_oids = None self.old_count = 0 self.force_refresh = False self.thread = None self.revtext = GitDagLineEdit(context) self.maxresults = standard.SpinBox() self.zoom_out = qtutils.create_action_button( tooltip=N_('Zoom Out'), icon=icons.zoom_out() ) self.zoom_in = qtutils.create_action_button( tooltip=N_('Zoom In'), icon=icons.zoom_in() ) self.zoom_to_fit = qtutils.create_action_button( tooltip=N_('Zoom to Fit'), icon=icons.zoom_fit_best() ) self.treewidget = CommitTreeWidget(context, self) self.diffwidget = diff.DiffWidget(context, self, is_commit=True) self.filewidget = filelist.FileWidget(context, self) self.graphview = GraphView(context, self) self.treewidget.commits_selected.connect(self.commits_selected) self.graphview.commits_selected.connect(self.commits_selected) self.commits_selected.connect(self.select_commits) self.commits_selected.connect(self.diffwidget.commits_selected) self.commits_selected.connect(self.filewidget.commits_selected) self.commits_selected.connect(self.graphview.select_commits) self.commits_selected.connect(self.treewidget.select_commits) self.filewidget.files_selected.connect(self.diffwidget.files_selected) self.filewidget.difftool_selected.connect(self.difftool_selected) self.filewidget.histories_selected.connect(self.histories_selected) self.proxy = FocusRedirectProxy( self.treewidget, self.graphview, self.filewidget ) self.viewer_actions = actions = viewer_actions(self) self.treewidget.menu_actions = actions self.graphview.menu_actions = actions self.controls_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.revtext, self.maxresults ) self.controls_widget = QtWidgets.QWidget() self.controls_widget.setLayout(self.controls_layout) self.log_dock = qtutils.create_dock('Log', 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.file_dock = qtutils.create_dock('Files', N_('Files'), self) self.file_dock.setWidget(self.filewidget) self.diff_panel = diff.DiffPanel(self.diffwidget, self.diffwidget.diff, self) self.diff_options = diff.Options(self.diffwidget) self.diffwidget.set_options(self.diff_options) self.diff_options.hide_advanced_options() self.diff_options.set_diff_type(main.Types.TEXT) self.diff_dock = qtutils.create_dock('Diff', N_('Diff'), self) self.diff_dock.setWidget(self.diff_panel) diff_titlebar = self.diff_dock.titleBarWidget() diff_titlebar.add_corner_widget(self.diff_options) self.graph_controls_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.zoom_out, self.zoom_in, self.zoom_to_fit, defs.spacing, ) self.graph_controls_widget = QtWidgets.QWidget() self.graph_controls_widget.setLayout(self.graph_controls_layout) self.graphview_dock = qtutils.create_dock('Graph', 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 ) self.refresh_action = qtutils.add_action( self, N_('Refresh'), self.refresh, hotkeys.REFRESH ) # Create the application menu self.menubar = QtWidgets.QMenuBar(self) self.setMenuBar(self.menubar) # View Menu self.view_menu = qtutils.add_menu(N_('View'), self.menubar) self.view_menu.addAction(self.refresh_action) 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.addAction(self.file_dock.toggleViewAction()) self.view_menu.addSeparator() self.view_menu.addAction(self.lock_layout_action) left = Qt.LeftDockWidgetArea right = Qt.RightDockWidgetArea self.addDockWidget(left, self.log_dock) self.addDockWidget(left, self.diff_dock) self.addDockWidget(right, self.graphview_dock) self.addDockWidget(right, self.file_dock) # Also re-loads dag.* from the saved state self.init_state(context.settings, 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.treewidget.zoom_to_fit.connect(self.graphview.zoom_to_fit) self.treewidget.diff_commits.connect(self.diff_commits) self.graphview.diff_commits.connect(self.diff_commits) self.filewidget.grab_file.connect(self.grab_file) self.maxresults.editingFinished.connect(self.display) self.revtext.textChanged.connect(self.text_changed) self.revtext.activated.connect(self.display) self.revtext.enter.connect(self.display) self.revtext.down.connect(self.focus_tree) # The model is updated in another thread so use # signals/slots to bring control back to the main GUI thread self.model.updated.connect(self.model_updated, type=Qt.QueuedConnection) qtutils.add_action(self, 'FocusInput', self.focus_input, hotkeys.FOCUS_INPUT) qtutils.add_action(self, 'FocusTree', self.focus_tree, hotkeys.FOCUS_TREE) qtutils.add_action(self, 'FocusDiff', self.focus_diff, hotkeys.FOCUS_DIFF) qtutils.add_close_action(self) self.set_params(params) def set_params(self, params): context = self.context self.params = params # Update fields affected by model self.revtext.setText(params.ref) self.maxresults.setValue(params.count) self.update_window_title() if self.thread is not None: self.thread.stop() self.thread = ReaderThread(context, params, self) thread = self.thread thread.begin.connect(self.thread_begin, type=Qt.QueuedConnection) thread.status.connect(self.thread_status, type=Qt.QueuedConnection) thread.add.connect(self.add_commits, type=Qt.QueuedConnection) thread.end.connect(self.thread_end, type=Qt.QueuedConnection) def focus_input(self): """Focus the revision input field""" self.revtext.setFocus() def focus_tree(self): """Focus the revision tree list widget""" self.treewidget.setFocus() def focus_diff(self): """Focus the diff widget""" self.diffwidget.setFocus() def text_changed(self, txt): self.params.ref = txt self.update_window_title() def update_window_title(self): project = self.model.project if self.params.ref: self.setWindowTitle( N_('%(project)s: %(ref)s - DAG') % { 'project': project, 'ref': self.params.ref, } ) else: self.setWindowTitle(project + N_(' - DAG')) def export_state(self): state = standard.MainWindow.export_state(self) state['count'] = self.params.count state['log'] = self.treewidget.export_state() state['word_wrap'] = self.diffwidget.options.enable_word_wrapping.isChecked() return state def apply_state(self, state): result = standard.MainWindow.apply_state(self, state) try: count = state['count'] if self.params.overridden('count'): count = self.params.count except (KeyError, TypeError, ValueError, AttributeError): count = self.params.count result = False self.params.set_count(count) self.lock_layout_action.setChecked(state.get('lock_layout', False)) self.diffwidget.set_word_wrapping(state.get('word_wrap', False), update=True) try: log_state = state['log'] except (KeyError, ValueError): log_state = None if log_state: self.treewidget.apply_state(log_state) return result def model_updated(self): self.display() self.update_window_title() def refresh(self): """Unconditionally refresh the DAG""" # self.force_refresh triggers an Unconditional redraw self.force_refresh = True cmds.do(cmds.Refresh, self.context) def display(self): """Update the view when the Git refs change""" ref = get(self.revtext) count = get(self.maxresults) context = self.context model = self.model # The DAG tries to avoid updating when the object IDs have not # changed. Without doing this the DAG constantly redraws itself # whenever inotify sends update events, which hurts usability. # # To minimize redraws we leverage `git rev-parse`. The strategy is to # use `git rev-parse` on the input line, which converts each argument # into object IDs. From there it's a simple matter of detecting when # the object IDs changed. # # In addition to object IDs, we also need to know when the set of # named references (branches, tags) changes so that an update is # triggered when new branches and tags are created. refs = set(model.local_branches + model.remote_branches + model.tags) argv = utils.shell_split(ref or 'HEAD') oids = gitcmds.parse_refs(context, argv) update = ( self.force_refresh or count != self.old_count or oids != self.old_oids or refs != self.old_refs ) if update: self.thread.stop() self.params.set_ref(ref) self.params.set_count(count) self.thread.start() self.old_oids = oids self.old_count = count self.old_refs = refs self.force_refresh = False def select_commits(self, commits): self.selection = commits def clear(self): self.commits.clear() self.commit_list = [] self.graphview.clear() self.treewidget.clear() def add_commits(self, commits): self.commit_list.extend(commits) # Keep track of commits for commit_obj in commits: self.commits[commit_obj.oid] = 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_begin(self): self.clear() def thread_end(self): self.restore_selection() def thread_status(self, successful): self.revtext.hint.set_error(not successful) def restore_selection(self): selection = self.selection try: commit_obj = self.commit_list[-1] except IndexError: # No commits, exist, early-out return new_commits = [self.commits.get(s.oid, None) for s in selection] new_commits = [c for c in new_commits if c is not None] if new_commits: # The old selection exists in the new state self.commits_selected.emit(sort_by_generation(new_commits)) else: # The old selection is now empty. Select the top-most commit self.commits_selected.emit([commit_obj]) self.graphview.set_initial_view() def diff_commits(self, left, right): paths = self.params.paths() if paths: difftool.difftool_launch(self.context, left=left, right=right, paths=paths) else: difftool.diff_commits(self.context, self, left, right) # Qt overrides def closeEvent(self, event): self.revtext.close_popup() self.thread.stop() standard.MainWindow.closeEvent(self, event) def histories_selected(self, histories): argv = [self.model.currentbranch, '--'] argv.extend(histories) rev_text = core.list2cmdline(argv) self.revtext.setText(rev_text) self.display() def difftool_selected(self, files): bottom, top = self.treewidget.selected_commit_range() if not top: return difftool.difftool_launch( self.context, left=bottom, left_take_parent=True, right=top, paths=files ) def grab_file(self, filename): """Save the selected file from the file list widget""" oid = self.treewidget.selected_oid() model = browse.BrowseModel(oid, filename=filename) browse.save_path(self.context, filename, model) class ReaderThread(QtCore.QThread): begin = Signal() add = Signal(object) end = Signal() status = Signal(object) def __init__(self, context, params, parent): QtCore.QThread.__init__(self, parent) self.context = context self.params = params self._abort = False self._stop = False self._mutex = QtCore.QMutex() self._condition = QtCore.QWaitCondition() def run(self): context = self.context repo = dag.RepoReader(context, self.params) repo.reset() self.begin.emit() commits = [] for commit in repo.get(): self._mutex.lock() if self._stop: self._condition.wait(self._mutex) self._mutex.unlock() if self._abort: repo.reset() return commits.append(commit) if len(commits) >= 512: self.add.emit(commits) commits = [] self.status.emit(repo.returncode == 0) if commits: self.add.emit(commits) self.end.emit() 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: _label_font = None @classmethod def label_font(cls): font = cls._label_font if font is None: font = cls._label_font = QtWidgets.QApplication.font() font.setPointSize(6) return font class Edge(QtWidgets.QGraphicsItem): item_type = qtutils.standard_item_type_value(1) def __init__(self, source, dest): QtWidgets.QGraphicsItem.__init__(self) self.setAcceptedMouseButtons(Qt.NoButton) self.source = source self.dest = dest self.commit = source.commit self.setZValue(-2) self.recompute_bound() self.path = None self.path_valid = False # Choose a new color for new branch edges if self.source.x() < self.dest.x(): color = EdgeColor.cycle() 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, 2.0, line, Qt.SquareCap, Qt.RoundJoin) def recompute_bound(self): 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() def commits_were_invalidated(self): self.recompute_bound() self.prepareGeometryChange() # The path should not be recomputed immediately because just small part # of DAG is actually shown at same time. It will be recomputed on # demand in course of 'paint' method. self.path_valid = False # Hence, just queue redrawing. self.update() # Qt overrides def type(self): return self.item_type def boundingRect(self): return self.bound def recompute_path(self): QRectF = QtCore.QRectF QPointF = QtCore.QPointF arc_rect = 10 connector_length = 5 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()) else: # Define points starting from the 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 the destination. 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 destination is at the left of the source, then we need to # reverse some values. if self.source.x() > self.dest.x(): point3 = QPointF(point2.x() - arc_rect, point3.y()) point6 = QPointF(point5.x() + arc_rect, point6.y()) 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) self.path = path self.path_valid = True def paint(self, painter, _option, _widget): if not self.path_valid: self.recompute_path() painter.setPen(self.pen) painter.drawPath(self.path) class EdgeColor: """An edge color factory""" current_color_index = 0 colors = [ QtGui.QColor(Qt.red), QtGui.QColor(Qt.cyan), QtGui.QColor(Qt.magenta), QtGui.QColor(Qt.green), # Orange; Qt.yellow is too low-contrast qtutils.rgba(0xFF, 0x66, 0x00), ] @classmethod def update_colors(cls, theme): """Update the colors based on the color theme""" if theme.is_dark or theme.is_palette_dark: cls.colors.extend([ QtGui.QColor(Qt.red).lighter(), QtGui.QColor(Qt.cyan).lighter(), QtGui.QColor(Qt.magenta).lighter(), QtGui.QColor(Qt.green).lighter(), QtGui.QColor(Qt.yellow).lighter(), ]) else: cls.colors.extend([ QtGui.QColor(Qt.blue), QtGui.QColor(Qt.darkRed), QtGui.QColor(Qt.darkCyan), QtGui.QColor(Qt.darkMagenta), QtGui.QColor(Qt.darkGreen), QtGui.QColor(Qt.darkYellow), QtGui.QColor(Qt.darkBlue), ]) @classmethod def cycle(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] @classmethod def reset(cls): cls.current_color_index = 0 class Commit(QtWidgets.QGraphicsItem): item_type = qtutils.standard_item_type_value(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) commit_pen.setColor(outline_color) def __init__( self, commit, selectable=QtWidgets.QGraphicsItem.ItemIsSelectable, cursor=Qt.PointingHandCursor, xpos=commit_radius / 2.0 + 1.0, cached_commit_color=commit_color, cached_merge_color=merge_color, ): QtWidgets.QGraphicsItem.__init__(self) self.commit = commit self.selected = False self.setZValue(0) self.setFlag(selectable) self.setCursor(cursor) self.setToolTip(commit.oid[:12] + ': ' + commit.summary) if commit.tags: self.label = label = Label(commit) label.setParentItem(self) label.setPos(xpos + 1, -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 self.edges = {} def itemChange(self, change, value): if change == QtWidgets.QGraphicsItem.ItemSelectedHasChanged: # Cache the pen for use in paint() if value: 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) commit_pen.setColor(color) self.commit_pen = commit_pen return QtWidgets.QGraphicsItem.itemChange(self, change, value) def type(self): return self.item_type def boundingRect(self): return self.item_bbox def shape(self): return self.item_shape def paint(self, painter, option, _widget): # Do not draw outside the exposed rectangle. painter.setClipRect(option.exposedRect) # Draw ellipse painter.setPen(self.commit_pen) painter.setBrush(self.brush) painter.drawEllipse(self.inner_rect) def mousePressEvent(self, event): QtWidgets.QGraphicsItem.mousePressEvent(self, event) self.pressed = True self.selected = self.isSelected() def mouseMoveEvent(self, event): if self.pressed: self.dragged = True QtWidgets.QGraphicsItem.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): QtWidgets.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(QtWidgets.QGraphicsItem): item_type = qtutils.graphics_item_type_value(3) head_color = QtGui.QColor(Qt.green) other_color = QtGui.QColor(Qt.white) remote_color = QtGui.QColor(Qt.yellow) head_pen = QtGui.QPen() head_pen.setColor(QtGui.QColor(Qt.black)) head_pen.setWidth(1) text_pen = QtGui.QPen() text_pen.setColor(QtGui.QColor(Qt.black)) text_pen.setWidth(1) border = 1 item_spacing = 8 text_x_offset = 3 text_y_offset = 0 def __init__(self, commit): QtWidgets.QGraphicsItem.__init__(self) self.setZValue(-1) self.commit = commit def type(self): return self.item_type def boundingRect(self, cache=Cache): QPainterPath = QtGui.QPainterPath QRectF = QtCore.QRectF width = 72 height = 18 current_width = 0 spacing = self.item_spacing border_x = self.border + self.text_x_offset border_y = self.border + self.text_y_offset font = cache.label_font() item_shape = QPainterPath() base_rect = QRectF(0, 0, width, height) base_rect = base_rect.adjusted(-border_x, -border_y, border_x, border_y) item_shape.addRect(base_rect) for tag in self.commit.tags: text_shape = QPainterPath() text_shape.addText(current_width, 0, font, tag) text_rect = text_shape.boundingRect() box_rect = text_rect.adjusted(-border_x, -border_y, border_x, border_y) item_shape.addRect(box_rect) current_width = item_shape.boundingRect().width() + spacing return item_shape.boundingRect() def paint(self, painter, _option, _widget, cache=Cache): # Draw tags and branches font = cache.label_font() painter.setFont(font) current_width = 3 border = self.border x_offset = self.text_x_offset y_offset = self.text_y_offset spacing = self.item_spacing QRectF = QtCore.QRectF HEAD = 'HEAD' remotes_prefix = 'remotes/' tags_prefix = 'tags/' heads_prefix = 'heads/' remotes_len = len(remotes_prefix) tags_len = len(tags_prefix) heads_len = len(heads_prefix) for tag in self.commit.tags: if tag == HEAD: painter.setPen(self.text_pen) painter.setBrush(self.remote_color) elif tag.startswith(remotes_prefix): tag = tag[remotes_len:] painter.setPen(self.text_pen) painter.setBrush(self.other_color) elif tag.startswith(tags_prefix): tag = tag[tags_len:] painter.setPen(self.text_pen) painter.setBrush(self.remote_color) elif tag.startswith(heads_prefix): tag = tag[heads_len:] painter.setPen(self.head_pen) painter.setBrush(self.head_color) else: painter.setPen(self.text_pen) painter.setBrush(self.other_color) text_rect = painter.boundingRect( QRectF(current_width, 0, 0, 0), Qt.TextSingleLine, tag ) box_rect = text_rect.adjusted(-x_offset, -y_offset, x_offset, y_offset) painter.drawRoundedRect(box_rect, border, border) painter.drawText(text_rect, Qt.TextSingleLine, tag) current_width += text_rect.width() + spacing class GraphView(QtWidgets.QGraphicsView, ViewerMixin): commits_selected = Signal(object) diff_commits = Signal(object, object) x_adjust = int(Commit.commit_radius * 4 / 3) y_adjust = int(Commit.commit_radius * 4 / 3) x_off = -18 y_off = -20 def __init__(self, context, parent): QtWidgets.QGraphicsView.__init__(self, parent) ViewerMixin.__init__(self) EdgeColor.update_colors(context.app.theme) theme = context.app.theme highlight = theme.selection_color() Commit.commit_selected_color = highlight Commit.selected_outline_color = highlight.darker() self.context = context self.columns = {} self.menu_actions = None self.commits = [] self.items = {} self.mouse_start = [0, 0] self.saved_matrix = self.transform() self.max_column = 0 self.min_column = 0 self.frontier = {} self.tagged_cells = set() self.x_start = 24 self.x_min = 24 self.x_offsets = collections.defaultdict(lambda: self.x_min) self.is_panning = False self.pressed = False self.selecting = False self.last_mouse = [0, 0] self.zoom = 2 self.setDragMode(self.RubberBandDrag) scene = QtWidgets.QGraphicsScene(self) scene.setItemIndexMethod(QtWidgets.QGraphicsScene.BspTreeIndex) scene.selectionChanged.connect(self.selection_changed) self.setScene(scene) self.setRenderHint(QtGui.QPainter.Antialiasing) self.setViewportUpdateMode(self.SmartViewportUpdate) self.setCacheMode(QtWidgets.QGraphicsView.CacheBackground) self.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QtWidgets.QGraphicsView.NoAnchor) background_color = qtutils.css_color(context.app.theme.background_color_rgb()) self.setBackgroundBrush(background_color) qtutils.add_action( self, N_('Zoom In'), self.zoom_in, hotkeys.ZOOM_IN, hotkeys.ZOOM_IN_SECONDARY, ) qtutils.add_action(self, N_('Zoom Out'), self.zoom_out, hotkeys.ZOOM_OUT) qtutils.add_action(self, N_('Zoom to Fit'), self.zoom_to_fit, hotkeys.FIT) qtutils.add_action( self, N_('Select Parent'), self._select_parent, hotkeys.MOVE_DOWN_TERTIARY ) qtutils.add_action( self, N_('Select Oldest Parent'), self._select_oldest_parent, hotkeys.MOVE_DOWN, ) qtutils.add_action( self, N_('Select Child'), self._select_child, hotkeys.MOVE_UP_TERTIARY ) qtutils.add_action( self, N_('Select Newest Child'), self._select_newest_child, hotkeys.MOVE_UP ) def clear(self): EdgeColor.reset() self.scene().clear() self.items.clear() self.x_offsets.clear() self.x_min = 24 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 selection_changed(self): # Broadcast selection to other widgets selected_items = self.scene().selectedItems() commits = sort_by_generation([item.commit for item in selected_items]) self.set_selecting(True) self.commits_selected.emit(commits) self.set_selecting(False) def select_commits(self, commits): if self.selecting: return with qtutils.BlockSignals(self.scene()): self.select([commit.oid for commit in commits]) def select(self, oids): """Select the item for the oids""" self.scene().clearSelection() for oid in oids: try: item = self.items[oid] except KeyError: continue item.setSelected(True) item_rect = item.sceneTransform().mapRect(item.boundingRect()) self.ensureVisible(item_rect) def _get_item_by_generation(self, commits, criteria_func): """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_func(generation, commit.generation): oid = commit.oid generation = commit.generation try: return self.items[oid] 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 context = self.context selected_commits = sort_by_generation([n.commit for n in items]) oids = [c.oid for c in selected_commits] all_oids = [c.oid for c in sort_by_generation(self.commits)] cmds.do(cmds.FormatPatch, context, oids, all_oids) 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): items = [] selected = self.selected_items() if selected: items.extend(selected) if not selected and self.commits: commit = self.commits[-1] items.append(self.items[commit.oid]) bounds = self.scene().itemsBoundingRect() bounds.adjust(-64, 0, 0, 0) self.setSceneRect(bounds) 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 = y_min = maxsize x_max = y_max = -maxsize for item in items: pos = item.pos() x_val = pos.x() y_val = pos.y() x_min = min(x_min, x_val) x_max = max(x_max, x_val) y_min = min(y_min, y_val) y_max = max(y_max, y_val) rect = QtCore.QRectF(x_min, y_min, abs(x_max - x_min), abs(y_max - y_min)) x_adjust = abs(GraphView.x_adjust) y_adjust = abs(GraphView.y_adjust) count = max(2.0, 10.0 - len(items) / 2.0) y_offset = int(y_adjust * count) x_offset = int(x_adjust * count) rect.setX(rect.x() - x_offset // 2) rect.setY(rect.y() - y_adjust // 2) rect.setHeight(rect.height() + y_offset) rect.setWidth(rect.width() + x_offset) self.fitInView(rect, Qt.KeepAspectRatio) self.scene().invalidate() def handle_event(self, event_handler, event, update=True): event_handler(self, event) if update: self.update() def set_selecting(self, selecting): self.selecting = selecting def pan(self, event): pos = event.pos() x_offset = pos.x() - self.mouse_start[0] y_offset = pos.y() - self.mouse_start[1] if x_offset == 0 and y_offset == 0: return rect = QtCore.QRect(0, 0, abs(x_offset), abs(y_offset)) delta = self.mapToScene(rect).boundingRect() x_translate = delta.width() if x_offset < 0.0: x_translate = -x_translate y_translate = delta.height() if y_offset < 0.0: y_translate = -y_translate matrix = self.transform() matrix.reset() matrix *= self.saved_matrix matrix.translate(x_translate, y_translate) self.setTransformationAnchor(QtWidgets.QGraphicsView.NoAnchor) self.setTransform(matrix) def wheel_zoom(self, event): """Handle mouse wheel zooming.""" delta = qtcompat.wheel_delta(event) zoom = math.pow(2.0, delta / 512.0) factor = ( self.transform() .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(QtWidgets.QGraphicsView.AnchorUnderMouse) self.zoom = zoom self.scale(zoom, zoom) def wheel_pan(self, event): """Handle mouse wheel panning.""" unit = QtCore.QRectF(0.0, 0.0, 1.0, 1.0) factor = 1.0 / self.transform().mapRect(unit).width() tx, ty = qtcompat.wheel_translation(event) matrix = self.transform().translate(tx * factor, ty * factor) self.setTransformationAnchor(QtWidgets.QGraphicsView.NoAnchor) self.setTransform(matrix) def scale_view(self, scale): factor = ( self.transform() .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 = False scrollbar = self.verticalScrollBar() scrollbar_offset = 1.0 if scrollbar: value = get(scrollbar) minimum = scrollbar.minimum() maximum = scrollbar.maximum() scrollbar_range = maximum - minimum distance = value - minimum nonzero_range = scrollbar_range > 0.1 if nonzero_range: scrollbar_offset = distance / scrollbar_range adjust_scrollbars = True self.setTransformationAnchor(QtWidgets.QGraphicsView.NoAnchor) self.scale(scale, scale) scrollbar = self.verticalScrollBar() if scrollbar and adjust_scrollbars: minimum = scrollbar.minimum() maximum = scrollbar.maximum() scrollbar_range = maximum - minimum value = minimum + int(float(scrollbar_range) * scrollbar_offset) 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.items[commit.oid] = item for ref in commit.tags: self.items[ref] = item scene.addItem(item) self.layout_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.oid] except KeyError: continue # The history is truncated. for parent in reversed(commit.parents): try: parent_item = self.items[parent.oid] except KeyError: continue # The history is truncated. try: edge = parent_item.edges[commit.oid] except KeyError: edge = Edge(parent_item, commit_item) else: continue parent_item.edges[commit.oid] = edge commit_item.edges[parent.oid] = edge scene.addItem(edge) def layout_commits(self): positions = self.position_nodes() # Each edge is accounted in two commits. Hence, accumulate invalid # edges to prevent double edge invalidation. invalid_edges = set() for oid, (x_val, y_val) in positions.items(): item = self.items[oid] pos = item.pos() if pos != (x_val, y_val): item.setPos(x_val, y_val) for edge in item.edges.values(): invalid_edges.add(edge) for edge in invalid_edges: edge.commits_were_invalidated() # Commit node layout technique # # Nodes are aligned by a mesh. Columns and rows are distributed using # algorithms described below. # # Row assignment algorithm # # The algorithm aims consequent. # 1. A commit should be above all its parents. # 2. No commit should be at right side of a commit with a tag in same row. # This prevents overlapping of tag labels with commits and other labels. # 3. Commit density should be maximized. # # The algorithm requires that all parents of a commit were assigned column. # Nodes must be traversed in generation ascend order. This guarantees that all # parents of a commit were assigned row. So, the algorithm may operate in # course of column assignment algorithm. # # Row assignment uses frontier. A frontier is a dictionary that contains # minimum available row index for each column. It propagates during the # algorithm. Set of cells with tags is also maintained to meet second aim. # # Initialization is performed by reset_rows method. Each new column should # be declared using declare_column method. Getting row for a cell is # implemented in alloc_cell method. Frontier must be propagated for any child # of fork commit which occupies different column. This meets first aim. # # Column assignment algorithm # # The algorithm traverses nodes in generation ascend order. This guarantees # that a node will be visited after all its parents. # # The set of occupied columns are maintained during work. Initially it is # empty and no node occupied a column. Empty columns are allocated on demand. # Free index for column being allocated is searched in following way. # 1. Start from desired column and look towards graph center (0 column). # 2. Start from center and look in both directions simultaneously. # Desired column is defaulted to 0. Fork node should set desired column for # children equal to its one. This prevents branch from jumping too far from # its fork. # # Initialization is performed by reset_columns method. Column allocation is # implemented in alloc_column method. Initialization and main loop are in # recompute_grid method. The method also embeds row assignment algorithm by # implementation. # # Actions for each node are follow. # 1. If the node was not assigned a column then it is assigned empty one. # 2. Allocate row. # 3. Allocate columns for children. # If a child have a column assigned then it should no be overridden. One of # children is assigned same column as the node. If the node is a fork then the # child is chosen in generation descent order. This is a heuristic and it only # affects resulting appearance of the graph. Other children are assigned empty # columns in same order. It is the heuristic too. # 4. If no child occupies column of the node then leave it. # It is possible in consequent situations. # 4.1 The node is a leaf. # 4.2 The node is a fork and all its children are already assigned side # column. It is possible if all the children are merges. # 4.3 Single node child is a merge that is already assigned a column. # 5. Propagate frontier with respect to this node. # Each frontier entry corresponding to column occupied by any node's child # must be gather than node row index. This meets first aim of the row # assignment algorithm. # Note that frontier of child that occupies same row was propagated during # step 2. Hence, it must be propagated for children on side columns. def reset_columns(self): # Some children of displayed commits might not be accounted in # 'commits' list. It is common case during loading of big graph. # But, they are assigned a column that must be reset. Hence, use # depth-first traversal to reset all columns assigned. for node in self.commits: if node.column is None: continue stack = [node] while stack: node = stack.pop() node.column = None for child in node.children: if child.column is not None: stack.append(child) self.columns = {} self.max_column = 0 self.min_column = 0 def reset_rows(self): self.frontier = {} self.tagged_cells = set() def declare_column(self, column): if self.frontier: # Align new column frontier by frontier of nearest column. If all # columns were left then select maximum frontier value. if not self.columns: self.frontier[column] = max(list(self.frontier.values())) return # This is heuristic that mostly affects roots. Note that the # frontier values for fork children will be overridden in course of # propagate_frontier. for offset in itertools.count(1): for value in (column + offset, column - offset): if value not in self.columns: # Column is not occupied. continue try: frontier = self.frontier[value] except KeyError: # Column 'c' was never allocated. continue frontier -= 1 # The frontier of the column may be higher because of # tag overlapping prevention performed for previous head. try: if self.frontier[column] >= frontier: break except KeyError: pass self.frontier[column] = frontier break else: continue break else: # First commit must be assigned 0 row. self.frontier[column] = 0 def alloc_column(self, column=0): columns = self.columns # First, look for free column by moving from desired column to graph # center (column 0). for c in range(column, 0, -1 if column > 0 else 1): if c not in columns: if c > self.max_column: self.max_column = c elif c < self.min_column: self.min_column = c break else: # If no free column was found between graph center and desired # column then look for free one by moving from center along both # directions simultaneously. for c in itertools.count(0): if c not in columns: if c > self.max_column: self.max_column = c break c = -c if c not in columns: if c < self.min_column: self.min_column = c break self.declare_column(c) columns[c] = 1 return c def alloc_cell(self, column, tags): # Get empty cell from frontier. cell_row = self.frontier[column] if tags: # Prevent overlapping of tag with cells already allocated a row. if self.x_off > 0: can_overlap = list(range(column + 1, self.max_column + 1)) else: can_overlap = list(range(column - 1, self.min_column - 1, -1)) for value in can_overlap: frontier = self.frontier[value] if frontier > cell_row: cell_row = frontier # Avoid overlapping with tags of commits at cell_row. if self.x_off > 0: can_overlap = list(range(self.min_column, column)) else: can_overlap = list(range(self.max_column, column, -1)) for cell_row in itertools.count(cell_row): for value in can_overlap: if (value, cell_row) in self.tagged_cells: # Overlapping. Try next row. break else: # No overlapping was found. break # Note that all checks should be made for new cell_row value. if tags: self.tagged_cells.add((column, cell_row)) # Propagate frontier. self.frontier[column] = cell_row + 1 return cell_row def propagate_frontier(self, column, value): current = self.frontier[column] if current < value: self.frontier[column] = value def leave_column(self, column): count = self.columns[column] if count == 1: del self.columns[column] else: self.columns[column] = count - 1 def recompute_grid(self): self.reset_columns() self.reset_rows() for node in sort_by_generation(list(self.commits)): if node.column is None: # Node is either root or its parent is not in items. This # happens when tree loading is in progress. Allocate new # columns for such nodes. node.column = self.alloc_column() node.row = self.alloc_cell(node.column, node.tags) # Allocate columns for children which are still without one. Also # propagate frontier for children. if node.is_fork(): sorted_children = sorted( node.children, key=lambda c: c.generation, reverse=True ) citer = iter(sorted_children) for child in citer: if child.column is None: # Top most child occupies column of parent. child.column = node.column # Note that frontier is propagated in course of # alloc_cell. break self.propagate_frontier(child.column, node.row + 1) else: # No child occupies same column. self.leave_column(node.column) # Note that the loop below will pass no iteration. # Rest children are allocated new column. for child in citer: if child.column is None: child.column = self.alloc_column(node.column) self.propagate_frontier(child.column, node.row + 1) elif node.children: child = node.children[0] if child.column is None: child.column = node.column # Note that frontier is propagated in course of alloc_cell. elif child.column != node.column: # Child node have other parents and occupies column of one # of them. self.leave_column(node.column) # But frontier must be propagated with respect to this # parent. self.propagate_frontier(child.column, node.row + 1) else: # This is a leaf node. self.leave_column(node.column) def position_nodes(self): self.recompute_grid() x_start = self.x_start x_min = self.x_min x_off = self.x_off y_off = self.y_off positions = {} for node in self.commits: x_val = x_start + node.column * x_off y_val = y_off + node.row * y_off positions[node.oid] = (x_val, y_val) x_min = min(x_min, x_val) self.x_min = x_min return positions # 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 = self.transform() self.is_panning = True return if event.button() == Qt.RightButton: event.ignore() return if event.button() == Qt.LeftButton: self.pressed = True self.handle_event(QtWidgets.QGraphicsView.mousePressEvent, event) def mouseMoveEvent(self, event): if self.is_panning: self.pan(event) return pos = self.mapToScene(event.pos()) self.last_mouse[0] = pos.x() self.last_mouse[1] = pos.y() self.handle_event(QtWidgets.QGraphicsView.mouseMoveEvent, event, update=False) def mouseReleaseEvent(self, event): self.pressed = False if event.button() == Qt.MidButton: self.is_panning = False return self.handle_event(QtWidgets.QGraphicsView.mouseReleaseEvent, event) self.viewport().repaint() def wheelEvent(self, event): """Handle Qt mouse wheel events.""" if event.modifiers() & Qt.ControlModifier: self.wheel_zoom(event) else: self.wheel_pan(event) def fitInView(self, rect, flags=Qt.IgnoreAspectRatio): """Override fitInView to remove unwanted margins https://bugreports.qt.io/browse/QTBUG-42331 - based on QT sources """ if self.scene() is None or rect.isNull(): return unity = self.transform().mapRect(QtCore.QRectF(0, 0, 1, 1)) self.scale(1.0 / unity.width(), 1.0 / unity.height()) view_rect = self.viewport().rect() scene_rect = self.transform().mapRect(rect) xratio = view_rect.width() / scene_rect.width() yratio = view_rect.height() / scene_rect.height() if flags == Qt.KeepAspectRatio: xratio = yratio = min(xratio, yratio) elif flags == Qt.KeepAspectRatioByExpanding: xratio = yratio = max(xratio, yratio) self.scale(xratio, yratio) self.centerOn(rect.center()) def sort_by_generation(commits): """Sort commits by their generation. Ensures consistent diffs and patch exports""" if len(commits) <= 1: return commits commits.sort(key=lambda x: x.generation) return commits # Glossary # ======== # oid -- Git objects IDs (i.e. SHA-1 IDs) # ref -- Git references that resolve to a commit-ish (HEAD, branches, tags) git-cola-4.6.1/cola/widgets/defs.py000066400000000000000000000014711457126473700171230ustar00rootroot00000000000000import os import math try: scale_factor = float(os.getenv('GIT_COLA_SCALE', '1')) except ValueError: scale_factor = 1.0 def scale(value, factor=scale_factor): return int(value * factor) no_margin = 0 small_margin = scale(2) margin = scale(4) large_margin = scale(12) no_spacing = 0 spacing = scale(4) titlebar_spacing = scale(8) button_spacing = scale(12) cursor_width = scale(2) handle_width = scale(4) tool_button_height = scale(28) default_icon = scale(16) small_icon = scale(12) medium_icon = scale(48) large_icon = scale(96) huge_icon = scale(192) max_size = scale(4096) border = max(1, scale(0.5)) checkbox = scale(12) radio = scale(22) logo_text = 24 radio_border = max(1, scale(1.0 - (1.0 / math.pi))) separator = scale(3) dialog_w = scale(720) dialog_h = scale(445) msgbox_h = scale(128) git-cola-4.6.1/cola/widgets/diff.py000066400000000000000000002006741457126473700171200ustar00rootroot00000000000000from functools import partial import os import re from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from ..i18n import N_ from ..editpatch import edit_patch from ..interaction import Interaction from ..models import main from ..models import prefs from ..qtutils import get from .. import actions from .. import cmds from .. import core from .. import diffparse from .. import gitcmds from .. import gravatar from .. import hotkeys from .. import icons from .. import utils from .. import qtutils from .text import TextDecorator from .text import VimHintedPlainTextEdit from .text import PlainTextLabel from .text import RichTextLabel from .text import TextSearchWidget from . import defs from . import standard from . import imageview class DiffSyntaxHighlighter(QtGui.QSyntaxHighlighter): """Implements the diff syntax highlighting""" INITIAL_STATE = -1 DEFAULT_STATE = 0 DIFFSTAT_STATE = 1 DIFF_FILE_HEADER_STATE = 2 DIFF_STATE = 3 SUBMODULE_STATE = 4 END_STATE = 5 DIFF_FILE_HEADER_START_RGX = re.compile(r'diff --git a/.* b/.*') DIFF_HUNK_HEADER_RGX = re.compile( r'(?:@@ -[0-9,]+ \+[0-9,]+ @@)|(?:@@@ (?:-[0-9,]+ ){2}\+[0-9,]+ @@@)' ) BAD_WHITESPACE_RGX = re.compile(r'\s+$') def __init__(self, context, doc, whitespace=True, is_commit=False): QtGui.QSyntaxHighlighter.__init__(self, doc) self.whitespace = whitespace self.enabled = True self.is_commit = is_commit QPalette = QtGui.QPalette cfg = context.cfg palette = QPalette() disabled = palette.color(QPalette.Disabled, QPalette.Text) header = qtutils.rgb_hex(disabled) dark = palette.color(QPalette.Base).lightnessF() < 0.5 self.color_text = qtutils.rgb_triple(cfg.color('text', '030303')) self.color_add = qtutils.rgb_triple( cfg.color('add', '77aa77' if dark else 'd2ffe4') ) self.color_remove = qtutils.rgb_triple( cfg.color('remove', 'aa7777' if dark else 'fee0e4') ) self.color_header = qtutils.rgb_triple(cfg.color('header', header)) self.diff_header_fmt = qtutils.make_format(foreground=self.color_header) self.bold_diff_header_fmt = qtutils.make_format( foreground=self.color_header, bold=True ) self.diff_add_fmt = qtutils.make_format( foreground=self.color_text, background=self.color_add ) self.diff_remove_fmt = qtutils.make_format( foreground=self.color_text, background=self.color_remove ) self.bad_whitespace_fmt = qtutils.make_format(background=Qt.red) self.setCurrentBlockState(self.INITIAL_STATE) def set_enabled(self, enabled): self.enabled = enabled def highlightBlock(self, text): """Highlight the current text block""" if not self.enabled or not text: return formats = [] state = self.get_next_state(text) if state == self.DIFFSTAT_STATE: state, formats = self.get_formats_for_diffstat(state, text) elif state == self.DIFF_FILE_HEADER_STATE: state, formats = self.get_formats_for_diff_header(state, text) elif state == self.DIFF_STATE: state, formats = self.get_formats_for_diff_text(state, text) for start, end, fmt in formats: self.setFormat(start, end, fmt) self.setCurrentBlockState(state) def get_next_state(self, text): """Transition to the next state based on the input text""" state = self.previousBlockState() if state == DiffSyntaxHighlighter.INITIAL_STATE: if text.startswith('Submodule '): state = DiffSyntaxHighlighter.SUBMODULE_STATE elif text.startswith('diff --git '): state = DiffSyntaxHighlighter.DIFFSTAT_STATE elif self.is_commit: state = DiffSyntaxHighlighter.DEFAULT_STATE else: state = DiffSyntaxHighlighter.DIFFSTAT_STATE return state def get_formats_for_diffstat(self, state, text): """Returns (state, [(start, end, fmt), ...]) for highlighting diffstat text""" formats = [] if self.DIFF_FILE_HEADER_START_RGX.match(text): state = self.DIFF_FILE_HEADER_STATE end = len(text) fmt = self.diff_header_fmt formats.append((0, end, fmt)) elif self.DIFF_HUNK_HEADER_RGX.match(text): state = self.DIFF_STATE end = len(text) fmt = self.bold_diff_header_fmt formats.append((0, end, fmt)) elif '|' in text: offset = text.index('|') formats.append((0, offset, self.bold_diff_header_fmt)) formats.append((offset, len(text) - offset, self.diff_header_fmt)) else: formats.append((0, len(text), self.diff_header_fmt)) return state, formats def get_formats_for_diff_header(self, state, text): """Returns (state, [(start, end, fmt), ...]) for highlighting diff headers""" formats = [] if self.DIFF_HUNK_HEADER_RGX.match(text): state = self.DIFF_STATE formats.append((0, len(text), self.bold_diff_header_fmt)) else: formats.append((0, len(text), self.diff_header_fmt)) return state, formats def get_formats_for_diff_text(self, state, text): """Return (state, [(start, end fmt), ...]) for highlighting diff text""" formats = [] if self.DIFF_FILE_HEADER_START_RGX.match(text): state = self.DIFF_FILE_HEADER_STATE formats.append((0, len(text), self.diff_header_fmt)) elif self.DIFF_HUNK_HEADER_RGX.match(text): formats.append((0, len(text), self.bold_diff_header_fmt)) elif text.startswith('-'): if text == '-- ': state = self.END_STATE else: formats.append((0, len(text), self.diff_remove_fmt)) elif text.startswith('+'): formats.append((0, len(text), self.diff_add_fmt)) if self.whitespace: match = self.BAD_WHITESPACE_RGX.search(text) if match is not None: start = match.start() formats.append((start, len(text) - start, self.bad_whitespace_fmt)) return state, formats class DiffTextEdit(VimHintedPlainTextEdit): """A textedit for interacting with diff text""" def __init__( self, context, parent, is_commit=False, whitespace=True, numbers=False ): VimHintedPlainTextEdit.__init__(self, context, '', parent=parent) # Diff/patch syntax highlighter self.highlighter = DiffSyntaxHighlighter( context, self.document(), is_commit=is_commit, whitespace=whitespace ) if numbers: self.numbers = DiffLineNumbers(context, self) self.numbers.hide() else: self.numbers = None self.scrollvalue = None self.copy_diff_action = qtutils.add_action( self, N_('Copy Diff'), self.copy_diff, hotkeys.COPY_DIFF, ) self.copy_diff_action.setIcon(icons.copy()) self.copy_diff_action.setEnabled(False) self.menu_actions.append(self.copy_diff_action) self.cursorPositionChanged.connect(self._cursor_changed) self.selectionChanged.connect(self._selection_changed) def setFont(self, font): """Override setFont() so that we can use a custom "block" cursor""" super().setFont(font) if prefs.block_cursor(self.context): width = qtutils.text_width(font, 'M') self.setCursorWidth(width) def _cursor_changed(self): """Update the line number display when the cursor changes""" line_number = max(0, self.textCursor().blockNumber()) if self.numbers is not None: self.numbers.set_highlighted(line_number) def _selection_changed(self): """Respond to selection changes""" selected = bool(self.selected_text()) self.copy_diff_action.setEnabled(selected) def resizeEvent(self, event): super().resizeEvent(event) if self.numbers: self.numbers.refresh_size() def save_scrollbar(self): """Save the scrollbar value, but only on the first call""" if self.scrollvalue is None: scrollbar = self.verticalScrollBar() if scrollbar: scrollvalue = get(scrollbar) else: scrollvalue = None self.scrollvalue = scrollvalue def restore_scrollbar(self): """Restore the scrollbar and clear state""" scrollbar = self.verticalScrollBar() scrollvalue = self.scrollvalue if scrollbar and scrollvalue is not None: scrollbar.setValue(scrollvalue) self.scrollvalue = None def set_loading_message(self): """Add a pending loading message in the diff view""" self.hint.set_value('+++ ' + N_('Loading...')) self.set_value('') def set_diff(self, diff): """Set the diff text, but save the scrollbar""" diff = diff.rstrip('\n') # diffs include two empty newlines self.save_scrollbar() self.hint.set_value('') if self.numbers: self.numbers.set_diff(diff) self.set_value(diff) self.restore_scrollbar() def selected_diff_stripped(self): """Return the selected diff stripped of any diff characters""" sep, selection = self.selected_text_lines() return sep.join(_strip_diff(line) for line in selection) def copy_diff(self): """Copy the selected diff text stripped of any diff prefix characters""" text = self.selected_diff_stripped() qtutils.set_clipboard(text) def selected_lines(self): """Return selected lines""" cursor = self.textCursor() selection_start = cursor.selectionStart() selection_end = max(selection_start, cursor.selectionEnd() - 1) first_line_idx = -1 last_line_idx = -1 line_idx = 0 line_start = 0 for line_idx, line in enumerate(get(self, default='').splitlines()): line_end = line_start + len(line) if line_start <= selection_start <= line_end: first_line_idx = line_idx if line_start <= selection_end <= line_end: last_line_idx = line_idx break line_start = line_end + 1 if first_line_idx == -1: first_line_idx = line_idx if last_line_idx == -1: last_line_idx = line_idx return first_line_idx, last_line_idx def selected_text_lines(self): """Return selected lines and the CRLF / LF separator""" first_line_idx, last_line_idx = self.selected_lines() text = get(self, default='') sep = _get_sep(text) lines = [] for line_idx, line in enumerate(text.split(sep)): if first_line_idx <= line_idx <= last_line_idx: lines.append(line) return sep, lines def _get_sep(text): """Return either CRLF or LF based on the content""" if '\r\n' in text: sep = '\r\n' else: sep = '\n' return sep def _strip_diff(value): """Remove +/-/ from a selection""" if value.startswith(('+', '-', ' ')): return value[1:] return value class DiffLineNumbers(TextDecorator): def __init__(self, context, parent): TextDecorator.__init__(self, parent) self.highlight_line = -1 self.lines = None self.parser = diffparse.DiffLines() self.formatter = diffparse.FormatDigits() font = qtutils.diff_font(context) self.setFont(font) self._char_width = qtutils.text_width(font, 'M') QPalette = QtGui.QPalette self._palette = palette = self.palette() self._base = palette.color(QtGui.QPalette.Base) self._highlight = palette.color(QPalette.Highlight) self._highlight.setAlphaF(0.3) self._highlight_text = palette.color(QPalette.HighlightedText) self._window = palette.color(QPalette.Window) self._disabled = palette.color(QPalette.Disabled, QPalette.Text) def set_diff(self, diff): self.lines = self.parser.parse(diff) self.formatter.set_digits(self.parser.digits()) def width_hint(self): if not self.isVisible(): return 0 parser = self.parser if parser.merge: columns = 3 extra = 3 # one space in-between, one space after else: columns = 2 extra = 2 # one space in-between, one space after digits = parser.digits() * columns return defs.margin + (self._char_width * (digits + extra)) def set_highlighted(self, line_number): """Set the line to highlight""" self.highlight_line = line_number def current_line(self): lines = self.lines if lines and self.highlight_line >= 0: # Find the next valid line for i in range(self.highlight_line, len(lines)): # take the "new" line number: last value in tuple line_number = lines[i][-1] if line_number > 0: return line_number # Find the previous valid line for i in range(self.highlight_line - 1, -1, -1): # take the "new" line number: last value in tuple if i < len(lines): line_number = lines[i][-1] if line_number > 0: return line_number return None def paintEvent(self, event): """Paint the line number""" if not self.lines: return painter = QtGui.QPainter(self) painter.fillRect(event.rect(), self._base) editor = self.editor content_offset = editor.contentOffset() block = editor.firstVisibleBlock() width = self.width() text_width = width - (defs.margin * 2) text_flags = Qt.AlignRight | Qt.AlignVCenter event_rect_bottom = event.rect().bottom() highlight_line = self.highlight_line highlight = self._highlight highlight_text = self._highlight_text disabled = self._disabled fmt = self.formatter lines = self.lines num_lines = len(lines) while block.isValid(): block_number = block.blockNumber() if block_number >= num_lines: break block_geom = editor.blockBoundingGeometry(block) rect = block_geom.translated(content_offset).toRect() if not block.isVisible() or rect.top() >= event_rect_bottom: break if block_number == highlight_line: painter.fillRect(rect.x(), rect.y(), width, rect.height(), highlight) painter.setPen(highlight_text) else: painter.setPen(disabled) line = lines[block_number] if len(line) == 2: a, b = line text = fmt.value(a, b) elif len(line) == 3: old, base, new = line text = fmt.merge_value(old, base, new) painter.drawText( rect.x(), rect.y(), text_width, rect.height(), text_flags, text, ) block = block.next() class Viewer(QtWidgets.QFrame): """Text and image diff viewers""" INDEX_TEXT = 0 INDEX_IMAGE = 1 def __init__(self, context, parent=None): super().__init__(parent) self.context = context self.model = model = context.model self.images = [] self.pixmaps = [] self.options = options = Options(self) self.filename = PlainTextLabel(parent=self) self.filename.setAlignment(Qt.AlignVCenter | Qt.AlignLeft) font = self.font() font.setItalic(True) self.filename.setFont(font) self.filename.elide() self.text = DiffEditor(context, options, self) self.image = imageview.ImageView(parent=self) self.image.setFocusPolicy(Qt.NoFocus) self.search_widget = TextSearchWidget(self.text, self) self.search_widget.hide() self._drag_has_patches = False self.setAcceptDrops(True) self.setFocusProxy(self.text) stack = self.stack = QtWidgets.QStackedWidget(self) stack.addWidget(self.text) stack.addWidget(self.image) self.main_layout = qtutils.vbox( defs.no_margin, defs.no_spacing, self.stack, self.search_widget, ) self.setLayout(self.main_layout) # Observe images model.images_changed.connect(self.set_images, type=Qt.QueuedConnection) # Observe the diff type model.diff_type_changed.connect(self.set_diff_type, type=Qt.QueuedConnection) # Observe the file type model.file_type_changed.connect(self.set_file_type, type=Qt.QueuedConnection) # Observe the image mode combo box options.image_mode.currentIndexChanged.connect(lambda _: self.render()) options.zoom_mode.currentIndexChanged.connect(lambda _: self.render()) self.search_action = qtutils.add_action( self, N_('Search in Diff'), self.show_search_diff, hotkeys.SEARCH, ) def dragEnterEvent(self, event): """Accepts drops if the mimedata contains patches""" super().dragEnterEvent(event) patches = get_patches_from_mimedata(event.mimeData()) if patches: event.acceptProposedAction() self._drag_has_patches = True def dragLeaveEvent(self, event): """End the drag+drop interaction""" super().dragLeaveEvent(event) if self._drag_has_patches: event.accept() else: event.ignore() self._drag_has_patches = False def dropEvent(self, event): """Apply patches when dropped onto the widget""" if not self._drag_has_patches: event.ignore() return event.setDropAction(Qt.CopyAction) super().dropEvent(event) self._drag_has_patches = False patches = get_patches_from_mimedata(event.mimeData()) if patches: apply_patches(self.context, patches=patches) event.accept() # must be called after dropEvent() def show_search_diff(self): """Show a dialog for searching diffs""" # The diff search is only active in text mode. if self.stack.currentIndex() != self.INDEX_TEXT: return if not self.search_widget.isVisible(): self.search_widget.show() self.search_widget.setFocus() def export_state(self, state): state['show_diff_line_numbers'] = self.options.show_line_numbers.isChecked() state['show_diff_filenames'] = self.options.show_filenames.isChecked() state['image_diff_mode'] = self.options.image_mode.currentIndex() state['image_zoom_mode'] = self.options.zoom_mode.currentIndex() state['word_wrap'] = self.options.enable_word_wrapping.isChecked() return state def apply_state(self, state): diff_numbers = bool(state.get('show_diff_line_numbers', False)) self.set_line_numbers(diff_numbers, update=True) show_filenames = bool(state.get('show_diff_filenames', True)) self.set_show_filenames(show_filenames, update=True) image_mode = utils.asint(state.get('image_diff_mode', 0)) self.options.image_mode.set_index(image_mode) zoom_mode = utils.asint(state.get('image_zoom_mode', 0)) self.options.zoom_mode.set_index(zoom_mode) word_wrap = bool(state.get('word_wrap', True)) self.set_word_wrapping(word_wrap, update=True) return True def set_diff_type(self, diff_type): """Manage the image and text diff views when selection changes""" # The "diff type" is whether the diff viewer is displaying an image. self.options.set_diff_type(diff_type) if diff_type == main.Types.IMAGE: self.stack.setCurrentWidget(self.image) self.search_widget.hide() self.render() else: self.stack.setCurrentWidget(self.text) def set_file_type(self, file_type): """Manage the diff options when the file type changes""" # The "file type" is whether the file itself is an image. self.options.set_file_type(file_type) def enable_filename_tracking(self): """Enable displaying the currently selected filename""" self.context.selection.selection_changed.connect( self.update_filename, type=Qt.QueuedConnection ) def update_filename(self): """Update the filename display when the selection changes""" filename = self.context.selection.filename() self.filename.set_text(filename or '') def update_options(self): """Emit a signal indicating that options have changed""" self.text.update_options() show_filenames = get(self.options.show_filenames) self.set_show_filenames(show_filenames) def set_show_filenames(self, enabled, update=False): """Enable/disable displaying the selected filename""" self.filename.setVisible(enabled) if update: with qtutils.BlockSignals(self.options.show_filenames): self.options.show_filenames.setChecked(enabled) def set_line_numbers(self, enabled, update=False): """Enable/disable line numbers in the text widget""" self.text.set_line_numbers(enabled, update=update) def set_word_wrapping(self, enabled, update=False): """Enable/disable word wrapping in the text widget""" self.text.set_word_wrapping(enabled, update=update) def reset(self): self.image.pixmap = QtGui.QPixmap() self.cleanup() def cleanup(self): for image, unlink in self.images: if unlink and core.exists(image): os.unlink(image) self.images = [] def set_images(self, images): self.images = images self.pixmaps = [] if not images: self.reset() return False # In order to comp, we first have to load all the images all_pixmaps = [QtGui.QPixmap(image[0]) for image in images] pixmaps = [pixmap for pixmap in all_pixmaps if not pixmap.isNull()] if not pixmaps: self.reset() return False self.pixmaps = pixmaps self.render() self.cleanup() return True def render(self): # Update images if self.pixmaps: mode = self.options.image_mode.currentIndex() if mode == self.options.SIDE_BY_SIDE: image = self.render_side_by_side() elif mode == self.options.DIFF: image = self.render_diff() elif mode == self.options.XOR: image = self.render_xor() elif mode == self.options.PIXEL_XOR: image = self.render_pixel_xor() else: image = self.render_side_by_side() else: image = QtGui.QPixmap() self.image.pixmap = image # Apply zoom zoom_mode = self.options.zoom_mode.currentIndex() zoom_factor = self.options.zoom_factors[zoom_mode][1] if zoom_factor > 0.0: self.image.resetTransform() self.image.scale(zoom_factor, zoom_factor) poly = self.image.mapToScene(self.image.viewport().rect()) self.image.last_scene_roi = poly.boundingRect() def render_side_by_side(self): # Side-by-side lineup comp pixmaps = self.pixmaps width = sum(pixmap.width() for pixmap in pixmaps) height = max(pixmap.height() for pixmap in pixmaps) image = create_image(width, height) # Paint each pixmap painter = create_painter(image) x = 0 for pixmap in pixmaps: painter.drawPixmap(x, 0, pixmap) x += pixmap.width() painter.end() return image def render_comp(self, comp_mode): # Get the max size to use as the render canvas pixmaps = self.pixmaps if len(pixmaps) == 1: return pixmaps[0] width = max(pixmap.width() for pixmap in pixmaps) height = max(pixmap.height() for pixmap in pixmaps) image = create_image(width, height) painter = create_painter(image) for pixmap in (pixmaps[0], pixmaps[-1]): x = (width - pixmap.width()) // 2 y = (height - pixmap.height()) // 2 painter.drawPixmap(x, y, pixmap) painter.setCompositionMode(comp_mode) painter.end() return image def render_diff(self): comp_mode = QtGui.QPainter.CompositionMode_Difference return self.render_comp(comp_mode) def render_xor(self): comp_mode = QtGui.QPainter.CompositionMode_Xor return self.render_comp(comp_mode) def render_pixel_xor(self): comp_mode = QtGui.QPainter.RasterOp_SourceXorDestination return self.render_comp(comp_mode) def create_image(width, height): size = QtCore.QSize(width, height) image = QtGui.QImage(size, QtGui.QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) return image def create_painter(image): painter = QtGui.QPainter(image) painter.fillRect(image.rect(), Qt.transparent) return painter class Options(QtWidgets.QWidget): """Provide the options widget used by the editor Actions are registered on the parent widget. """ # mode combobox indexes SIDE_BY_SIDE = 0 DIFF = 1 XOR = 2 PIXEL_XOR = 3 def __init__(self, parent): super().__init__(parent) # Create widgets self.widget = parent self.ignore_space_at_eol = self.add_option( N_('Ignore changes in whitespace at EOL') ) self.ignore_space_change = self.add_option( N_('Ignore changes in amount of whitespace') ) self.ignore_all_space = self.add_option(N_('Ignore all whitespace')) self.function_context = self.add_option( N_('Show whole surrounding functions of changes') ) self.show_line_numbers = qtutils.add_action_bool( self, N_('Show line numbers'), self.set_line_numbers, True ) self.show_filenames = self.add_option(N_('Show filenames')) self.enable_word_wrapping = qtutils.add_action_bool( self, N_('Enable word wrapping'), self.set_word_wrapping, True ) self.options = qtutils.create_action_button( tooltip=N_('Diff Options'), icon=icons.configure() ) self.toggle_image_diff = qtutils.create_action_button( tooltip=N_('Toggle image diff'), icon=icons.visualize() ) self.toggle_image_diff.hide() self.image_mode = qtutils.combo( [N_('Side by side'), N_('Diff'), N_('XOR'), N_('Pixel XOR')] ) self.zoom_factors = ( (N_('Zoom to Fit'), 0.0), (N_('25%'), 0.25), (N_('50%'), 0.5), (N_('100%'), 1.0), (N_('200%'), 2.0), (N_('400%'), 4.0), (N_('800%'), 8.0), ) zoom_modes = [factor[0] for factor in self.zoom_factors] self.zoom_mode = qtutils.combo(zoom_modes, parent=self) self.menu = menu = qtutils.create_menu(N_('Diff Options'), self.options) self.options.setMenu(menu) menu.addAction(self.ignore_space_at_eol) menu.addAction(self.ignore_space_change) menu.addAction(self.ignore_all_space) menu.addSeparator() menu.addAction(self.function_context) menu.addAction(self.show_line_numbers) menu.addAction(self.show_filenames) menu.addSeparator() menu.addAction(self.enable_word_wrapping) # Layouts layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.image_mode, self.zoom_mode, self.options, self.toggle_image_diff, ) self.setLayout(layout) # Policies self.image_mode.setFocusPolicy(Qt.NoFocus) self.zoom_mode.setFocusPolicy(Qt.NoFocus) self.options.setFocusPolicy(Qt.NoFocus) self.toggle_image_diff.setFocusPolicy(Qt.NoFocus) self.setFocusPolicy(Qt.NoFocus) def set_file_type(self, file_type): """Set whether we are viewing an image file type""" is_image = file_type == main.Types.IMAGE self.toggle_image_diff.setVisible(is_image) def set_diff_type(self, diff_type): """Toggle between image and text diffs""" is_text = diff_type == main.Types.TEXT is_image = diff_type == main.Types.IMAGE self.options.setVisible(is_text) self.image_mode.setVisible(is_image) self.zoom_mode.setVisible(is_image) if is_image: self.toggle_image_diff.setIcon(icons.diff()) else: self.toggle_image_diff.setIcon(icons.visualize()) def add_option(self, title): """Add a diff option which calls update_options() on change""" action = qtutils.add_action(self, title, self.update_options) action.setCheckable(True) return action def update_options(self): """Update diff options in response to UI events""" space_at_eol = get(self.ignore_space_at_eol) space_change = get(self.ignore_space_change) all_space = get(self.ignore_all_space) function_context = get(self.function_context) gitcmds.update_diff_overrides( space_at_eol, space_change, all_space, function_context ) self.widget.update_options() def set_line_numbers(self, value): """Enable / disable line numbers""" self.widget.set_line_numbers(value, update=False) def set_word_wrapping(self, value): """Respond to Qt action callbacks""" self.widget.set_word_wrapping(value, update=False) def hide_advanced_options(self): """Hide advanced options that are not applicable to the DiffWidget""" self.show_filenames.setVisible(False) self.show_line_numbers.setVisible(False) self.ignore_space_at_eol.setVisible(False) self.ignore_space_change.setVisible(False) self.ignore_all_space.setVisible(False) self.function_context.setVisible(False) class DiffEditor(DiffTextEdit): up = Signal() down = Signal() options_changed = Signal() def __init__(self, context, options, parent): DiffTextEdit.__init__(self, context, parent, numbers=True) self.context = context self.model = model = context.model self.selection_model = selection_model = context.selection # "Diff Options" tool menu self.options = options self.action_apply_selection = qtutils.add_action( self, 'Apply', self.apply_selection, hotkeys.STAGE_DIFF, hotkeys.STAGE_DIFF_ALT, ) self.action_revert_selection = qtutils.add_action( self, 'Revert', self.revert_selection, hotkeys.REVERT, hotkeys.REVERT_ALT ) self.action_revert_selection.setIcon(icons.undo()) self.action_edit_and_apply_selection = qtutils.add_action( self, 'Edit and Apply', partial(self.apply_selection, edit=True), hotkeys.EDIT_AND_STAGE_DIFF, ) self.action_edit_and_revert_selection = qtutils.add_action( self, 'Edit and Revert', partial(self.revert_selection, edit=True), hotkeys.EDIT_AND_REVERT, ) self.action_edit_and_revert_selection.setIcon(icons.undo()) self.launch_editor = actions.launch_editor_at_line( context, self, hotkeys.EDIT_SHORT, *hotkeys.ACCEPT ) self.launch_difftool = actions.launch_difftool(context, self) self.stage_or_unstage = actions.stage_or_unstage(context, self) # Emit up/down signals so that they can be routed by the main widget self.move_up = actions.move_up(self) self.move_down = actions.move_down(self) model.diff_text_updated.connect(self.set_diff, type=Qt.QueuedConnection) selection_model.selection_changed.connect( self.refresh, type=Qt.QueuedConnection ) # Update the selection model when the cursor changes self.cursorPositionChanged.connect(self._update_line_number) qtutils.connect_button(options.toggle_image_diff, self.toggle_diff_type) def toggle_diff_type(self): cmds.do(cmds.ToggleDiffType, self.context) def refresh(self): enabled = False s = self.selection_model.selection() model = self.model if model.is_partially_stageable(): item = s.modified[0] if s.modified else None if item in model.submodules: pass elif item not in model.unstaged_deleted: enabled = True self.action_revert_selection.setEnabled(enabled) def set_line_numbers(self, enabled, update=False): """Enable/disable the diff line number display""" self.numbers.setVisible(enabled) if update: with qtutils.BlockSignals(self.options.show_line_numbers): self.options.show_line_numbers.setChecked(enabled) # Refresh the display. Not doing this results in the display not # correctly displaying the line numbers widget until the text scrolls. self.set_value(self.value()) def update_options(self): self.options_changed.emit() def create_context_menu(self, event_pos): """Override create_context_menu() to display a completely custom menu""" menu = super().create_context_menu(event_pos) context = self.context model = self.model s = self.selection_model.selection() filename = self.selection_model.filename() # These menu actions will be inserted at the start of the widget. current_actions = menu.actions() menu_actions = [] add_action = menu_actions.append edit_actions_added = False stage_action_added = False if s.staged and model.is_unstageable(): item = s.staged[0] if item not in model.submodules and item not in model.staged_deleted: if self.has_selection(): apply_text = N_('Unstage Selected Lines') else: apply_text = N_('Unstage Diff Hunk') self.action_apply_selection.setText(apply_text) self.action_apply_selection.setIcon(icons.remove()) add_action(self.action_apply_selection) stage_action_added = self._add_stage_or_unstage_action( menu, add_action, stage_action_added ) if model.is_partially_stageable(): item = s.modified[0] if s.modified else None if item in model.submodules: path = core.abspath(item) action = qtutils.add_action_with_icon( menu, icons.add(), cmds.Stage.name(), cmds.run(cmds.Stage, context, s.modified), hotkeys.STAGE_SELECTION, ) add_action(action) stage_action_added = self._add_stage_or_unstage_action( menu, add_action, stage_action_added ) action = qtutils.add_action_with_icon( menu, icons.cola(), N_('Launch git-cola'), cmds.run(cmds.OpenRepo, context, path), ) add_action(action) elif item and item not in model.unstaged_deleted: if self.has_selection(): apply_text = N_('Stage Selected Lines') edit_and_apply_text = N_('Edit Selected Lines to Stage...') revert_text = N_('Revert Selected Lines...') edit_and_revert_text = N_('Edit Selected Lines to Revert...') else: apply_text = N_('Stage Diff Hunk') edit_and_apply_text = N_('Edit Diff Hunk to Stage...') revert_text = N_('Revert Diff Hunk...') edit_and_revert_text = N_('Edit Diff Hunk to Revert...') self.action_apply_selection.setText(apply_text) self.action_apply_selection.setIcon(icons.add()) add_action(self.action_apply_selection) self.action_revert_selection.setText(revert_text) add_action(self.action_revert_selection) stage_action_added = self._add_stage_or_unstage_action( menu, add_action, stage_action_added ) # Do not show the "edit" action when the file does not exist. add_action(qtutils.menu_separator(menu)) if filename and core.exists(filename): add_action(self.launch_editor) # Removed files can still be diffed. add_action(self.launch_difftool) edit_actions_added = True add_action(qtutils.menu_separator(menu)) self.action_edit_and_apply_selection.setText(edit_and_apply_text) self.action_edit_and_apply_selection.setIcon(icons.add()) add_action(self.action_edit_and_apply_selection) self.action_edit_and_revert_selection.setText(edit_and_revert_text) add_action(self.action_edit_and_revert_selection) if s.staged and model.is_unstageable(): item = s.staged[0] if item in model.submodules: path = core.abspath(item) action = qtutils.add_action_with_icon( menu, icons.remove(), cmds.Unstage.name(), cmds.run(cmds.Unstage, context, s.staged), hotkeys.STAGE_SELECTION, ) add_action(action) stage_action_added = self._add_stage_or_unstage_action( menu, add_action, stage_action_added ) qtutils.add_action_with_icon( menu, icons.cola(), N_('Launch git-cola'), cmds.run(cmds.OpenRepo, context, path), ) add_action(action) elif item not in model.staged_deleted: # Do not show the "edit" action when the file does not exist. add_action(qtutils.menu_separator(menu)) if filename and core.exists(filename): add_action(self.launch_editor) # Removed files can still be diffed. add_action(self.launch_difftool) add_action(qtutils.menu_separator(menu)) edit_actions_added = True if self.has_selection(): edit_and_apply_text = N_('Edit Selected Lines to Unstage...') else: edit_and_apply_text = N_('Edit Diff Hunk to Unstage...') self.action_edit_and_apply_selection.setText(edit_and_apply_text) self.action_edit_and_apply_selection.setIcon(icons.remove()) add_action(self.action_edit_and_apply_selection) if not edit_actions_added and (model.is_stageable() or model.is_unstageable()): add_action(qtutils.menu_separator(menu)) # Do not show the "edit" action when the file does not exist. # Untracked files exist by definition. if filename and core.exists(filename): add_action(self.launch_editor) # Removed files can still be diffed. add_action(self.launch_difftool) add_action(qtutils.menu_separator(menu)) _add_patch_actions(self, self.context, menu) # Add the Previous/Next File actions, which improves discoverability # of their associated shortcuts add_action(qtutils.menu_separator(menu)) add_action(self.move_up) add_action(self.move_down) add_action(qtutils.menu_separator(menu)) if current_actions: first_action = current_actions[0] else: first_action = None menu.insertActions(first_action, menu_actions) return menu def _add_stage_or_unstage_action(self, menu, add_action, already_added): """Add the Stage / Unstage menu action""" if already_added: return True model = self.context.model s = self.selection_model.selection() if model.is_stageable() or model.is_unstageable(): if (model.is_amend_mode() and s.staged) or not self.model.is_stageable(): self.stage_or_unstage.setText(N_('Unstage')) self.stage_or_unstage.setIcon(icons.remove()) else: self.stage_or_unstage.setText(N_('Stage')) self.stage_or_unstage.setIcon(icons.add()) add_action(qtutils.menu_separator(menu)) add_action(self.stage_or_unstage) return True 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. if not self.has_selection(): cursor = self.cursorForPosition(event.pos()) self.setTextCursor(cursor) return super().mousePressEvent(event) def setPlainText(self, text): """setPlainText(str) while retaining scrollbar positions""" model = self.model mode = model.mode highlight = mode not in ( model.mode_none, model.mode_display, model.mode_untracked, ) self.highlighter.set_enabled(highlight) scrollbar = self.verticalScrollBar() if scrollbar: scrollvalue = get(scrollbar) else: scrollvalue = None if text is None: return DiffTextEdit.setPlainText(self, text) if scrollbar and scrollvalue is not None: scrollbar.setValue(scrollvalue) def apply_selection(self, *, edit=False): model = self.model s = self.selection_model.single_selection() if model.is_partially_stageable() and (s.modified or s.untracked): self.process_diff_selection(edit=edit) elif model.is_unstageable(): self.process_diff_selection(reverse=True, edit=edit) def revert_selection(self, *, edit=False): """Destructively revert selected lines or hunk from a worktree file.""" if not edit: if self.has_selection(): title = N_('Revert Selected Lines?') ok_text = N_('Revert Selected Lines') else: title = N_('Revert Diff Hunk?') ok_text = N_('Revert Diff Hunk') if not Interaction.confirm( title, N_( 'This operation drops uncommitted changes.\n' 'These changes cannot be recovered.' ), N_('Revert the uncommitted changes?'), ok_text, default=True, icon=icons.undo(), ): return self.process_diff_selection(reverse=True, apply_to_worktree=True, edit=edit) def extract_patch(self, reverse=False): first_line_idx, last_line_idx = self.selected_lines() patch = diffparse.Patch.parse(self.model.filename, self.model.diff_text) if self.has_selection(): return patch.extract_subset(first_line_idx, last_line_idx, reverse=reverse) return patch.extract_hunk(first_line_idx, reverse=reverse) def patch_encoding(self): if isinstance(self.model.diff_text, core.UStr): # original encoding must prevail return self.model.diff_text.encoding return self.context.cfg.file_encoding(self.model.filename) def process_diff_selection( self, reverse=False, apply_to_worktree=False, edit=False ): """Implement un/staging of the selected line(s) or hunk.""" if self.selection_model.is_empty(): return patch = self.extract_patch(reverse) if not patch.has_changes(): return patch_encoding = self.patch_encoding() if edit: patch = edit_patch( patch, patch_encoding, self.context, reverse=reverse, apply_to_worktree=apply_to_worktree, ) if not patch.has_changes(): return cmds.do( cmds.ApplyPatch, self.context, patch, patch_encoding, apply_to_worktree, ) def _update_line_number(self): """Update the selection model when the cursor changes""" self.selection_model.line_number = self.numbers.current_line() def _add_patch_actions(widget, context, menu): """Add actions for manipulating patch files""" patches_menu = menu.addMenu(N_('Patches')) patches_menu.setIcon(icons.diff()) export_action = qtutils.add_action( patches_menu, N_('Export Patch'), lambda: _export_patch(widget, context), ) export_action.setIcon(icons.save()) patches_menu.addAction(export_action) # Build the "Append Patch" menu dynamically. append_menu = patches_menu.addMenu(N_('Append Patch')) append_menu.setIcon(icons.add()) append_menu.aboutToShow.connect( lambda: _build_patch_append_menu(widget, context, append_menu) ) def _build_patch_append_menu(widget, context, menu): """Build the "Append Patch" sub-menu""" # Build the menu when first displayed only. This initial check avoids # re-populating the menu with duplicate actions. menu_actions = menu.actions() if menu_actions: return choose_patch_action = qtutils.add_action( menu, N_('Choose Patch...'), lambda: _export_patch(widget, context, append=True), ) choose_patch_action.setIcon(icons.diff()) menu.addAction(choose_patch_action) subdir_menus = {} path = prefs.patches_directory(context) patches = get_patches_from_dir(path) for patch in patches: relpath = os.path.relpath(patch, start=path) sub_menu = _add_patch_subdirs(menu, subdir_menus, relpath) patch_basename = os.path.basename(relpath) append_action = qtutils.add_action( sub_menu, patch_basename, lambda patch_file=patch: _append_patch(widget, patch_file), ) append_action.setIcon(icons.save()) sub_menu.addAction(append_action) def _add_patch_subdirs(menu, subdir_menus, relpath): """Build menu leading up to the patch""" # If the path contains no directory separators then add it to the # root of the menu. if os.sep not in relpath: return menu # Loop over each directory component and build a menu if it doesn't already exist. components = [] for dirname in os.path.dirname(relpath).split(os.sep): components.append(dirname) current_dir = os.sep.join(components) try: menu = subdir_menus[current_dir] except KeyError: menu = subdir_menus[current_dir] = menu.addMenu(dirname) menu.setIcon(icons.folder()) return menu def _export_patch(diff_editor, context, append=False): """Export the selected diff to a patch file""" if diff_editor.selection_model.is_empty(): return patch = diff_editor.extract_patch(reverse=False) if not patch.has_changes(): return directory = prefs.patches_directory(context) if append: filename = qtutils.existing_file(directory, title=N_('Append Patch...')) else: default_filename = os.path.join(directory, 'diff.patch') filename = qtutils.save_as(default_filename) if not filename: return _write_patch_to_file(diff_editor, patch, filename, append=append) def _append_patch(diff_editor, filename): """Append diffs to the specified patch file""" if diff_editor.selection_model.is_empty(): return patch = diff_editor.extract_patch(reverse=False) if not patch.has_changes(): return _write_patch_to_file(diff_editor, patch, filename, append=True) def _write_patch_to_file(diff_editor, patch, filename, append=False): """Write diffs from the Diff Editor to the specified patch file""" encoding = diff_editor.patch_encoding() content = patch.as_text() try: core.write(filename, content, encoding=encoding, append=append) except OSError as exc: _, details = utils.format_exception(exc) title = N_('Error writing patch') msg = N_('Unable to write patch to "%s". Check permissions?' % filename) Interaction.critical(title, message=msg, details=details) return Interaction.log('Patch written to "%s"' % filename) class DiffWidget(QtWidgets.QWidget): """Display commit metadata and text diffs""" def __init__(self, context, parent, is_commit=False, options=None): QtWidgets.QWidget.__init__(self, parent) self.context = context self.oid = 'HEAD' self.oid_start = None self.oid_end = None self.options = options 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) self.gravatar_label = gravatar.GravatarLabel(self.context, parent=self) self.oid_label = PlainTextLabel(parent=self) self.oid_label.setAlignment(Qt.AlignBottom) self.oid_label.elide() self.author_label = RichTextLabel(parent=self) self.author_label.setFont(author_font) self.author_label.setAlignment(Qt.AlignTop) self.author_label.elide() self.date_label = PlainTextLabel(parent=self) self.date_label.setAlignment(Qt.AlignTop) self.date_label.elide() self.summary_label = PlainTextLabel(parent=self) self.summary_label.setFont(summary_font) self.summary_label.setAlignment(Qt.AlignTop) self.summary_label.elide() self.diff = DiffTextEdit(context, self, is_commit=is_commit, whitespace=False) self.setFocusProxy(self.diff) self.info_layout = qtutils.vbox( defs.no_margin, defs.no_spacing, self.oid_label, self.author_label, self.date_label, self.summary_label, ) self.logo_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.gravatar_label, self.info_layout ) self.logo_layout.setContentsMargins(defs.margin, 0, defs.margin, 0) self.main_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.logo_layout, self.diff ) self.setLayout(self.main_layout) self.set_tabwidth(prefs.tabwidth(context)) def set_tabwidth(self, width): self.diff.set_tabwidth(width) def set_word_wrapping(self, enabled, update=False): """Enable and disable word wrapping""" self.diff.set_word_wrapping(enabled, update=update) def set_options(self, options): """Register an options widget""" self.options = options self.diff.set_options(options) def start_diff_task(self, task): """Clear the display and start a diff-gathering task""" self.diff.save_scrollbar() self.diff.set_loading_message() self.context.runtask.start(task, result=self.set_diff) def set_diff_oid(self, oid, filename=None): """Set the diff from a single commit object ID""" task = DiffInfoTask(self.context, oid, filename) self.start_diff_task(task) def set_diff_range(self, start, end, filename=None): task = DiffRangeTask(self.context, start + '~', end, filename) self.start_diff_task(task) def commits_selected(self, commits): """Display an appropriate diff when commits are selected""" if not commits: self.clear() return commit = commits[-1] oid = commit.oid author = commit.author or '' email = commit.email or '' date = commit.authdate or '' summary = commit.summary or '' self.set_details(oid, author, email, date, summary) self.oid = oid if len(commits) > 1: start, end = commits[0], commits[-1] self.set_diff_range(start.oid, end.oid) self.oid_start = start self.oid_end = end else: self.set_diff_oid(oid) self.oid_start = None self.oid_end = None def set_diff(self, diff): """Set the diff text""" self.diff.set_diff(diff) def set_details(self, oid, author, email, date, summary): 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.date_label.set_text(date) self.date_label.setVisible(bool(date)) self.oid_label.set_text(oid) self.author_label.set_template(author_text, author_template) self.summary_label.set_text(summary) self.gravatar_label.set_email(email) def clear(self): self.date_label.set_text('') self.oid_label.set_text('') self.author_label.set_text('') self.summary_label.set_text('') self.gravatar_label.clear() self.diff.clear() def files_selected(self, filenames): """Update the view when a filename is selected""" oid_start = self.oid_start oid_end = self.oid_end extra_args = {} if filenames: extra_args['filename'] = filenames[0] if oid_start and oid_end: self.set_diff_range(oid_start.oid, oid_end.oid, **extra_args) else: self.set_diff_oid(self.oid, **extra_args) class DiffPanel(QtWidgets.QWidget): """A combined diff + search panel""" def __init__(self, diff_widget, text_widget, parent): super().__init__(parent) self.diff_widget = diff_widget self.search_widget = TextSearchWidget(text_widget, self) self.search_widget.hide() layout = qtutils.vbox( defs.no_margin, defs.spacing, self.diff_widget, self.search_widget ) self.setLayout(layout) self.setFocusProxy(self.diff_widget) self.search_action = qtutils.add_action( self, N_('Search in Diff'), self.show_search, hotkeys.SEARCH, ) def show_search(self): """Show a dialog for searching diffs""" # The diff search is only active in text mode. if not self.search_widget.isVisible(): self.search_widget.show() self.search_widget.setFocus() class DiffInfoTask(qtutils.Task): """Gather diffs for a single commit""" def __init__(self, context, oid, filename): qtutils.Task.__init__(self) self.context = context self.oid = oid self.filename = filename def task(self): context = self.context oid = self.oid return gitcmds.diff_info(context, oid, filename=self.filename) class DiffRangeTask(qtutils.Task): """Gather diffs for a range of commits""" def __init__(self, context, start, end, filename): qtutils.Task.__init__(self) self.context = context self.start = start self.end = end self.filename = filename def task(self): context = self.context return gitcmds.diff_range(context, self.start, self.end, filename=self.filename) def apply_patches(context, patches=None): """Open the ApplyPatches dialog""" parent = qtutils.active_window() dlg = new_apply_patches(context, patches=patches, parent=parent) dlg.show() dlg.raise_() return dlg def new_apply_patches(context, patches=None, parent=None): """Create a new instances of the ApplyPatches dialog""" dlg = ApplyPatches(context, parent=parent) if patches: dlg.add_paths(patches) return dlg def get_patches_from_paths(paths): """Returns all patches beneath a given path""" paths = [core.decode(p) for p in paths] patches = [p for p in paths if core.isfile(p) and p.endswith(('.patch', '.mbox'))] dirs = [p for p in paths if core.isdir(p)] dirs.sort() for d in dirs: patches.extend(get_patches_from_dir(d)) return patches def get_patches_from_mimedata(mimedata): """Extract path files from a QMimeData payload""" urls = mimedata.urls() if not urls: return [] paths = [x.path() for x in urls] return get_patches_from_paths(paths) def get_patches_from_dir(path): """Find patches in a subdirectory""" patches = [] for root, _, files in core.walk(path): for name in [f for f in files if f.endswith(('.patch', '.mbox'))]: patches.append(core.decode(os.path.join(root, name))) return patches class ApplyPatches(standard.Dialog): def __init__(self, context, parent=None): super().__init__(parent=parent) self.context = context self.setWindowTitle(N_('Apply Patches')) self.setAcceptDrops(True) if parent is not None: self.setWindowModality(Qt.WindowModal) self.curdir = core.getcwd() self.inner_drag = False self.usage = QtWidgets.QLabel() self.usage.setText( N_( """

Drag and drop or use the Add button to add patches to the list

""" ) ) self.tree = PatchTreeWidget(parent=self) self.tree.setHeaderHidden(True) self.tree.itemSelectionChanged.connect(self._tree_selection_changed) self.diffwidget = DiffWidget(context, self, is_commit=True) self.add_button = qtutils.create_toolbutton( text=N_('Add'), icon=icons.add(), tooltip=N_('Add patches (+)') ) self.remove_button = qtutils.create_toolbutton( text=N_('Remove'), icon=icons.remove(), tooltip=N_('Remove selected (Delete)'), ) self.apply_button = qtutils.create_button(text=N_('Apply'), icon=icons.ok()) self.close_button = qtutils.close_button() self.add_action = qtutils.add_action( self, N_('Add'), self.add_files, hotkeys.ADD_ITEM ) self.remove_action = qtutils.add_action( self, N_('Remove'), self.tree.remove_selected, hotkeys.DELETE, hotkeys.BACKSPACE, hotkeys.REMOVE_ITEM, ) self.top_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.add_button, self.remove_button, qtutils.STRETCH, self.usage, ) self.bottom_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, qtutils.STRETCH, self.close_button, self.apply_button, ) self.splitter = qtutils.splitter(Qt.Vertical, self.tree, self.diffwidget) self.main_layout = qtutils.vbox( defs.margin, defs.spacing, self.top_layout, self.splitter, self.bottom_layout, ) self.setLayout(self.main_layout) qtutils.connect_button(self.add_button, self.add_files) qtutils.connect_button(self.remove_button, self.tree.remove_selected) qtutils.connect_button(self.apply_button, self.apply_patches) qtutils.connect_button(self.close_button, self.close) self.init_state(None, self.resize, 720, 480) def apply_patches(self): items = self.tree.items() if not items: return context = self.context patches = [i.data(0, Qt.UserRole) for i in items] cmds.do(cmds.ApplyPatches, context, patches) self.accept() def add_files(self): files = qtutils.open_files( N_('Select patch file(s)...'), directory=self.curdir, filters='Patches (*.patch *.mbox)', ) if not files: return self.curdir = os.path.dirname(files[0]) self.add_paths([core.relpath(f) for f in files]) def dragEnterEvent(self, event): """Accepts drops if the mimedata contains patches""" super().dragEnterEvent(event) patches = get_patches_from_mimedata(event.mimeData()) if patches: event.acceptProposedAction() def dropEvent(self, event): """Add dropped patches""" event.accept() patches = get_patches_from_mimedata(event.mimeData()) if not patches: return self.add_paths(patches) def add_paths(self, paths): self.tree.add_paths(paths) def _tree_selection_changed(self): items = self.tree.selected_items() if not items: return item = items[-1] # take the last item path = item.data(0, Qt.UserRole) if not core.exists(path): return commit = parse_patch(path) self.diffwidget.set_details( commit.oid, commit.author, commit.email, commit.date, commit.summary ) self.diffwidget.set_diff(commit.diff) def export_state(self): """Export persistent settings""" state = super().export_state() state['sizes'] = get(self.splitter) return state def apply_state(self, state): """Apply persistent settings""" result = super().apply_state(state) try: self.splitter.setSizes(state['sizes']) except (AttributeError, KeyError, ValueError, TypeError): pass return result class PatchTreeWidget(standard.DraggableTreeWidget): def add_paths(self, paths): patches = get_patches_from_paths(paths) if not patches: return items = [] icon = icons.file_text() for patch in patches: item = QtWidgets.QTreeWidgetItem() flags = item.flags() & ~Qt.ItemIsDropEnabled item.setFlags(flags) item.setIcon(0, icon) item.setText(0, os.path.basename(patch)) item.setData(0, Qt.UserRole, patch) item.setToolTip(0, patch) items.append(item) self.addTopLevelItems(items) def remove_selected(self): idxs = self.selectedIndexes() rows = [idx.row() for idx in idxs] for row in reversed(sorted(rows)): self.invisibleRootItem().takeChild(row) class Commit: """Container for commit details""" def __init__(self): self.content = '' self.author = '' self.email = '' self.oid = '' self.summary = '' self.diff = '' self.date = '' def parse_patch(path): content = core.read(path) commit = Commit() parse(content, commit) return commit def parse(content, commit): """Parse commit details from a patch""" from_rgx = re.compile(r'^From (?P[a-f0-9]{40}) .*$') author_rgx = re.compile(r'^From: (?P[^<]+) <(?P[^>]+)>$') date_rgx = re.compile(r'^Date: (?P.*)$') subject_rgx = re.compile(r'^Subject: (?P.*)$') commit.content = content lines = content.splitlines() for idx, line in enumerate(lines): match = from_rgx.match(line) if match: commit.oid = match.group('oid') continue match = author_rgx.match(line) if match: commit.author = match.group('author') commit.email = match.group('email') continue match = date_rgx.match(line) if match: commit.date = match.group('date') continue match = subject_rgx.match(line) if match: commit.summary = match.group('summary') commit.diff = '\n'.join(lines[idx + 1 :]) break git-cola-4.6.1/cola/widgets/editremotes.py000066400000000000000000000356371457126473700205410ustar00rootroot00000000000000import operator from qtpy import QtCore from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from ..git import STDOUT from ..i18n import N_ from ..qtutils import get from .. import cmds from .. import core from .. import gitcmds from .. import icons from .. import qtutils from .. import utils from . import completion from . import defs from . import standard from . import text def editor(context, run=True): view = RemoteEditor(context, parent=qtutils.active_window()) if run: view.show() view.exec_() return view class RemoteEditor(standard.Dialog): def __init__(self, context, parent=None): standard.Dialog.__init__(self, parent) self.setWindowTitle(N_('Edit Remotes')) if parent is not None: self.setWindowModality(Qt.WindowModal) self.context = context self.current_name = '' self.current_url = '' hint = N_('Edit remotes by selecting them from the list') self.default_hint = hint self.remote_list = [] self.remotes = QtWidgets.QListWidget() self.remotes.setToolTip(N_('Remote git repositories - double-click to rename')) self.editor = RemoteWidget(context, self) self.save_button = qtutils.create_button( text=N_('Save'), icon=icons.save(), default=True ) self.reset_button = qtutils.create_button( text=N_('Reset'), icon=icons.discard() ) tooltip = 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.' ) hint = self.default_hint self.info = text.VimHintedPlainTextEdit(context, hint, parent=self) self.info.setToolTip(tooltip) text_width, text_height = qtutils.text_size(self.info.font(), 'M') width = text_width * 42 height = text_height * 13 self.info.setMinimumWidth(width) self.info.setMinimumHeight(height) self.info_thread = RemoteInfoThread(context, self) icon = icons.add() tooltip = N_('Add new remote git repository') self.add_button = qtutils.create_toolbutton(icon=icon, tooltip=tooltip) self.refresh_button = qtutils.create_toolbutton( icon=icons.sync(), tooltip=N_('Refresh') ) self.delete_button = qtutils.create_toolbutton( icon=icons.remove(), tooltip=N_('Delete remote') ) self.close_button = qtutils.close_button() self._edit_button_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.save_button, self.reset_button ) self._edit_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.editor, self._edit_button_layout ) self._display_layout = qtutils.vbox( defs.no_margin, defs.spacing, self._edit_layout, self.info ) self._display_widget = QtWidgets.QWidget(self) self._display_widget.setLayout(self._display_layout) self._top_layout = qtutils.splitter( Qt.Horizontal, self.remotes, self._display_widget ) width = self._top_layout.width() self._top_layout.setSizes([width // 4, width * 3 // 4]) self._button_layout = qtutils.hbox( defs.margin, defs.spacing, self.add_button, self.delete_button, self.refresh_button, qtutils.STRETCH, self.close_button, ) self._layout = qtutils.vbox( defs.margin, defs.spacing, self._top_layout, self._button_layout ) self.setLayout(self._layout) qtutils.connect_button(self.add_button, self.add) qtutils.connect_button(self.delete_button, self.delete) qtutils.connect_button(self.refresh_button, self.refresh) qtutils.connect_button(self.close_button, self.accept) qtutils.connect_button(self.save_button, self.save) qtutils.connect_button(self.reset_button, self.reset) qtutils.add_close_action(self) thread = self.info_thread thread.result.connect(self.set_info, type=Qt.QueuedConnection) self.editor.remote_name.returnPressed.connect(self.save) self.editor.remote_url.returnPressed.connect(self.save) self.editor.valid.connect(self.editor_valid) self.remotes.itemChanged.connect(self.remote_item_renamed) self.remotes.itemSelectionChanged.connect(self.selection_changed) self.disable_editor() self.init_state(None, self.resize_widget, parent) self.remotes.setFocus(Qt.OtherFocusReason) self.refresh() def reset(self): focus = self.focusWidget() if self.current_name: self.activate_remote(self.current_name, gather_info=False) restore_focus(focus) @property def changed(self): url = self.editor.url name = self.editor.name return url != self.current_url or name != self.current_name def save(self): if not self.changed: return context = self.context name = self.editor.name url = self.editor.url old_url = self.current_url old_name = self.current_name name_changed = name and name != old_name url_changed = url and url != old_url focus = self.focusWidget() name_ok = url_ok = False # Run the corresponding command if name_changed and url_changed: name_ok, url_ok = cmds.do(cmds.RemoteEdit, context, old_name, name, url) elif name_changed: result = cmds.do(cmds.RemoteRename, context, old_name, name) name_ok = result[0] elif url_changed: result = cmds.do(cmds.RemoteSetURL, context, name, url) url_ok = result[0] # Update state if the change succeeded gather = False if url_changed and url_ok: self.current_url = url gather = True # A name change requires a refresh if name_changed and name_ok: self.current_name = name self.refresh(select=False) remotes = utils.Sequence(self.remote_list) idx = remotes.index(name) self.select_remote(idx) gather = False # already done by select_remote() restore_focus(focus) if gather: self.gather_info() def editor_valid(self, valid): changed = self.changed self.reset_button.setEnabled(changed) self.save_button.setEnabled(changed and valid) def disable_editor(self): self.save_button.setEnabled(False) self.reset_button.setEnabled(False) self.editor.setEnabled(False) self.editor.name = '' self.editor.url = '' self.info.hint.set_value(self.default_hint) self.info.set_value('') def resize_widget(self, parent): """Set the initial size of the widget""" width, height = qtutils.default_size(parent, 720, 445) self.resize(width, height) def set_info(self, info): self.info.hint.set_value(self.default_hint) self.info.set_value(info) def select_remote(self, index): if index >= 0: item = self.remotes.item(index) if item: item.setSelected(True) def refresh(self, select=True): git = self.context.git remotes = git.remote()[STDOUT].splitlines() # Ignore notifications from self.remotes while mutating. with qtutils.BlockSignals(self.remotes): self.remotes.clear() self.remotes.addItems(remotes) self.remote_list = remotes for idx in range(len(remotes)): item = self.remotes.item(idx) item.setFlags(item.flags() | Qt.ItemIsEditable) if select: if not self.current_name and remotes: # Nothing is selected; select the first item self.select_remote(0) elif self.current_name and remotes: # Reselect the previously selected item remote_seq = utils.Sequence(remotes) idx = remote_seq.index(self.current_name) if idx >= 0: item = self.remotes.item(idx) if item: item.setSelected(True) def add(self): if add_remote(self.context, self): self.refresh(select=False) # Newly added remote will be last; select it self.select_remote(len(self.remote_list) - 1) def delete(self): remote = qtutils.selected_item(self.remotes, self.remote_list) if not remote: return cmds.do(cmds.RemoteRemove, self.context, remote) self.refresh(select=False) def remote_item_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 = item.text() if new_name == old_name: return if not new_name: item.setText(old_name) return context = self.context ok, status, _, _ = cmds.do(cmds.RemoteRename, context, old_name, new_name) if ok and status == 0: self.remote_list[idx] = new_name self.activate_remote(new_name) else: item.setText(old_name) def selection_changed(self): remote = qtutils.selected_item(self.remotes, self.remote_list) if not remote: self.disable_editor() return self.activate_remote(remote) def activate_remote(self, name, gather_info=True): url = gitcmds.remote_url(self.context, name) self.current_name = name self.current_url = url self.editor.setEnabled(True) self.editor.name = name self.editor.url = url if gather_info: self.gather_info() def gather_info(self): name = self.current_name self.info.hint.set_value(N_('Gathering info for "%s"...') % name) self.info.set_value('') self.info_thread.remote = name self.info_thread.start() def add_remote(context, parent, name='', url='', readonly_url=False): """Bring up the "Add Remote" dialog""" widget = AddRemoteDialog(context, parent, readonly_url=readonly_url) if name: widget.name = name if url: widget.url = url if widget.run(): cmds.do(cmds.RemoteAdd, context, widget.name, widget.url) result = True else: result = False return result def restore_focus(focus): if focus: focus.setFocus(Qt.OtherFocusReason) if hasattr(focus, 'selectAll'): focus.selectAll() class RemoteInfoThread(QtCore.QThread): result = Signal(object) def __init__(self, context, parent): QtCore.QThread.__init__(self, parent) self.context = context self.remote = None def run(self): remote = self.remote if remote is None: return git = self.context.git _, out, err = git.remote('show', '-n', remote) self.result.emit(out + err) class AddRemoteDialog(QtWidgets.QDialog): def __init__(self, context, parent, readonly_url=False): super().__init__(parent) self.context = context if parent: self.setWindowModality(Qt.WindowModal) self.context = context self.widget = RemoteWidget(context, self, readonly_url=readonly_url) self.add_button = qtutils.create_button( text=N_('Add Remote'), icon=icons.ok(), enabled=False ) self.close_button = qtutils.close_button() self._button_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, qtutils.STRETCH, self.close_button, self.add_button, ) self._layout = qtutils.vbox( defs.margin, defs.spacing, self.widget, self._button_layout ) self.setLayout(self._layout) self.widget.valid.connect(self.add_button.setEnabled) qtutils.connect_button(self.add_button, self.accept) qtutils.connect_button(self.close_button, self.reject) def set_name(self, value): self.widget.name = value def set_url(self, value): self.widget.url = value name = property(operator.attrgetter('widget.name'), set_name) url = property(operator.attrgetter('widget.url'), set_url) def run(self): self.show() self.raise_() return self.exec_() == QtWidgets.QDialog.Accepted def lineedit(context, hint): """Create a HintedLineEdit with a preset minimum width""" widget = text.HintedLineEdit(context, hint) width = qtutils.text_width(widget.font(), 'M') widget.setMinimumWidth(width * 32) return widget class RemoteWidget(QtWidgets.QWidget): name = property( lambda self: get(self.remote_name), lambda self, value: self.remote_name.set_value(value), ) url = property( lambda self: get(self.remote_url), lambda self, value: self.remote_url.set_value(value), ) valid = Signal(bool) def __init__(self, context, parent, readonly_url=False): super().__init__(parent) self.setWindowModality(Qt.WindowModal) self.context = context self.setWindowTitle(N_('Add remote')) self.remote_name = lineedit(context, N_('Name for the new remote')) self.remote_url = lineedit(context, 'git://git.example.com/repo.git') self.open_button = qtutils.create_button( text=N_('Browse...'), icon=icons.folder(), tooltip=N_('Select repository') ) self.url_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.remote_url, self.open_button ) validate_remote = completion.RemoteValidator(self.remote_name) self.remote_name.setValidator(validate_remote) self._form = qtutils.form( defs.margin, defs.spacing, (N_('Name'), self.remote_name), (N_('URL'), self.url_layout), ) self._layout = qtutils.vbox(defs.margin, defs.spacing, self._form) self.setLayout(self._layout) self.remote_name.textChanged.connect(self.validate) self.remote_url.textChanged.connect(self.validate) qtutils.connect_button(self.open_button, self.open_repo) if readonly_url: self.remote_url.setReadOnly(True) self.open_button.setEnabled(False) def validate(self, _text): name = self.name url = self.url self.valid.emit(bool(name) and bool(url)) def open_repo(self): git = self.context.git repo = qtutils.opendir_dialog(N_('Open Git Repository'), core.getcwd()) if repo and git.is_git_repository(repo): self.url = repo git-cola-4.6.1/cola/widgets/filelist.py000066400000000000000000000123431457126473700200150ustar00rootroot00000000000000from qtpy import QtWidgets from qtpy.QtCore import Signal from qtpy.QtCore import QSize from qtpy.QtCore import Qt from .. import cmds from .. import hotkeys from .. import qtutils from ..i18n import N_ from .standard import TreeWidget class FileWidget(TreeWidget): files_selected = Signal(object) difftool_selected = Signal(object) histories_selected = Signal(object) grab_file = Signal(object) remark_toggled = Signal(object, object) def __init__(self, context, parent, remarks=False): TreeWidget.__init__(self, parent) self.context = context labels = [N_('Filename'), N_('Additions'), N_('Deletions')] self.setHeaderLabels(labels) self.show_history_action = qtutils.add_action( self, N_('Show History'), self.show_history, hotkeys.HISTORY ) self.launch_difftool_action = qtutils.add_action( self, N_('Launch Diff Tool'), self.show_diff ) self.launch_editor_action = qtutils.add_action( self, N_('Launch Editor'), self.edit_paths, hotkeys.EDIT ) self.grab_file_action = qtutils.add_action( self, N_('Grab File...'), self._grab_file ) if remarks: self.toggle_remark_actions = tuple( qtutils.add_action( self, r, lambda remark=r: self.toggle_remark(remark), hotkeys.hotkey(Qt.CTRL | getattr(Qt, 'Key_' + r)), ) for r in map(str, range(10)) ) else: self.toggle_remark_actions = tuple() self.itemSelectionChanged.connect(self.selection_changed) def selection_changed(self): items = self.selected_items() self.files_selected.emit([i.path for i in items]) def commits_selected(self, commits): if not commits: self.clear() return git = self.context.git paths = [] if len(commits) > 1: # Get a list of changed files for a commit range. start = commits[0].oid + '~' end = commits[-1].oid status, out, _ = git.diff(start, end, z=True, numstat=True, no_renames=True) if status == 0: paths = [f for f in out.rstrip('\0').split('\0') if f] else: # Get the list of changed files in a single commit. commit = commits[0] oid = commit.oid status, out, _ = git.show( oid, z=True, numstat=True, oneline=True, no_renames=True ) if status == 0: paths = [f for f in out.rstrip('\0').split('\0') if f] if paths: paths = paths[1:] # Skip over the summary on the first line. self.list_files(paths) def list_files(self, files_log): self.clear() if not files_log: return files = [] for filename in files_log: item = FileTreeWidgetItem(filename) files.append(item) self.insertTopLevelItems(0, files) def adjust_columns(self, size, old_size): if size.isValid() and old_size.isValid(): width = self.columnWidth(0) + size.width() - old_size.width() self.setColumnWidth(0, width) else: width = self.width() two_thirds = (width * 2) // 3 one_sixth = width // 6 self.setColumnWidth(0, two_thirds) self.setColumnWidth(1, one_sixth) self.setColumnWidth(2, one_sixth) def show(self): self.adjust_columns(QSize(), QSize()) def resizeEvent(self, event): self.adjust_columns(event.size(), event.oldSize()) def contextMenuEvent(self, event): menu = qtutils.create_menu(N_('Actions'), self) menu.addAction(self.grab_file_action) menu.addAction(self.show_history_action) menu.addAction(self.launch_difftool_action) menu.addAction(self.launch_editor_action) if self.toggle_remark_actions: menu_toggle_remark = menu.addMenu(N_('Toggle remark of touching commits')) tuple(map(menu_toggle_remark.addAction, self.toggle_remark_actions)) menu.exec_(self.mapToGlobal(event.pos())) def show_diff(self): self.difftool_selected.emit(self.selected_paths()) def _grab_file(self): for path in self.selected_paths(): self.grab_file.emit(path) def selected_paths(self): return [i.path for i in self.selected_items()] def edit_paths(self): cmds.do(cmds.Edit, self.context, self.selected_paths()) def show_history(self): items = self.selected_items() paths = [i.path for i in items] self.histories_selected.emit(paths) def toggle_remark(self, remark): items = self.selected_items() paths = tuple(i.path for i in items) self.remark_toggled.emit(remark, paths) class FileTreeWidgetItem(QtWidgets.QTreeWidgetItem): def __init__(self, file_log, parent=None): QtWidgets.QTreeWidgetItem.__init__(self, parent) texts = file_log.split('\t') self.path = path = texts[2] self.setText(0, path) self.setText(1, texts[0]) self.setText(2, texts[1]) git-cola-4.6.1/cola/widgets/filetree.py000066400000000000000000000022741457126473700200030ustar00rootroot00000000000000from qtpy import QtCore from qtpy import QtWidgets from .. import icons from . import standard class FileTree(standard.TreeWidget): def __init__(self, parent=None): standard.TreeWidget.__init__(self, parent=parent) self.setSelectionMode(self.ExtendedSelection) self.setHeaderHidden(True) def set_filenames(self, filenames, select=False): self.clear() if not filenames: return items = [] from_filename = icons.from_filename for filename in filenames: icon = from_filename(filename) item = QtWidgets.QTreeWidgetItem() item.setIcon(0, icon) item.setText(0, filename) item.setData(0, QtCore.Qt.UserRole, filename) items.append(item) self.addTopLevelItems(items) if select and items: items[0].setSelected(True) def has_selection(self): return bool(self.selectedItems()) def selected_filenames(self): items = self.selectedItems() if not items: return [] return [filename_from_item(i) for i in items] def filename_from_item(item): return item.data(0, QtCore.Qt.UserRole) git-cola-4.6.1/cola/widgets/finder.py000066400000000000000000000153211457126473700174500ustar00rootroot00000000000000"""File finder widgets""" import os from functools import partial from qtpy import QtCore from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from ..i18n import N_ from ..qtutils import get from ..utils import Group from .. import cmds from .. import core from .. import gitcmds from .. import hotkeys from .. import icons from .. import utils from .. import qtutils from . import completion from . import defs from . import filetree from . import standard from . import text def finder(context, paths=None): """Prompt and use 'git grep' to find the content.""" parent = qtutils.active_window() widget = new_finder(context, paths=paths, parent=parent) widget.show() widget.raise_() return widget def new_finder(context, paths=None, parent=None): """Create a finder widget""" widget = Finder(context, parent=parent) widget.search_for(paths or '') return widget def add_wildcards(arg): """Add "*" around user input to generate ls-files pathspec matches >>> '*x*' == \ add_wildcards('x') == \ add_wildcards('*x') == \ add_wildcards('x*') == \ add_wildcards('*x*') True """ if not arg.startswith('*'): arg = '*' + arg if not arg.endswith('*'): arg = arg + '*' return arg def show_help(context): """Show the help page""" help_text = N_( """ Keyboard Shortcuts ------------------ J, Down = Move Down K, Up = Move Up Enter = Edit Selected Files Spacebar = Open File Using Default Application Ctrl + L = Focus Text Entry Field ? = Show Help The up and down arrows change focus between the text entry field and the results. """ ) title = N_('Help - Find Files') return text.text_dialog(context, help_text, title) class FindFilesThread(QtCore.QThread): """Finds files asynchronously""" result = Signal(object) def __init__(self, context, parent): QtCore.QThread.__init__(self, parent) self.context = context self.query = None def run(self): context = self.context query = self.query if query is None: args = [] else: args = [add_wildcards(arg) for arg in utils.shell_split(query)] filenames = gitcmds.tracked_files(context, *args) if query == self.query: self.result.emit(filenames) else: self.run() class Finder(standard.Dialog): """File Finder dialog""" def __init__(self, context, parent=None): standard.Dialog.__init__(self, parent) self.context = context self.setWindowTitle(N_('Find Files')) if parent is not None: self.setWindowModality(Qt.WindowModal) label = os.path.basename(core.getcwd()) + '/' self.input_label = QtWidgets.QLabel(label) self.input_txt = completion.GitTrackedLineEdit(context, hint=N_(' ...')) self.tree = filetree.FileTree(parent=self) self.edit_button = qtutils.edit_button(default=True) self.edit_button.setShortcut(hotkeys.EDIT) name = cmds.OpenDefaultApp.name() icon = icons.default_app() self.open_default_button = qtutils.create_button(text=name, icon=icon) self.open_default_button.setShortcut(hotkeys.PRIMARY_ACTION) self.button_group = Group(self.edit_button, self.open_default_button) self.button_group.setEnabled(False) self.refresh_button = qtutils.refresh_button() self.refresh_button.setShortcut(hotkeys.REFRESH) self.help_button = qtutils.create_button( text=N_('Help'), tooltip=N_('Show help\nShortcut: ?'), icon=icons.question() ) self.close_button = qtutils.close_button() self.input_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.input_label, self.input_txt ) self.bottom_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.help_button, self.refresh_button, qtutils.STRETCH, self.close_button, self.open_default_button, self.edit_button, ) self.main_layout = qtutils.vbox( defs.margin, defs.no_spacing, self.input_layout, self.tree, self.bottom_layout, ) self.setLayout(self.main_layout) self.setFocusProxy(self.input_txt) thread = self.worker_thread = FindFilesThread(context, self) thread.result.connect(self.process_result, type=Qt.QueuedConnection) self.input_txt.textChanged.connect(lambda s: self.search()) self.input_txt.activated.connect(self.focus_tree) self.input_txt.down.connect(self.focus_tree) self.input_txt.enter.connect(self.focus_tree) item_selection_changed = self.tree_item_selection_changed self.tree.itemSelectionChanged.connect(item_selection_changed) self.tree.up.connect(self.focus_input) self.tree.space.connect(self.open_default) qtutils.add_action( self, 'Focus Input', self.focus_input, hotkeys.FOCUS, hotkeys.FINDER ) self.show_help_action = qtutils.add_action( self, N_('Show Help'), partial(show_help, context), hotkeys.QUESTION ) qtutils.connect_button(self.edit_button, self.edit) qtutils.connect_button(self.open_default_button, self.open_default) qtutils.connect_button(self.refresh_button, self.search) qtutils.connect_button(self.help_button, partial(show_help, context)) qtutils.connect_button(self.close_button, self.close) qtutils.add_close_action(self) self.init_size(parent=parent) def focus_tree(self): self.tree.setFocus() def focus_input(self): self.input_txt.setFocus() def search(self): self.button_group.setEnabled(False) self.refresh_button.setEnabled(False) query = get(self.input_txt) self.worker_thread.query = query self.worker_thread.start() def search_for(self, txt): self.input_txt.set_value(txt) self.focus_input() def process_result(self, filenames): self.tree.set_filenames(filenames, select=True) self.refresh_button.setEnabled(True) def edit(self): context = self.context paths = self.tree.selected_filenames() cmds.do(cmds.Edit, context, paths, background_editor=True) def open_default(self): context = self.context paths = self.tree.selected_filenames() cmds.do(cmds.OpenDefaultApp, context, paths) def tree_item_selection_changed(self): enabled = bool(self.tree.selected_item()) self.button_group.setEnabled(enabled) git-cola-4.6.1/cola/widgets/gitignore.py000066400000000000000000000073231457126473700201730ustar00rootroot00000000000000"""Provides the StashView dialog.""" from qtpy import QtCore from qtpy import QtWidgets from .. import cmds from .. import qtutils from ..i18n import N_ from . import defs from .standard import Dialog def gitignore_view(context): """Launches a gitignore dialog""" view = AddToGitIgnore(context, parent=qtutils.active_window()) view.show() return view class AddToGitIgnore(Dialog): def __init__(self, context, parent=None): Dialog.__init__(self, parent=parent) self.context = context self.selection = context.selection if parent is not None: self.setWindowModality(QtCore.Qt.WindowModal) self.setWindowTitle(N_('Add to exclusions')) # Create text self.text_description = QtWidgets.QLabel() self.text_description.setText(N_('Ignore filename or pattern')) # Create edit filename self.edit_filename = QtWidgets.QLineEdit() self.check_filename() self.filename_layt = qtutils.vbox( defs.no_margin, defs.spacing, self.text_description, self.edit_filename ) # Create radio options self.radio_filename = qtutils.radio( text=N_('Ignore exact filename'), checked=True ) self.radio_pattern = qtutils.radio(text=N_('Ignore custom pattern')) self.name_radio_group = qtutils.buttongroup( self.radio_filename, self.radio_pattern ) self.name_radio_layt = qtutils.vbox( defs.no_margin, defs.spacing, self.radio_filename, self.radio_pattern ) self.radio_in_repo = qtutils.radio(text=N_('Add to .gitignore'), checked=True) self.radio_local = qtutils.radio(text=N_('Add to local .git/info/exclude')) self.location_radio_group = qtutils.buttongroup( self.radio_in_repo, self.radio_local ) self.location_radio_layt = qtutils.vbox( defs.no_margin, defs.spacing, self.radio_in_repo, self.radio_local ) # Create buttons self.button_apply = qtutils.ok_button(text=N_('Add')) self.button_close = qtutils.close_button() self.btn_layt = qtutils.hbox( defs.no_margin, defs.spacing, qtutils.STRETCH, self.button_close, self.button_apply, ) # Layout self.main_layout = qtutils.vbox( defs.margin, defs.spacing, self.name_radio_layt, defs.button_spacing, self.filename_layt, defs.button_spacing, self.location_radio_layt, qtutils.STRETCH, self.btn_layt, ) self.setLayout(self.main_layout) # Connect actions qtutils.connect_toggle(self.radio_pattern, self.check_pattern) qtutils.connect_toggle(self.radio_filename, self.check_filename) qtutils.connect_button(self.button_apply, self.apply) qtutils.connect_button(self.button_close, self.close) self.init_state(None, self.resize_widget, parent) def resize_widget(self, parent): """Set the initial size of the widget""" width, height = qtutils.default_size(parent, 720, 400) self.resize(width, max(400, height // 2)) def check_pattern(self): self.edit_filename.setDisabled(False) def check_filename(self): self.edit_filename.setText('/' + ';/'.join(self.selection.untracked)) self.edit_filename.setDisabled(True) def close(self): self.reject() def apply(self): context = self.context cmds.do( cmds.Ignore, context, self.edit_filename.text().split(';'), self.radio_local.isChecked(), ) self.accept() git-cola-4.6.1/cola/widgets/grep.py000066400000000000000000000315251457126473700171420ustar00rootroot00000000000000from qtpy import QtCore from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from ..i18n import N_ from ..utils import Group from .. import cmds from .. import core from .. import hotkeys from .. import utils from .. import qtutils from ..qtutils import get from .standard import Dialog from .text import HintedLineEdit from .text import VimHintedPlainTextEdit from .text import VimTextBrowser from . import defs def grep(context): """Prompt and use 'git grep' to find the content.""" widget = new_grep(context, parent=qtutils.active_window()) widget.show() return widget def new_grep(context, text=None, parent=None): """Construct a new Grep dialog""" widget = Grep(context, parent=parent) if text: widget.search_for(text) return widget def parse_grep_line(line): """Parse a grep result line into (filename, line_number, content)""" try: filename, line_number, contents = line.split(':', 2) result = (filename, line_number, contents) except ValueError: result = None return result def goto_grep(context, line): """Called when Search -> Grep's right-click 'goto' action.""" parsed_line = parse_grep_line(line) if parsed_line: filename, line_number, _ = parsed_line cmds.do( cmds.Edit, context, [filename], line_number=line_number, background_editor=True, ) class GrepThread(QtCore.QThread): """Gather `git grep` results in a background thread""" result = Signal(object, object, object) def __init__(self, context, parent): QtCore.QThread.__init__(self, parent) self.context = context self.query = None self.shell = False self.regexp_mode = '--basic-regexp' def run(self): if self.query is None: return git = self.context.git query = self.query if self.shell: args = utils.shell_split(query) else: args = [query] status, out, err = git.grep(self.regexp_mode, n=True, _readonly=True, *args) if query == self.query: self.result.emit(status, out, err) else: self.run() class Grep(Dialog): """A dialog for searching content using `git grep`""" def __init__(self, context, parent=None): Dialog.__init__(self, parent) self.context = context self.grep_result = '' self.setWindowTitle(N_('Search')) if parent is not None: self.setWindowModality(Qt.WindowModal) self.edit_action = qtutils.add_action(self, N_('Edit'), self.edit, hotkeys.EDIT) self.refresh_action = qtutils.add_action( self, N_('Refresh'), self.search, *hotkeys.REFRESH_HOTKEYS ) self.input_label = QtWidgets.QLabel('git grep') self.input_label.setFont(qtutils.diff_font(context)) self.input_txt = HintedLineEdit( context, N_('command-line arguments'), parent=self ) self.regexp_combo = combo = QtWidgets.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) tooltip0 = N_('Search using a POSIX basic regular expression') tooltip1 = N_('Search using a POSIX extended regular expression') tooltip2 = N_('Search for a fixed string') combo.setItemData(0, tooltip0, Qt.ToolTipRole) combo.setItemData(1, tooltip1, Qt.ToolTipRole) combo.setItemData(2, tooltip2, 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(context, N_('grep result...'), self) self.preview_txt = PreviewTextView(context, self) self.preview_txt.setFocusProxy(self.result_txt) self.edit_button = qtutils.edit_button(default=True) qtutils.button_action(self.edit_button, self.edit_action) self.refresh_button = qtutils.refresh_button() qtutils.button_action(self.refresh_button, self.refresh_action) text = N_('Shell arguments') tooltip = N_( 'Parse arguments using a shell.\n' 'Queries with spaces will require "double quotes".' ) self.shell_checkbox = qtutils.checkbox( text=text, tooltip=tooltip, checked=False ) self.close_button = qtutils.close_button() self.refresh_group = Group(self.refresh_action, self.refresh_button) self.refresh_group.setEnabled(False) self.edit_group = Group(self.edit_action, self.edit_button) self.edit_group.setEnabled(False) self.input_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.input_label, self.input_txt, self.regexp_combo, ) self.bottom_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.refresh_button, self.shell_checkbox, qtutils.STRETCH, self.close_button, self.edit_button, ) self.splitter = qtutils.splitter(Qt.Vertical, self.result_txt, self.preview_txt) self.mainlayout = qtutils.vbox( defs.margin, defs.no_spacing, self.input_layout, self.splitter, self.bottom_layout, ) self.setLayout(self.mainlayout) thread = self.worker_thread = GrepThread(context, self) thread.result.connect(self.process_result, type=Qt.QueuedConnection) self.input_txt.textChanged.connect(lambda s: self.search()) self.regexp_combo.currentIndexChanged.connect(lambda x: self.search()) self.result_txt.leave.connect(self.input_txt.setFocus) self.result_txt.cursorPositionChanged.connect(self.update_preview) qtutils.add_action( self.input_txt, 'Focus Results', self.focus_results, hotkeys.DOWN, *hotkeys.ACCEPT ) qtutils.add_action(self, 'Focus Input', self.focus_input, hotkeys.FOCUS) qtutils.connect_toggle(self.shell_checkbox, lambda x: self.search()) qtutils.connect_button(self.close_button, self.close) qtutils.add_close_action(self) self.init_size(parent=parent) def focus_input(self): """Focus the grep input field and select the text""" self.input_txt.setFocus() self.input_txt.selectAll() def focus_results(self): """Give focus to the results window""" self.result_txt.setFocus() def regexp_mode(self): """Return the selected grep regex mode""" idx = self.regexp_combo.currentIndex() return self.regexp_combo.itemData(idx, Qt.UserRole) def search(self): """Initiate a search by starting the GrepThread""" self.edit_group.setEnabled(False) self.refresh_group.setEnabled(False) query = get(self.input_txt) if len(query) < 2: self.result_txt.clear() self.preview_txt.clear() return self.worker_thread.query = query self.worker_thread.shell = get(self.shell_checkbox) self.worker_thread.regexp_mode = self.regexp_mode() self.worker_thread.start() def search_for(self, txt): """Set the initial value of the input text""" self.input_txt.set_value(txt) def text_scroll(self): """Return the scrollbar value for the results window""" scrollbar = self.result_txt.verticalScrollBar() if scrollbar: return get(scrollbar) return None def set_text_scroll(self, scroll): """Set the scrollbar value for the results window""" scrollbar = self.result_txt.verticalScrollBar() if scrollbar and scroll is not None: scrollbar.setValue(scroll) def text_offset(self): """Return the cursor's offset within the result text""" return self.result_txt.textCursor().position() def set_text_offset(self, offset): """Set the text cursor from an offset""" cursor = self.result_txt.textCursor() cursor.setPosition(offset) self.result_txt.setTextCursor(cursor) def process_result(self, status, out, err): """Apply the results from grep to the widgets""" 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.grep_result = value self.result_txt.set_value(value) # restore self.set_text_scroll(scroll) self.set_text_offset(offset) enabled = status == 0 self.edit_group.setEnabled(enabled) self.refresh_group.setEnabled(True) if not value: self.preview_txt.clear() def update_preview(self): """Update the file preview window""" parsed_line = parse_grep_line(self.result_txt.selected_line()) if parsed_line: filename, line_number, _ = parsed_line self.preview_txt.preview(filename, line_number) def edit(self): """Launch an editor on the currently selected line""" goto_grep(self.context, self.result_txt.selected_line()) def export_state(self): """Export persistent settings""" state = super().export_state() state['sizes'] = get(self.splitter) return state def apply_state(self, state): """Apply persistent settings""" result = super().apply_state(state) try: self.splitter.setSizes(state['sizes']) except (AttributeError, KeyError, ValueError, TypeError): result = False return result class GrepTextView(VimHintedPlainTextEdit): """A text view with hotkeys for launching editors""" def __init__(self, context, hint, parent): VimHintedPlainTextEdit.__init__(self, context, hint, parent=parent) self.context = context self.goto_action = qtutils.add_action(self, 'Launch Editor', self.edit) self.goto_action.setShortcut(hotkeys.EDIT) self.menu_actions.append(self.goto_action) def edit(self): goto_grep(self.context, self.selected_line()) class PreviewTask(qtutils.Task): """Asynchronous task for loading file content""" def __init__(self, filename, line_number): qtutils.Task.__init__(self) self.content = '' self.filename = filename self.line_number = line_number def task(self): try: self.content = core.read(self.filename, errors='ignore') except OSError: pass return (self.filename, self.content, self.line_number) class PreviewTextView(VimTextBrowser): """Preview window for file contents""" def __init__(self, context, parent): VimTextBrowser.__init__(self, context, parent) self.filename = None self.content = None self.runtask = qtutils.RunTask(parent=self) def preview(self, filename, line_number): """Preview a file at the specified line number""" if filename != self.filename: request = PreviewTask(filename, line_number) self.runtask.start(request, finish=self.show_preview) else: self.scroll_to_line(line_number) def clear(self): self.filename = '' self.content = '' super().clear() def show_preview(self, task): """Show the results of the asynchronous file read""" filename = task.filename content = task.content line_number = task.line_number if filename != self.filename: self.filename = filename self.content = content self.set_value(content) self.scroll_to_line(line_number) def scroll_to_line(self, line_number): """Scroll to the specified line number""" try: line_num = int(line_number) - 1 except ValueError: return self.numbers.set_highlighted(line_num) cursor = self.textCursor() cursor.setPosition(0) self.setTextCursor(cursor) self.ensureCursorVisible() cursor.movePosition(cursor.Down, cursor.MoveAnchor, line_num) cursor.movePosition(cursor.EndOfLine, cursor.KeepAnchor) self.setTextCursor(cursor) self.ensureCursorVisible() scrollbar = self.verticalScrollBar() step = scrollbar.pageStep() // 2 position = scrollbar.sliderPosition() + step scrollbar.setSliderPosition(position) self.ensureCursorVisible() git-cola-4.6.1/cola/widgets/highlighter.py000066400000000000000000000063041457126473700205000ustar00rootroot00000000000000from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets 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): if not have_pygments: return doc = edit.document() 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 fmt = QtGui.QTextCharFormat(parent_format) font = fmt.font() if style.styles_token(token): tstyle = style.style_for_token(token) if tstyle['color']: fmt.setForeground(QtGui.QColor('#' + tstyle['color'])) if tstyle['bold']: font.setWeight(QtGui.QFont.Bold) if tstyle['italic']: font.setItalic(True) if tstyle['underline']: fmt.setFontUnderline(True) if tstyle['bgcolor']: fmt.setBackground(QtGui.QColor('#' + tstyle['bgcolor'])) token_formats[token] = fmt return fmt text = 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) fmt = 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 = fmt 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__': app = QtWidgets.QApplication([]) python = QtWidgets.QPlainTextEdit() with open(__file__, encoding='utf-8') as f: python.setPlainText(f.read()) python.setWindowTitle('python') python.show() highlight_document(python, __file__) app.exec_() git-cola-4.6.1/cola/widgets/imageview.py000066400000000000000000000374331457126473700201660ustar00rootroot00000000000000# Copyright (c) 2018-2024 David Aguilar # # Git Cola is GPL licensed, but this file has a more permissive license. # This file is dual-licensed Git Cola GPL + pyqimageview MIT. # imageview.py was originally based on the pyqimageview: # https://github.com/nevion/pyqimageview/ # # The MIT License (MIT) # # Copyright (c) 2014 Jason Newton # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import argparse import os import sys from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal try: import numpy as np have_numpy = True except ImportError: have_numpy = False from .. import qtcompat main_loop_type = 'qt' def clamp(x, lo, hi): return max(min(x, hi), lo) class ImageView(QtWidgets.QGraphicsView): image_changed = Signal() def __init__(self, parent=None): super().__init__(parent) scene = QtWidgets.QGraphicsScene(self) self.graphics_pixmap = QtWidgets.QGraphicsPixmapItem() scene.addItem(self.graphics_pixmap) self.setScene(scene) self.zoom_factor = 1.125 self.rubberband = None self.panning = False self.first_show_occured = False self.last_scene_roi = None self.start_drag = QtCore.QPoint() self.checkerboard = None CHECK_MEDIUM = 8 CHECK_GRAY = 0x80 CHECK_LIGHT = 0xCC check_pattern = QtGui.QImage( CHECK_MEDIUM * 2, CHECK_MEDIUM * 2, QtGui.QImage.Format_RGB888 ) color_gray = QtGui.QColor(CHECK_GRAY, CHECK_GRAY, CHECK_GRAY) color_light = QtGui.QColor(CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT) painter = QtGui.QPainter(check_pattern) painter.fillRect(0, 0, CHECK_MEDIUM, CHECK_MEDIUM, color_gray) painter.fillRect( CHECK_MEDIUM, CHECK_MEDIUM, CHECK_MEDIUM, CHECK_MEDIUM, color_gray ) painter.fillRect(0, CHECK_MEDIUM, CHECK_MEDIUM, CHECK_MEDIUM, color_light) painter.fillRect(CHECK_MEDIUM, 0, CHECK_MEDIUM, CHECK_MEDIUM, color_light) self.check_pattern = check_pattern self.check_brush = QtGui.QBrush(check_pattern) def load(self, filename): image = QtGui.QImage() image.load(filename) ok = not image.isNull() if ok: self.pixmap = image return ok @property def pixmap(self): return self.graphics_pixmap.pixmap() @pixmap.setter def pixmap(self, image, image_format=None): pixmap = None if have_numpy and isinstance(image, np.ndarray): if image.ndim == 3: if image.shape[2] == 3: if image_format is None: image_format = QtGui.QImage.Format_RGB888 q_image = QtGui.QImage( image.data, image.shape[1], image.shape[0], image_format ) pixmap = QtGui.QPixmap.fromImage(q_image) elif image.shape[2] == 4: if image_format is None: image_format = QtGui.QImage.Format_RGB32 q_image = QtGui.QImage( image.data, image.shape[1], image.shape[0], image_format ) pixmap = QtGui.QPixmap.fromImage(q_image) else: raise TypeError(image) elif image.ndim == 2: if image_format is None: image_format = QtGui.QImage.Format_RGB888 q_image = QtGui.QImage( image.data, image.shape[1], image.shape[0], image_format ) pixmap = QtGui.QPixmap.fromImage(q_image) else: raise ValueError(image) elif isinstance(image, QtGui.QImage): pixmap = QtGui.QPixmap.fromImage(image) elif isinstance(image, QtGui.QPixmap): pixmap = image else: raise TypeError(image) if pixmap.hasAlpha(): checkerboard = QtGui.QImage( pixmap.width(), pixmap.height(), QtGui.QImage.Format_ARGB32 ) self.checkerboard = checkerboard painter = QtGui.QPainter(checkerboard) painter.fillRect(checkerboard.rect(), self.check_brush) painter.drawPixmap(0, 0, pixmap) pixmap = QtGui.QPixmap.fromImage(checkerboard) self.graphics_pixmap.setPixmap(pixmap) self.update_scene_rect() self.fitInView(self.image_scene_rect, flags=Qt.KeepAspectRatio) self.graphics_pixmap.update() self.image_changed.emit() # image property alias @property def image(self): return self.pixmap @image.setter def image(self, image): self.pixmap = image def update_scene_rect(self): pixmap = self.pixmap self.setSceneRect( QtCore.QRectF( QtCore.QPointF(0, 0), QtCore.QPointF(pixmap.width(), pixmap.height()) ) ) @property def image_scene_rect(self): return QtCore.QRectF( self.graphics_pixmap.pos(), QtCore.QSizeF(self.pixmap.size()) ) def resizeEvent(self, event): super().resizeEvent(event) self.update_scene_rect() event.accept() self.fitInView(self.last_scene_roi, Qt.KeepAspectRatio) self.update() def zoomROICentered(self, p, zoom_level_delta): roi = self.current_scene_ROI if not roi: return roi_dims = QtCore.QPointF(roi.width(), roi.height()) roi_scalef = 1 if zoom_level_delta > 0: roi_scalef = 1.0 / self.zoom_factor elif zoom_level_delta < 0: roi_scalef = self.zoom_factor nroi_dims = roi_dims * roi_scalef nroi_dims.setX(max(nroi_dims.x(), 1)) nroi_dims.setY(max(nroi_dims.y(), 1)) nroi_center = p nroi_dimsh = nroi_dims / 2.0 nroi_topleft = nroi_center - nroi_dimsh nroi = QtCore.QRectF( nroi_topleft.x(), nroi_topleft.y(), nroi_dims.x(), nroi_dims.y() ) self.fitInView(nroi, Qt.KeepAspectRatio) self.update() def zoomROITo(self, p, zoom_level_delta): roi = self.current_scene_ROI if not roi: return roi_dims = QtCore.QPointF(roi.width(), roi.height()) roi_topleft = roi.topLeft() roi_scalef = 1.0 if zoom_level_delta > 0: roi_scalef = 1.0 / self.zoom_factor elif zoom_level_delta < 0: roi_scalef = self.zoom_factor nroi_dims = roi_dims * roi_scalef nroi_dims.setX(max(nroi_dims.x(), 1.0)) nroi_dims.setY(max(nroi_dims.y(), 1.0)) prel_scaled_x = (p.x() - roi_topleft.x()) / roi_dims.x() prel_scaled_y = (p.y() - roi_topleft.y()) / roi_dims.y() nroi_topleft_x = p.x() - prel_scaled_x * nroi_dims.x() nroi_topleft_y = p.y() - prel_scaled_y * nroi_dims.y() nroi = QtCore.QRectF( nroi_topleft_x, nroi_topleft_y, nroi_dims.x(), nroi_dims.y() ) self.fitInView(nroi, Qt.KeepAspectRatio) self.update() def _scene_ROI(self, geometry): return QtCore.QRectF( self.mapToScene(geometry.topLeft()), self.mapToScene(geometry.bottomRight()) ) @property def current_scene_ROI(self): return self.last_scene_roi def mousePressEvent(self, event): super().mousePressEvent(event) button = event.button() modifier = event.modifiers() # pan if modifier == Qt.ControlModifier and button == Qt.LeftButton: self.start_drag = event.pos() self.panning = True # initiate/show ROI selection if modifier == Qt.ShiftModifier and button == Qt.LeftButton: self.start_drag = event.pos() if self.rubberband is None: self.rubberband = QtWidgets.QRubberBand( QtWidgets.QRubberBand.Rectangle, self.viewport() ) self.rubberband.setGeometry(QtCore.QRect(self.start_drag, QtCore.QSize())) self.rubberband.show() def mouseMoveEvent(self, event): super().mouseMoveEvent(event) # update selection display if self.rubberband is not None: self.rubberband.setGeometry( QtCore.QRect(self.start_drag, event.pos()).normalized() ) if self.panning: end_drag = event.pos() pan_vector = end_drag - self.start_drag scene2view = self.transform() # skip shear sx = scene2view.m11() sy = scene2view.m22() scene_pan_x = pan_vector.x() / sx scene_pan_y = pan_vector.y() / sy scene_pan_vector = QtCore.QPointF(scene_pan_x, scene_pan_y) roi = self.current_scene_ROI top_left = roi.topLeft() new_top_left = top_left - scene_pan_vector scene_rect = self.sceneRect() new_top_left.setX( clamp(new_top_left.x(), scene_rect.left(), scene_rect.right()) ) new_top_left.setY( clamp(new_top_left.y(), scene_rect.top(), scene_rect.bottom()) ) nroi = QtCore.QRectF(new_top_left, roi.size()) self.fitInView(nroi, Qt.KeepAspectRatio) self.start_drag = end_drag self.update() def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) # consume rubber band selection if self.rubberband is not None: self.rubberband.hide() # set view to ROI rect = self.rubberband.geometry().normalized() if rect.width() > 5 and rect.height() > 5: roi = QtCore.QRectF( self.mapToScene(rect.topLeft()), self.mapToScene(rect.bottomRight()) ) self.fitInView(roi, Qt.KeepAspectRatio) self.rubberband = None if self.panning: self.panning = False self.update() def wheelEvent(self, event): delta = qtcompat.wheel_delta(event) # adjust zoom if abs(delta) > 0: scene_pos = self.mapToScene(event.pos()) if delta >= 0: sign = 1 else: sign = -1 self.zoomROITo(scene_pos, sign) def reset(self): self.update_scene_rect() self.fitInView(self.image_scene_rect, flags=Qt.KeepAspectRatio) self.update() # override arbitrary and unwanted margins: # https://bugreports.qt.io/browse/QTBUG-42331 - based on QT sources def fitInView(self, rect, flags=Qt.IgnoreAspectRatio): if self.scene() is None or not rect or rect.isNull(): return self.last_scene_roi = rect unity = self.transform().mapRect(QtCore.QRectF(0.0, 0.0, 1.0, 1.0)) self.scale(1.0 / unity.width(), 1.0 / unity.height()) viewrect = self.viewport().rect() scene_rect = self.transform().mapRect(rect) xratio = viewrect.width() / scene_rect.width() yratio = viewrect.height() / scene_rect.height() if flags == Qt.KeepAspectRatio: xratio = yratio = min(xratio, yratio) elif flags == Qt.KeepAspectRatioByExpanding: xratio = yratio = max(xratio, yratio) self.scale(xratio, yratio) self.centerOn(rect.center()) class AppImageView(ImageView): def __init__(self, parent=None): ImageView.__init__(self, parent=parent) self.main_widget = None def mousePressEvent(self, event): ImageView.mousePressEvent(self, event) def mouseMoveEvent(self, event): ImageView.mouseMoveEvent(self, event) pos = event.pos() scene_pos = self.mapToScene(pos) msg = 'ui: %d, %d image: %d, %d' % ( pos.y(), pos.x(), int(scene_pos.y()), int(scene_pos.x()), ) self.main_widget.statusBar().showMessage(msg) class ImageViewerWindow(QtWidgets.QMainWindow): def __init__(self, image, input_path): QtWidgets.QMainWindow.__init__(self) self.image = image self.input_path = input_path self.image_view = AppImageView(parent=self) self.image_view.main_widget = self self.statusBar().showMessage('') padding = self.frameGeometry().size() - self.geometry().size() self.resize(image.size() + padding) central = QtWidgets.QWidget(self) self.vbox = QtWidgets.QVBoxLayout(central) self.vbox.setContentsMargins(0, 0, 0, 0) self.setCentralWidget(central) self.layout().setContentsMargins(0, 0, 0, 0) Expanding = QtWidgets.QSizePolicy.Expanding height_for_width = self.image_view.sizePolicy().hasHeightForWidth() policy = QtWidgets.QSizePolicy(Expanding, Expanding) policy.setHorizontalStretch(1) policy.setVerticalStretch(1) policy.setHeightForWidth(height_for_width) self.image_view.setSizePolicy(policy) self.image_view.setMouseTracking(True) self.image_view.setFocusPolicy(Qt.NoFocus) self.image_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.image_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.vbox.addWidget(self.image_view) screen = QtWidgets.QDesktopWidget().screenGeometry(self) size = self.geometry() self.move( (screen.width() - size.width()) // 4, (screen.height() - size.height()) // 4 ) self.update_view() self.image_view.reset() def hideEvent(self, _event): QtWidgets.QMainWindow.hide(self) def update_view(self): self.image_view.image = self.image self.setWindowTitle(self.make_window_title()) def make_window_title(self): return os.path.basename(self.input_path) def keyPressEvent(self, event): key = event.key() global main_loop_type if key == Qt.Key_Escape: if main_loop_type == 'qt': QtWidgets.QApplication.quit() elif main_loop_type == 'ipython': self.hide() # import IPython # IPython.get_ipython().ask_exit() def sigint_handler(*args): """Handler for the SIGINT signal.""" sys.stderr.write('\r') QtWidgets.QApplication.quit() def main(): parser = argparse.ArgumentParser(description='image viewer') parser.add_argument('image', help='path to the image') opts = parser.parse_args() input_image = opts.image image = QtGui.QImage() image.load(input_image) app = QtWidgets.QApplication(sys.argv) try: import signal signal.signal(signal.SIGINT, sigint_handler) except ImportError: pass window = ImageViewerWindow(image, input_image) window.show() app.exec_() if __name__ == '__main__': main() git-cola-4.6.1/cola/widgets/log.py000066400000000000000000000112321457126473700167570ustar00rootroot00000000000000import time from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from .. import core from .. import qtutils from ..i18n import N_ from . import defs from . import text from . import standard class LogWidget(QtWidgets.QFrame): """A simple dialog to display command logs.""" channel = Signal(object) def __init__(self, context, parent=None, output=None): QtWidgets.QFrame.__init__(self, parent) self.output_text = text.VimTextEdit(context, parent=self) self.highlighter = LogSyntaxHighlighter(self.output_text.document()) if output: self.set_output(output) self.main_layout = qtutils.vbox(defs.no_margin, defs.spacing, self.output_text) self.setLayout(self.main_layout) self.setFocusProxy(self.output_text) self.channel.connect(self.append, type=Qt.QueuedConnection) self.log(N_('Right-click links to open:')) self.log(' Documentation: https://git-cola.readthedocs.io/en/latest/') self.log( ' Keyboard Shortcuts: ' 'https://git-cola.gitlab.io/share/doc/git-cola/hotkeys.html\n' ) def clear(self): self.output_text.clear() def set_output(self, output): self.output_text.set_value(output) def log_status(self, status, out, err=None): msg = [] if out: msg.append(out) if err: msg.append(err) if status: msg.append(N_('exit code %s') % status) self.log('\n'.join(msg)) def append(self, msg): """Append to the end of the log message""" if not msg: return msg = core.decode(msg) cursor = self.output_text.textCursor() cursor.movePosition(cursor.End) text_widget = self.output_text # NOTE: the ': ' colon-SP-SP suffix is for the syntax highlighter prefix = core.decode(time.strftime('%Y-%m-%d %H:%M:%S: ')) # ISO-8601 for line in msg.split('\n'): cursor.insertText(prefix + line + '\n') cursor.movePosition(cursor.End) text_widget.setTextCursor(cursor) def log(self, msg): """Add output to the log window""" # Funnel through a Qt queued to allow thread-safe logging from # asynchronous QRunnables, filesystem notification, etc. self.channel.emit(msg) class LogSyntaxHighlighter(QtGui.QSyntaxHighlighter): """Implements the log syntax highlighting""" def __init__(self, doc): QtGui.QSyntaxHighlighter.__init__(self, doc) palette = QtGui.QPalette() QPalette = QtGui.QPalette self.disabled_color = palette.color(QPalette.Disabled, QPalette.Text) def highlightBlock(self, block_text): end = block_text.find(': ') if end > 0: self.setFormat(0, end + 1, self.disabled_color) class RemoteMessage(standard.Dialog): """Provides a dialog to display remote messages""" def __init__(self, context, message, parent=None): standard.Dialog.__init__(self, parent=parent) self.context = context self.model = context.model self.setWindowTitle(N_('Remote Messages')) if parent is not None: self.setWindowModality(Qt.WindowModal) self.text = text.VimTextEdit(context, parent=self) self.text.set_value(message) # Set a monospace font, as some remote git messages include ASCII art self.text.setFont(qtutils.default_monospace_font()) self.close_button = qtutils.close_button() self.close_button.setDefault(True) self.bottom_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, qtutils.STRETCH, self.close_button ) self.main_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.text, self.bottom_layout ) self.setLayout(self.main_layout) qtutils.connect_button(self.close_button, self.close) self.resize(defs.scale(720), defs.scale(400)) def show_remote_messages(parent, context): """Return a closure for the `result` callback from RunTask.start()""" def show_remote_messages_callback(result): """Display the asynchronous "result" when remote tasks complete""" _, out, err = result output = '\n\n'.join(x for x in (out, err) if x) if output: message = N_('Right-click links to open:') + '\n\n' + output else: message = output # Display a window if the remote sent a message if message: view = RemoteMessage(context, message, parent=parent) view.show() view.exec_() return show_remote_messages_callback git-cola-4.6.1/cola/widgets/main.py000066400000000000000000001503131457126473700171260ustar00rootroot00000000000000"""Main UI for authoring commits and other Git Cola interactions""" import os from functools import partial from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from ..compat import uchr from ..compat import WIN32 from ..i18n import N_ from ..interaction import Interaction from ..models import prefs from ..qtutils import get from .. import cmds from .. import core from .. import guicmds from .. import git from .. import gitcmds from .. import hotkeys from .. import icons from .. import qtutils from .. import resources from .. import utils from .. import version from . import about from . import action from . import archive from . import bookmarks from . import branch from . import submodules from . import browse from . import cfgactions from . import clone from . import commitmsg from . import common from . import compare from . import createbranch from . import createtag from . import dag from . import defs from . import diff from . import finder from . import editremotes from . import grep from . import log from . import merge from . import prefs as prefs_widget from . import recent from . import remote from . import search from . import standard from . import status from . import stash from . import toolbar class MainView(standard.MainWindow): config_actions_changed = Signal(object) def __init__(self, context, parent=None): standard.MainWindow.__init__(self, parent) self.setAttribute(Qt.WA_DeleteOnClose) self.context = context self.git = context.git self.dag = None self.model = context.model self.prefs_model = prefs_model = prefs.PreferencesModel(context) self.toolbar_state = toolbar.ToolBarState(context, self) # The widget version is used by import/export_state(). # Change this whenever dockwidgets are removed. self.widget_version = 2 create_dock = qtutils.create_dock cfg = context.cfg self.browser_dockable = cfg.get('cola.browserdockable') if self.browser_dockable: browser = browse.worktree_browser( context, parent=self, show=False, update=False ) self.browserdock = create_dock( 'Browser', N_('Browser'), self, widget=browser ) # "Actions" widget self.actionswidget = action.ActionButtons(context, self) self.actionsdock = create_dock( 'Actions', N_('Actions'), self, widget=self.actionswidget ) qtutils.hide_dock(self.actionsdock) # "Repository Status" widget self.statusdock = create_dock( 'Status', N_('Status'), self, func=lambda dock: status.StatusWidget(context, dock.titleBarWidget(), dock), ) self.statuswidget = self.statusdock.widget() # "Switch Repository" widgets self.bookmarksdock = create_dock( 'Favorites', N_('Favorites'), self, func=lambda dock: bookmarks.bookmark(context, dock), ) bookmarkswidget = self.bookmarksdock.widget() qtutils.hide_dock(self.bookmarksdock) self.recentdock = create_dock( 'Recent', N_('Recent'), self, func=lambda dock: bookmarks.recent(context, dock), ) recentwidget = self.recentdock.widget() qtutils.hide_dock(self.recentdock) bookmarkswidget.connect_to(recentwidget) # "Branch" widgets self.branchdock = create_dock( 'Branches', N_('Branches'), self, func=partial(branch.BranchesWidget, context), ) self.branchwidget = self.branchdock.widget() titlebar = self.branchdock.titleBarWidget() titlebar.add_corner_widget(self.branchwidget.filter_button) titlebar.add_corner_widget(self.branchwidget.sort_order_button) # "Submodule" widgets self.submodulesdock = create_dock( 'Submodules', N_('Submodules'), self, func=partial(submodules.SubmodulesWidget, context), ) self.submoduleswidget = self.submodulesdock.widget() # "Commit Message Editor" widget self.position_label = QtWidgets.QLabel() self.position_label.setAlignment(Qt.AlignCenter) font = qtutils.default_monospace_font() font.setPointSize(int(font.pointSize() * 0.8)) self.position_label.setFont(font) # make the position label fixed size to avoid layout issues text_width = qtutils.text_width(font, '99:999') width = text_width + defs.spacing self.position_label.setMinimumWidth(width) editor = commitmsg.CommitMessageEditor(context, self) self.commiteditor = editor self.commitdock = create_dock('Commit', N_('Commit'), self, widget=editor) titlebar = self.commitdock.titleBarWidget() titlebar.add_title_widget(self.commiteditor.commit_progress_bar) titlebar.add_corner_widget(self.position_label) # "Console" widget self.logwidget = log.LogWidget(context) self.logdock = create_dock( 'Console', N_('Console'), self, widget=self.logwidget ) qtutils.hide_dock(self.logdock) # "Diff Viewer" widget self.diffdock = create_dock( 'Diff', N_('Diff'), self, func=lambda dock: diff.Viewer(context, parent=dock), ) self.diffviewer = self.diffdock.widget() self.diffviewer.set_diff_type(self.model.diff_type) self.diffviewer.enable_filename_tracking() self.diffeditor = self.diffviewer.text titlebar = self.diffdock.titleBarWidget() titlebar.add_title_widget(self.diffviewer.filename) titlebar.add_corner_widget(self.diffviewer.options) # All Actions add_action = qtutils.add_action add_action_bool = qtutils.add_action_bool self.commit_amend_action = add_action_bool( self, N_('Amend Last Commit'), partial(cmds.do, cmds.AmendMode, context), False, ) self.commit_amend_action.setIcon(icons.edit()) self.commit_amend_action.setShortcut(hotkeys.AMEND) self.commit_amend_action.setShortcutContext(Qt.WidgetShortcut) self.unstage_all_action = add_action( self, N_('Unstage All'), cmds.run(cmds.UnstageAll, context) ) self.unstage_all_action.setIcon(icons.remove()) self.undo_commit_action = add_action( self, N_('Undo Last Commit'), cmds.run(cmds.UndoLastCommit, context) ) self.undo_commit_action.setIcon(icons.style_dialog_discard()) self.unstage_selected_action = add_action( self, N_('Unstage'), cmds.run(cmds.UnstageSelected, context) ) self.unstage_selected_action.setIcon(icons.remove()) self.show_diffstat_action = add_action( self, N_('Diffstat'), self.statuswidget.select_header, hotkeys.DIFFSTAT ) self.show_diffstat_action.setIcon(icons.diff()) self.stage_modified_action = add_action( self, cmds.StageModified.name(), cmds.run(cmds.StageModified, context), hotkeys.STAGE_MODIFIED, ) self.stage_modified_action.setIcon(icons.add()) self.stage_untracked_action = add_action( self, cmds.StageUntracked.name(), cmds.run(cmds.StageUntracked, context), hotkeys.STAGE_UNTRACKED, ) self.stage_untracked_action.setIcon(icons.add()) self.apply_patches_action = add_action( self, N_('Apply Patches...'), partial(diff.apply_patches, context) ) self.apply_patches_action.setIcon(icons.diff()) self.apply_patches_abort_action = qtutils.add_action_with_tooltip( self, N_('Abort Applying Patches...'), N_('Abort the current "git am" patch session'), cmds.run(cmds.AbortApplyPatch, context), ) self.apply_patches_abort_action.setIcon(icons.style_dialog_discard()) self.apply_patches_continue_action = qtutils.add_action_with_tooltip( self, N_('Continue Applying Patches'), N_('Commit the current state and continue applying patches'), cmds.run(cmds.ApplyPatchesContinue, context), ) self.apply_patches_continue_action.setIcon(icons.commit()) self.apply_patches_skip_action = qtutils.add_action_with_tooltip( self, N_('Skip Current Patch'), N_('Skip applying the current patch and continue applying patches'), cmds.run(cmds.ApplyPatchesContinue, context), ) self.apply_patches_skip_action.setIcon(icons.discard()) self.export_patches_action = add_action( self, N_('Export Patches...'), partial(guicmds.export_patches, context), hotkeys.EXPORT, ) self.export_patches_action.setIcon(icons.save()) self.new_repository_action = add_action( self, N_('New Repository...'), partial(guicmds.open_new_repo, context) ) self.new_repository_action.setIcon(icons.new()) self.new_bare_repository_action = add_action( self, N_('New Bare Repository...'), partial(guicmds.new_bare_repo, context) ) self.new_bare_repository_action.setIcon(icons.new()) prefs_func = partial( prefs_widget.preferences, context, parent=self, model=prefs_model ) self.preferences_action = add_action( self, N_('Preferences'), prefs_func, QtGui.QKeySequence.Preferences ) self.preferences_action.setIcon(icons.configure()) self.edit_remotes_action = add_action( self, N_('Edit Remotes...'), partial(editremotes.editor, context) ) self.edit_remotes_action.setIcon(icons.edit()) self.rescan_action = add_action( self, cmds.Refresh.name(), cmds.run(cmds.Refresh, context), *hotkeys.REFRESH_HOTKEYS, ) self.rescan_action.setIcon(icons.sync()) self.find_files_action = add_action( self, N_('Find Files'), partial(finder.finder, context), hotkeys.FINDER, ) self.find_files_action.setIcon(icons.search()) self.browse_recently_modified_action = add_action( self, N_('Recently Modified Files...'), partial(recent.browse_recent_files, context), hotkeys.EDIT_SECONDARY, ) self.browse_recently_modified_action.setIcon(icons.directory()) self.cherry_pick_action = add_action( self, N_('Cherry-Pick...'), partial(guicmds.cherry_pick, context), hotkeys.CHERRY_PICK, ) self.cherry_pick_action.setIcon(icons.cherry_pick()) self.cherry_pick_abort_action = add_action( self, N_('Abort Cherry-Pick...'), cmds.run(cmds.AbortCherryPick, context) ) self.cherry_pick_abort_action.setIcon(icons.style_dialog_discard()) self.load_commitmsg_action = add_action( self, N_('Load Commit Message...'), partial(guicmds.load_commitmsg, context) ) self.load_commitmsg_action.setIcon(icons.file_text()) self.prepare_commitmsg_hook_action = add_action( self, N_('Prepare Commit Message'), cmds.run(cmds.PrepareCommitMessageHook, context), hotkeys.PREPARE_COMMIT_MESSAGE, ) self.save_tarball_action = add_action( self, N_('Save As Tarball/Zip...'), partial(archive.save_archive, context) ) self.save_tarball_action.setIcon(icons.file_zip()) self.quit_action = add_action(self, N_('Quit'), self.close, hotkeys.QUIT) self.grep_action = add_action( self, N_('Grep'), partial(grep.grep, context), hotkeys.GREP ) self.grep_action.setIcon(icons.search()) self.merge_local_action = add_action( self, N_('Merge...'), partial(merge.local_merge, context), hotkeys.MERGE ) self.merge_local_action.setIcon(icons.merge()) self.merge_abort_action = add_action( self, N_('Abort Merge...'), cmds.run(cmds.AbortMerge, context) ) self.merge_abort_action.setIcon(icons.style_dialog_discard()) self.update_submodules_action = add_action( self, N_('Update All Submodules...'), cmds.run(cmds.SubmodulesUpdate, context), ) self.update_submodules_action.setIcon(icons.sync()) self.add_submodule_action = add_action( self, N_('Add Submodule...'), partial(submodules.add_submodule, context, parent=self), ) self.add_submodule_action.setIcon(icons.add()) self.fetch_action = qtutils.add_action_with_tooltip( self, N_('Fetch...'), N_('Fetch from one or more remotes using "git fetch"'), partial(remote.fetch, context), hotkeys.FETCH, ) self.fetch_action.setIcon(icons.download()) self.push_action = qtutils.add_action_with_tooltip( self, N_('Push...'), N_('Push to one or more remotes using "git push"'), partial(remote.push, context), hotkeys.PUSH, ) self.push_action.setIcon(icons.push()) self.pull_action = qtutils.add_action_with_tooltip( self, N_('Pull...'), N_('Integrate changes using "git pull"'), partial(remote.pull, context), hotkeys.PULL, ) self.pull_action.setIcon(icons.pull()) self.open_repo_action = add_action( self, N_('Open...'), partial(guicmds.open_repo, context), hotkeys.OPEN ) self.open_repo_action.setIcon(icons.folder()) self.open_repo_new_action = add_action( self, N_('Open in New Window...'), partial(guicmds.open_repo_in_new_window, context), ) self.open_repo_new_action.setIcon(icons.folder()) self.stash_action = qtutils.add_action_with_tooltip( self, N_('Stash...'), N_('Temporarily stash away uncommitted changes using "git stash"'), partial(stash.view, context), hotkeys.STASH, ) self.stash_action.setIcon(icons.commit()) self.reset_soft_action = qtutils.add_action_with_tooltip( self, N_('Reset Branch (Soft)'), cmds.ResetSoft.tooltip(''), partial(guicmds.reset_soft, context), ) self.reset_soft_action.setIcon(icons.style_dialog_reset()) self.reset_mixed_action = qtutils.add_action_with_tooltip( self, N_('Reset Branch and Stage (Mixed)'), cmds.ResetMixed.tooltip(''), partial(guicmds.reset_mixed, context), ) self.reset_mixed_action.setIcon(icons.style_dialog_reset()) self.reset_keep_action = qtutils.add_action_with_tooltip( self, N_('Restore Worktree and Reset All (Keep Unstaged Changes)'), cmds.ResetKeep.tooltip(''), partial(guicmds.reset_keep, context), ) self.reset_keep_action.setIcon(icons.style_dialog_reset()) self.reset_merge_action = qtutils.add_action_with_tooltip( self, N_('Restore Worktree and Reset All (Merge)'), cmds.ResetMerge.tooltip(''), partial(guicmds.reset_merge, context), ) self.reset_merge_action.setIcon(icons.style_dialog_reset()) self.reset_hard_action = qtutils.add_action_with_tooltip( self, N_('Restore Worktree and Reset All (Hard)'), cmds.ResetHard.tooltip(''), partial(guicmds.reset_hard, context), ) self.reset_hard_action.setIcon(icons.style_dialog_reset()) self.restore_worktree_action = qtutils.add_action_with_tooltip( self, N_('Restore Worktree'), cmds.RestoreWorktree.tooltip(''), partial(guicmds.restore_worktree, context), ) self.restore_worktree_action.setIcon(icons.edit()) self.clone_repo_action = add_action( self, N_('Clone...'), partial(clone.clone, context) ) self.clone_repo_action.setIcon(icons.repo()) self.help_docs_action = add_action( self, N_('Documentation'), resources.show_html_docs, QtGui.QKeySequence.HelpContents, ) self.help_shortcuts_action = add_action( self, N_('Keyboard Shortcuts'), about.show_shortcuts, hotkeys.QUESTION ) self.visualize_current_action = add_action( self, N_('Visualize Current Branch...'), cmds.run(cmds.VisualizeCurrent, context), ) self.visualize_current_action.setIcon(icons.visualize()) self.visualize_all_action = add_action( self, N_('Visualize All Branches...'), cmds.run(cmds.VisualizeAll, context) ) self.visualize_all_action.setIcon(icons.visualize()) self.search_commits_action = add_action( self, N_('Search...'), partial(search.search, context) ) self.search_commits_action.setIcon(icons.search()) self.browse_branch_action = add_action( self, N_('Browse Current Branch...'), partial(guicmds.browse_current, context), ) self.browse_branch_action.setIcon(icons.directory()) self.browse_other_branch_action = add_action( self, N_('Browse Other Branch...'), partial(guicmds.browse_other, context) ) self.browse_other_branch_action.setIcon(icons.directory()) self.load_commitmsg_template_action = add_action( self, N_('Get Commit Message Template'), cmds.run(cmds.LoadCommitMessageFromTemplate, context), ) self.load_commitmsg_template_action.setIcon(icons.style_dialog_apply()) self.help_about_action = add_action( self, N_('About'), partial(about.about_dialog, context) ) self.diff_against_commit_action = add_action( self, N_('Against Commit... (Diff Mode)'), partial(guicmds.diff_against_commit, context), ) self.diff_against_commit_action.setIcon(icons.compare()) self.exit_diff_mode_action = add_action( self, N_('Exit Diff Mode'), cmds.run(cmds.ResetMode, context) ) self.exit_diff_mode_action.setIcon(icons.compare()) self.diff_expression_action = add_action( self, N_('Expression...'), partial(guicmds.diff_expression, context) ) self.diff_expression_action.setIcon(icons.compare()) self.branch_compare_action = add_action( self, N_('Branches...'), partial(compare.compare_branches, context) ) self.branch_compare_action.setIcon(icons.compare()) self.create_tag_action = add_action( self, N_('Create Tag...'), partial(createtag.create_tag, context), ) self.create_tag_action.setIcon(icons.tag()) self.create_branch_action = add_action( self, N_('Create...'), partial(createbranch.create_new_branch, context), hotkeys.BRANCH, ) self.create_branch_action.setIcon(icons.branch()) self.delete_branch_action = add_action( self, N_('Delete...'), partial(guicmds.delete_branch, context) ) self.delete_branch_action.setIcon(icons.discard()) self.delete_remote_branch_action = add_action( self, N_('Delete Remote Branch...'), partial(guicmds.delete_remote_branch, context), ) self.delete_remote_branch_action.setIcon(icons.discard()) self.rename_branch_action = add_action( self, N_('Rename Branch...'), partial(guicmds.rename_branch, context) ) self.rename_branch_action.setIcon(icons.edit()) self.checkout_branch_action = add_action( self, N_('Checkout...'), partial(guicmds.checkout_branch, context), hotkeys.CHECKOUT, ) self.checkout_branch_action.setIcon(icons.branch()) self.branch_review_action = add_action( self, N_('Review...'), partial(guicmds.review_branch, context) ) self.branch_review_action.setIcon(icons.compare()) self.browse_action = add_action( self, N_('File Browser...'), partial(browse.worktree_browser, context) ) self.browse_action.setIcon(icons.cola()) self.dag_action = add_action(self, N_('DAG...'), self.git_dag) self.dag_action.setIcon(icons.cola()) self.rebase_start_action = add_action( self, N_('Start Interactive Rebase...'), cmds.run(cmds.Rebase, context), hotkeys.REBASE_START_AND_CONTINUE, ) self.rebase_start_action.setIcon(icons.play()) self.rebase_edit_todo_action = add_action( self, N_('Edit...'), cmds.run(cmds.RebaseEditTodo, context) ) self.rebase_edit_todo_action.setIcon(icons.edit()) self.rebase_continue_action = add_action( self, N_('Continue'), cmds.run(cmds.RebaseContinue, context), hotkeys.REBASE_START_AND_CONTINUE, ) self.rebase_continue_action.setIcon(icons.play()) self.rebase_skip_action = add_action( self, N_('Skip Current Patch'), cmds.run(cmds.RebaseSkip, context) ) self.rebase_skip_action.setIcon(icons.delete()) self.rebase_abort_action = add_action( self, N_('Abort'), cmds.run(cmds.RebaseAbort, context) ) self.rebase_abort_action.setIcon(icons.close()) # For "Start Rebase" only, reverse the first argument to setEnabled() # so that we can operate on it as a group. # We can do this because can_rebase == not is_rebasing self.rebase_start_action_proxy = utils.Proxy( self.rebase_start_action, setEnabled=lambda x: self.rebase_start_action.setEnabled(not x), ) self.rebase_group = utils.Group( self.rebase_start_action_proxy, self.rebase_edit_todo_action, self.rebase_continue_action, self.rebase_skip_action, self.rebase_abort_action, ) self.annex_init_action = qtutils.add_action( self, N_('Initialize Git Annex'), cmds.run(cmds.AnnexInit, context) ) self.lfs_init_action = qtutils.add_action( self, N_('Initialize Git LFS'), cmds.run(cmds.LFSInstall, context) ) self.lock_layout_action = add_action_bool( self, N_('Lock Layout'), self.set_lock_layout, False ) self.reset_layout_action = add_action( self, N_('Reset Layout'), self.reset_layout ) self.quick_repository_search = add_action( self, N_('Quick Open...'), lambda: guicmds.open_quick_repo_search(self.context, parent=self), hotkeys.OPEN_REPO_SEARCH, ) self.quick_repository_search.setIcon(icons.search()) self.terminal_action = common.terminal_action( context, self, hotkey=hotkeys.TERMINAL ) # Create the application menu self.menubar = QtWidgets.QMenuBar(self) self.setMenuBar(self.menubar) # File Menu add_menu = qtutils.add_menu self.file_menu = add_menu(N_('&File'), self.menubar) self.file_menu.addAction(self.quick_repository_search) # File->Open Recent menu self.open_recent_menu = self.file_menu.addMenu(N_('Open Recent')) self.open_recent_menu.setIcon(icons.folder()) self.file_menu.addAction(self.open_repo_action) self.file_menu.addAction(self.open_repo_new_action) self.file_menu.addSeparator() self.file_menu.addAction(self.new_repository_action) self.file_menu.addAction(self.new_bare_repository_action) self.file_menu.addAction(self.clone_repo_action) self.file_menu.addSeparator() self.file_menu.addAction(self.rescan_action) self.file_menu.addAction(self.find_files_action) self.file_menu.addAction(self.edit_remotes_action) self.file_menu.addAction(self.browse_recently_modified_action) self.file_menu.addSeparator() self.file_menu.addAction(self.save_tarball_action) self.patches_menu = self.file_menu.addMenu(N_('Patches')) self.patches_menu.setIcon(icons.diff()) self.patches_menu.addAction(self.export_patches_action) self.patches_menu.addAction(self.apply_patches_action) self.patches_menu.addAction(self.apply_patches_continue_action) self.patches_menu.addAction(self.apply_patches_skip_action) self.patches_menu.addAction(self.apply_patches_abort_action) # Git Annex / Git LFS annex = core.find_executable('git-annex') lfs = core.find_executable('git-lfs') if annex or lfs: self.file_menu.addSeparator() if annex: self.file_menu.addAction(self.annex_init_action) if lfs: self.file_menu.addAction(self.lfs_init_action) self.file_menu.addSeparator() self.file_menu.addAction(self.preferences_action) self.file_menu.addAction(self.quit_action) # Edit Menu self.edit_proxy = edit_proxy = FocusProxy( editor, editor.summary, editor.description ) copy_widgets = ( self, editor.summary, editor.description, self.diffeditor, bookmarkswidget.tree, recentwidget.tree, ) select_widgets = copy_widgets + (self.statuswidget.tree,) edit_proxy.override('copy', copy_widgets) edit_proxy.override('selectAll', select_widgets) edit_menu = self.edit_menu = add_menu(N_('&Edit'), self.menubar) undo = add_action(edit_menu, N_('Undo'), edit_proxy.undo, hotkeys.UNDO) undo.setIcon(icons.undo()) redo = add_action(edit_menu, N_('Redo'), edit_proxy.redo, hotkeys.REDO) redo.setIcon(icons.redo()) edit_menu.addSeparator() cut = add_action(edit_menu, N_('Cut'), edit_proxy.cut, hotkeys.CUT) cut.setIcon(icons.cut()) copy = add_action(edit_menu, N_('Copy'), edit_proxy.copy, hotkeys.COPY) copy.setIcon(icons.copy()) paste = add_action(edit_menu, N_('Paste'), edit_proxy.paste, hotkeys.PASTE) paste.setIcon(icons.paste()) delete = add_action(edit_menu, N_('Delete'), edit_proxy.delete, hotkeys.DELETE) delete.setIcon(icons.delete()) edit_menu.addSeparator() select_all = add_action( edit_menu, N_('Select All'), edit_proxy.selectAll, hotkeys.SELECT_ALL ) select_all.setIcon(icons.select_all()) edit_menu.addSeparator() qtutils.add_menu_actions(edit_menu, self.commiteditor.menu_actions) # Actions menu self.actions_menu = add_menu(N_('Actions'), self.menubar) if self.terminal_action is not None: self.actions_menu.addAction(self.terminal_action) self.actions_menu.addAction(self.fetch_action) self.actions_menu.addAction(self.push_action) self.actions_menu.addAction(self.pull_action) self.actions_menu.addAction(self.stash_action) self.actions_menu.addSeparator() self.actions_menu.addAction(self.create_tag_action) self.actions_menu.addAction(self.cherry_pick_action) self.actions_menu.addAction(self.cherry_pick_abort_action) self.actions_menu.addAction(self.merge_local_action) self.actions_menu.addAction(self.merge_abort_action) self.actions_menu.addSeparator() self.actions_menu.addAction(self.update_submodules_action) self.actions_menu.addAction(self.add_submodule_action) self.actions_menu.addSeparator() self.actions_menu.addAction(self.grep_action) self.actions_menu.addAction(self.search_commits_action) # Commit Menu self.commit_menu = add_menu(N_('Commit@@verb'), self.menubar) self.commit_menu.setTitle(N_('Commit@@verb')) self.commit_menu.addAction(self.commiteditor.commit_action) self.commit_menu.addAction(self.commit_amend_action) self.commit_menu.addAction(self.undo_commit_action) self.commit_menu.addSeparator() self.commit_menu.addAction(self.statuswidget.tree.process_selection_action) self.commit_menu.addAction(self.statuswidget.tree.stage_or_unstage_all_action) self.commit_menu.addAction(self.stage_modified_action) self.commit_menu.addAction(self.stage_untracked_action) self.commit_menu.addSeparator() self.commit_menu.addAction(self.unstage_all_action) self.commit_menu.addAction(self.unstage_selected_action) self.commit_menu.addSeparator() self.commit_menu.addAction(self.load_commitmsg_action) self.commit_menu.addAction(self.load_commitmsg_template_action) self.commit_menu.addAction(self.prepare_commitmsg_hook_action) # Diff Menu self.diff_menu = add_menu(N_('Diff'), self.menubar) self.diff_menu.addAction(self.diff_expression_action) self.diff_menu.addAction(self.branch_compare_action) self.diff_menu.addAction(self.show_diffstat_action) self.diff_menu.addSeparator() self.diff_menu.addAction(self.diff_against_commit_action) self.diff_menu.addAction(self.exit_diff_mode_action) # Branch Menu self.branch_menu = add_menu(N_('Branch'), self.menubar) self.branch_menu.addAction(self.branch_review_action) self.branch_menu.addSeparator() self.branch_menu.addAction(self.create_branch_action) self.branch_menu.addAction(self.checkout_branch_action) self.branch_menu.addAction(self.delete_branch_action) self.branch_menu.addAction(self.delete_remote_branch_action) self.branch_menu.addAction(self.rename_branch_action) self.branch_menu.addSeparator() self.branch_menu.addAction(self.browse_branch_action) self.branch_menu.addAction(self.browse_other_branch_action) self.branch_menu.addSeparator() self.branch_menu.addAction(self.visualize_current_action) self.branch_menu.addAction(self.visualize_all_action) # Rebase menu self.rebase_menu = add_menu(N_('Rebase'), self.menubar) 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) # Reset menu self.reset_menu = add_menu(N_('Reset'), self.menubar) self.reset_menu.addAction(self.unstage_all_action) self.reset_menu.addAction(self.undo_commit_action) self.reset_menu.addSeparator() self.reset_menu.addAction(self.reset_soft_action) self.reset_menu.addAction(self.reset_mixed_action) self.reset_menu.addAction(self.restore_worktree_action) self.reset_menu.addSeparator() self.reset_menu.addAction(self.reset_keep_action) self.reset_menu.addAction(self.reset_merge_action) self.reset_menu.addAction(self.reset_hard_action) # View Menu self.view_menu = add_menu(N_('View'), self.menubar) self.view_menu.aboutToShow.connect(lambda: self.build_view_menu(self.view_menu)) self.setup_dockwidget_view_menu() if utils.is_darwin(): # The native macOS menu doesn't show empty entries. self.build_view_menu(self.view_menu) # Help Menu self.help_menu = add_menu(N_('Help'), self.menubar) self.help_menu.addAction(self.help_docs_action) self.help_menu.addAction(self.help_shortcuts_action) self.help_menu.addAction(self.help_about_action) # Arrange dock widgets bottom = Qt.BottomDockWidgetArea top = Qt.TopDockWidgetArea self.addDockWidget(top, self.statusdock) self.addDockWidget(top, self.commitdock) if self.browser_dockable: self.addDockWidget(top, self.browserdock) self.tabifyDockWidget(self.browserdock, self.commitdock) self.addDockWidget(top, self.branchdock) self.addDockWidget(top, self.submodulesdock) self.addDockWidget(top, self.bookmarksdock) self.addDockWidget(top, self.recentdock) self.tabifyDockWidget(self.branchdock, self.submodulesdock) self.tabifyDockWidget(self.submodulesdock, self.bookmarksdock) self.tabifyDockWidget(self.bookmarksdock, self.recentdock) self.branchdock.raise_() self.addDockWidget(bottom, self.diffdock) self.addDockWidget(bottom, self.actionsdock) self.addDockWidget(bottom, self.logdock) self.tabifyDockWidget(self.actionsdock, self.logdock) # Listen for model notifications self.model.updated.connect(self.refresh, type=Qt.QueuedConnection) self.model.mode_changed.connect( lambda mode: self.refresh(), type=Qt.QueuedConnection ) prefs_model.config_updated.connect(self._config_updated) # Set a default value self.show_cursor_position(1, 0) self.commit_menu.aboutToShow.connect(self.update_menu_actions) self.open_recent_menu.aboutToShow.connect(self.build_recent_menu) self.commiteditor.cursor_changed.connect(self.show_cursor_position) self.diffeditor.options_changed.connect(self.statuswidget.refresh) self.diffeditor.up.connect(self.statuswidget.move_up) self.diffeditor.down.connect(self.statuswidget.move_down) self.commiteditor.up.connect(self.statuswidget.move_up) self.commiteditor.down.connect(self.statuswidget.move_down) self.config_actions_changed.connect( lambda names_and_shortcuts: _install_config_actions( context, self.actions_menu, names_and_shortcuts, ), type=Qt.QueuedConnection, ) self.init_state(context.settings, self.set_initial_size) # Route command output here Interaction.log_status = self.logwidget.log_status Interaction.log = self.logwidget.log # Focus the status widget; this must be deferred QtCore.QTimer.singleShot(0, self.initialize) def initialize(self): context = self.context git_version = version.git_version_str(context) if git_version: ok = True Interaction.log( git_version + '\n' + N_('git cola version %s') % version.version() ) else: ok = False error_msg = N_('error: unable to execute git') Interaction.log(error_msg) if ok: self.statuswidget.setFocus() else: title = N_('error: unable to execute git') msg = title details = '' if WIN32: details = git.win32_git_error_hint() Interaction.critical(title, message=msg, details=details) self.context.app.exit(2) def set_initial_size(self): # Default size; this is thrown out when save/restore is used width, height = qtutils.desktop_size() self.resize((width * 3) // 4, height) self.statuswidget.set_initial_size() self.commiteditor.set_initial_size() def set_filter(self, txt): self.statuswidget.set_filter(txt) # Qt overrides def closeEvent(self, event): """Save state in the settings""" commit_msg = self.commiteditor.commit_message(raw=True) self.model.save_commitmsg(msg=commit_msg) for browser in list(self.context.browser_windows): browser.close() standard.MainWindow.closeEvent(self, event) def create_view_menu(self): menu = qtutils.create_menu(N_('View'), self) self.build_view_menu(menu) return menu def build_view_menu(self, menu): menu.clear() menu.addAction(self.browse_action) menu.addAction(self.dag_action) menu.addSeparator() popup_menu = self.createPopupMenu() for menu_action in popup_menu.actions(): menu_action.setParent(menu) menu.addAction(menu_action) context = self.context menu_action = menu.addAction( N_('New Toolbar'), partial(toolbar.add_toolbar, context, self) ) menu_action.setIcon(icons.add()) menu.addSeparator() dockwidgets = [ self.logdock, self.commitdock, self.statusdock, self.diffdock, self.actionsdock, self.bookmarksdock, self.recentdock, self.branchdock, self.submodulesdock, ] if self.browser_dockable: dockwidgets.append(self.browserdock) for dockwidget in dockwidgets: # Associate the action with the shortcut toggleview = dockwidget.toggleViewAction() menu.addAction(toggleview) menu.addSeparator() menu.addAction(self.lock_layout_action) menu.addAction(self.reset_layout_action) return menu def contextMenuEvent(self, event): menu = self.create_view_menu() menu.exec_(event.globalPos()) def build_recent_menu(self): cmd = cmds.OpenRepo context = self.context settings = context.settings settings.load() menu = self.open_recent_menu menu.clear() worktree = context.git.worktree() for entry in settings.recent: directory = entry['path'] if directory == worktree: # Omit the current worktree from the "Open Recent" menu. continue name = entry['name'] text = f'{name} {uchr(0x2192)} {directory}' menu.addAction(text, cmds.run(cmd, context, directory)) # 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.commiteditor.setFont(font) elif config == prefs.TABWIDTH: # This can be set locally or globally, so we have to use the # effective value otherwise we'll update when we shouldn't. # For example, if this value is overridden locally, and the # global value is tweaked, we should not update. value = prefs.tabwidth(self.context) self.diffeditor.set_tabwidth(value) self.commiteditor.set_tabwidth(value) elif config == prefs.EXPANDTAB: self.commiteditor.set_expandtab(value) elif config == prefs.LINEBREAK: # enables automatic line breaks self.commiteditor.set_linebreak(value) elif config == prefs.SORT_BOOKMARKS: self.bookmarksdock.widget().reload_bookmarks() elif config == prefs.TEXTWIDTH: # Use the effective value for the same reason as tabwidth. value = prefs.textwidth(self.context) self.commiteditor.set_textwidth(value) elif config == prefs.SHOW_PATH: # the path in the window title was toggled self.refresh_window_title() def start(self, context): """Do the expensive "get_config_actions()" call in the background""" # Install .git-config-defined actions task = qtutils.SimpleTask(self.get_config_actions) context.runtask.start(task) def get_config_actions(self): actions = cfgactions.get_config_actions(self.context) self.config_actions_changed.emit(actions) def refresh(self): """Update the title with the current branch and directory name.""" curbranch = self.model.currentbranch is_merging = self.model.is_merging is_rebasing = self.model.is_rebasing is_applying_patch = self.model.is_applying_patch is_cherry_picking = self.model.is_rebasing curdir = core.getcwd() msg = N_('Repository: %s') % curdir msg += '\n' msg += N_('Branch: %s') % curbranch if is_rebasing: msg += '\n\n' msg += N_( 'This repository is currently being rebased.\n' 'Resolve conflicts, commit changes, and run:\n' ' Rebase > Continue' ) elif is_applying_patch: msg += '\n\n' msg += N_( 'This repository has unresolved conflicts after applying a patch.\n' 'Resolve conflicts and commit changes.' ) elif is_cherry_picking: msg += '\n\n' msg += N_( 'This repository is in the middle of a cherry-pick.\n' 'Resolve conflicts and commit changes.' ) elif is_merging: msg += '\n\n' msg += N_( 'This repository is in the middle of a merge.\n' 'Resolve conflicts and commit changes.' ) self.refresh_window_title() if self.mode == self.model.mode_amend: self.commit_amend_action.setChecked(True) else: self.commit_amend_action.setChecked(False) self.commitdock.setToolTip(msg) self.actionswidget.set_mode(self.mode) self.commiteditor.set_mode(self.mode) self.statuswidget.set_mode(self.mode) self.update_actions() def refresh_window_title(self): """Refresh the window title when state changes""" alerts = [] project = self.model.project curbranch = self.model.currentbranch is_cherry_picking = self.model.is_cherry_picking is_merging = self.model.is_merging is_rebasing = self.model.is_rebasing is_applying_patch = self.model.is_applying_patch is_diff_mode = self.model.is_diff_mode() is_amend_mode = self.mode == self.model.mode_amend prefix = uchr(0xAB) suffix = uchr(0xBB) if is_amend_mode: alerts.append(N_('Amending')) elif is_diff_mode: alerts.append(N_('Diff Mode')) elif is_cherry_picking: alerts.append(N_('Cherry-picking')) elif is_merging: alerts.append(N_('Merging')) elif is_rebasing: alerts.append(N_('Rebasing')) elif is_applying_patch: alerts.append(N_('Applying Patch')) if alerts: alert_text = (prefix + ' %s ' + suffix + ' ') % ', '.join(alerts) else: alert_text = '' if self.model.cfg.get(prefs.SHOW_PATH, True): path_text = self.git.worktree() else: path_text = '' title = f'{project}: {curbranch} {alert_text}{path_text}' self.setWindowTitle(title) def update_actions(self): is_rebasing = self.model.is_rebasing self.rebase_group.setEnabled(is_rebasing) enabled = not self.model.is_empty_repository() self.rename_branch_action.setEnabled(enabled) self.delete_branch_action.setEnabled(enabled) self.annex_init_action.setEnabled(not self.model.annex) self.lfs_init_action.setEnabled(not self.model.lfs) self.merge_abort_action.setEnabled(self.model.is_merging) self.cherry_pick_abort_action.setEnabled(self.model.is_cherry_picking) self.apply_patches_continue_action.setEnabled(self.model.is_applying_patch) self.apply_patches_skip_action.setEnabled(self.model.is_applying_patch) self.apply_patches_abort_action.setEnabled(self.model.is_applying_patch) diff_mode = self.model.mode == self.model.mode_diff self.exit_diff_mode_action.setEnabled(diff_mode) def update_menu_actions(self): # Enable the Prepare Commit Message action if the hook exists hook = gitcmds.prepare_commit_message_hook(self.context) enabled = os.path.exists(hook) self.prepare_commitmsg_hook_action.setEnabled(enabled) def export_state(self): state = standard.MainWindow.export_state(self) show_status_filter = self.statuswidget.filter_widget.isVisible() state['show_status_filter'] = show_status_filter state['toolbars'] = self.toolbar_state.export_state() state['ref_sort'] = self.model.ref_sort self.diffviewer.export_state(state) return state def apply_state(self, state): """Imports data for save/restore""" base_ok = standard.MainWindow.apply_state(self, state) lock_layout = state.get('lock_layout', False) self.lock_layout_action.setChecked(lock_layout) show_status_filter = state.get('show_status_filter', False) self.statuswidget.filter_widget.setVisible(show_status_filter) toolbars = state.get('toolbars', []) self.toolbar_state.apply_state(toolbars) sort_key = state.get('ref_sort', 0) self.model.set_ref_sort(sort_key) diff_ok = self.diffviewer.apply_state(state) return base_ok and diff_ok 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.logdock), (optkey + '+1', self.commitdock), (optkey + '+2', self.statusdock), (optkey + '+3', self.diffdock), (optkey + '+4', self.actionsdock), (optkey + '+5', self.bookmarksdock), (optkey + '+6', self.recentdock), (optkey + '+7', self.branchdock), (optkey + '+8', self.submodulesdock), ) for shortcut, dockwidget in dockwidgets: # Associate the action with the shortcut toggleview = dockwidget.toggleViewAction() toggleview.setShortcut('Shift+' + shortcut) def showdock(show, dockwidget=dockwidget): if show: dockwidget.raise_() dockwidget.widget().setFocus() else: self.setFocus() self.addAction(toggleview) qtutils.connect_action_bool(toggleview, showdock) # Create a new shortcut Shift+ that gives focus toggleview = QtWidgets.QAction(self) toggleview.setShortcut(shortcut) def focusdock(dockwidget=dockwidget): focus_dock(dockwidget) self.addAction(toggleview) qtutils.connect_action(toggleview, focusdock) # These widgets warrant home-row hotkey status qtutils.add_action( self, 'Focus Commit Message', lambda: focus_dock(self.commitdock), hotkeys.FOCUS, ) qtutils.add_action( self, 'Focus Status Window', lambda: focus_dock(self.statusdock), hotkeys.FOCUS_STATUS, ) qtutils.add_action( self, 'Focus Diff Editor', lambda: focus_dock(self.diffdock), hotkeys.FOCUS_DIFF, ) def git_dag(self): self.dag = dag.git_dag(self.context, existing_view=self.dag) def show_cursor_position(self, rows, cols): display_content = '%02d:%02d' % (rows, cols) css = """ """ if cols > 78: cls = 'error' elif cols > 72: cls = 'second-warning' elif cols > 64: cls = 'first-warning' else: cls = 'good' div = f'
{display_content}
' self.position_label.setText(css + div) class FocusProxy: """Proxy over child widgets and operate on the focused widget""" def __init__(self, *widgets): self.widgets = widgets self.overrides = {} def override(self, name, widgets): self.overrides[name] = widgets def focus(self, name): """Return the currently focused widget""" widgets = self.overrides.get(name, self.widgets) # The parent must be the parent of all the proxied widgets parent = widgets[0] # The first widget is used as a fallback fallback = widgets[1] # We ignore the parent when delegating to child widgets widgets = widgets[1:] focus = parent.focusWidget() if focus not in widgets: focus = fallback return focus def __getattr__(self, name): """Return a callback that calls a common child method""" def callback(): focus = self.focus(name) func = getattr(focus, name, None) if func: func() return callback def delete(self): """Specialized delete() to deal with QLineEdit vs. QTextEdit""" focus = self.focus('delete') if hasattr(focus, 'del_'): focus.del_() elif hasattr(focus, 'textCursor'): focus.textCursor().deleteChar() def show_dock(dockwidget): dockwidget.raise_() dockwidget.widget().setFocus() def focus_dock(dockwidget): if get(dockwidget.toggleViewAction()): show_dock(dockwidget) else: dockwidget.toggleViewAction().trigger() def _install_config_actions(context, menu, names_and_shortcuts): """Install .gitconfig-defined actions""" if not names_and_shortcuts: return menu.addSeparator() cache = {} for name, shortcut in names_and_shortcuts: sub_menu, action_name = build_menus(name, menu, cache) callback = cmds.run(cmds.RunConfigAction, context, name) menu_action = sub_menu.addAction(action_name, callback) if shortcut: menu_action.setShortcut(shortcut) def build_menus(name, menu, cache): """Create a chain of QMenu entries parented under a root QMenu A name of "a/b/c" create a menu chain of menu -> QMenu("a") -> QMenu("b") and returns a tuple of (QMenu("b"), "c"). :param name: The full entry path, ex: "a/b/c" where "a/b" is the menu chain. :param menu: The root menu under which to create the menu chain. :param cache: A dict cache of previously created menus to avoid duplicates. """ # NOTE: utils.split() and friends are used instead of os.path.split() because # slash '/' is the only supported "/name" separator. Use of os.path.split() # would introduce differences in behavior across platforms. # If the menu_path is empty then no parent menus need to be created. # The action will be added to the root menu. menu_path, text = utils.split(utils.normalize_slash(name)) if not menu_path: return (menu, text) # When menu_path contains ex: "a/b" we will create two menus: "a" and "b". # The root menu is the parent of "a" and "a" is the parent of "b". # The menu returned to the caller is "b". # # Loop over the individual menu basenames alongside the full subpath returned by # pathset(). The subpath is a cache key for finding previously created menus. menu_names = utils.splitpath(menu_path) # ['a', 'b'] menu_pathset = utils.pathset(menu_path) # ['a', 'a/b'] for menu_name, menu_id in zip(menu_names, menu_pathset): try: menu = cache[menu_id] except KeyError: menu = cache[menu_id] = menu.addMenu(menu_name) return (menu, text) git-cola-4.6.1/cola/widgets/merge.py000066400000000000000000000210001457126473700172670ustar00rootroot00000000000000from qtpy import QtWidgets from qtpy.QtCore import Qt from ..i18n import N_ from ..interaction import Interaction from ..qtutils import get from .. import cmds from .. import icons from .. import qtutils from . import completion from . import standard from . import defs def local_merge(context): """Provides a dialog for merging branches""" view = Merge(context, qtutils.active_window()) view.show() view.raise_() return view class Merge(standard.Dialog): """Provides a dialog for merging branches.""" def __init__(self, context, parent=None, ref=None): standard.Dialog.__init__(self, parent=parent) self.context = context self.cfg = cfg = context.cfg self.model = context.model if parent is not None: self.setWindowModality(Qt.WindowModal) # Widgets self.title_label = QtWidgets.QLabel() self.revision_label = QtWidgets.QLabel() self.revision_label.setText(N_('Revision to Merge')) self.revision = completion.GitRefLineEdit(context) self.revision.setToolTip(N_('Revision to Merge')) if ref: self.revision.set_value(ref) self.radio_local = qtutils.radio(text=N_('Local Branch'), checked=True) self.radio_remote = qtutils.radio(text=N_('Tracking Branch')) self.radio_tag = qtutils.radio(text=N_('Tag')) self.revisions = QtWidgets.QListWidget() self.revisions.setAlternatingRowColors(True) self.button_viz = qtutils.create_button( text=N_('Visualize'), icon=icons.visualize() ) tooltip = N_('Squash the merged commits into a single commit') self.checkbox_squash = qtutils.checkbox(text=N_('Squash'), tooltip=tooltip) tooltip = N_( 'Always create a merge commit when enabled, ' 'even when the merge is a fast-forward update' ) self.checkbox_noff = qtutils.checkbox( text=N_('No fast forward'), tooltip=tooltip, checked=False ) self.checkbox_noff_state = False tooltip = N_( 'Commit the merge if there are no conflicts. ' 'Uncheck to leave the merge uncommitted' ) self.checkbox_commit = qtutils.checkbox( text=N_('Commit'), tooltip=tooltip, checked=True ) self.checkbox_commit_state = True text = N_('Create Signed Commit') checked = cfg.get('cola.signcommits', False) tooltip = N_('GPG-sign the merge commit') self.checkbox_sign = qtutils.checkbox( text=text, checked=checked, tooltip=tooltip ) self.button_close = qtutils.close_button() icon = icons.merge() self.button_merge = qtutils.create_button( text=N_('Merge'), icon=icon, default=True ) # Layouts self.revlayt = qtutils.hbox( defs.no_margin, defs.spacing, self.revision_label, self.revision, qtutils.STRETCH, self.title_label, ) self.radiolayt = qtutils.hbox( defs.no_margin, defs.spacing, self.radio_local, self.radio_remote, self.radio_tag, ) self.buttonlayt = qtutils.hbox( defs.no_margin, defs.button_spacing, self.button_viz, self.checkbox_squash, self.checkbox_noff, self.checkbox_commit, self.checkbox_sign, qtutils.STRETCH, self.button_close, self.button_merge, ) self.mainlayt = qtutils.vbox( defs.margin, defs.spacing, self.radiolayt, self.revisions, self.revlayt, self.buttonlayt, ) self.setLayout(self.mainlayt) # Signal/slot connections self.revision.textChanged.connect(self.update_title) self.revision.enter.connect(self.merge_revision) self.revisions.itemSelectionChanged.connect(self.revision_selected) qtutils.connect_released(self.radio_local, self.update_revisions) qtutils.connect_released(self.radio_remote, self.update_revisions) qtutils.connect_released(self.radio_tag, self.update_revisions) qtutils.connect_button(self.button_merge, self.merge_revision) qtutils.connect_button(self.checkbox_squash, self.toggle_squash) qtutils.connect_button(self.button_viz, self.viz_revision) qtutils.connect_button(self.button_close, self.reject) # Observer messages self.model.updated.connect(self.update_all) self.update_all() self.init_size(parent=parent) self.revision.setFocus() def update_all(self): """Set the branch name for the window title and label.""" self.update_title() self.update_revisions() def update_title(self, _txt=None): branch = self.model.currentbranch revision = self.revision.text() if revision: txt = N_('Merge "%(revision)s" into "%(branch)s"') % { 'revision': revision, 'branch': branch, } else: txt = N_('Merge into "%s"') % branch self.button_merge.setEnabled(bool(revision)) self.title_label.setText(txt) self.setWindowTitle(txt) def toggle_squash(self): """Toggles the commit checkbox based on the squash checkbox.""" if get(self.checkbox_squash): self.checkbox_commit_state = self.checkbox_commit.checkState() self.checkbox_commit.setCheckState(Qt.Unchecked) self.checkbox_commit.setDisabled(True) self.checkbox_noff_state = self.checkbox_noff.checkState() self.checkbox_noff.setCheckState(Qt.Unchecked) self.checkbox_noff.setDisabled(True) else: self.checkbox_noff.setDisabled(False) oldstateff = self.checkbox_noff_state self.checkbox_noff.setCheckState(oldstateff) 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 revision = qtutils.selected_item(widget, revlist) if revision is not None: self.revision.setText(revision) def current_revisions(self): """Retrieve candidate items to merge""" if get(self.radio_local): return self.model.local_branches if get(self.radio_remote): return self.model.remote_branches if get(self.radio_tag): return self.model.tags return [] def viz_revision(self): """Launch a gitk-like viewer on the selection revision""" revision = self.revision.text() if not revision: Interaction.information( N_('No Revision Specified'), N_('You must specify a revision to view.') ) return cmds.do(cmds.VisualizeRevision, self.context, revision) def merge_revision(self): """Merge the selected revision/branch""" revision = self.revision.text() if not revision: Interaction.information( N_('No Revision Specified'), N_('You must specify a revision to merge.') ) return noff = get(self.checkbox_noff) no_commit = not get(self.checkbox_commit) squash = get(self.checkbox_squash) sign = get(self.checkbox_sign) context = self.context cmds.do(cmds.Merge, context, revision, no_commit, squash, noff, sign) self.accept() def export_state(self): """Export persistent settings""" state = super().export_state() state['no-ff'] = get(self.checkbox_noff) state['sign'] = get(self.checkbox_sign) state['commit'] = get(self.checkbox_commit) return state def apply_state(self, state): """Apply persistent settings""" result = super().apply_state(state) self.checkbox_noff.setChecked(state.get('no-ff', False)) self.checkbox_sign.setChecked(state.get('sign', False)) self.checkbox_commit.setChecked(state.get('commit', True)) return result git-cola-4.6.1/cola/widgets/prefs.py000066400000000000000000000463121457126473700173240ustar00rootroot00000000000000from qtpy import QtCore from qtpy import QtWidgets from . import defs from . import standard from .. import cmds from .. import hidpi from .. import icons from .. import qtutils from .. import themes from ..compat import ustr from ..i18n import N_ from ..models import prefs from ..models.prefs import Defaults from ..models.prefs import fallback_editor def preferences(context, model=None, parent=None): if model is None: model = prefs.PreferencesModel(context) view = PreferencesView(context, model, parent=parent) view.show() view.raise_() return view class FormWidget(QtWidgets.QWidget): def __init__(self, context, model, parent, source='global'): QtWidgets.QWidget.__init__(self, parent) self.context = context self.cfg = context.cfg self.model = model self.config_to_widget = {} self.widget_to_config = {} self.source = source self.defaults = {} self.setLayout(QtWidgets.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, QtWidgets.QSpinBox): widget.valueChanged.connect(self._int_config_changed(config)) elif isinstance(widget, QtWidgets.QCheckBox): widget.toggled.connect(self._bool_config_changed(config)) elif isinstance(widget, QtWidgets.QLineEdit): widget.editingFinished.connect(self._text_config_changed(config, widget)) widget.returnPressed.connect(self._text_config_changed(config, widget)) elif isinstance(widget, qtutils.ComboBox): widget.currentIndexChanged.connect( self._item_config_changed(config, widget) ) def _int_config_changed(self, config): def runner(value): cmds.do(prefs.SetConfig, self.model, self.source, config, value) return runner def _bool_config_changed(self, config): def runner(value): cmds.do(prefs.SetConfig, self.model, self.source, config, value) return runner def _text_config_changed(self, config, widget): def runner(): value = widget.text() cmds.do(prefs.SetConfig, self.model, self.source, config, value) return runner def _item_config_changed(self, config, widget): def runner(): value = widget.current_data() cmds.do(prefs.SetConfig, self.model, self.source, config, value) return runner def update_from_config(self): if self.source == 'global': getter = self.cfg.get_user_or_system else: getter = self.cfg.get for config, widget in self.widget_to_config.items(): value = getter(config) if value is None: value = self.defaults[config] set_widget_value(widget, value) def set_widget_value(widget, value): """Set a value on a widget without emitting notifications""" with qtutils.BlockSignals(widget): if isinstance(widget, QtWidgets.QSpinBox): widget.setValue(value) elif isinstance(widget, QtWidgets.QLineEdit): widget.setText(value) elif isinstance(widget, QtWidgets.QCheckBox): widget.setChecked(value) elif hasattr(widget, 'set_value'): widget.set_value(value) class RepoFormWidget(FormWidget): def __init__(self, context, model, parent, source): FormWidget.__init__(self, context, model, parent, source=source) self.name = QtWidgets.QLineEdit() self.email = QtWidgets.QLineEdit() tooltip = N_( 'Default directory when exporting patches.\n' 'Relative paths are relative to the current repository.\n' 'Absolute path are used as-is.' ) patches_directory = prefs.patches_directory(context) self.patches_directory = standard.DirectoryPathLineEdit(patches_directory, self) self.patches_directory.setToolTip(tooltip) tooltip = N_( """ This option determines how the supplied commit message should be cleaned up before committing. The can be strip, whitespace, verbatim, scissors or default. strip Strip leading and trailing empty lines, trailing whitespace, commentary and collapse consecutive empty lines. whitespace Same as strip except #commentary is not removed. verbatim Do not change the message at all. scissors Same as whitespace except that everything from (and including) the line found below is truncated, if the message is to be edited. "#" can be customized with core.commentChar. # ------------------------ >8 ------------------------""" ) self.commit_cleanup = qtutils.combo( prefs.commit_cleanup_modes(), tooltip=tooltip ) self.diff_context = standard.SpinBox(value=5, mini=2, maxi=9995) self.merge_verbosity = standard.SpinBox(value=5, maxi=5) self.merge_summary = qtutils.checkbox(checked=True) self.autotemplate = qtutils.checkbox(checked=False) self.merge_diffstat = qtutils.checkbox(checked=True) self.display_untracked = qtutils.checkbox(checked=True) self.show_path = qtutils.checkbox(checked=True) self.logdate = qtutils.combo(prefs.date_formats()) tooltip = N_( 'The date-time format used when displaying dates in Git DAG.\n' 'This value is passed to git log --date=' ) self.logdate.setToolTip(tooltip) tooltip = N_('Detect conflict markers in unmerged files') self.check_conflicts = qtutils.checkbox(checked=True, tooltip=tooltip) tooltip = N_('Use gravatar.com to lookup icons for author emails') self.enable_gravatar = qtutils.checkbox(checked=True, tooltip=tooltip) tooltip = N_('Prevent "Stage" from staging all files when nothing is selected') self.safe_mode = qtutils.checkbox(checked=False, tooltip=tooltip) tooltip = N_('Enable path autocompletion in tools') self.autocomplete_paths = qtutils.checkbox(checked=True, tooltip=tooltip) tooltip = N_('Check whether a commit has been published when amending') self.check_published_commits = qtutils.checkbox(checked=True, tooltip=tooltip) self.add_row(N_('User Name'), self.name) self.add_row(N_('Email Address'), self.email) self.add_row(N_('Log Date Format'), self.logdate) self.add_row(N_('Commit Message Cleanup'), self.commit_cleanup) 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_('Patches Directory'), self.patches_directory) self.add_row(N_('Summarize Merge Commits'), self.merge_summary) self.add_row( N_('Automatically Load Commit Message Template'), self.autotemplate ) self.add_row(N_('Show Full Paths in the Window Title'), self.show_path) self.add_row(N_('Show Diffstat After Merge'), self.merge_diffstat) self.add_row(N_('Display Untracked Files'), self.display_untracked) self.add_row(N_('Detect Conflict Markers'), self.check_conflicts) self.add_row(N_('Enable Gravatar Icons'), self.enable_gravatar) self.add_row(N_('Safe Mode'), self.safe_mode) self.add_row(N_('Autocomplete Paths'), self.autocomplete_paths) self.add_row( N_('Check Published Commits when Amending'), self.check_published_commits ) self.set_config({ prefs.AUTOTEMPLATE: (self.autotemplate, Defaults.autotemplate), prefs.AUTOCOMPLETE_PATHS: ( self.autocomplete_paths, Defaults.autocomplete_paths, ), prefs.CHECK_CONFLICTS: (self.check_conflicts, Defaults.check_conflicts), prefs.CHECK_PUBLISHED_COMMITS: ( self.check_published_commits, Defaults.check_published_commits, ), prefs.COMMIT_CLEANUP: (self.commit_cleanup, Defaults.commit_cleanup), prefs.DIFFCONTEXT: (self.diff_context, Defaults.diff_context), prefs.DISPLAY_UNTRACKED: ( self.display_untracked, Defaults.display_untracked, ), prefs.ENABLE_GRAVATAR: (self.enable_gravatar, Defaults.enable_gravatar), prefs.LOGDATE: (self.logdate, Defaults.logdate), prefs.MERGE_DIFFSTAT: (self.merge_diffstat, Defaults.merge_diffstat), prefs.MERGE_SUMMARY: (self.merge_summary, Defaults.merge_summary), prefs.MERGE_VERBOSITY: (self.merge_verbosity, Defaults.merge_verbosity), prefs.PATCHES_DIRECTORY: ( self.patches_directory, Defaults.patches_directory, ), prefs.SAFE_MODE: (self.safe_mode, Defaults.safe_mode), prefs.SHOW_PATH: (self.show_path, Defaults.show_path), prefs.USER_NAME: (self.name, ''), prefs.USER_EMAIL: (self.email, ''), }) class SettingsFormWidget(FormWidget): def __init__(self, context, model, parent): FormWidget.__init__(self, context, model, parent) self.fixed_font = QtWidgets.QFontComboBox() self.font_size = standard.SpinBox(value=12, mini=6, maxi=192) self.maxrecent = standard.SpinBox(maxi=99) self.tabwidth = standard.SpinBox(maxi=42) self.textwidth = standard.SpinBox(maxi=150) self.editor = QtWidgets.QLineEdit() self.historybrowser = QtWidgets.QLineEdit() self.blameviewer = QtWidgets.QLineEdit() self.difftool = QtWidgets.QLineEdit() self.mergetool = QtWidgets.QLineEdit() self.linebreak = qtutils.checkbox() self.mouse_zoom = qtutils.checkbox() self.keep_merge_backups = qtutils.checkbox() self.sort_bookmarks = qtutils.checkbox() self.save_window_settings = qtutils.checkbox() self.check_spelling = qtutils.checkbox() self.expandtab = qtutils.checkbox() self.resize_browser_columns = qtutils.checkbox(checked=False) self.add_row(N_('Fixed-Width Font'), self.fixed_font) self.add_row(N_('Font Size'), self.font_size) self.add_row(N_('Text Width'), self.textwidth) self.add_row(N_('Tab Width'), self.tabwidth) self.add_row(N_('Editor'), self.editor) self.add_row(N_('History Browser'), self.historybrowser) self.add_row(N_('Blame Viewer'), self.blameviewer) self.add_row(N_('Diff Tool'), self.difftool) self.add_row(N_('Merge Tool'), self.mergetool) self.add_row(N_('Recent repository count'), self.maxrecent) self.add_row(N_('Auto-Wrap Lines'), self.linebreak) self.add_row(N_('Insert spaces instead of tabs'), self.expandtab) self.add_row(N_('Sort bookmarks alphabetically'), self.sort_bookmarks) self.add_row(N_('Keep *.orig Merge Backups'), self.keep_merge_backups) self.add_row(N_('Save GUI Settings'), self.save_window_settings) self.add_row(N_('Resize File Browser columns'), self.resize_browser_columns) self.add_row(N_('Check spelling'), self.check_spelling) self.add_row(N_('Ctrl+MouseWheel to Zoom'), self.mouse_zoom) self.set_config({ prefs.SAVEWINDOWSETTINGS: ( self.save_window_settings, Defaults.save_window_settings, ), prefs.TABWIDTH: (self.tabwidth, Defaults.tabwidth), prefs.EXPANDTAB: (self.expandtab, Defaults.expandtab), prefs.TEXTWIDTH: (self.textwidth, Defaults.textwidth), prefs.LINEBREAK: (self.linebreak, Defaults.linebreak), prefs.MAXRECENT: (self.maxrecent, Defaults.maxrecent), prefs.SORT_BOOKMARKS: (self.sort_bookmarks, Defaults.sort_bookmarks), prefs.DIFFTOOL: (self.difftool, Defaults.difftool), prefs.EDITOR: (self.editor, fallback_editor()), prefs.HISTORY_BROWSER: ( self.historybrowser, prefs.default_history_browser(), ), prefs.BLAME_VIEWER: (self.blameviewer, Defaults.blame_viewer), prefs.MERGE_KEEPBACKUP: ( self.keep_merge_backups, Defaults.merge_keep_backup, ), prefs.MERGETOOL: (self.mergetool, Defaults.mergetool), prefs.RESIZE_BROWSER_COLUMNS: ( self.resize_browser_columns, Defaults.resize_browser_columns, ), prefs.SPELL_CHECK: (self.check_spelling, Defaults.spellcheck), prefs.MOUSE_ZOOM: (self.mouse_zoom, Defaults.mouse_zoom), }) self.fixed_font.currentFontChanged.connect(self.current_font_changed) self.font_size.valueChanged.connect(self.font_size_changed) def update_from_config(self): """Update widgets to the current config values""" FormWidget.update_from_config(self) context = self.context with qtutils.BlockSignals(self.fixed_font): font = qtutils.diff_font(context) self.fixed_font.setCurrentFont(font) with qtutils.BlockSignals(self.font_size): font_size = font.pointSize() self.font_size.setValue(font_size) def font_size_changed(self, size): font = self.fixed_font.currentFont() font.setPointSize(size) cmds.do(prefs.SetConfig, self.model, 'global', prefs.FONTDIFF, font.toString()) def current_font_changed(self, font): cmds.do(prefs.SetConfig, self.model, 'global', prefs.FONTDIFF, font.toString()) class AppearanceFormWidget(FormWidget): def __init__(self, context, model, parent): FormWidget.__init__(self, context, model, parent) # Theme selectors self.themes = themes.get_all_themes() self.theme = qtutils.combo_mapped(themes.options(themes=self.themes)) self.icon_theme = qtutils.combo_mapped(icons.icon_themes()) # The transform to ustr is needed because the config reader will convert # "0", "1", and "2" into integers. The "1.5" value, though, is # parsed as a string, so the transform is effectively a no-op. self.high_dpi = qtutils.combo_mapped(hidpi.options(), transform=ustr) self.high_dpi.setEnabled(hidpi.is_supported()) self.bold_headers = qtutils.checkbox() self.status_show_totals = qtutils.checkbox() self.status_indent = qtutils.checkbox() self.block_cursor = qtutils.checkbox(checked=True) self.add_row(N_('GUI theme'), self.theme) self.add_row(N_('Icon theme'), self.icon_theme) self.add_row(N_('High DPI'), self.high_dpi) self.add_row(N_('Bold on dark headers instead of italic'), self.bold_headers) self.add_row(N_('Show file counts in Status titles'), self.status_show_totals) self.add_row(N_('Indent Status paths'), self.status_indent) self.add_row(N_('Use a block cursor in diff editors'), self.block_cursor) self.set_config({ prefs.BOLD_HEADERS: (self.bold_headers, Defaults.bold_headers), prefs.HIDPI: (self.high_dpi, Defaults.hidpi), prefs.STATUS_SHOW_TOTALS: ( self.status_show_totals, Defaults.status_show_totals, ), prefs.STATUS_INDENT: (self.status_indent, Defaults.status_indent), prefs.THEME: (self.theme, Defaults.theme), prefs.ICON_THEME: (self.icon_theme, Defaults.icon_theme), prefs.BLOCK_CURSOR: (self.block_cursor, Defaults.block_cursor), }) self.theme.currentIndexChanged.connect(self._theme_changed) def _theme_changed(self, theme_idx): """Set the icon theme to dark/light when the main theme changes""" # Set the icon theme to a theme that corresponds to the main settings. try: theme = self.themes[theme_idx] except IndexError: return icon_theme = self.icon_theme.current_data() if theme.name == 'default': if icon_theme in ('light', 'dark'): self.icon_theme.set_value('default') elif theme.is_dark: if icon_theme in ('default', 'light'): self.icon_theme.set_value('dark') elif not theme.is_dark: if icon_theme in ('default', 'dark'): self.icon_theme.set_value('light') class AppearanceWidget(QtWidgets.QWidget): def __init__(self, form, parent): QtWidgets.QWidget.__init__(self, parent) self.form = form self.label = QtWidgets.QLabel( '
' + N_('Restart the application after changing appearance settings.') + '
' ) layout = qtutils.vbox( defs.margin, defs.spacing, self.form, defs.spacing * 4, self.label, qtutils.STRETCH, ) self.setLayout(layout) def update_from_config(self): self.form.update_from_config() class PreferencesView(standard.Dialog): def __init__(self, context, model, parent=None): standard.Dialog.__init__(self, parent=parent) self.context = context self.setWindowTitle(N_('Preferences')) if parent is not None: self.setWindowModality(QtCore.Qt.WindowModal) self.resize(600, 360) self.tab_bar = QtWidgets.QTabBar() self.tab_bar.setDrawBase(False) self.tab_bar.addTab(N_('All Repositories')) self.tab_bar.addTab(N_('Current Repository')) self.tab_bar.addTab(N_('Settings')) self.tab_bar.addTab(N_('Appearance')) self.user_form = RepoFormWidget(context, model, self, source='global') self.repo_form = RepoFormWidget(context, model, self, source='local') self.options_form = SettingsFormWidget(context, model, self) self.appearance_form = AppearanceFormWidget(context, model, self) self.appearance = AppearanceWidget(self.appearance_form, self) self.stack_widget = QtWidgets.QStackedWidget() self.stack_widget.addWidget(self.user_form) self.stack_widget.addWidget(self.repo_form) self.stack_widget.addWidget(self.options_form) self.stack_widget.addWidget(self.appearance) self.close_button = qtutils.close_button() self.button_layout = qtutils.hbox( defs.no_margin, defs.spacing, qtutils.STRETCH, self.close_button ) self.main_layout = qtutils.vbox( defs.margin, defs.spacing, self.tab_bar, self.stack_widget, self.button_layout, ) self.setLayout(self.main_layout) self.tab_bar.currentChanged.connect(self.stack_widget.setCurrentIndex) self.stack_widget.currentChanged.connect(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.stack_widget.widget(idx) widget.update_from_config() git-cola-4.6.1/cola/widgets/recent.py000066400000000000000000000112561457126473700174640ustar00rootroot00000000000000from qtpy import QtCore from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from ..i18n import N_ from ..qtutils import get from .. import cmds from .. import gitcmds from .. import hotkeys from .. import icons from .. import qtutils from .browse import GitTreeWidget from .browse import GitFileTreeModel from . import defs from . import standard def browse_recent_files(context): dialog = RecentFiles(context, parent=qtutils.active_window()) dialog.show() return dialog class UpdateFileListThread(QtCore.QThread): result = Signal(object) def __init__(self, context, count): QtCore.QThread.__init__(self) self.context = context self.count = count def run(self): context = self.context ref = 'HEAD~%d' % self.count filenames = gitcmds.diff_index_filenames(context, ref) self.result.emit(filenames) class RecentFiles(standard.Dialog): def __init__(self, context, parent=None): standard.Dialog.__init__(self, parent=parent) self.context = context self.setWindowTitle(N_('Recently Modified Files')) if parent is not None: self.setWindowModality(Qt.WindowModal) count = 8 self.update_thread = UpdateFileListThread(context, count) self.count = standard.SpinBox( value=count, maxi=10000, suffix=N_(' commits ago') ) self.count_label = QtWidgets.QLabel() self.count_label.setText(N_('Showing changes since')) self.refresh_button = qtutils.refresh_button(enabled=False) self.tree = GitTreeWidget(parent=self) self.tree_model = GitFileTreeModel(self) self.tree.setModel(self.tree_model) self.expand_button = qtutils.create_button( text=N_('Expand all'), icon=icons.unfold() ) self.collapse_button = qtutils.create_button( text=N_('Collapse all'), icon=icons.fold() ) self.edit_button = qtutils.edit_button(enabled=False, default=True) self.close_button = qtutils.close_button() self.top_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.count_label, self.count, qtutils.STRETCH, self.refresh_button, ) self.button_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.expand_button, self.collapse_button, qtutils.STRETCH, self.close_button, self.edit_button, ) self.main_layout = qtutils.vbox( defs.margin, defs.spacing, self.top_layout, self.tree, self.button_layout ) self.setLayout(self.main_layout) self.tree.selection_changed.connect(self.tree_selection_changed) self.tree.path_chosen.connect(self.edit_file) self.count.valueChanged.connect(self.count_changed) self.count.editingFinished.connect(self.refresh) thread = self.update_thread thread.result.connect(self.set_filenames, type=Qt.QueuedConnection) 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, hotkeys.REFRESH) self.update_thread.start() self.init_size(parent=parent) 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, self.context, 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 = get(self.count) self.update_thread.start() def count_changed(self, _value): self.refresh_button.setEnabled(True) def tree_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-4.6.1/cola/widgets/remote.py000066400000000000000000000663001457126473700174770ustar00rootroot00000000000000"""Widgets for Fetch, Push, and Pull""" import fnmatch from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from ..i18n import N_ from ..interaction import Interaction from ..qtutils import connect_button from ..qtutils import get from .. import gitcmds from .. import icons from .. import qtutils from .. import utils from . import defs from . import log from . import standard FETCH = 'FETCH' PUSH = 'PUSH' PULL = 'PULL' def fetch(context): """Fetch from remote repositories""" return run(context, Fetch) def push(context): """Push to remote repositories""" return run(context, Push) def pull(context): """Pull from remote repositories""" return run(context, Pull) def run(context, RemoteDialog): """Launches fetch/push/pull dialogs.""" # Copy global stuff over to speedup startup parent = qtutils.active_window() view = RemoteDialog(context, parent=parent) view.show() return view def combine(result, prev): """Combine multiple (status, out, err) tuples into a combined tuple The current state is passed in via `prev`. The status code is a max() over all the subprocess status codes. Individual (out, err) strings are sequentially concatenated together. """ if isinstance(prev, (tuple, list)): if len(prev) != 3: raise AssertionError('combine() with length %d' % len(prev)) combined = ( max(prev[0], result[0]), combine(prev[1], result[1]), combine(prev[2], result[2]), ) elif prev and result: combined = prev + '\n\n' + result elif prev: combined = prev else: combined = result return combined def uncheck(value, *checkboxes): """Uncheck the specified checkboxes if value is True""" if value: for checkbox in checkboxes: checkbox.setChecked(False) def strip_remotes(remote_branches): """Strip the / prefixes from branches e.g. "origin/main" becomes "main". """ branches = [utils.strip_one(branch) for branch in remote_branches] return [branch for branch in branches if branch != 'HEAD'] def get_default_remote(context): """Get the name of the default remote to use for pushing. This will be the remote the branch is set to track, if it is set. If it is not, remote.pushDefault will be used (or origin if not set) """ upstream_remote = gitcmds.upstream_remote(context) return upstream_remote or context.cfg.get('remote.pushDefault', default='origin') class ActionTask(qtutils.Task): """Run actions asynchronously""" def __init__(self, model_action, remote, kwargs): qtutils.Task.__init__(self) self.model_action = model_action self.remote = remote self.kwargs = kwargs def task(self): """Runs the model action and captures the result""" return self.model_action(self.remote, **self.kwargs) class RemoteActionDialog(standard.Dialog): """Interface for performing remote operations""" def __init__(self, context, action, title, parent=None, icon=None): """Customize the dialog based on the remote action""" standard.Dialog.__init__(self, parent=parent) self.setWindowTitle(title) if parent is not None: self.setWindowModality(Qt.WindowModal) self.context = context self.model = model = context.model self.action = action self.filtered_remote_branches = [] self.selected_remotes = [] self.runtask = qtutils.RunTask(parent=self) self.local_label = QtWidgets.QLabel() self.local_label.setText(N_('Local Branch')) self.local_branch = QtWidgets.QLineEdit() qtutils.add_completer(self.local_branch, model.local_branches) self.local_branches = QtWidgets.QListWidget() self.local_branches.addItems(model.local_branches) self.remote_label = QtWidgets.QLabel() self.remote_label.setText(N_('Remote')) self.remote_name = QtWidgets.QLineEdit() qtutils.add_completer(self.remote_name, model.remotes) self.remote_name.editingFinished.connect(self.remote_name_edited) self.remote_name.textEdited.connect(lambda x: self.remote_name_edited()) self.remotes = QtWidgets.QListWidget() if action == PUSH: mode = QtWidgets.QAbstractItemView.ExtendedSelection self.remotes.setSelectionMode(mode) self.remotes.addItems(model.remotes) self.remote_branch_label = QtWidgets.QLabel() self.remote_branch_label.setText(N_('Remote Branch')) self.remote_branch = QtWidgets.QLineEdit() remote_branches = strip_remotes(model.remote_branches) qtutils.add_completer(self.remote_branch, remote_branches) self.remote_branches = QtWidgets.QListWidget() self.remote_branches.addItems(model.remote_branches) text = N_('Prompt on creation') tooltip = N_('Prompt when pushing creates new remote branches') self.prompt_checkbox = qtutils.checkbox( checked=True, text=text, tooltip=tooltip ) text = N_('Show remote messages') tooltip = N_('Display remote messages in a separate dialog') self.remote_messages_checkbox = qtutils.checkbox( checked=False, text=text, tooltip=tooltip ) text = N_('Fast-forward only') tooltip = N_( 'Refuse to merge unless the current HEAD is already up-' 'to-date or the merge can be resolved as a fast-forward' ) self.ff_only_checkbox = qtutils.checkbox( checked=True, text=text, tooltip=tooltip ) text = N_('No fast-forward') tooltip = N_( 'Create a merge commit even when the merge resolves as a fast-forward' ) self.no_ff_checkbox = qtutils.checkbox( checked=False, text=text, tooltip=tooltip ) text = N_('Force') tooltip = N_( 'Allow non-fast-forward updates. Using "force" can ' 'cause the remote repository to lose commits; ' 'use it with care' ) self.force_checkbox = qtutils.checkbox( checked=False, text=text, tooltip=tooltip ) self.tags_checkbox = qtutils.checkbox(text=N_('Include tags ')) tooltip = N_( 'Remove remote-tracking branches that no longer exist on the remote' ) self.prune_checkbox = qtutils.checkbox(text=N_('Prune '), tooltip=tooltip) tooltip = N_('Rebase the current branch instead of merging') self.rebase_checkbox = qtutils.checkbox(text=N_('Rebase'), tooltip=tooltip) text = N_('Set upstream') tooltip = N_('Configure the remote branch as the the new upstream') self.upstream_checkbox = qtutils.checkbox(text=text, tooltip=tooltip) text = N_('Close on completion') tooltip = N_('Close dialog when completed') self.close_on_completion_checkbox = qtutils.checkbox( checked=True, text=text, tooltip=tooltip ) self.action_button = qtutils.ok_button(title, icon=icon) self.close_button = qtutils.close_button() self.buttons_group = utils.Group(self.close_button, self.action_button) self.inputs_group = utils.Group( self.close_on_completion_checkbox, self.force_checkbox, self.ff_only_checkbox, self.local_branch, self.local_branches, self.tags_checkbox, self.prune_checkbox, self.rebase_checkbox, self.remote_name, self.remotes, self.remote_branch, self.remote_branches, self.upstream_checkbox, self.prompt_checkbox, self.remote_messages_checkbox, ) self.progress = standard.progress_bar( self, disable=(self.buttons_group, self.inputs_group), ) self.local_branch_layout = qtutils.hbox( defs.small_margin, defs.spacing, self.local_label, self.local_branch ) self.remote_layout = qtutils.hbox( defs.small_margin, defs.spacing, self.remote_label, self.remote_name ) self.remote_branch_layout = qtutils.hbox( defs.small_margin, defs.spacing, self.remote_branch_label, self.remote_branch, ) self.options_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.force_checkbox, self.ff_only_checkbox, self.no_ff_checkbox, self.tags_checkbox, self.prune_checkbox, self.rebase_checkbox, self.upstream_checkbox, self.prompt_checkbox, self.close_on_completion_checkbox, self.remote_messages_checkbox, qtutils.STRETCH, self.progress, self.close_button, self.action_button, ) self.remote_input_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.remote_layout, self.remotes ) self.local_branch_input_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.local_branch_layout, self.local_branches ) self.remote_branch_input_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.remote_branch_layout, self.remote_branches, ) if action == PUSH: widgets = ( self.remote_input_layout, self.local_branch_input_layout, self.remote_branch_input_layout, ) else: # fetch and pull widgets = ( self.remote_input_layout, self.remote_branch_input_layout, self.local_branch_input_layout, ) self.top_layout = qtutils.hbox(defs.no_margin, defs.spacing, *widgets) self.main_layout = qtutils.vbox( defs.margin, defs.spacing, self.top_layout, self.options_layout ) self.setLayout(self.main_layout) default_remote = get_default_remote(context) remotes = model.remotes if default_remote in remotes: idx = remotes.index(default_remote) if self.select_remote(idx): self.set_remote_name(default_remote) else: if self.select_first_remote(): self.set_remote_name(remotes[0]) # Trim the remote list to just the default remote self.update_remotes() self.set_field_defaults() # Setup signals and slots self.remotes.itemSelectionChanged.connect(self.update_remotes) local = self.local_branches local.itemSelectionChanged.connect(self.update_local_branches) remote = self.remote_branches remote.itemSelectionChanged.connect(self.update_remote_branches) self.no_ff_checkbox.toggled.connect( lambda x: uncheck(x, self.ff_only_checkbox, self.rebase_checkbox) ) self.ff_only_checkbox.toggled.connect( lambda x: uncheck(x, self.no_ff_checkbox, self.rebase_checkbox) ) self.rebase_checkbox.toggled.connect( lambda x: uncheck(x, self.no_ff_checkbox, self.ff_only_checkbox) ) 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' ) if action != FETCH: self.prune_checkbox.hide() if action != PUSH: # Push-only options self.upstream_checkbox.hide() self.prompt_checkbox.hide() if action == PULL: # Fetch and Push-only options self.force_checkbox.hide() self.tags_checkbox.hide() self.local_label.hide() self.local_branch.hide() self.local_branches.hide() else: # Pull-only options self.rebase_checkbox.hide() self.no_ff_checkbox.hide() self.ff_only_checkbox.hide() self.init_size(parent=parent) def set_rebase(self, value): """Check the rebase checkbox""" self.rebase_checkbox.setChecked(value) def set_field_defaults(self): """Set sensible initial defaults""" # Default to "git fetch origin main" action = self.action if action in (FETCH, 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): """Set the remote name""" self.remote_name.setText(remote_name) def set_local_branch(self, branch): """Set the local branch name""" self.local_branch.setText(branch) if branch: self.local_branch.selectAll() def set_remote_branch(self, branch): """Set the remote branch name""" self.remote_branch.setText(branch) if branch: self.remote_branch.selectAll() def set_remote_branches(self, branches): """Set the list of remote branches""" self.remote_branches.clear() self.remote_branches.addItems(branches) self.filtered_remote_branches = branches qtutils.add_completer(self.remote_branch, strip_remotes(branches)) def select_first_remote(self): """Select the first remote in the list view""" return self.select_remote(0) def select_remote(self, idx): """Select a remote by index""" item = self.remotes.item(idx) if item: item.setSelected(True) self.remotes.setCurrentItem(item) self.set_remote_name(item.text()) result = True else: result = False return result def select_remote_by_name(self, remote): """Select a remote by name""" remotes = self.model.remotes if remote in remotes: idx = remotes.index(remote) result = self.select_remote(idx) else: result = False return result def set_selected_remotes(self, remotes): """Set the list of selected remotes Return True if all remotes were found and selected. """ # Invalid remote names are ignored. # This handles a remote going away between sessions. # The selection is unchanged when none of the specified remotes exist. found = False for remote in remotes: if remote in self.model.remotes: found = True break if found: # Only clear the selection if the specified remotes exist self.remotes.clearSelection() found = all(self.select_remote_by_name(x) for x in remotes) return found def select_local_branch(self, idx): """Selects a local branch by index in the list view""" item = self.local_branches.item(idx) if item: item.setSelected(True) self.local_branches.setCurrentItem(item) self.local_branch.setText(item.text()) result = True else: result = False return result 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 = '{}\t({})'.format(remote_name, N_('URL: %s') % url) displayed.append(display) qtutils.set_items(widget, displayed) def update_remotes(self): """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) self.set_remote_to(selection, self.selected_remotes) def set_remote_to(self, _remote, selected_remotes): context = self.context all_branches = gitcmds.branch_list(context, remote=True) branches = [] patterns = [] for remote_name in selected_remotes: patterns.append(remote_name + '/*') 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 remote_name_edited(self): """Update the current remote when the remote name is typed manually""" remote = self.remote_name.text() self.set_remote_to(remote, [remote]) def update_local_branches(self): """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): """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/pull""" remote_name = self.remote_name.text() local_branch = self.local_branch.text() remote_branch = self.remote_branch.text() ff_only = get(self.ff_only_checkbox) force = get(self.force_checkbox) no_ff = get(self.no_ff_checkbox) rebase = get(self.rebase_checkbox) set_upstream = get(self.upstream_checkbox) tags = get(self.tags_checkbox) prune = get(self.prune_checkbox) return ( remote_name, { 'ff_only': ff_only, 'force': force, 'local_branch': local_branch, 'no_ff': no_ff, 'rebase': rebase, 'remote_branch': remote_branch, 'set_upstream': set_upstream, 'tags': tags, 'prune': prune, }, ) # Actions def push_to_all(self, _remote, *args, **kwargs): """Push to all selected remotes""" 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_callback(self): """Perform the actual fetch/push/pull operation""" action = self.action remote_messages = get(self.remote_messages_checkbox) 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 = 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 = self.remote_branch.text() local_branch = self.local_branch.text() if action == PUSH and not remote_branch: branch = local_branch candidate = f'{remote}/{branch}' prompt = get(self.prompt_checkbox) if prompt and candidate not in self.model.remote_branches: title = N_('Push') args = { '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 Interaction.confirm( title, msg, info_txt, ok_text, icon=icons.cola() ): return if get(self.force_checkbox): 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 return if not Interaction.confirm( title, msg, info_txt, ok_text, default=False, icon=icons.discard() ): return self.progress.setMaximumHeight( self.action_button.height() - defs.small_margin * 2 ) # Use a thread to update in the background task = ActionTask(model_action, remote, kwargs) if remote_messages: result = log.show_remote_messages(self, self.context) else: result = None self.runtask.start( task, progress=self.progress, finish=self.action_completed, result=result, ) def action_completed(self, task): """Grab the results of the action and finish up""" if not task.result or not isinstance(task.result, (list, tuple)): return status, out, err = task.result command = 'git %s' % self.action.lower() message = Interaction.format_command_status(command, status) details = Interaction.format_out_err(out, err) log_message = message if details: log_message += '\n\n' + details Interaction.log(log_message) if status == 0: close_on_completion = get(self.close_on_completion_checkbox) if close_on_completion: 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) def export_state(self): """Export persistent settings""" state = standard.Dialog.export_state(self) state['close_on_completion'] = get(self.close_on_completion_checkbox) state['remote_messages'] = get(self.remote_messages_checkbox) return state def apply_state(self, state): """Apply persistent settings""" result = standard.Dialog.apply_state(self, state) # Restore the "close on completion" checkbox close_on_completion = bool(state.get('close_on_completion', True)) self.close_on_completion_checkbox.setChecked(close_on_completion) # Restore the "show remote messages" checkbox remote_messages = bool(state.get('remote_messages', False)) self.remote_messages_checkbox.setChecked(remote_messages) return result # Use distinct classes so that each saves its own set of preferences class Fetch(RemoteActionDialog): """Fetch from remote repositories""" def __init__(self, context, parent=None): super().__init__(context, FETCH, N_('Fetch'), parent=parent, icon=icons.repo()) def export_state(self): """Export persistent settings""" state = RemoteActionDialog.export_state(self) state['tags'] = get(self.tags_checkbox) state['prune'] = get(self.prune_checkbox) return state def apply_state(self, state): """Apply persistent settings""" result = RemoteActionDialog.apply_state(self, state) tags = bool(state.get('tags', False)) self.tags_checkbox.setChecked(tags) prune = bool(state.get('prune', False)) self.prune_checkbox.setChecked(prune) return result class Push(RemoteActionDialog): """Push to remote repositories""" def __init__(self, context, parent=None): super().__init__(context, PUSH, N_('Push'), parent=parent, icon=icons.push()) def export_state(self): """Export persistent settings""" state = RemoteActionDialog.export_state(self) state['prompt'] = get(self.prompt_checkbox) state['tags'] = get(self.tags_checkbox) return state def apply_state(self, state): """Apply persistent settings""" result = RemoteActionDialog.apply_state(self, state) # Restore the "prompt on creation" checkbox prompt = bool(state.get('prompt', True)) self.prompt_checkbox.setChecked(prompt) # Restore the "tags" checkbox tags = bool(state.get('tags', False)) self.tags_checkbox.setChecked(tags) return result class Pull(RemoteActionDialog): """Pull from remote repositories""" def __init__(self, context, parent=None): super().__init__(context, PULL, N_('Pull'), parent=parent, icon=icons.pull()) def apply_state(self, state): """Apply persistent settings""" result = RemoteActionDialog.apply_state(self, state) # Rebase has the highest priority rebase = bool(state.get('rebase', False)) self.rebase_checkbox.setChecked(rebase) ff_only = not rebase and bool(state.get('ff_only', False)) no_ff = not rebase and not ff_only and bool(state.get('no_ff', False)) self.no_ff_checkbox.setChecked(no_ff) # Allow users coming from older versions that have rebase=False to # pickup the new ff_only=True default by only setting ff_only False # when it either exists in the config or when rebase=True. if 'ff_only' in state or rebase: self.ff_only_checkbox.setChecked(ff_only) return result def export_state(self): """Export persistent settings""" state = RemoteActionDialog.export_state(self) state['ff_only'] = get(self.ff_only_checkbox) state['no_ff'] = get(self.no_ff_checkbox) state['rebase'] = get(self.rebase_checkbox) return state git-cola-4.6.1/cola/widgets/search.py000066400000000000000000000257021457126473700174520ustar00rootroot00000000000000"""A widget for searching git commits""" import time from qtpy import QtCore from qtpy import QtWidgets from qtpy.QtCore import Qt from ..i18n import N_ from ..interaction import Interaction from ..git import STDOUT from ..qtutils import connect_button from ..qtutils import create_toolbutton from ..qtutils import get from .. import core from .. import gitcmds from .. import icons from .. import utils from .. import qtutils from . import diff from . import defs from . import standard def mkdate(timespec): return '%04d-%02d-%02d' % time.localtime(timespec)[:3] class SearchOptions: def __init__(self): self.query = '' self.max_count = 500 self.start_date = '' self.end_date = '' class SearchWidget(standard.Dialog): def __init__(self, context, parent): standard.Dialog.__init__(self, parent) self.context = context self.setWindowTitle(N_('Search')) self.mode_combo = QtWidgets.QComboBox() self.browse_button = create_toolbutton( icon=icons.folder(), tooltip=N_('Browse...') ) self.query = QtWidgets.QLineEdit() self.start_date = QtWidgets.QDateEdit() self.start_date.setCurrentSection(QtWidgets.QDateTimeEdit.YearSection) self.start_date.setCalendarPopup(True) self.start_date.setDisplayFormat(N_('yyyy-MM-dd')) self.end_date = QtWidgets.QDateEdit() self.end_date.setCurrentSection(QtWidgets.QDateTimeEdit.YearSection) self.end_date.setCalendarPopup(True) self.end_date.setDisplayFormat(N_('yyyy-MM-dd')) icon = icons.search() self.search_button = qtutils.create_button( text=N_('Search'), icon=icon, default=True ) self.max_count = standard.SpinBox(value=500, mini=5, maxi=9995, step=5) self.commit_list = QtWidgets.QListWidget() self.commit_list.setMinimumSize(QtCore.QSize(10, 10)) self.commit_list.setAlternatingRowColors(True) selection_mode = QtWidgets.QAbstractItemView.SingleSelection self.commit_list.setSelectionMode(selection_mode) self.commit_text = diff.DiffTextEdit(context, self, whitespace=False) self.button_export = qtutils.create_button( text=N_('Export Patches'), icon=icons.diff() ) self.button_cherrypick = qtutils.create_button( text=N_('Cherry Pick'), icon=icons.cherry_pick() ) self.button_close = qtutils.close_button() self.top_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, self.query, self.start_date, self.end_date, self.browse_button, self.search_button, qtutils.STRETCH, self.mode_combo, self.max_count, ) self.splitter = qtutils.splitter( Qt.Vertical, self.commit_list, self.commit_text ) self.bottom_layout = qtutils.hbox( defs.no_margin, defs.spacing, qtutils.STRETCH, self.button_close, self.button_export, self.button_cherrypick, ) self.main_layout = qtutils.vbox( defs.margin, defs.spacing, self.top_layout, self.splitter, self.bottom_layout, ) self.setLayout(self.main_layout) self.init_size(parent=parent) def search(context): """Return a callback to handle various search actions.""" return search_commits(context, qtutils.active_window()) class SearchEngine: def __init__(self, context, model): self.context = context 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 self.validate(): return self.results() return [] def validate(self): return len(self.model.query) > 1 def revisions(self, *args, **kwargs): git = self.context.git 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(*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): git = self.context.git 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, context, model, parent): """ Search diffs and commit logs :param model: SearchOptions instance """ SearchWidget.__init__(self, context, 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') self.results = [] # 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.mode_combo.currentIndexChanged.connect(self.mode_changed) self.commit_list.itemSelectionChanged.connect(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_changed(self, _idx): mode = self.mode() self.update_shown_widgets(mode) if mode == self.PATH: self.browse_callback() def set_commits(self, commits): widget = self.commit_list widget.clear() widget.addItems(commits) def set_start_date(self, datestr): set_date(self.start_date, datestr) def set_end_date(self, datestr): set_date(self.end_date, datestr) 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 self.mode_combo.currentText() def search_callback(self, *args): engineclass = self.engines[self.mode()] self.model.query = get(self.query) self.model.max_count = get(self.max_count) self.model.start_date = get(self.start_date) self.model.end_date = get(self.end_date) self.results = engineclass(self.context, self.model).search() if self.results: self.display_results() else: self.commit_list.clear() self.commit_text.setText('') def browse_callback(self): paths = qtutils.open_files(N_('Choose Paths')) if not paths: return filepaths = [] curdir = core.getcwd() prefix_len = len(curdir) + 1 for path in paths: if not path.startswith(curdir): continue relpath = path[prefix_len:] if relpath: filepaths.append(relpath) query = core.list2cmdline(filepaths) self.query.setText(query) if query: self.search_callback() def display_results(self): commits = [result[1] for result in self.results] self.set_commits(commits) def selected_revision(self): result = qtutils.selected_item(self.commit_list, self.results) return result[0] if result else None def display(self, *args): context = self.context revision = self.selected_revision() if revision is None: self.commit_text.setText('') else: qtutils.set_clipboard(revision) diff_text = gitcmds.commit_diff(context, revision) self.commit_text.setText(diff_text) def export_patch(self): context = self.context revision = self.selected_revision() if revision is not None: Interaction.log_status( *gitcmds.export_patchset(context, revision, revision) ) def cherry_pick(self): git = self.context.git revision = self.selected_revision() if revision is not None: Interaction.log_status(*git.cherry_pick(revision)) def set_date(widget, datestr): fmt = Qt.ISODate date = QtCore.QDate.fromString(datestr, fmt) if date: widget.setDate(date) def search_commits(context, parent): opts = SearchOptions() widget = Search(context, opts, parent) widget.show() return widget git-cola-4.6.1/cola/widgets/selectcommits.py000066400000000000000000000141051457126473700210530ustar00rootroot00000000000000"""A GUI for selecting commits""" from qtpy import QtWidgets from qtpy.QtCore import Qt from .. import gitcmds from .. import qtutils from ..i18n import N_ from ..icons import folder from ..interaction import Interaction from ..models import prefs from . import completion from . import defs from .diff import DiffTextEdit from .standard import Dialog def select_commits(context, title, revs, summaries, multiselect=True): """Use the SelectCommits to select commits from a list.""" model = Model(revs, summaries) parent = qtutils.active_window() dialog = SelectCommits(context, model, parent, title, multiselect=multiselect) return dialog.select_commits() def select_commits_and_output(context, title, revs, summaries, multiselect=True): """Select commits from a list and output path""" model = Model(revs, summaries) parent = qtutils.active_window() dialog = SelectCommitsAndOutput( context, model, parent, title, multiselect=multiselect ) return dialog.select_commits_and_output() class Model: def __init__(self, revs, summaries): self.revisions = revs self.summaries = summaries class SelectCommits(Dialog): def __init__(self, context, model, parent=None, title=None, multiselect=True): Dialog.__init__(self, parent) self.context = context self.model = model if title: self.setWindowTitle(title) if multiselect: mode = QtWidgets.QAbstractItemView.ExtendedSelection else: mode = QtWidgets.QAbstractItemView.SingleSelection commits = self.commits = QtWidgets.QListWidget() commits.setSelectionMode(mode) commits.setAlternatingRowColors(True) self.commit_text = DiffTextEdit(context, self, whitespace=False) self.revision_label = QtWidgets.QLabel() self.revision_label.setText(N_('Revision Expression:')) self.revision = completion.GitRefLineEdit(context) self.revision.setReadOnly(True) self.search_label = QtWidgets.QLabel() self.search_label.setText(N_('Search:')) self.search = QtWidgets.QLineEdit() self.search.setReadOnly(False) self.search.textChanged.connect(self.search_list) self.select_button = qtutils.ok_button(N_('Select'), enabled=False) # Make the list widget slightly larger self.splitter = qtutils.splitter(Qt.Vertical, self.commits, self.commit_text) self.splitter.setSizes([100, 150]) self.input_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.search_label, self.search, qtutils.STRETCH, self.revision_label, self.revision, self.select_button, ) self.main_layout = qtutils.vbox( defs.margin, defs.margin, self.input_layout, self.splitter ) self.setLayout(self.main_layout) commits.itemSelectionChanged.connect(self.commit_oid_selected) commits.itemDoubleClicked.connect(self.commit_oid_double_clicked) qtutils.connect_button(self.select_button, self.accept) self.init_state(None, self.resize_widget, parent) def resize_widget(self, parent): """Set the initial size of the widget""" width, height = qtutils.default_size(parent, 720, 480) self.resize(width, height) def selected_commit(self): return qtutils.selected_item(self.commits, self.model.revisions) def selected_commits(self): return qtutils.selected_items(self.commits, self.model.revisions) 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.commits, summaries) self.show() if self.exec_() != QtWidgets.QDialog.Accepted: return [] return self.selected_commits() def commit_oid_selected(self): context = self.context oid = self.selected_commit() selected = oid is not None self.select_button.setEnabled(selected) if not selected: self.commit_text.set_value('') self.revision.setText('') return self.revision.setText(oid) self.revision.selectAll() # Display the oid's commit commit_diff = gitcmds.commit_diff(context, oid) self.commit_text.setText(commit_diff) def commit_oid_double_clicked(self, _item): oid = self.selected_commit() if oid: self.accept() def search_list(self, text): if text: for i in range(self.commits.count()): self.commits.item(i).setHidden(True) search_items = self.commits.findItems(text, Qt.MatchContains) for items in search_items: items.setHidden(False) class SelectCommitsAndOutput(SelectCommits): def __init__(self, context, model, parent=None, title=None, multiselect=True): SelectCommits.__init__(self, context, model, parent, title, multiselect) self.output_dir = prefs.patches_directory(context) self.select_output = qtutils.create_button( tooltip=N_('Select output dir'), icon=folder() ) self.output_text = QtWidgets.QLineEdit() self.output_text.setReadOnly(True) self.output_text.setText(self.output_dir) output_layout = qtutils.hbox( defs.no_margin, defs.no_spacing, self.select_output, self.output_text ) self.input_layout.insertLayout(1, output_layout) qtutils.connect_button(self.select_output, self.show_output_dialog) def select_commits_and_output(self): to_export = SelectCommits.select_commits(self) output = self.output_dir return {'to_export': to_export, 'output': output} def show_output_dialog(self): self.output_dir = qtutils.opendir_dialog( N_('Select output directory'), self.output_dir ) if not self.output_dir: return self.output_text.setText(self.output_dir) git-cola-4.6.1/cola/widgets/spellcheck.py000066400000000000000000000174731457126473700203300ustar00rootroot00000000000000import re from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from .. import qtutils from .. import spellcheck from ..i18n import N_ from .text import HintedTextEdit class SpellCheckTextEdit(HintedTextEdit): def __init__(self, context, hint, check=None, parent=None): HintedTextEdit.__init__(self, context, hint, parent) # Default dictionary based on the current locale. self.spellcheck = check or 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 = QtGui.QMouseEvent( QtCore.QEvent.MouseButtonPress, event.pos(), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier, ) HintedTextEdit.mousePressEvent(self, event) def create_context_menu(self, event_pos): popup_menu = super().create_context_menu(event_pos) # Check if the selected word is misspelled and offer spelling # suggestions if it is. spell_menu = None if self.textCursor().hasSelection(): text = self.textCursor().selectedText() if not self.spellcheck.check(text): title = N_('Spelling Suggestions') spell_menu = qtutils.create_menu(title, self) for word in self.spellcheck.suggest(text): action = SpellAction(word, spell_menu) action.result.connect(self.correct) spell_menu.addAction(action) # Only add the spelling suggests to the menu if there are # suggestions. if spell_menu.actions(): popup_menu.addSeparator() popup_menu.addMenu(spell_menu) return popup_menu def contextMenuEvent(self, event): """Select the current word and then show a context menu""" # Select the word under the cursor before calling the default contextMenuEvent. cursor = self.textCursor() cursor.select(QtGui.QTextCursor.WordUnderCursor) self.setTextCursor(cursor) super().contextMenuEvent(event) def correct(self, word): """Replaces the selected text with word.""" cursor = self.textCursor() cursor.beginEditBlock() cursor.removeSelectedText() cursor.insertText(word) cursor.endEditBlock() class SpellCheckLineEdit(SpellCheckTextEdit): """A fake QLineEdit that provides spellcheck capabilities This class emulates QLineEdit using our QPlainTextEdit base class so that we can leverage the existing spellcheck feature. """ down_pressed = QtCore.Signal() # This widget is a single-line QTextEdit as described in # http://blog.ssokolow.com/archives/2022/07/22/a-qlineedit-replacement-with-spell-checking/ def __init__(self, context, hint, check=None, parent=None): super().__init__(context, hint, check=check, parent=parent) self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setWordWrapMode(QtGui.QTextOption.NoWrap) self.setTabChangesFocus(True) self.textChanged.connect(self._trim_changed_text_lines) def focusInEvent(self, event): """Select text when entering with a tab to mimic QLineEdit""" super().focusInEvent(event) if event.reason() in ( Qt.BacktabFocusReason, Qt.ShortcutFocusReason, Qt.TabFocusReason, ): self.selectAll() def focusOutEvent(self, event): """De-select text when exiting with tab to mimic QLineEdit""" super().focusOutEvent(event) if event.reason() in ( Qt.BacktabFocusReason, Qt.MouseFocusReason, Qt.ShortcutFocusReason, Qt.TabFocusReason, ): cur = self.textCursor() cur.movePosition(QtGui.QTextCursor.End) self.setTextCursor(cur) def keyPressEvent(self, event): """Handle the up/down arrow keys""" event_key = event.key() if event_key == Qt.Key_Up: cursor = self.textCursor() if cursor.position() == 0: cursor.clearSelection() else: if event.modifiers() & Qt.ShiftModifier: mode = QtGui.QTextCursor.KeepAnchor else: mode = QtGui.QTextCursor.MoveAnchor cursor.setPosition(0, mode) self.setTextCursor(cursor) return if event_key == Qt.Key_Down: cursor = self.textCursor() cur_position = cursor.position() end_position = len(self.value()) if cur_position == end_position: cursor.clearSelection() self.setTextCursor(cursor) self.down_pressed.emit() else: if event.modifiers() & Qt.ShiftModifier: mode = QtGui.QTextCursor.KeepAnchor else: mode = QtGui.QTextCursor.MoveAnchor cursor.setPosition(end_position, mode) self.setTextCursor(cursor) return super().keyPressEvent(event) def minimumSizeHint(self): """Match QLineEdit's size behavior""" block_fmt = self.document().firstBlock().blockFormat() width = super().minimumSizeHint().width() height = int( QtGui.QFontMetricsF(self.font()).lineSpacing() + block_fmt.topMargin() + block_fmt.bottomMargin() + self.document().documentMargin() + 2 * self.frameWidth() ) style_opts = QtWidgets.QStyleOptionFrame() style_opts.initFrom(self) style_opts.lineWidth = self.frameWidth() return self.style().sizeFromContents( QtWidgets.QStyle.CT_LineEdit, style_opts, QtCore.QSize(width, height), self ) def sizeHint(self): """Use the minimum size as the sizeHint()""" return self.minimumSizeHint() def _trim_changed_text_lines(self): """Trim the document to a single line to enforce a maximum of one line""" # self.setMaximumBlockCount(1) Undo/Redo. if self.document().blockCount() > 1: self.document().setPlainText(self.document().firstBlock().text()) class Highlighter(QtGui.QSyntaxHighlighter): WORDS = r"(?iu)[\w']+" def __init__(self, doc, spellcheck_widget): QtGui.QSyntaxHighlighter.__init__(self, doc) self.spellcheck = spellcheck_widget self.enabled = False def enable(self, enabled): self.enabled = enabled self.rehighlight() def highlightBlock(self, text): if not self.enabled: return fmt = QtGui.QTextCharFormat() fmt.setUnderlineColor(Qt.red) fmt.setUnderlineStyle(QtGui.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(QtWidgets.QAction): """QAction that returns the text in a signal.""" result = QtCore.Signal(object) def __init__(self, *args): QtWidgets.QAction.__init__(self, *args) self.triggered.connect(self.correct) def correct(self): self.result.emit(self.text()) git-cola-4.6.1/cola/widgets/standard.py000066400000000000000000001110351457126473700200000ustar00rootroot00000000000000from functools import partial import os import time from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from qtpy.QtWidgets import QDockWidget from ..i18n import N_ from ..interaction import Interaction from ..settings import Settings, mklist from ..models import prefs from .. import core from .. import hotkeys from .. import icons from .. import qtcompat from .. import qtutils from .. import utils from . import defs class WidgetMixin: """Mix-in for common utilities and serialization of widget state""" closed = Signal(QtWidgets.QWidget) def __init__(self): self._unmaximized_rect = {} def center(self): parent = self.parent() if parent is None: return left = parent.x() width = parent.width() center_x = left + width // 2 x = center_x - self.width() // 2 y = parent.y() self.move(x, y) def resize_to_desktop(self): width, height = qtutils.desktop_size() if utils.is_darwin(): self.resize(width, height) else: shown = self.isVisible() # earlier show() fools Windows focus stealing prevention. The main # window is blocked for the duration of "git rebase" and we don't # want to present a blocked window with git-cola-sequence-editor # hidden somewhere. self.show() self.setWindowState(Qt.WindowMaximized) if not shown: self.hide() def name(self): """Returns the name of the view class""" return self.__class__.__name__.lower() def save_state(self, settings=None): save = True context = getattr(self, 'context', None) if context: cfg = context.cfg save = cfg.get('cola.savewindowsettings', default=True) if save: if settings is None: settings = Settings.read() settings.save_gui_state(self) def restore_state(self, settings=None): if settings is None: settings = Settings.read() state = settings.get_gui_state(self) if state: result = self.apply_state(state) else: result = False return result def apply_state(self, state): """Imports data for view save/restore""" width = utils.asint(state.get('width')) height = utils.asint(state.get('height')) x = utils.asint(state.get('x')) y = utils.asint(state.get('y')) geometry = state.get('geometry', '') if geometry: from_base64 = QtCore.QByteArray.fromBase64 result = self.restoreGeometry(from_base64(core.encode(geometry))) elif width and height: # Users migrating from older versions won't have 'geometry'. # They'll be upgraded to the new format on shutdown. self.resize(width, height) self.move(x, y) result = True else: result = False return result def export_state(self): """Exports data for view save/restore""" state = {} geometry = self.saveGeometry() state['geometry'] = geometry.toBase64().data().decode('ascii') # Until 2020: co-exist with older versions state['width'] = self.width() state['height'] = self.height() state['x'] = self.x() state['y'] = self.y() return state def save_settings(self, settings=None): return self.save_state(settings=settings) def closeEvent(self, event): self.save_settings() self.closed.emit(self) self.Base.closeEvent(self, event) def init_size(self, parent=None, settings=None, width=0, height=0): if not width: width = defs.dialog_w if not height: height = defs.dialog_h self.init_state(settings, self.resize_to_parent, parent, width, height) def init_state(self, settings, callback, *args, **kwargs): """Restore saved settings or set the initial location""" if not self.restore_state(settings=settings): callback(*args, **kwargs) self.center() def resize_to_parent(self, parent, w, h): """Set the initial size of the widget""" width, height = qtutils.default_size(parent, w, h) self.resize(width, height) class MainWindowMixin(WidgetMixin): def __init__(self): WidgetMixin.__init__(self) # Dockwidget options self.dockwidgets = [] self.lock_layout = False self.widget_version = 0 qtcompat.set_common_dock_options(self) self.default_state = None def init_state(self, settings, callback, *args, **kwargs): """Save the initial state before calling the parent initializer""" self.default_state = self.saveState(self.widget_version) super().init_state(settings, callback, *args, **kwargs) def export_state(self): """Exports data for save/restore""" state = WidgetMixin.export_state(self) windowstate = self.saveState(self.widget_version) state['lock_layout'] = self.lock_layout state['windowstate'] = windowstate.toBase64().data().decode('ascii') return state def save_settings(self, settings=None): if settings is None: context = getattr(self, 'context', None) if context is None: settings = Settings.read() else: settings = context.settings settings.load() settings.add_recent(core.getcwd(), prefs.maxrecent(context)) return WidgetMixin.save_settings(self, settings=settings) def apply_state(self, state): result = WidgetMixin.apply_state(self, state) windowstate = state.get('windowstate', '') if windowstate: from_base64 = QtCore.QByteArray.fromBase64 result = ( self.restoreState( from_base64(core.encode(windowstate)), self.widget_version ) and result ) else: result = False self.lock_layout = state.get('lock_layout', self.lock_layout) self.update_dockwidget_lock_state() self.update_dockwidget_tooltips() return result def reset_layout(self): self.restoreState(self.default_state, self.widget_version) 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 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 ListWidget(QtWidgets.QListWidget): """QListWidget with vim j/k navigation hotkeys""" def __init__(self, parent=None): super().__init__(parent) self.up_action = qtutils.add_action( self, N_('Move Up'), self.move_up, hotkeys.MOVE_UP, hotkeys.MOVE_UP_SECONDARY, ) self.down_action = qtutils.add_action( self, N_('Move Down'), self.move_down, hotkeys.MOVE_DOWN, hotkeys.MOVE_DOWN_SECONDARY, ) def selected_item(self): return self.currentItem() def selected_items(self): return self.selectedItems() def move_up(self): self.move(-1) def move_down(self): self.move(1) def move(self, direction): item = self.selected_item() if item: row = (self.row(item) + direction) % self.count() elif self.count() > 0: row = (self.count() + direction) % self.count() else: return new_item = self.item(row) if new_item: self.setCurrentItem(new_item) class TreeMixin: def __init__(self, widget, Base): self.widget = widget self.Base = Base widget.setAlternatingRowColors(True) widget.setUniformRowHeights(True) widget.setAllColumnsShowFocus(True) widget.setAnimated(True) widget.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. widget = self.widget index = widget.currentIndex() was_expanded = widget.isExpanded(index) was_collapsed = not was_expanded # Vim keybindings... event = _create_vim_navigation_key_event(event) # Read the updated event key to take the mappings into account key = event.key() if key == Qt.Key_Up: idxs = widget.selectedIndexes() rows = [idx.row() for idx in idxs] if len(rows) == 1 and rows[0] == 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. widget.up.emit() elif key == Qt.Key_Space: widget.space.emit() result = self.Base.keyPressEvent(widget, event) # Let others hook in here before we change the indexes widget.index_about_to_change.emit() # Automatically select the first entry when expanding a directory if key == Qt.Key_Right and was_collapsed and widget.isExpanded(index): index = widget.moveCursor(widget.MoveDown, event.modifiers()) widget.setCurrentIndex(index) # Process non-root entries with valid parents only. elif key == Qt.Key_Left and index.parent().isValid(): # File entries have rowCount() == 0 model = widget.model() if hasattr(model, 'itemFromIndex'): item = model.itemFromIndex(index) if hasattr(item, 'rowCount') and item.rowCount() == 0: widget.setCurrentIndex(index.parent()) # Otherwise, do this for collapsed directories only elif was_collapsed: widget.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 = widget.model().index(0, 0, QtCore.QModelIndex()) if index.isValid(): widget.setCurrentIndex(index) return result def item_from_index(self, item): """Return a QModelIndex from the provided item""" if hasattr(self, 'itemFromIndex'): index = self.itemFromIndex(item) else: index = self.model().itemFromIndex() return index def items(self): root = self.widget.invisibleRootItem() child = root.child count = root.childCount() return [child(i) for i in range(count)] def selected_items(self): """Return all selected items""" widget = self.widget if hasattr(widget, 'selectedItems'): return widget.selectedItems() if hasattr(widget, 'itemFromIndex'): item_from_index = widget.itemFromIndex else: item_from_index = widget.model().itemFromIndex return [item_from_index(i) for i in widget.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 current_item(self): item = None widget = self.widget if hasattr(widget, 'currentItem'): item = widget.currentItem() else: index = widget.currentIndex() if index.isValid(): item = widget.model().itemFromIndex(index) return item def column_widths(self): """Return the tree's column widths""" widget = self.widget count = widget.header().count() return [widget.columnWidth(i) for i in range(count)] def set_column_widths(self, widths): """Set the tree's column widths""" if widths: widget = self.widget count = widget.header().count() if len(widths) > count: widths = widths[:count] for idx, value in enumerate(widths): widget.setColumnWidth(idx, value) def _create_vim_navigation_key_event(event): """Support minimal Vim-like keybindings by rewriting the QKeyEvents""" 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()) return event class DraggableTreeMixin(TreeMixin): """A tree widget with internal drag+drop reordering of rows Expects that the widget provides an `items_moved` signal. """ def __init__(self, widget, Base): super().__init__(widget, Base) self._inner_drag = False widget.setAcceptDrops(True) widget.setSelectionMode(widget.SingleSelection) widget.setDragEnabled(True) widget.setDropIndicatorShown(True) widget.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove) widget.setSortingEnabled(False) def dragEnterEvent(self, event): """Accept internal drags only""" widget = self.widget self.Base.dragEnterEvent(widget, event) self._inner_drag = event.source() == widget if self._inner_drag: event.acceptProposedAction() else: event.ignore() def dragLeaveEvent(self, event): widget = self.widget self.Base.dragLeaveEvent(widget, event) if self._inner_drag: event.accept() else: event.ignore() self._inner_drag = False def dropEvent(self, event): """Re-select selected items after an internal move""" if not self._inner_drag: event.ignore() return widget = self.widget clicked_items = self.selected_items() event.setDropAction(Qt.MoveAction) self.Base.dropEvent(widget, event) if clicked_items: widget.clearSelection() for item in clicked_items: item.setSelected(True) widget.items_moved.emit(clicked_items) self._inner_drag = False event.accept() # must be called after dropEvent() def mousePressEvent(self, event): """Clear the selection when a mouse click hits no item""" widget = self.widget clicked_item = widget.itemAt(event.pos()) if clicked_item is None: widget.clearSelection() return self.Base.mousePressEvent(widget, event) class Widget(WidgetMixin, QtWidgets.QWidget): Base = QtWidgets.QWidget def __init__(self, parent=None): QtWidgets.QWidget.__init__(self, parent) WidgetMixin.__init__(self) class Dialog(WidgetMixin, QtWidgets.QDialog): Base = QtWidgets.QDialog def __init__(self, parent=None): QtWidgets.QDialog.__init__(self, parent) WidgetMixin.__init__(self) # Disable the Help button hint on Windows if hasattr(Qt, 'WindowContextHelpButtonHint'): help_hint = Qt.WindowContextHelpButtonHint flags = self.windowFlags() & ~help_hint self.setWindowFlags(flags) def accept(self): self.save_settings() self.dispose() return self.Base.accept(self) def reject(self): self.save_settings() self.dispose() return self.Base.reject(self) def dispose(self): """Extension method for model de-registration in sub-classes""" return def close(self): """save_settings() is handled by accept() and reject()""" self.dispose() self.Base.close(self) def closeEvent(self, event): """save_settings() is handled by accept() and reject()""" self.dispose() self.Base.closeEvent(self, event) class MainWindow(MainWindowMixin, QtWidgets.QMainWindow): Base = QtWidgets.QMainWindow def __init__(self, parent=None): QtWidgets.QMainWindow.__init__(self, parent) MainWindowMixin.__init__(self) class TreeView(QtWidgets.QTreeView): Mixin = TreeMixin up = Signal() space = Signal() index_about_to_change = Signal() def __init__(self, parent=None): QtWidgets.QTreeView.__init__(self, parent) self._mixin = self.Mixin(self, QtWidgets.QTreeView) def keyPressEvent(self, event): return self._mixin.keyPressEvent(event) def current_item(self): return self._mixin.current_item() def selected_item(self): return self._mixin.selected_item() def selected_items(self): return self._mixin.selected_items() def items(self): return self._mixin.items() def column_widths(self): return self._mixin.column_widths() def set_column_widths(self, widths): return self._mixin.set_column_widths(widths) class TreeWidget(QtWidgets.QTreeWidget): Mixin = TreeMixin up = Signal() space = Signal() index_about_to_change = Signal() def __init__(self, parent=None): super().__init__(parent) self._mixin = self.Mixin(self, QtWidgets.QTreeWidget) def keyPressEvent(self, event): return self._mixin.keyPressEvent(event) def current_item(self): return self._mixin.current_item() def selected_item(self): return self._mixin.selected_item() def selected_items(self): return self._mixin.selected_items() def items(self): return self._mixin.items() def column_widths(self): return self._mixin.column_widths() def set_column_widths(self, widths): return self._mixin.set_column_widths(widths) class DraggableTreeWidget(TreeWidget): Mixin = DraggableTreeMixin items_moved = Signal(object) def mousePressEvent(self, event): return self._mixin.mousePressEvent(event) def dropEvent(self, event): return self._mixin.dropEvent(event) def dragLeaveEvent(self, event): return self._mixin.dragLeaveEvent(event) def dragEnterEvent(self, event): return self._mixin.dragEnterEvent(event) class ProgressDialog(QtWidgets.QProgressDialog): """Custom progress dialog This dialog ignores the ESC key so that it is not prematurely closed. A thread is spawned to animate the progress label text. """ def __init__(self, title, label, parent): QtWidgets.QProgressDialog.__init__(self, parent) self._parent = parent if parent is not None: self.setWindowModality(Qt.WindowModal) self.animation_thread = ProgressAnimationThread(label, self) self.animation_thread.updated.connect(self.set_text, type=Qt.QueuedConnection) self.reset() self.setRange(0, 0) self.setMinimumDuration(0) self.setCancelButton(None) self.setFont(qtutils.default_monospace_font()) self.set_details(title, label) def set_details(self, title, label): """Update the window title and progress label""" self.setWindowTitle(title) self.setLabelText(label + ' ') self.animation_thread.set_text(label) def set_text(self, txt): """Set the label text""" self.setLabelText(txt) def keyPressEvent(self, event): """Customize keyPressEvent to remove the ESC key cancel feature""" if event.key() != Qt.Key_Escape: super().keyPressEvent(event) def start(self): """Start the animation thread and use a wait cursor""" self.show() QtWidgets.QApplication.setOverrideCursor(Qt.WaitCursor) self.animation_thread.start() def stop(self): """Stop the animation thread and restore the normal cursor""" self.animation_thread.stop() self.animation_thread.wait() QtWidgets.QApplication.restoreOverrideCursor() self.hide() class ProgressAnimationThread(QtCore.QThread): """Emits a pseudo-animated text stream for progress bars""" # The updated signal is emitted on each tick. updated = Signal(object) def __init__(self, txt, parent, sleep_time=0.1): QtCore.QThread.__init__(self, parent) self.running = False self.txt = txt self.sleep_time = sleep_time self.symbols = [ '. ..', '.. .', '... ', ' ... ', ' ...', ] self.idx = -1 def set_text(self, txt): """Set the text prefix""" self.txt = txt def tick(self): """Tick to the next animated text value""" self.idx = (self.idx + 1) % len(self.symbols) return self.txt + self.symbols[self.idx] def stop(self): """Stop the animation thread""" self.running = False def run(self): """Emit ticks until stopped""" self.running = True while self.running: self.updated.emit(self.tick()) time.sleep(self.sleep_time) class ProgressTickThread(QtCore.QThread): """Emits an int stream for progress bars""" # The updated signal emits progress tick values. updated = Signal(int) # The activated signal is emitted when the progress bar is displayed. activated = Signal() def __init__( self, parent, maximum, start_time=1.0, sleep_time=0.05, ): QtCore.QThread.__init__(self, parent) self.running = False self.sleep_time = sleep_time self.maximum = maximum self.start_time = start_time self.value = 0 self.step = 1 def tick(self): """Cycle to the next tick value Returned values are in the inclusive (0, maximum + 1) range. """ self.value = (self.value + self.step) % (self.maximum + 1) if self.value == self.maximum: self.step = -1 elif self.value == 0: self.step = 1 return self.value def stop(self): """Stop the tick thread and reset to the initial state""" self.running = False self.value = 0 self.step = 1 def run(self): """Start the tick thread The progress bar will not be activated until after the start_time interval has elapsed. """ initial_time = time.time() active = False self.running = True self.value = 0 self.step = 1 while self.running: if active: self.updated.emit(self.tick()) else: now = time.time() if self.start_time < (now - initial_time): active = True self.activated.emit() time.sleep(self.sleep_time) class SpinBox(QtWidgets.QSpinBox): def __init__( self, parent=None, value=None, mini=1, maxi=99999, step=0, prefix='', suffix='' ): QtWidgets.QSpinBox.__init__(self, parent) self.setPrefix(prefix) self.setSuffix(suffix) self.setWrapping(True) self.setMinimum(mini) self.setMaximum(maxi) if step: self.setSingleStep(step) if value is not None: self.setValue(value) text_width = qtutils.text_width(self.font(), 'MMMMMM') width = max(self.minimumWidth(), text_width) self.setMinimumWidth(width) class DirectoryPathLineEdit(QtWidgets.QWidget): """A combined line edit and file browser button""" def __init__(self, path, parent): QtWidgets.QWidget.__init__(self, parent) self.line_edit = QtWidgets.QLineEdit() self.line_edit.setText(path) self.browse_button = qtutils.create_button( tooltip=N_('Select directory'), icon=icons.folder() ) layout = qtutils.hbox( defs.no_margin, defs.spacing, self.browse_button, self.line_edit, ) self.setLayout(layout) qtutils.connect_button(self.browse_button, self._select_directory) def set_value(self, value): """Set the path value""" self.line_edit.setText(value) def value(self): """Return the current path value""" return self.line_edit.text().strip() def _select_directory(self): """Open a file browser and select a directory""" output_dir = qtutils.opendir_dialog(N_('Select directory'), self.value()) if not output_dir: return # Make the directory relative only if it the current directory or # or subdirectory from the current directory. current_dir = core.getcwd() if output_dir == current_dir: output_dir = '.' elif output_dir.startswith(current_dir + os.sep): output_dir = os.path.relpath(output_dir) self.set_value(output_dir) def export_header_columns(widget, state): """Save QHeaderView column sizes""" columns = [] header = widget.horizontalHeader() for idx in range(header.count()): columns.append(header.sectionSize(idx)) state['columns'] = columns def apply_header_columns(widget, state): """Apply QHeaderView column sizes""" columns = mklist(state.get('columns', [])) header = widget.horizontalHeader() if header.stretchLastSection(): # Setting the size will make the section wider than necessary, which # defeats the purpose of the stretch flag. Skip the last column when # it's stretchy so that it retains the stretchy behavior. columns = columns[:-1] for idx, size in enumerate(columns): header.resizeSection(idx, size) class MessageBox(Dialog): """Improved QMessageBox replacement QMessageBox has a lot of usability issues. It sometimes cannot be resized, and it brings along a lots of annoying properties that we'd have to workaround, so we use a simple custom dialog instead. """ def __init__( self, parent=None, title='', text='', info='', details='', logo=None, default=False, ok_icon=None, ok_text='', cancel_text=None, cancel_icon=None, ): Dialog.__init__(self, parent=parent) if parent: self.setWindowModality(Qt.WindowModal) if title: self.setWindowTitle(title) self.logo_label = QtWidgets.QLabel() if logo: # Render into a 1-inch wide pixmap pixmap = logo.pixmap(defs.large_icon) self.logo_label.setPixmap(pixmap) else: self.logo_label.hide() self.text_label = QtWidgets.QLabel() self.text_label.setText(text) self.info_label = QtWidgets.QLabel() if info: self.info_label.setText(info) else: self.info_label.hide() ok_icon = icons.mkicon(ok_icon, icons.ok) self.button_ok = qtutils.create_button(text=ok_text, icon=ok_icon) self.button_close = qtutils.close_button(text=cancel_text, icon=cancel_icon) if ok_text: self.button_ok.setText(ok_text) else: self.button_ok.hide() self.details_text = QtWidgets.QPlainTextEdit() self.details_text.setReadOnly(True) if details: self.details_text.setFont(qtutils.default_monospace_font()) self.details_text.setPlainText(details) else: self.details_text.hide() self.info_layout = qtutils.vbox( defs.large_margin, defs.button_spacing, self.text_label, self.info_label, qtutils.STRETCH, ) self.top_layout = qtutils.hbox( defs.large_margin, defs.button_spacing, self.logo_label, self.info_layout, qtutils.STRETCH, ) self.buttons_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, qtutils.STRETCH, self.button_close, self.button_ok, ) self.main_layout = qtutils.vbox( defs.margin, defs.button_spacing, self.top_layout, self.buttons_layout, self.details_text, ) self.main_layout.setStretchFactor(self.details_text, 2) self.setLayout(self.main_layout) if default: self.button_ok.setDefault(True) self.button_ok.setFocus() else: self.button_close.setDefault(True) self.button_close.setFocus() qtutils.connect_button(self.button_ok, self.accept) qtutils.connect_button(self.button_close, self.reject) self.init_state(None, self.set_initial_size) def set_initial_size(self): width = defs.dialog_w height = defs.msgbox_h self.resize(width, height) def keyPressEvent(self, event): """Handle Y/N hotkeys""" key = event.key() if key == Qt.Key_Y: QtCore.QTimer.singleShot(0, self.accept) elif key in (Qt.Key_N, Qt.Key_Q): QtCore.QTimer.singleShot(0, self.reject) elif key == Qt.Key_Tab: if self.button_ok.isVisible(): event.accept() if self.focusWidget() == self.button_close: self.button_ok.setFocus() else: self.button_close.setFocus() return Dialog.keyPressEvent(self, event) def run(self): self.show() return self.exec_() def apply_state(self, state): """Imports data for view save/restore""" desktop_width, desktop_height = qtutils.desktop_size() width = min(desktop_width, utils.asint(state.get('width'))) height = min(desktop_height, utils.asint(state.get('height'))) x = min(desktop_width, utils.asint(state.get('x'))) y = min(desktop_height, utils.asint(state.get('y'))) result = False if width and height: self.resize(width, height) self.move(x, y) result = True return result def export_state(self): """Exports data for view save/restore""" desktop_width, desktop_height = qtutils.desktop_size() state = {} state['width'] = min(desktop_width, self.width()) state['height'] = min(desktop_height, self.height()) state['x'] = min(desktop_width, self.x()) state['y'] = min(desktop_height, self.y()) return state def confirm( title, text, informative_text, ok_text, icon=None, default=True, cancel_text=None, cancel_icon=None, ): """Confirm that an action should take place""" cancel_text = cancel_text or N_('Cancel') logo = icons.from_style(QtWidgets.QStyle.SP_MessageBoxQuestion) mbox = MessageBox( parent=qtutils.active_window(), title=title, text=text, info=informative_text, ok_text=ok_text, ok_icon=icon, cancel_text=cancel_text, cancel_icon=cancel_icon, logo=logo, default=default, ) return mbox.run() == mbox.Accepted def critical(title, message=None, details=None): """Show a warning with the provided title and message.""" if message is None: message = title logo = icons.from_style(QtWidgets.QStyle.SP_MessageBoxCritical) mbox = MessageBox( parent=qtutils.active_window(), title=title, text=message, details=details, logo=logo, ) mbox.run() def command_error(title, cmd, status, out, err): """Report an error message about a failed command""" details = Interaction.format_out_err(out, err) message = Interaction.format_command_status(cmd, status) critical(title, message=message, details=details) 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 = MessageBox( parent=qtutils.active_window(), title=title, text=message, info=informative_text, details=details, logo=icons.cola(), ) mbox.run() def progress(title, text, parent): """Create a new ProgressDialog""" return ProgressDialog(title, text, parent) class ProgressBar(QtWidgets.QProgressBar): """An indeterminate progress bar with animated scrolling""" def __init__(self, parent, maximum, hide=(), disable=(), visible=False): super().__init__(parent) self.setTextVisible(False) self.setMaximum(maximum) if not visible: self.setVisible(False) self.progress_thread = ProgressTickThread(self, maximum) self.progress_thread.updated.connect(self.setValue, type=Qt.QueuedConnection) self.progress_thread.activated.connect(self.activate, type=Qt.QueuedConnection) self._widgets_to_hide = hide self._widgets_to_disable = disable def start(self): """Start the progress tick thread""" QtWidgets.QApplication.setOverrideCursor(Qt.WaitCursor) for widget in self._widgets_to_disable: widget.setEnabled(False) self.progress_thread.start() def activate(self): """Hide widgets and display the progress bar""" for widget in self._widgets_to_hide: widget.hide() self.show() def stop(self): """Stop the progress tick thread, re-enable and display widgets""" self.progress_thread.stop() self.progress_thread.wait() for widget in self._widgets_to_disable: widget.setEnabled(True) self.hide() for widget in self._widgets_to_hide: widget.show() QtWidgets.QApplication.restoreOverrideCursor() def progress_bar(parent, maximum=10, hide=(), disable=()): """Return a text-less progress bar""" widget = ProgressBar(parent, maximum, hide=hide, disable=disable) return widget def question(title, text, default=True, logo=None): """Launches a QMessageBox question with the provided title and message. Passing "default=False" will make "No" the default choice.""" parent = qtutils.active_window() if logo is None: logo = icons.from_style(QtWidgets.QStyle.SP_MessageBoxQuestion) msgbox = MessageBox( parent=parent, title=title, text=text, default=default, logo=logo, ok_text=N_('Yes'), cancel_text=N_('No'), ) return msgbox.run() == msgbox.Accepted def save_as(filename, title): return qtutils.save_as(filename, title=title) def async_command(title, cmd, runtask): task = qtutils.SimpleTask(partial(core.run_command, cmd)) task.connect(partial(async_command_result, title, cmd)) runtask.start(task) def async_command_result(title, cmd, result): status, out, err = result cmd_string = core.list2cmdline(cmd) Interaction.command(title, cmd_string, status, out, err) def install(): """Install the GUI-model interaction hooks""" Interaction.critical = staticmethod(critical) Interaction.confirm = staticmethod(confirm) Interaction.question = staticmethod(question) Interaction.information = staticmethod(information) Interaction.command_error = staticmethod(command_error) Interaction.save_as = staticmethod(save_as) Interaction.async_command = staticmethod(async_command) git-cola-4.6.1/cola/widgets/startup.py000066400000000000000000000463031457126473700177070ustar00rootroot00000000000000"""The startup dialog is presented when no repositories can be found at startup""" from qtpy.QtCore import Qt from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from ..i18n import N_ from ..models import prefs from .. import cmds from .. import core from .. import display from .. import guicmds from .. import hotkeys from .. import icons from .. import qtutils from .. import utils from .. import version from . import clone from . import defs from . import standard ICON_MODE = 0 LIST_MODE = 1 class StartupDialog(standard.Dialog): """Provides a GUI to Open or Clone a git repository.""" def __init__(self, context, parent=None): standard.Dialog.__init__(self, parent) self.context = context self.setWindowTitle(N_('git-cola')) # Top-most large icon logo_pixmap = icons.cola().pixmap(defs.huge_icon, defs.huge_icon) self.logo_label = QtWidgets.QLabel() self.logo_label.setPixmap(logo_pixmap) self.logo_label.setAlignment(Qt.AlignCenter) self.logo_text_label = qtutils.label(text=version.cola_version()) self.logo_text_label.setAlignment(Qt.AlignCenter) self.repodir = None if context.runtask: self.runtask = context.runtask else: self.runtask = context.runtask = qtutils.RunTask(parent=self) self.new_button = qtutils.create_button(text=N_('New...'), icon=icons.new()) self.open_button = qtutils.create_button( text=N_('Open Git Repository'), icon=icons.folder() ) self.clone_button = qtutils.create_button( text=N_('Clone...'), icon=icons.cola() ) self.close_button = qtutils.close_button() self.bookmarks_model = bookmarks_model = QtGui.QStandardItemModel() self.items = items = [] item = QtGui.QStandardItem(N_('Browse...')) item.setEditable(False) item.setIcon(icons.open_directory()) bookmarks_model.appendRow(item) # The tab bar allows choosing between Folder and List mode self.tab_bar = QtWidgets.QTabBar() self.tab_bar.setMovable(False) self.tab_bar.addTab(icons.directory(), N_('Folder')) self.tab_bar.addTab(icons.three_bars(), N_('List')) # Bookmarks/"Favorites" and Recent are lists of {name,path: str} normalize = display.normalize_path settings = context.settings all_repos = get_all_repos(self.context, settings) added = set() builder = BuildItem(self.context) default_view_mode = ICON_MODE for repo, is_bookmark in all_repos: path = normalize(repo['path']) name = normalize(repo['name']) if path in added: continue added.add(path) item = builder.get(path, name, default_view_mode, is_bookmark) bookmarks_model.appendRow(item) items.append(item) self.bookmarks = BookmarksListView( context, bookmarks_model, self.open_selected_bookmark, self.set_model, ) self.tab_layout = qtutils.vbox( defs.no_margin, defs.no_spacing, self.tab_bar, self.bookmarks ) self.logo_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.logo_label, self.logo_text_label, defs.button_spacing, qtutils.STRETCH, ) self.button_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.open_button, self.clone_button, self.new_button, qtutils.STRETCH, self.close_button, ) self.main_layout = qtutils.grid(defs.margin, defs.spacing) self.main_layout.addItem(self.logo_layout, 1, 1) self.main_layout.addItem(self.tab_layout, 1, 2) self.main_layout.addItem(self.button_layout, 2, 1, columnSpan=2) self.setLayout(self.main_layout) qtutils.connect_button(self.open_button, self.open_repo) qtutils.connect_button(self.clone_button, self.clone_repo) qtutils.connect_button(self.new_button, self.new_repo) qtutils.connect_button(self.close_button, self.reject) self.tab_bar.currentChanged.connect(self.tab_changed) self.init_state(settings, self.resize_widget) self.setFocusProxy(self.bookmarks) self.bookmarks.setFocus() # Update the list mode list_mode = context.cfg.get('cola.startupmode', default='folder') self.list_mode = list_mode if list_mode == 'list': self.tab_bar.setCurrentIndex(1) def tab_changed(self, idx): bookmarks = self.bookmarks if idx == ICON_MODE: mode = QtWidgets.QListView.IconMode icon_size = make_size(defs.medium_icon) grid_size = make_size(defs.large_icon) list_mode = 'folder' view_mode = ICON_MODE rename_enabled = True else: mode = QtWidgets.QListView.ListMode icon_size = make_size(defs.default_icon) grid_size = QtCore.QSize() list_mode = 'list' view_mode = LIST_MODE rename_enabled = False self.bookmarks.set_rename_enabled(rename_enabled) self.bookmarks.set_view_mode(view_mode) bookmarks.setViewMode(mode) bookmarks.setIconSize(icon_size) bookmarks.setGridSize(grid_size) new_items = [] builder = BuildItem(self.context) for item in self.items: if isinstance(item, PromptWidgetItem): item = builder.get(item.path, item.name, view_mode, item.is_bookmark) new_items.append(item) self.set_model(new_items) if list_mode != self.list_mode: self.list_mode = list_mode self.context.cfg.set_user('cola.startupmode', list_mode) def resize_widget(self): width, height = qtutils.desktop_size() self.setGeometry( width // 4, height // 4, width // 2, height // 2, ) 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_() == QtWidgets.QDialog.Accepted: return self.repodir return None def open_repo(self): self.repodir = self.get_selected_bookmark() if not self.repodir: self.repodir = qtutils.opendir_dialog( N_('Open Git Repository'), core.getcwd() ) if self.repodir: self.accept() def clone_repo(self): context = self.context progress = standard.progress('', '', self) clone.clone_repo(context, True, progress, self.clone_repo_done, False) def clone_repo_done(self, task): if task.cmd and task.cmd.status == 0: self.repodir = task.destdir self.accept() else: clone.task_finished(task) def new_repo(self): context = self.context repodir = guicmds.new_repo(context) if repodir: self.repodir = repodir self.accept() def open_selected_bookmark(self): selected = self.bookmarks.selectedIndexes() if selected: self.open_bookmark(selected[0]) def open_bookmark(self, index): if index.row() == 0: self.open_repo() else: self.repodir = self.bookmarks_model.data(index, Qt.UserRole) if not self.repodir: return if not core.exists(self.repodir): self.handle_broken_repo(index) return self.accept() def handle_broken_repo(self, index): settings = self.context.settings all_repos = get_all_repos(self.context, settings) repodir = self.bookmarks_model.data(index, Qt.UserRole) repo = next(repo for repo, is_bookmark in all_repos if repo['path'] == repodir) title = N_('Repository Not Found') text = N_('%s could not be opened. Remove from bookmarks?') % repo['path'] logo = icons.from_style(QtWidgets.QStyle.SP_MessageBoxWarning) if standard.question(title, text, N_('Remove'), logo=logo): self.context.settings.remove_bookmark(repo['path'], repo['name']) self.context.settings.remove_recent(repo['path']) self.context.settings.save() item = self.bookmarks_model.item(index.row()) self.items.remove(item) self.bookmarks_model.removeRow(index.row()) def get_selected_bookmark(self): selected = self.bookmarks.selectedIndexes() if selected and selected[0].row() != 0: return self.bookmarks_model.data(selected[0], Qt.UserRole) return None def set_model(self, items): bookmarks_model = self.bookmarks_model self.items = new_items = [] bookmarks_model.clear() item = QtGui.QStandardItem(N_('Browse...')) item.setEditable(False) item.setIcon(icons.open_directory()) bookmarks_model.appendRow(item) for item in items: bookmarks_model.appendRow(item) new_items.append(item) def get_all_repos(context, settings): """Return a sorted list of bookmarks and recent repositories""" bookmarks = settings.bookmarks recent = settings.recent all_repos = [(repo, True) for repo in bookmarks] + [ (repo, False) for repo in recent ] if prefs.sort_bookmarks(context): all_repos.sort(key=lambda details: details[0]['path'].lower()) return all_repos class BookmarksListView(QtWidgets.QListView): """ List view class implementation of QWidgets.QListView for bookmarks and recent repos. Almost methods is comes from `cola/widgets/bookmarks.py`. """ def __init__(self, context, model, open_selected_repo, set_model, parent=None): super().__init__(parent) self.current_mode = ICON_MODE self.context = context self.open_selected_repo = open_selected_repo self.set_model = set_model self.setEditTriggers(self.SelectedClicked) self.activated.connect(self.open_selected_repo) self.setModel(model) self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) self.setViewMode(QtWidgets.QListView.IconMode) self.setResizeMode(QtWidgets.QListView.Adjust) self.setGridSize(make_size(defs.large_icon)) self.setIconSize(make_size(defs.medium_icon)) self.setDragEnabled(False) self.setWordWrap(True) # Context Menu self.open_action = qtutils.add_action( self, N_('Open'), self.open_selected_repo, hotkeys.OPEN ) self.accept_action = qtutils.add_action( self, N_('Accept'), self.accept_repo, *hotkeys.ACCEPT ) self.open_new_action = qtutils.add_action( self, N_('Open in New Window'), self.open_new_repo, hotkeys.NEW ) self.set_default_repo_action = qtutils.add_action( self, N_('Set Default Repository'), self.set_default_repo ) self.clear_default_repo_action = qtutils.add_action( self, N_('Clear Default Repository'), self.clear_default_repo ) self.rename_repo_action = qtutils.add_action( self, N_('Rename Repository'), self.rename_repo ) self.open_default_action = qtutils.add_action( self, cmds.OpenDefaultApp.name(), self.open_default, hotkeys.PRIMARY_ACTION ) self.launch_editor_action = qtutils.add_action( self, cmds.Edit.name(), self.launch_editor, hotkeys.EDIT ) self.launch_terminal_action = qtutils.add_action( self, cmds.LaunchTerminal.name(), self.launch_terminal, hotkeys.TERMINAL ) self.copy_action = qtutils.add_action(self, N_('Copy'), self.copy, hotkeys.COPY) self.delete_action = qtutils.add_action(self, N_('Delete'), self.delete_item) self.remove_missing_action = qtutils.add_action( self, N_('Prune Missing Entries'), self.remove_missing ) self.remove_missing_action.setToolTip( N_('Remove stale entries for repositories that no longer exist') ) self.model().itemChanged.connect(self.item_changed) self.action_group = utils.Group( self.open_action, self.open_new_action, self.copy_action, self.launch_editor_action, self.launch_terminal_action, self.open_default_action, self.rename_repo_action, self.delete_action, ) self.action_group.setEnabled(True) self.set_default_repo_action.setEnabled(True) self.clear_default_repo_action.setEnabled(True) def set_rename_enabled(self, is_enabled): self.rename_repo_action.setEnabled(is_enabled) def set_view_mode(self, view_mode): self.current_mode = view_mode def selected_item(self): index = self.currentIndex() return self.model().itemFromIndex(index) def refresh(self): self.model().layoutChanged.emit() context = self.context settings = context.settings builder = BuildItem(context) normalize = display.normalize_path items = [] added = set() all_repos = get_all_repos(self.context, settings) for repo, is_bookmark in all_repos: path = normalize(repo['path']) name = normalize(repo['name']) if path in added: continue added.add(path) item = builder.get(path, name, self.current_mode, is_bookmark) items.append(item) self.set_model(items) def contextMenuEvent(self, event): """Configures prompt's context menu.""" item = self.selected_item() if isinstance(item, PromptWidgetItem): menu = qtutils.create_menu(N_('Actions'), self) menu.addAction(self.open_action) menu.addAction(self.open_new_action) menu.addAction(self.open_default_action) menu.addSeparator() menu.addAction(self.copy_action) menu.addAction(self.launch_editor_action) menu.addAction(self.launch_terminal_action) menu.addSeparator() if item and item.is_default: menu.addAction(self.clear_default_repo_action) else: menu.addAction(self.set_default_repo_action) menu.addAction(self.rename_repo_action) menu.addSeparator() menu.addAction(self.delete_action) menu.addAction(self.remove_missing_action) menu.exec_(self.mapToGlobal(event.pos())) def item_changed(self, item): self.rename_entry(item, item.text()) def rename_entry(self, item, new_name): settings = self.context.settings if item.is_bookmark: rename = settings.rename_bookmark else: rename = settings.rename_recent if rename(item.path, item.name, new_name): settings.save() item.name = new_name else: item.setText(item.name) def apply_func(self, func, *args, **kwargs): item = self.selected_item() if item: func(item, *args, **kwargs) def copy(self): self.apply_func(lambda item: qtutils.set_clipboard(item.path)) def open_default(self): context = self.context self.apply_func(lambda item: cmds.do(cmds.OpenDefaultApp, context, [item.path])) def set_default_repo(self): self.apply_func(self.set_default_item) def set_default_item(self, item): context = self.context cmds.do(cmds.SetDefaultRepo, context, item.path) self.refresh() def clear_default_repo(self): self.apply_func(self.clear_default_item) def clear_default_item(self, _item): context = self.context cmds.do(cmds.SetDefaultRepo, context, None) self.refresh() def rename_repo(self): index = self.currentIndex() self.edit(index) def accept_repo(self): self.apply_func(self.accept_item) def accept_item(self, _item): if self.state() & self.EditingState: current_index = self.currentIndex() widget = self.indexWidget(current_index) if widget: self.commitData(widget) self.closePersistentEditor(current_index) self.refresh() else: self.open_selected_repo() def open_new_repo(self): context = self.context self.apply_func(lambda item: cmds.do(cmds.OpenNewRepo, context, item.path)) def launch_editor(self): context = self.context self.apply_func(lambda item: cmds.do(cmds.Edit, context, [item.path])) def launch_terminal(self): context = self.context self.apply_func(lambda item: cmds.do(cmds.LaunchTerminal, context, item.path)) def delete_item(self): """Remove the selected repo item If the item comes from bookmarks (item.is_bookmark) then delete the item from the Bookmarks list, otherwise delete it from the Recents list. """ item = self.selected_item() if not item: return if item.is_bookmark: cmd = cmds.RemoveBookmark else: cmd = cmds.RemoveRecent context = self.context ok, _, _, _ = cmds.do(cmd, context, item.path, item.name, icon=icons.discard()) if ok: self.refresh() def remove_missing(self): """Remove missing entries from the favorites/recent file list""" settings = self.context.settings settings.remove_missing_bookmarks() settings.remove_missing_recent() self.refresh() class BuildItem: def __init__(self, context): self.star_icon = icons.star() self.folder_icon = icons.folder() cfg = context.cfg self.default_repo = cfg.get('cola.defaultrepo') def get(self, path, name, mode, is_bookmark): is_default = self.default_repo == path if is_default: icon = self.star_icon else: icon = self.folder_icon return PromptWidgetItem(path, name, mode, icon, is_default, is_bookmark) class PromptWidgetItem(QtGui.QStandardItem): def __init__(self, path, name, mode, icon, is_default, is_bookmark): QtGui.QStandardItem.__init__(self, icon, name) self.path = path self.name = name self.mode = mode self.is_default = is_default self.is_bookmark = is_bookmark editable = mode == ICON_MODE if self.mode == ICON_MODE: item_text = self.name else: item_text = self.path user_role = Qt.UserRole self.setEditable(editable) self.setData(path, user_role) self.setIcon(icon) self.setText(item_text) self.setToolTip(path) def make_size(size): """Construct a QSize from a single value""" return QtCore.QSize(size, size) git-cola-4.6.1/cola/widgets/stash.py000066400000000000000000000241071457126473700173250ustar00rootroot00000000000000"""Widgets for manipulating git stashes""" from qtpy.QtCore import Qt from ..i18n import N_ from ..interaction import Interaction from ..models import stash from ..qtutils import get from .. import cmds from .. import hotkeys from .. import icons from .. import qtutils from . import defs from . import diff from . import standard def view(context, show=True): """Launches a stash dialog using the provided model + view""" model = stash.StashModel(context) stash_view = StashView(context, model, parent=qtutils.active_window()) if show: stash_view.show() stash_view.raise_() return stash_view class StashView(standard.Dialog): def __init__(self, context, model, parent=None): standard.Dialog.__init__(self, parent=parent) self.context = context self.model = model self.stashes = [] self.revids = [] self.names = [] self.setWindowTitle(N_('Stash')) if parent is not None: self.setWindowModality(Qt.WindowModal) self.stash_list = standard.ListWidget(parent=self) self.stash_text = diff.DiffTextEdit(context, self) self.button_rename = qtutils.create_button( text=N_('Rename'), tooltip=N_('Rename the selected stash'), icon=icons.edit(), ) self.button_apply = qtutils.create_button( text=N_('Apply'), tooltip=N_('Apply the selected stash'), icon=icons.ok() ) self.button_save = qtutils.create_button( text=N_('Save'), tooltip=N_('Save modified state to new stash'), icon=icons.save(), default=True, ) self.button_drop = qtutils.create_button( text=N_('Drop'), tooltip=N_('Drop the selected stash'), icon=icons.discard() ) self.button_pop = qtutils.create_button( text=N_('Pop'), tooltip=N_('Apply and drop the selected stash (git stash pop)'), icon=icons.discard(), ) self.button_close = qtutils.close_button() self.keep_index = qtutils.checkbox( text=N_('Keep Index'), checked=True, tooltip=N_('Stash unstaged changes only, keeping staged changes'), ) self.stash_index = qtutils.checkbox( text=N_('Stash Index'), tooltip=N_('Stash staged changes only') ) # Arrange layouts self.splitter = qtutils.splitter( Qt.Horizontal, self.stash_list, self.stash_text ) self.splitter.setChildrenCollapsible(False) self.btn_layt = qtutils.hbox( defs.no_margin, defs.button_spacing, self.stash_index, self.keep_index, qtutils.STRETCH, self.button_close, self.button_save, self.button_rename, self.button_apply, self.button_pop, self.button_drop, ) self.main_layt = qtutils.vbox( defs.margin, defs.spacing, self.splitter, self.btn_layt ) self.setLayout(self.main_layt) self.splitter.setSizes([self.width() // 3, self.width() * 2 // 3]) # Apply stash with Ctrl+Enter self.apply_action = qtutils.add_action( self, N_('Apply'), self.stash_apply, hotkeys.APPLY ) # Pop stash with Ctrl+Backspace self.pop_action = qtutils.add_action( self, N_('Pop'), self.stash_pop, hotkeys.DELETE_FILE_SECONDARY ) # Drop stash with Ctrl+Shift+Backspace self.drop_action = qtutils.add_action( self, N_('Pop'), self.stash_drop, hotkeys.DELETE_FILE ) self.stash_list.itemSelectionChanged.connect(self.item_selected) qtutils.connect_button(self.button_save, self.stash_save) qtutils.connect_button(self.button_rename, self.stash_rename) qtutils.connect_button(self.button_apply, self.stash_apply) qtutils.connect_button(self.button_pop, self.stash_pop) qtutils.connect_button(self.button_drop, self.stash_drop) qtutils.connect_button(self.button_close, self.close_and_rescan) qtutils.connect_checkbox(self.stash_index, self.stash_index_clicked) qtutils.connect_checkbox(self.keep_index, self.keep_index_clicked) self.init_size(parent=parent) self.update_from_model() self.update_actions() def close_and_rescan(self): cmds.do(cmds.Rescan, self.context) self.reject() # "stash" and "keep" index are mutually disable, but we don't # want a radio button because we'd have to add a 3rd "default" option. def stash_index_clicked(self, clicked): if clicked: self.keep_index.setChecked(False) def keep_index_clicked(self, clicked): if clicked: self.stash_index.setChecked(False) 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): is_staged = self.model.is_staged() self.stash_index.setEnabled(is_staged) is_changed = self.model.is_changed() self.keep_index.setEnabled(is_changed) self.button_save.setEnabled(is_changed) is_selected = bool(self.selected_stash()) self.apply_action.setEnabled(is_selected) self.drop_action.setEnabled(is_selected) self.pop_action.setEnabled(is_selected) self.button_rename.setEnabled(is_selected) self.button_apply.setEnabled(is_selected) self.button_drop.setEnabled(is_selected) self.button_pop.setEnabled(is_selected) def update_from_model(self): """Initiates git queries on the model and updates the view""" stashes, revids, author_dates, names = self.model.stash_info() self.stashes = stashes self.revids = revids self.names = names self.stash_list.clear() self.stash_list.addItems(self.stashes) if self.stash_list.count() > 0: for i in range(self.stash_list.count()): self.stash_list.item(i).setToolTip(author_dates[i]) item = self.stash_list.item(0) self.stash_list.setCurrentItem(item) # "Stash Index" depends on staged changes, so disable this option # if there are no staged changes. is_staged = self.model.is_staged() if get(self.stash_index) and not is_staged: self.stash_index.setChecked(False) def stash_rename(self): """Renames the currently selected stash""" selection = self.selected_stash() name = self.selected_name() new_name, ok = qtutils.prompt( N_('Enter a new name for the stash'), text=name, title=N_('Rename Stash'), parent=self, ) if not ok or not new_name: return if new_name == name: Interaction.information( N_('No change made'), N_('The stash has not been renamed') ) return context = self.context cmds.do(stash.RenameStash, context, selection, new_name) self.update_from_model() def stash_pop(self): self.stash_apply(pop=True) def stash_apply(self, pop=False): """Applies the currently selected stash""" selection = self.selected_stash() if not selection: return context = self.context index = get(self.keep_index) cmds.do(stash.ApplyStash, context, selection, index, pop) self.update_from_model() 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_('Enter a name for the stash'), title=N_('Save Stash'), parent=self ) if not ok or not stash_name: return context = self.context keep_index = get(self.keep_index) stash_index = get(self.stash_index) if stash_index: cmds.do(stash.StashIndex, context, stash_name) else: cmds.do(stash.SaveStash, context, stash_name, keep_index) self.update_from_model() def stash_drop(self): """Drops the currently selected stash""" selection = self.selected_stash() name = self.selected_name() if not selection: return if not Interaction.confirm( N_('Drop Stash?'), N_('Recovering a dropped stash is not possible.'), N_('Drop the "%s" stash?') % name, N_('Drop Stash'), default=True, icon=icons.discard(), ): return cmds.do(stash.DropStash, self.context, selection) self.update_from_model() self.stash_text.setPlainText('') def export_state(self): """Export persistent settings""" state = super().export_state() state['keep_index'] = get(self.keep_index) state['stash_index'] = get(self.stash_index) state['sizes'] = get(self.splitter) return state def apply_state(self, state): """Apply persistent settings""" result = super().apply_state(state) keep_index = bool(state.get('keep_index', True)) stash_index = bool(state.get('stash_index', False)) self.keep_index.setChecked(keep_index) self.stash_index.setChecked(stash_index) try: self.splitter.setSizes(state['sizes']) except (KeyError, ValueError, AttributeError): pass return result git-cola-4.6.1/cola/widgets/status.py000066400000000000000000001672751457126473700175440ustar00rootroot00000000000000import itertools import os from functools import partial from qtpy.QtCore import Qt from qtpy import QtCore from qtpy import QtWidgets from ..i18n import N_ from ..models import prefs from ..models import selection from ..widgets import gitignore from ..widgets import standard from ..qtutils import get from ..settings import Settings from .. import actions from .. import cmds from .. import core from .. import difftool from .. import hotkeys from .. import icons from .. import qtutils from .. import utils from . import common from . import completion from . import defs from . import text # Top-level status widget item indexes. HEADER_IDX = -1 STAGED_IDX = 0 UNMERGED_IDX = 1 MODIFIED_IDX = 2 UNTRACKED_IDX = 3 END_IDX = 4 # Indexes into the saved_selection entries. NEW_PATHS_IDX = 0 OLD_PATHS_IDX = 1 SELECTION_IDX = 2 SELECT_FN_IDX = 3 class StatusWidget(QtWidgets.QFrame): """ Provides a git-status-like repository widget. This widget observes the main model and broadcasts Qt signals. """ def __init__(self, context, titlebar, parent): QtWidgets.QFrame.__init__(self, parent) self.context = context tooltip = N_('Toggle the paths filter') icon = icons.ellipsis() self.filter_button = qtutils.create_action_button(tooltip=tooltip, icon=icon) self.filter_widget = StatusFilterWidget(context) self.filter_widget.hide() self.tree = StatusTreeWidget(context, parent=self) self.setFocusProxy(self.tree) tooltip = N_('Exit "Diff" mode') icon = icons.circle_slash_red() self.exit_diff_mode_button = qtutils.create_action_button( tooltip=tooltip, icon=icon, visible=False ) self.main_layout = qtutils.vbox( defs.no_margin, defs.no_spacing, self.filter_widget, self.tree ) self.setLayout(self.main_layout) self.toggle_action = qtutils.add_action( self, tooltip, self.toggle_filter, hotkeys.FILTER ) titlebar.add_corner_widget(self.exit_diff_mode_button) titlebar.add_corner_widget(self.filter_button) qtutils.connect_button(self.filter_button, self.toggle_filter) qtutils.connect_button( self.exit_diff_mode_button, cmds.run(cmds.ResetMode, self.context) ) def toggle_filter(self): """Toggle the paths filter""" shown = not self.filter_widget.isVisible() self.filter_widget.setVisible(shown) if shown: self.filter_widget.setFocus() else: self.tree.setFocus() def set_initial_size(self): """Set the initial size of the status widget""" self.setMaximumWidth(222) QtCore.QTimer.singleShot(1, lambda: self.setMaximumWidth(2**13)) def refresh(self): """Refresh the tree and rerun the diff to see updates""" self.tree.show_selection() def set_filter(self, txt): """Set the filter text""" self.filter_widget.setVisible(True) self.filter_widget.text.set_value(txt) self.filter_widget.apply_filter() def set_mode(self, mode): """React to changes in model's editing mode""" exit_diff_mode_visible = mode == self.context.model.mode_diff self.exit_diff_mode_button.setVisible(exit_diff_mode_visible) def move_up(self): self.tree.move_up() def move_down(self): self.tree.move_down() def select_header(self): self.tree.select_header() class StatusTreeWidget(QtWidgets.QTreeWidget): # Read-only access to the mode state mode = property(lambda self: self._model.mode) def __init__(self, context, parent=None): QtWidgets.QTreeWidget.__init__(self, parent) self.context = context self.selection_model = context.selection self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) self.headerItem().setHidden(True) self.setAllColumnsShowFocus(True) self.setSortingEnabled(False) self.setUniformRowHeights(True) self.setAnimated(True) self.setRootIsDecorated(False) self.setAutoScroll(False) self.setDragEnabled(True) self.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly) self._alt_drag = False if not prefs.status_indent(context): self.setIndentation(0) ok_icon = icons.ok() compare = icons.compare() question = icons.question() self._add_toplevel_item(N_('Staged'), ok_icon, hide=True) self._add_toplevel_item(N_('Unmerged'), compare, hide=True) self._add_toplevel_item(N_('Modified'), compare, hide=True) self._add_toplevel_item(N_('Untracked'), question, hide=True) # Used to restore the selection self.old_vscroll = None self.old_hscroll = None self.old_selection = None self.old_contents = None self.old_current_item = None self.previous_contents = None self.was_visible = True self.expanded_items = set() self.image_formats = qtutils.ImageFormats() self.process_selection_action = qtutils.add_action( self, cmds.StageOrUnstage.name(), self._stage_selection, hotkeys.STAGE_SELECTION, ) self.process_selection_action.setIcon(icons.add()) self.stage_or_unstage_all_action = qtutils.add_action( self, cmds.StageOrUnstageAll.name(), cmds.run(cmds.StageOrUnstageAll, self.context), hotkeys.STAGE_ALL, ) self.stage_or_unstage_all_action.setIcon(icons.add()) self.revert_unstaged_edits_action = qtutils.add_action( self, cmds.RevertUnstagedEdits.name(), cmds.run(cmds.RevertUnstagedEdits, context), hotkeys.REVERT, hotkeys.REVERT_ALT, ) self.revert_unstaged_edits_action.setIcon(icons.undo()) self.launch_difftool_action = qtutils.add_action( self, difftool.LaunchDifftool.name(), cmds.run(difftool.LaunchDifftool, context), hotkeys.DIFF, ) self.launch_difftool_action.setIcon(icons.diff()) self.launch_editor_action = actions.launch_editor_at_line( context, self, *hotkeys.ACCEPT ) self.default_app_action = common.default_app_action( context, self, self.selected_group ) self.parent_dir_action = common.parent_dir_action( context, self, self.selected_group ) self.worktree_dir_action = common.worktree_dir_action(context, self) self.terminal_action = common.terminal_action( context, self, func=self.selected_group ) self.up_action = qtutils.add_action( self, N_('Move Up'), self.move_up, hotkeys.MOVE_UP, hotkeys.MOVE_UP_SECONDARY, ) self.down_action = qtutils.add_action( self, N_('Move Down'), self.move_down, hotkeys.MOVE_DOWN, hotkeys.MOVE_DOWN_SECONDARY, ) # Checkout the selected paths using "git checkout --ours". self.checkout_ours_action = qtutils.add_action( self, cmds.CheckoutOurs.name(), cmds.run(cmds.CheckoutOurs, context) ) # Checkout the selected paths using "git checkout --theirs". self.checkout_theirs_action = qtutils.add_action( self, cmds.CheckoutTheirs.name(), cmds.run(cmds.CheckoutTheirs, context) ) self.copy_path_action = qtutils.add_action( self, N_('Copy Path to Clipboard'), partial(copy_path, context), hotkeys.COPY, ) self.copy_path_action.setIcon(icons.copy()) self.copy_relpath_action = qtutils.add_action( self, N_('Copy Relative Path to Clipboard'), partial(copy_relpath, context), hotkeys.CUT, ) self.copy_relpath_action.setIcon(icons.copy()) self.copy_leading_paths_value = 1 self.copy_basename_action = qtutils.add_action( self, N_('Copy Basename to Clipboard'), partial(copy_basename, context) ) self.copy_basename_action.setIcon(icons.copy()) self.copy_customize_action = qtutils.add_action( self, N_('Customize...'), partial(customize_copy_actions, context, self) ) self.copy_customize_action.setIcon(icons.configure()) self.view_history_action = qtutils.add_action( self, N_('View History...'), partial(view_history, context), hotkeys.HISTORY ) self.view_blame_action = qtutils.add_action( self, N_('Blame...'), partial(view_blame, context), hotkeys.BLAME ) self.annex_add_action = qtutils.add_action( self, N_('Add to Git Annex'), cmds.run(cmds.AnnexAdd, context) ) self.lfs_track_action = qtutils.add_action( self, N_('Add to Git LFS'), cmds.run(cmds.LFSTrack, context) ) # MoveToTrash and Delete use the same shortcut. # We will only bind one of them, depending on whether or not the # MoveToTrash command is available. When available, the hotkey # is bound to MoveToTrash, otherwise it is bound to Delete. if cmds.MoveToTrash.AVAILABLE: self.move_to_trash_action = qtutils.add_action( self, N_('Move files to trash'), self._trash_untracked_files, hotkeys.TRASH, ) self.move_to_trash_action.setIcon(icons.discard()) delete_shortcut = hotkeys.DELETE_FILE else: self.move_to_trash_action = None delete_shortcut = hotkeys.DELETE_FILE_SECONDARY self.delete_untracked_files_action = qtutils.add_action( self, N_('Delete Files...'), self._delete_untracked_files, delete_shortcut ) self.delete_untracked_files_action.setIcon(icons.discard()) # The model is stored as self._model because self.model() is a # QTreeWidgetItem method that returns a QAbstractItemModel. self._model = context.model self._model.previous_contents.connect( self._set_previous_contents, type=Qt.QueuedConnection ) self._model.about_to_update.connect( self._about_to_update, type=Qt.QueuedConnection ) self._model.updated.connect(self.refresh, type=Qt.QueuedConnection) self._model.diff_text_changed.connect( self._make_current_item_visible, type=Qt.QueuedConnection ) self.itemSelectionChanged.connect(self.show_selection) self.itemDoubleClicked.connect(cmds.run(cmds.StageOrUnstage, self.context)) self.itemCollapsed.connect(lambda x: self._update_column_widths()) self.itemExpanded.connect(lambda x: self._update_column_widths()) def _make_current_item_visible(self): item = self.currentItem() if item: qtutils.scroll_to_item(self, item) def _add_toplevel_item(self, txt, icon, hide=False): context = self.context font = self.font() if prefs.bold_headers(context): font.setBold(True) else: font.setItalic(True) item = QtWidgets.QTreeWidgetItem(self) item.setFont(0, font) item.setText(0, txt) item.setIcon(0, icon) if prefs.bold_headers(context): item.setBackground(0, self.palette().midlight()) if hide: item.setHidden(True) def _restore_selection(self): """Apply the old selection to the newly updated items""" # This function is called after a new set of items have been added to # the per-category file lists. Its purpose is to either restore the # existing selection or to create a new intuitive selection based on # a combination of the old items, the old selection and the new items. if not self.old_selection or not self.old_contents: return # The old set of categorized files. old_c = self.old_contents # The old selection. old_s = self.old_selection # The current/new set of categorized files. new_c = self.contents() select_staged = partial(_select_item, self, new_c.staged, self._staged_item) select_unmerged = partial( _select_item, self, new_c.unmerged, self._unmerged_item ) select_modified = partial( _select_item, self, new_c.modified, self._modified_item ) select_untracked = partial( _select_item, self, 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 _apply_toplevel_selection(self, category, idx): return # Reselect the current item selection_info = saved_selection[category] new = selection_info[NEW_PATHS_IDX] old = selection_info[OLD_PATHS_IDX] reselect = selection_info[SELECT_FN_IDX] try: item = old[idx] except IndexError: item = None if item and item in new: reselect(item, current=True) # Restore previously selected items. # When reselecting in this section we only care that the items are # selected; we do not need to rerun the callbacks which were triggered # above for the current item. Block signals to skip the callbacks. # # Reselect items that were previously selected and still exist in the # current path lists. This handles a common case such as a Ctrl-R # refresh which results in the same exact path state. did_reselect = False with qtutils.BlockSignals(self): for new, old, sel, reselect in saved_selection: for item in sel: if item in new: reselect(item, current=False) did_reselect = True # The status widget is used to interactively work your way down the # list of Staged, Unmerged, Modified and Untracked items and perform # an operation on them. # # For Staged items we intend to work our way down the list of Staged # items while we unstage each item. For every other category we work # our way down the list of {Unmerged,Modified,Untracked} items while # we stage each item. # # The following block of code implements the behavior of selecting # the next item based on the previous selection. for new, old, sel, 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 sel: # 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 # If we already reselected stuff then there's nothing more to do. if did_reselect: return # If we got this far then nothing was reselected and made current. # Try a few more heuristics that we can use to keep something selected. if self.old_current_item: category, idx = self.old_current_item _transplant_selection_across_sections( category, idx, self.previous_contents, saved_selection ) def _restore_scrollbars(self): """Restore scrollbars to the stored values""" qtutils.set_scrollbar_values(self, self.old_hscroll, self.old_vscroll) self.old_hscroll = None self.old_vscroll = None def _stage_selection(self): """Stage or unstage files according to the selection""" context = self.context selected_indexes = self.selected_indexes() is_header = any(category == HEADER_IDX for (category, idx) in selected_indexes) if is_header: is_staged = any( idx == STAGED_IDX and category == HEADER_IDX for (category, idx) in selected_indexes ) is_modified = any( idx == MODIFIED_IDX and category == HEADER_IDX for (category, idx) in selected_indexes ) is_untracked = any( idx == UNTRACKED_IDX and category == HEADER_IDX for (category, idx) in selected_indexes ) # A header item: 'Staged', 'Modified' or 'Untracked'. if is_staged: # If we have the staged header selected then the only sensible # thing to do is to unstage everything and nothing else, even # if the modified or untracked headers are selected. cmds.do(cmds.UnstageAll, context) return # Everything was unstaged. There's nothing more to be done. if is_modified and is_untracked: # If both modified and untracked headers are selected then # stage everything. cmds.do(cmds.StageModifiedAndUntracked, context) return # Nothing more to do. # At this point we may stage all modified and untracked, and then # possibly a subset of the other category (e.g. all modified and # some untracked). We don't return here so that StageOrUnstage # gets a chance to run below. if is_modified: cmds.do(cmds.StageModified, context) elif is_untracked: cmds.do(cmds.StageUntracked, context) else: # Do nothing for unmerged items, by design pass # Now handle individual files cmds.do(cmds.StageOrUnstage, context) def _staged_item(self, itemidx): return self._subtree_item(STAGED_IDX, itemidx) def _modified_item(self, itemidx): return self._subtree_item(MODIFIED_IDX, itemidx) def _unmerged_item(self, itemidx): return self._subtree_item(UNMERGED_IDX, itemidx) def _untracked_item(self, itemidx): return self._subtree_item(UNTRACKED_IDX, itemidx) def _unstaged_item(self, itemidx): # is it modified? item = self.topLevelItem(MODIFIED_IDX) count = item.childCount() if itemidx < count: return item.child(itemidx) # is it unmerged? item = self.topLevelItem(UNMERGED_IDX) count += item.childCount() if itemidx < count: return item.child(itemidx) # is it untracked? item = self.topLevelItem(UNTRACKED_IDX) 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 _set_previous_contents(self, staged, unmerged, modified, untracked): """Callback triggered right before the model changes its contents""" self.previous_contents = selection.State(staged, unmerged, modified, untracked) def _about_to_update(self): self._save_scrollbars() self._save_selection() def _save_scrollbars(self): """Store the scrollbar values for later application""" hscroll, vscroll = qtutils.get_scrollbar_values(self) if hscroll is not None: self.old_hscroll = hscroll if vscroll is not None: self.old_vscroll = vscroll 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) if idx.parent().isValid(): parent_idx = idx.parent() entry = (parent_idx.row(), idx.row()) else: entry = (HEADER_IDX, 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 refresh(self): self._set_staged(self._model.staged) self._set_modified(self._model.modified) self._set_unmerged(self._model.unmerged) self._set_untracked(self._model.untracked) self._update_column_widths() self._update_actions() self._restore_selection() self._restore_scrollbars() def _update_actions(self, selected=None): if selected is None: selected = self.selection_model.selection() can_revert_edits = bool(selected.staged or selected.modified) self.revert_unstaged_edits_action.setEnabled(can_revert_edits) enabled = self.selection_model.filename() is not None self.default_app_action.setEnabled(enabled) self.parent_dir_action.setEnabled(enabled) self.copy_path_action.setEnabled(enabled) self.copy_relpath_action.setEnabled(enabled) self.copy_basename_action.setEnabled(enabled) def _set_staged(self, items): """Adds items to the 'Staged' sub-tree.""" with qtutils.BlockSignals(self): self._set_subtree( items, STAGED_IDX, N_('Staged'), staged=True, deleted_set=self._model.staged_deleted, ) def _set_modified(self, items): """Adds items to the 'Modified' sub-tree.""" with qtutils.BlockSignals(self): self._set_subtree( items, MODIFIED_IDX, N_('Modified'), deleted_set=self._model.unstaged_deleted, ) def _set_unmerged(self, items): """Adds items to the 'Unmerged' sub-tree.""" deleted_set = {path for path in items if not core.exists(path)} with qtutils.BlockSignals(self): self._set_subtree( items, UNMERGED_IDX, N_('Unmerged'), deleted_set=deleted_set ) def _set_untracked(self, items): """Adds items to the 'Untracked' sub-tree.""" with qtutils.BlockSignals(self): self._set_subtree(items, UNTRACKED_IDX, N_('Untracked'), untracked=True) def _set_subtree( self, items, idx, parent_title, staged=False, untracked=False, deleted_set=None ): """Add a list of items to a treewidget item.""" parent = self.topLevelItem(idx) hide = not bool(items) parent.setHidden(hide) # 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: deleted = deleted_set is not None and item in deleted_set treeitem = qtutils.create_treeitem( item, staged=staged, deleted=deleted, untracked=untracked ) parent.addChild(treeitem) self._expand_items(idx, items) if prefs.status_show_totals(self.context): parent.setText(0, f'{parent_title} ({len(items)})') 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.""" sel = self.selection() menu = qtutils.create_menu('Status', self) selected_indexes = self.selected_indexes() if selected_indexes: category, idx = selected_indexes[0] # A header item e.g. 'Staged', 'Modified', etc. if category == HEADER_IDX: return self._create_header_context_menu(menu, idx) if sel.staged: self._create_staged_context_menu(menu, sel) elif sel.unmerged: self._create_unmerged_context_menu(menu, sel) else: self._create_unstaged_context_menu(menu, sel) if not menu.isEmpty(): menu.addSeparator() if not self.selection_model.is_empty(): menu.addAction(self.default_app_action) menu.addAction(self.parent_dir_action) if self.terminal_action is not None: menu.addAction(self.terminal_action) menu.addAction(self.worktree_dir_action) self._add_copy_actions(menu) return menu def _add_copy_actions(self, menu): """Add the "Copy" sub-menu""" enabled = self.selection_model.filename() is not None self.copy_path_action.setEnabled(enabled) self.copy_relpath_action.setEnabled(enabled) self.copy_basename_action.setEnabled(enabled) copy_menu = QtWidgets.QMenu(N_('Copy...'), menu) copy_icon = icons.copy() copy_menu.setIcon(copy_icon) copy_leading_path_action = QtWidgets.QWidgetAction(copy_menu) copy_leading_path_action.setEnabled(enabled) widget = CopyLeadingPathWidget( N_('Copy Leading Path to Clipboard'), self.context, copy_menu ) # Store the value of the leading paths spin-box so that the value does not reset # every time the menu is shown and recreated. widget.set_value(self.copy_leading_paths_value) widget.spinbox.valueChanged.connect( partial(setattr, self, 'copy_leading_paths_value') ) copy_leading_path_action.setDefaultWidget(widget) # Copy the leading path when the action is activated. qtutils.connect_action( copy_leading_path_action, lambda widget=widget: copy_leading_path(context, widget.value()), ) menu.addSeparator() menu.addMenu(copy_menu) copy_menu.addAction(self.copy_path_action) copy_menu.addAction(self.copy_relpath_action) copy_menu.addAction(copy_leading_path_action) copy_menu.addAction(self.copy_basename_action) settings = Settings.read() copy_formats = settings.copy_formats if copy_formats: copy_menu.addSeparator() context = self.context for entry in copy_formats: name = entry.get('name', '') fmt = entry.get('format', '') if name and fmt: action = copy_menu.addAction(name, partial(copy_format, context, fmt)) action.setIcon(copy_icon) action.setEnabled(enabled) copy_menu.addSeparator() copy_menu.addAction(self.copy_customize_action) def _create_header_context_menu(self, menu, idx): context = self.context if idx == STAGED_IDX: menu.addAction( icons.remove(), N_('Unstage All'), cmds.run(cmds.UnstageAll, context) ) elif idx == UNMERGED_IDX: action = menu.addAction( icons.add(), cmds.StageUnmerged.name(), cmds.run(cmds.StageUnmerged, context), ) action.setShortcut(hotkeys.STAGE_SELECTION) elif idx == MODIFIED_IDX: action = menu.addAction( icons.add(), cmds.StageModified.name(), cmds.run(cmds.StageModified, context), ) action.setShortcut(hotkeys.STAGE_SELECTION) elif idx == UNTRACKED_IDX: action = menu.addAction( icons.add(), cmds.StageUntracked.name(), cmds.run(cmds.StageUntracked, context), ) action.setShortcut(hotkeys.STAGE_SELECTION) return menu def _create_staged_context_menu(self, menu, s): if s.staged[0] in self._model.submodules: return self._create_staged_submodule_context_menu(menu, s) context = self.context if self._model.is_unstageable(): action = menu.addAction( icons.remove(), N_('Unstage Selected'), cmds.run(cmds.Unstage, context, self.staged()), ) action.setShortcut(hotkeys.STAGE_SELECTION) menu.addAction(self.launch_editor_action) # Do all of the selected items exist? all_exist = all( i not in self._model.staged_deleted and core.exists(i) for i in self.staged() ) if all_exist: menu.addAction(self.launch_difftool_action) if self._model.is_undoable(): menu.addAction(self.revert_unstaged_edits_action) menu.addAction(self.view_history_action) menu.addAction(self.view_blame_action) return menu def _create_staged_submodule_context_menu(self, menu, s): context = self.context path = core.abspath(s.staged[0]) if len(self.staged()) == 1: menu.addAction( icons.cola(), N_('Launch git-cola'), cmds.run(cmds.OpenRepo, context, path), ) menu.addSeparator() action = menu.addAction( icons.remove(), N_('Unstage Selected'), cmds.run(cmds.Unstage, context, self.staged()), ) action.setShortcut(hotkeys.STAGE_SELECTION) menu.addAction(self.view_history_action) return menu def _create_unmerged_context_menu(self, menu, _s): context = self.context menu.addAction(self.launch_difftool_action) action = menu.addAction( icons.add(), N_('Stage Selected'), cmds.run(cmds.Stage, context, self.unstaged()), ) action.setShortcut(hotkeys.STAGE_SELECTION) menu.addAction(self.launch_editor_action) menu.addAction(self.view_history_action) menu.addAction(self.view_blame_action) menu.addSeparator() menu.addAction(self.checkout_ours_action) menu.addAction(self.checkout_theirs_action) return menu def _create_unstaged_context_menu(self, menu, s): context = self.context modified_submodule = s.modified and s.modified[0] in self._model.submodules if modified_submodule: return self._create_modified_submodule_context_menu(menu, s) if self._model.is_stageable(): action = menu.addAction( icons.add(), N_('Stage Selected'), cmds.run(cmds.Stage, context, self.unstaged()), ) action.setShortcut(hotkeys.STAGE_SELECTION) if not self.selection_model.is_empty(): menu.addAction(self.launch_editor_action) # Do all of the selected items exist? all_exist = all( i not in self._model.unstaged_deleted and core.exists(i) for i in self.staged() ) if all_exist and s.modified and self._model.is_stageable(): menu.addAction(self.launch_difftool_action) if s.modified and self._model.is_stageable() and self._model.is_undoable(): menu.addSeparator() menu.addAction(self.revert_unstaged_edits_action) if all_exist and s.untracked: # Git Annex / Git LFS annex = self._model.annex lfs = core.find_executable('git-lfs') if annex or lfs: menu.addSeparator() if annex: menu.addAction(self.annex_add_action) if lfs: menu.addAction(self.lfs_track_action) menu.addSeparator() if self.move_to_trash_action is not None: menu.addAction(self.move_to_trash_action) menu.addAction(self.delete_untracked_files_action) menu.addSeparator() menu.addAction( icons.edit(), N_('Ignore...'), partial(gitignore.gitignore_view, self.context), ) if not self.selection_model.is_empty(): menu.addAction(self.view_history_action) menu.addAction(self.view_blame_action) return menu def _create_modified_submodule_context_menu(self, menu, s): context = self.context path = core.abspath(s.modified[0]) if len(self.unstaged()) == 1: menu.addAction( icons.cola(), N_('Launch git-cola'), cmds.run(cmds.OpenRepo, context, path), ) menu.addAction( icons.pull(), N_('Update this submodule'), cmds.run(cmds.SubmoduleUpdate, context, path), ) menu.addSeparator() if self._model.is_stageable(): menu.addSeparator() action = menu.addAction( icons.add(), N_('Stage Selected'), cmds.run(cmds.Stage, context, self.unstaged()), ) action.setShortcut(hotkeys.STAGE_SELECTION) menu.addAction(self.view_history_action) return menu def _delete_untracked_files(self): cmds.do(cmds.Delete, self.context, self.untracked()) def _trash_untracked_files(self): cmds.do(cmds.MoveToTrash, self.context, self.untracked()) def selected_path(self): s = self.single_selection() return s.staged or s.unmerged or s.modified or s.untracked or None def single_selection(self): """Scan across staged, modified, etc. and return a single item.""" staged = None unmerged = None modified = None untracked = None s = self.selection() if s.staged: staged = s.staged[0] elif s.unmerged: unmerged = s.unmerged[0] elif s.modified: modified = s.modified[0] elif s.untracked: untracked = s.untracked[0] return selection.State(staged, unmerged, modified, untracked) 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 = (HEADER_IDX, 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 all of the current files in a selection.State container""" return selection.State( self._model.staged, self._model.unmerged, self._model.modified, self._model.untracked, ) def all_files(self): """Return all of the current active files as a flat list""" 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, sel in zip(c, s): if not content: continue if sel is not None: return offset + content.index(sel) offset += len(content) return None def select_by_index(self, idx): c = self.contents() to_try = [ (c.staged, STAGED_IDX), (c.unmerged, UNMERGED_IDX), (c.modified, MODIFIED_IDX), (c.untracked, UNTRACKED_IDX), ] for content, toplevel_idx in to_try: if not content: continue if idx < len(content): parent = self.topLevelItem(toplevel_idx) item = parent.child(idx) if item is not None: qtutils.select_item(self, item) return idx -= len(content) def staged(self): return qtutils.get_selected_values(self, STAGED_IDX, self._model.staged) def unstaged(self): return self.unmerged() + self.modified() + self.untracked() def modified(self): return qtutils.get_selected_values(self, MODIFIED_IDX, self._model.modified) def unmerged(self): return qtutils.get_selected_values(self, UNMERGED_IDX, self._model.unmerged) def untracked(self): return qtutils.get_selected_values(self, UNTRACKED_IDX, self._model.untracked) def staged_items(self): return qtutils.get_selected_items(self, STAGED_IDX) def unstaged_items(self): return self.unmerged_items() + self.modified_items() + self.untracked_items() def modified_items(self): return qtutils.get_selected_items(self, MODIFIED_IDX) def unmerged_items(self): return qtutils.get_selected_items(self, UNMERGED_IDX) def untracked_items(self): return qtutils.get_selected_items(self, UNTRACKED_IDX) def show_selection(self): """Show the selected item.""" context = self.context qtutils.scroll_to_item(self, self.currentItem()) # Sync the selection model selected = self.selection() selection_model = self.selection_model selection_model.set_selection(selected) self._update_actions(selected=selected) selected_indexes = self.selected_indexes() if not selected_indexes: if self._model.is_amend_mode() or self._model.is_diff_mode(): cmds.do(cmds.SetDiffText, context, '') else: cmds.do(cmds.ResetMode, context) return # A header item e.g. 'Staged', 'Modified', etc. category, idx = selected_indexes[0] header = category == HEADER_IDX if header: cls = { STAGED_IDX: cmds.DiffStagedSummary, MODIFIED_IDX: cmds.Diffstat, UNMERGED_IDX: cmds.UnmergedSummary, UNTRACKED_IDX: cmds.UntrackedSummary, }.get(idx, cmds.Diffstat) cmds.do(cls, context) return staged = category == STAGED_IDX modified = category == MODIFIED_IDX unmerged = category == UNMERGED_IDX untracked = category == UNTRACKED_IDX if staged: item = self.staged_items()[0] elif unmerged: item = self.unmerged_items()[0] elif modified: item = self.modified_items()[0] elif untracked: item = self.unstaged_items()[0] else: item = None # this shouldn't happen assert item is not None path = item.path deleted = item.deleted image = self.image_formats.ok(path) # Update the diff text if staged: cmds.do(cmds.DiffStaged, context, path, deleted=deleted) elif modified: cmds.do(cmds.Diff, context, path, deleted=deleted) elif unmerged: cmds.do(cmds.Diff, context, path) elif untracked: cmds.do(cmds.ShowUntracked, context, path) # Images are diffed differently. # DiffImage transitions the diff mode to image. # DiffText transitions the diff mode to text. if image: cmds.do( cmds.DiffImage, context, path, deleted, staged, modified, unmerged, untracked, ) else: cmds.do(cmds.DiffText, context) def select_header(self): """Select an active header, which triggers a diffstat""" for idx in ( STAGED_IDX, UNMERGED_IDX, MODIFIED_IDX, UNTRACKED_IDX, ): item = self.topLevelItem(idx) if item.childCount() > 0: self.clearSelection() self.setCurrentItem(item) return def move_up(self): """Select the item above the currently selected item""" 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 == HEADER_IDX: item = self.itemAbove(self.topLevelItem(toplevel_idx)) if item is not None: qtutils.select_item(self, 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): """Select the item below the currently selected item""" 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 == HEADER_IDX: item = self.itemBelow(self.topLevelItem(toplevel_idx)) if item is not None: qtutils.select_item(self, 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 mousePressEvent(self, event): """Keep track of whether to drag URLs or just text""" self._alt_drag = event.modifiers() & Qt.AltModifier return super().mousePressEvent(event) def mouseMoveEvent(self, event): """Keep track of whether to drag URLs or just text""" self._alt_drag = event.modifiers() & Qt.AltModifier return super().mouseMoveEvent(event) def mimeData(self, items): """Return a list of absolute-path URLs""" context = self.context paths = qtutils.paths_from_items(items, item_filter=_item_filter) include_urls = not self._alt_drag return qtutils.mimedata_from_paths(context, paths, include_urls=include_urls) def mimeTypes(self): """Return the mime types that this widget generates""" return qtutils.path_mimetypes(include_urls=not self._alt_drag) def _item_filter(item): """Filter items down to just those that exist on disk""" return not item.deleted and core.exists(item.path) def view_blame(context): """Signal that we should view blame for paths.""" cmds.do(cmds.BlamePaths, context) def view_history(context): """Signal that we should view history for paths.""" cmds.do(cmds.VisualizePaths, context, context.selection.union()) def copy_path(context, absolute=True): """Copy a selected path to the clipboard""" filename = context.selection.filename() qtutils.copy_path(filename, absolute=absolute) def copy_relpath(context): """Copy a selected relative path to the clipboard""" copy_path(context, absolute=False) def copy_basename(context): filename = os.path.basename(context.selection.filename()) basename, _ = os.path.splitext(filename) qtutils.copy_path(basename, absolute=False) def copy_leading_path(context, strip_components): """Peal off trailing path components and copy the current path to the clipboard""" filename = context.selection.filename() value = filename for _ in range(strip_components): value = os.path.dirname(value) qtutils.copy_path(value, absolute=False) def copy_format(context, fmt): """Add variables usable in the custom Copy format strings""" values = {} values['path'] = path = context.selection.filename() values['abspath'] = abspath = os.path.abspath(path) values['absdirname'] = os.path.dirname(abspath) values['dirname'] = os.path.dirname(path) values['filename'] = os.path.basename(path) values['basename'], values['ext'] = os.path.splitext(os.path.basename(path)) qtutils.set_clipboard(fmt % values) def show_help(context): """Display the help for the custom Copy format strings""" help_text = N_( r""" Format String Variables ----------------------- %(path)s = relative file path %(abspath)s = absolute file path %(dirname)s = relative directory path %(absdirname)s = absolute directory path %(filename)s = file basename %(basename)s = file basename without extension %(ext)s = file extension """ ) title = N_('Help - Custom Copy Actions') return text.text_dialog(context, help_text, title) class StatusFilterWidget(QtWidgets.QWidget): """Filter paths displayed by the Status tool""" def __init__(self, context, parent=None): QtWidgets.QWidget.__init__(self, parent) self.context = context hint = N_('Filter paths...') self.text = completion.GitStatusFilterLineEdit(context, hint=hint, parent=self) self.text.setToolTip(hint) self.setFocusProxy(self.text) self._filter = None self.main_layout = qtutils.hbox(defs.no_margin, defs.spacing, self.text) self.setLayout(self.main_layout) widget = self.text widget.changed.connect(self.apply_filter) widget.cleared.connect(self.apply_filter) widget.enter.connect(self.apply_filter) widget.editingFinished.connect(self.apply_filter) def apply_filter(self): """Apply the text filter to the model""" value = get(self.text) if value == self._filter: return self._filter = value paths = utils.shell_split(value) self.context.model.update_path_filter(paths) def customize_copy_actions(context, parent): """Customize copy actions""" dialog = CustomizeCopyActions(context, parent) dialog.show() dialog.exec_() class CustomizeCopyActions(standard.Dialog): """A dialog for defining custom Copy actions and format strings""" def __init__(self, context, parent): standard.Dialog.__init__(self, parent=parent) self.setWindowTitle(N_('Custom Copy Actions')) self.context = context self.table = QtWidgets.QTableWidget(self) self.table.setColumnCount(2) self.table.setHorizontalHeaderLabels([N_('Action Name'), N_('Format String')]) self.table.setSortingEnabled(False) self.table.verticalHeader().hide() self.table.horizontalHeader().setStretchLastSection(True) self.add_button = qtutils.create_button(N_('Add')) self.remove_button = qtutils.create_button(N_('Remove')) self.remove_button.setEnabled(False) self.show_help_button = qtutils.create_button(N_('Show Help')) self.show_help_button.setShortcut(hotkeys.QUESTION) self.close_button = qtutils.close_button() self.save_button = qtutils.ok_button(N_('Save')) self.buttons = qtutils.hbox( defs.no_margin, defs.button_spacing, self.add_button, self.remove_button, self.show_help_button, qtutils.STRETCH, self.close_button, self.save_button, ) layout = qtutils.vbox(defs.margin, defs.spacing, self.table, self.buttons) self.setLayout(layout) qtutils.connect_button(self.add_button, self.add) qtutils.connect_button(self.remove_button, self.remove) qtutils.connect_button(self.show_help_button, partial(show_help, context)) qtutils.connect_button(self.close_button, self.reject) qtutils.connect_button(self.save_button, self.save) qtutils.add_close_action(self) self.table.itemSelectionChanged.connect(self.table_selection_changed) self.init_size(parent=parent) QtCore.QTimer.singleShot(0, self.reload_settings) def reload_settings(self): """Update the view to match the current settings""" # Called once after the GUI is initialized settings = self.context.settings settings.load() table = self.table for entry in settings.copy_formats: name_string = entry.get('name', '') format_string = entry.get('format', '') if name_string and format_string: name = QtWidgets.QTableWidgetItem(name_string) fmt = QtWidgets.QTableWidgetItem(format_string) rows = table.rowCount() table.setRowCount(rows + 1) table.setItem(rows, 0, name) table.setItem(rows, 1, fmt) def export_state(self): """Export the current state into the saved settings""" state = super().export_state() standard.export_header_columns(self.table, state) return state def apply_state(self, state): """Restore state from the saved settings""" result = super().apply_state(state) standard.apply_header_columns(self.table, state) return result def add(self): """Add a custom Copy action and format string""" self.table.setFocus() rows = self.table.rowCount() self.table.setRowCount(rows + 1) name = QtWidgets.QTableWidgetItem(N_('Name')) fmt = QtWidgets.QTableWidgetItem(r'%(path)s') self.table.setItem(rows, 0, name) self.table.setItem(rows, 1, fmt) self.table.setCurrentCell(rows, 0) self.table.editItem(name) def remove(self): """Remove selected items""" # Gather a unique set of rows and remove them in reverse order rows = set() items = self.table.selectedItems() for item in items: rows.add(self.table.row(item)) for row in reversed(sorted(rows)): self.table.removeRow(row) def save(self): """Save custom copy actions to the settings""" copy_formats = [] for row in range(self.table.rowCount()): name = self.table.item(row, 0) fmt = self.table.item(row, 1) if name and fmt: entry = { 'name': name.text(), 'format': fmt.text(), } copy_formats.append(entry) settings = self.context.settings while settings.copy_formats: settings.copy_formats.pop() settings.copy_formats.extend(copy_formats) settings.save() self.accept() def table_selection_changed(self): """Update the enabled state of action buttons based on the current selection""" items = self.table.selectedItems() self.remove_button.setEnabled(bool(items)) def _select_item(widget, path_list, widget_getter, item, current=False): """Select the widget item based on the list index""" # The path lists and widget indexes have a 1:1 correspondence. # Lookup the item filename in the list and use that index to # retrieve the widget item and select it. idx = path_list.index(item) item = widget_getter(idx) if current: widget.setCurrentItem(item) item.setSelected(True) def _apply_toplevel_selection(widget, category, idx): """Select a top-level "header" item (ex: the Staged parent item) Return True when a top-level item is selected. """ is_top_level_item = category == HEADER_IDX if is_top_level_item: root_item = widget.invisibleRootItem() item = root_item.child(idx) if item is not None and item.childCount() == 0: # The item now has no children. Select a different top-level item # corresponding to the previously selected item. if idx == STAGED_IDX: # If "Staged" was previously selected try "Modified" and "Untracked". item = _get_first_item_with_children( root_item.child(MODIFIED_IDX), root_item.child(UNTRACKED_IDX) ) elif idx == UNMERGED_IDX: # If "Unmerged" was previously selected try "Staged". item = _get_first_item_with_children(root_item.child(STAGED_IDX)) elif idx == MODIFIED_IDX: # If "Modified" was previously selected try "Staged" or "Untracked". item = _get_first_item_with_children( root_item.child(STAGED_IDX), root_item.child(UNTRACKED_IDX) ) elif idx == UNTRACKED_IDX: # If "Untracked" was previously selected try "Staged". item = _get_first_item_with_children(root_item.child(STAGED_IDX)) if item is not None: with qtutils.BlockSignals(widget): widget.setCurrentItem(item) item.setSelected(True) widget.show_selection() return is_top_level_item def _get_first_item_with_children(*items): """Return the first item that contains child items""" for item in items: if item.childCount() > 0: return item return None def _transplant_selection_across_sections( category, idx, previous_contents, saved_selection ): """Transplant the selection to a different category""" # This function is used when the selection would otherwise become empty. # Apply heuristics to select the items based on the previous state. if not previous_contents: return staged, unmerged, modified, untracked = saved_selection prev_staged, prev_unmerged, prev_modified, prev_untracked = previous_contents # The current set of paths. staged_paths = staged[NEW_PATHS_IDX] unmerged_paths = unmerged[NEW_PATHS_IDX] modified_paths = modified[NEW_PATHS_IDX] untracked_paths = untracked[NEW_PATHS_IDX] # These callbacks select a path in the corresponding widget sub-tree lists. select_staged = staged[SELECT_FN_IDX] select_unmerged = unmerged[SELECT_FN_IDX] select_modified = modified[SELECT_FN_IDX] select_untracked = untracked[SELECT_FN_IDX] if category == STAGED_IDX: # Staged files can become Unmerged, Modified or Untracked. # If we previously had a staged file selected then try to select # it in either the Unmerged, Modified or Untracked sections. try: old_path = prev_staged[idx] except IndexError: return if old_path in unmerged_paths: select_unmerged(old_path, current=True) elif old_path in modified_paths: select_modified(old_path, current=True) elif old_path in untracked_paths: select_untracked(old_path, current=True) elif category == UNMERGED_IDX: # Unmerged files can become Staged, Modified or Untracked. # If we previously had an unmerged file selected then try to select it in # the Staged, Modified or Untracked sections. try: old_path = prev_unmerged[idx] except IndexError: return if old_path in staged_paths: select_staged(old_path, current=True) elif old_path in modified_paths: select_modified(old_path, current=True) elif old_path in untracked_paths: select_untracked(old_path, current=True) elif category == MODIFIED_IDX: # If we previously had a modified file selected then try to select # it in either the Staged or Untracked sections. try: old_path = prev_modified[idx] except IndexError: return if old_path in staged_paths: select_staged(old_path, current=True) elif old_path in untracked_paths: select_untracked(old_path, current=True) elif category == UNTRACKED_IDX: # If we previously had an untracked file selected then try to select # it in the Modified or Staged section. Modified is less common, but # it's possible for a file to be untracked and then the user adds and # modifies the file before we've refreshed our state. try: old_path = prev_untracked[idx] except IndexError: return if old_path in modified_paths: select_modified(old_path, current=True) elif old_path in staged_paths: select_staged(old_path, current=True) class CopyLeadingPathWidget(QtWidgets.QWidget): """A widget that holds a label and a spin-box for the number of paths to strip""" def __init__(self, title, context, parent): QtWidgets.QWidget.__init__(self, parent) self.context = context self.icon = QtWidgets.QLabel(self) self.label = QtWidgets.QLabel(self) self.spinbox = standard.SpinBox(value=1, mini=1, maxi=99, parent=self) self.spinbox.setToolTip(N_('The number of leading paths to strip')) icon = icons.copy() pixmap = icon.pixmap(defs.default_icon, defs.default_icon) self.icon.setPixmap(pixmap) self.label.setText(title) layout = qtutils.hbox( defs.small_margin, defs.titlebar_spacing, self.icon, self.label, qtutils.STRETCH, self.spinbox, ) self.setLayout(layout) theme = context.app.theme highlight_rgb = theme.highlight_color_rgb() text_rgb, highlight_text_rgb = theme.text_colors_rgb() disabled_text_rgb = theme.disabled_text_color_rgb() stylesheet = """ * {{ show-decoration-selected: 1 }} QLabel {{ color: {text_rgb}; show-decoration-selected: 1 }} QLabel:hover {{ color: {highlight_text_rgb}; background-color: {highlight_rgb}; background-clip: padding; show-decoration-selected: 1 }} QLabel:disabled {{ color: {disabled_text_rgb}; }} """.format( disabled_text_rgb=disabled_text_rgb, text_rgb=text_rgb, highlight_text_rgb=highlight_text_rgb, highlight_rgb=highlight_rgb, ) self.setStyleSheet(stylesheet) def value(self): """Return the current value of the spin-box""" return self.spinbox.value() def set_value(self, value): """Set the spin-box value""" self.spinbox.setValue(value) git-cola-4.6.1/cola/widgets/submodules.py000066400000000000000000000161671457126473700203740ustar00rootroot00000000000000"""Provides widgets related to submodules""" from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from .. import cmds from .. import compat from .. import core from .. import qtutils from .. import icons from ..i18n import N_ from ..widgets import defs from ..widgets import standard from ..widgets import text def add_submodule(context, parent): """Add a new submodule""" dlg = AddSubmodule(parent) dlg.show() if dlg.exec_() == standard.Dialog.Accepted: cmd = dlg.get(context) cmd.do() class SubmodulesWidget(QtWidgets.QFrame): def __init__(self, context, parent): super().__init__(parent) self.context = context self.setToolTip(N_('Submodules')) self.tree = SubmodulesTreeWidget(context, parent=self) self.setFocusProxy(self.tree) self.main_layout = qtutils.vbox(defs.no_margin, defs.spacing, self.tree) self.setLayout(self.main_layout) # Titlebar buttons self.add_button = qtutils.create_action_button( tooltip=N_('Add Submodule'), icon=icons.add() ) self.refresh_button = qtutils.create_action_button( tooltip=N_('Refresh'), icon=icons.sync() ) self.open_parent_button = qtutils.create_action_button( tooltip=N_('Open Parent'), icon=icons.repo() ) self.button_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.add_button, self.open_parent_button, self.refresh_button, ) self.corner_widget = QtWidgets.QWidget(self) self.corner_widget.setLayout(self.button_layout) titlebar = parent.titleBarWidget() titlebar.add_corner_widget(self.corner_widget) # Connections qtutils.connect_button(self.add_button, self.add_submodule) qtutils.connect_button(self.refresh_button, self.tree.update_model.emit) qtutils.connect_button( self.open_parent_button, cmds.run(cmds.OpenParentRepo, context) ) def add_submodule(self): add_submodule(self.context, self) class AddSubmodule(standard.Dialog): """Add a new submodule""" def __init__(self, parent): super().__init__(parent=parent) hint = N_('git://git.example.com/repo.git') tooltip = N_('Submodule URL (can be relative, ex: ../repo.git)') self.url_text = text.HintedDefaultLineEdit(hint, tooltip=tooltip, parent=self) hint = N_('path/to/submodule') tooltip = N_('Submodule path within the current repository (optional)') self.path_text = text.HintedDefaultLineEdit(hint, tooltip=tooltip, parent=self) hint = N_('Branch name') tooltip = N_('Submodule branch to track (optional)') self.branch_text = text.HintedDefaultLineEdit( hint, tooltip=tooltip, parent=self ) self.depth_spinbox = standard.SpinBox( mini=0, maxi=compat.maxint, value=0, parent=self ) self.depth_spinbox.setToolTip( N_( 'Create a shallow clone with history truncated to the ' 'specified number of revisions. 0 performs a full clone.' ) ) hint = N_('Reference URL') tooltip = N_('Reference repository to use when cloning (optional)') self.reference_text = text.HintedDefaultLineEdit( hint, tooltip=tooltip, parent=self ) self.add_button = qtutils.ok_button(N_('Add Submodule'), enabled=False) self.close_button = qtutils.close_button() self.form_layout = qtutils.form( defs.no_margin, defs.button_spacing, (N_('URL'), self.url_text), (N_('Path'), self.path_text), (N_('Branch'), self.branch_text), (N_('Depth'), self.depth_spinbox), (N_('Reference Repository'), self.reference_text), ) self.button_layout = qtutils.hbox( defs.no_margin, defs.button_spacing, qtutils.STRETCH, self.close_button, self.add_button, ) self.main_layout = qtutils.vbox( defs.large_margin, defs.spacing, self.form_layout, self.button_layout ) self.setLayout(self.main_layout) self.init_size(parent=qtutils.active_window()) self.url_text.textChanged.connect(lambda x: self._update_widgets()) qtutils.connect_button(self.add_button, self.accept) qtutils.connect_button(self.close_button, self.close) def _update_widgets(self): value = self.url_text.value() self.add_button.setEnabled(bool(value)) def get(self, context): return cmds.SubmoduleAdd( context, self.url_text.value(), self.path_text.value(), self.branch_text.value(), self.depth_spinbox.value(), self.reference_text.value(), ) class SubmodulesTreeWidget(standard.TreeWidget): update_model = Signal() def __init__(self, context, parent=None): standard.TreeWidget.__init__(self, parent=parent) model = context.model self.context = context self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) self.setHeaderHidden(True) # UI self._active = False self.list_helper = BuildItem() # Connections self.itemDoubleClicked.connect(self.tree_double_clicked) model.submodules_changed.connect(self.refresh, type=Qt.QueuedConnection) self.update_model.connect( model.update_submodules_list, type=Qt.QueuedConnection ) def refresh(self): if not self._active: return submodules = self.context.model.submodules_list items = [self.list_helper.get(entry) for entry in submodules] self.clear() if items: self.addTopLevelItems(items) def showEvent(self, event): """Defer updating widgets until the widget is visible""" if not self._active: self._active = True self.update_model.emit() return super().showEvent(event) def tree_double_clicked(self, item, _column): path = core.abspath(item.path) cmds.do(cmds.OpenRepo, self.context, path) class BuildItem: def __init__(self): self.state_folder_map = {} self.state_folder_map[''] = icons.folder() self.state_folder_map['+'] = icons.staged() self.state_folder_map['-'] = icons.modified() self.state_folder_map['U'] = icons.merge() def get(self, entry): """entry: same as returned from list_submodule""" name = entry[2] path = entry[2] tip = path + '\n' + entry[1] if entry[3]: tip += f'\n({entry[3]})' icon = self.state_folder_map[entry[0]] return SubmodulesTreeWidgetItem(name, path, tip, icon) class SubmodulesTreeWidgetItem(QtWidgets.QTreeWidgetItem): def __init__(self, name, path, tip, icon): QtWidgets.QTreeWidgetItem.__init__(self) self.path = path self.setIcon(0, icon) self.setText(0, name) self.setToolTip(0, tip) git-cola-4.6.1/cola/widgets/switcher.py000066400000000000000000000205531457126473700200340ustar00rootroot00000000000000"""Provides quick switcher""" import re from qtpy import QtCore from qtpy import QtGui from qtpy.QtCore import Qt from qtpy.QtCore import Signal from .. import qtutils from ..widgets import defs from ..widgets import standard from ..widgets import text def switcher_inner_view( context, entries, title=None, place_holder=None, enter_action=None, parent=None ): dialog = SwitcherInnerView( context, entries, title, place_holder, enter_action, parent ) dialog.show() return dialog def switcher_outer_view(context, entries, place_holder=None, parent=None): dialog = SwitcherOuterView(context, entries, place_holder, parent) dialog.show() return dialog def switcher_item(key, icon=None, name=None): return SwitcherListItem(key, icon, name) def moving_keys(): selection_move_keys = [ Qt.Key_Enter, Qt.Key_Return, Qt.Key_Up, Qt.Key_Down, Qt.Key_Home, Qt.Key_End, Qt.Key_PageUp, Qt.Key_PageDown, ] return selection_move_keys class Switcher(standard.Dialog): """ Quick switcher base class. This contains input field, filter proxy model. This will be inherited by outer-view class(SwitcherOuterView) or inner-view class (SwitcherInnerView). The inner-view class is a quick-switcher widget including view. In this case, this switcher will have switcher_list field, and show the items list in itself. The outer-view class is a quick-switcher widget without view(only input field), which shares model with other view class. The switcher_selection_move signal is the event that the selection move actions emit while the input field is focused. """ def __init__( self, context, entries_model, place_holder=None, parent=None, ): standard.Dialog.__init__(self, parent=parent) self.context = context self.entries_model = entries_model self.filter_input = SwitcherLineEdit(place_holder=place_holder, parent=self) self.proxy_model = SwitcherSortFilterProxyModel(entries_model, parent=self) self.switcher_list = None self.filter_input.textChanged.connect(self.filter_input_changed) def filter_input_changed(self): input_text = self.filter_input.text() pattern = '.*'.join(re.escape(c) for c in input_text) self.proxy_model.setFilterRegExp(pattern) class SwitcherInnerView(Switcher): def __init__( self, context, entries_model, title, place_holder=None, enter_action=None, parent=None, ): Switcher.__init__( self, context, entries_model, place_holder=place_holder, parent=parent, ) self.setWindowTitle(title) if parent is not None: self.setWindowModality(Qt.WindowModal) self.enter_action = enter_action self.switcher_list = SwitcherTreeView( self.proxy_model, self.enter_selected_item, parent=self ) self.main_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.filter_input, self.switcher_list ) self.setLayout(self.main_layout) # moving key has pressed while focusing on input field self.filter_input.switcher_selection_move.connect( self.switcher_list.keyPressEvent ) # escape key pressed while focusing on input field self.filter_input.switcher_escape.connect(self.close) self.filter_input.switcher_accept.connect(self.accept_selected_item) # some key except moving key has pressed while focusing on list view self.switcher_list.switcher_inner_text.connect(self.filter_input.keyPressEvent) # default selection for first index first_proxy_idx = self.proxy_model.index(0, 0) self.switcher_list.setCurrentIndex(first_proxy_idx) self.set_initial_geometry(parent) def accept_selected_item(self): item = self.switcher_list.selected_item() if item: self.enter_action(item) self.accept() def set_initial_geometry(self, parent): """Set the initial size and position""" if parent is None: return # Size width = parent.width() height = parent.height() self.resize(max(width * 2 // 3, 320), max(height * 2 // 3, 240)) def enter_selected_item(self, index): item = self.switcher_list.model().itemFromIndex(index) if item: self.enter_action(item) self.accept() class SwitcherOuterView(Switcher): def __init__(self, context, entries_model, place_holder=None, parent=None): Switcher.__init__( self, context, entries_model, place_holder=place_holder, parent=parent, ) self.filter_input.hide() self.main_layout = qtutils.vbox(defs.no_margin, defs.spacing, self.filter_input) self.setLayout(self.main_layout) def filter_input_changed(self): super().filter_input_changed() # Hide the input when it becomes empty. input_text = self.filter_input.text() if not input_text: self.filter_input.hide() class SwitcherLineEdit(text.LineEdit): """Quick switcher input line class""" # signal is for the event that selection move key like UP, DOWN has pressed # while focusing on this line edit widget switcher_selection_move = Signal(QtGui.QKeyEvent) switcher_visible = Signal(bool) switcher_accept = Signal() switcher_escape = Signal() def __init__(self, place_holder=None, parent=None): text.LineEdit.__init__(self, parent=parent) if place_holder: self.setPlaceholderText(place_holder) def keyPressEvent(self, event): """ To be able to move the selection while focus on the input field, input text field should be able to filter pressed key. If pressed key is moving selection key like UP or DOWN, the switcher_selection_move signal will be emitted and the view selection will be moved regardless whether Switcher is inner-view or outer-view. Or else, simply act like text input to the field. """ selection_moving_keys = moving_keys() pressed_key = event.key() if pressed_key == Qt.Key_Escape: self.switcher_escape.emit() elif pressed_key in (Qt.Key_Enter, Qt.Key_Return): self.switcher_accept.emit() elif pressed_key in selection_moving_keys: self.switcher_selection_move.emit(event) else: super().keyPressEvent(event) class SwitcherSortFilterProxyModel(QtCore.QSortFilterProxyModel): """Filtering class for candidate items.""" def __init__(self, entries, parent=None): QtCore.QSortFilterProxyModel.__init__(self, parent) self.entries = entries self.setDynamicSortFilter(True) self.setSourceModel(entries) self.setFilterCaseSensitivity(Qt.CaseInsensitive) def itemFromIndex(self, index): return self.entries.itemFromIndex(self.mapToSource(index)) class SwitcherTreeView(standard.TreeView): """Tree view class for showing proxy items in SwitcherSortFilterProxyModel""" # signal is for the event that some key except moving key has pressed # while focusing this view switcher_inner_text = Signal(QtGui.QKeyEvent) def __init__(self, entries_proxy_model, enter_action, parent=None): standard.TreeView.__init__(self, parent) self.setHeaderHidden(True) self.setModel(entries_proxy_model) self.doubleClicked.connect(enter_action) def keyPressEvent(self, event): """hooks when a key has pressed while focusing on list view""" selection_moving_keys = moving_keys() pressed_key = event.key() if pressed_key in selection_moving_keys or pressed_key == Qt.Key_Escape: super().keyPressEvent(event) else: self.switcher_inner_text.emit(event) class SwitcherListItem(QtGui.QStandardItem): """Item class for SwitcherTreeView and SwitcherSortFilterProxyModel""" def __init__(self, key, icon=None, name=None): QtGui.QStandardItem.__init__(self) self.key = key if not name: name = key self.setText(name) if icon: self.setIcon(icon) git-cola-4.6.1/cola/widgets/text.py000066400000000000000000001204201457126473700171620ustar00rootroot00000000000000"""Text widgets""" from functools import partial import math from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets from qtpy.QtCore import Qt from qtpy.QtCore import Signal from ..models import prefs from ..qtutils import get from .. import hotkeys from .. import icons from .. import qtutils from .. import utils from ..i18n import N_ from . import defs def get_stripped(widget): return widget.get().strip() class LineEdit(QtWidgets.QLineEdit): cursor_changed = Signal(int, int) esc_pressed = Signal() def __init__(self, parent=None, row=1, get_value=None, clear_button=False): QtWidgets.QLineEdit.__init__(self, parent) self._row = row if get_value is None: get_value = get_stripped self._get_value = get_value self.cursor_position = LineEditCursorPosition(self, row) self.menu_actions = [] if clear_button and hasattr(self, 'setClearButtonEnabled'): self.setClearButtonEnabled(True) def get(self): """Return the raw Unicode value from Qt""" return self.text() def value(self): """Return the processed value, e.g. stripped""" return self._get_value(self) def set_value(self, value, block=False): """Update the widget to the specified value""" if block: with qtutils.BlockSignals(self): self._set_value(value) else: self._set_value(value) def _set_value(self, value): """Implementation helper to update the widget to the specified value""" pos = self.cursorPosition() self.setText(value) self.setCursorPosition(pos) def keyPressEvent(self, event): key = event.key() if key == Qt.Key_Escape: self.esc_pressed.emit() super().keyPressEvent(event) class LineEditCursorPosition: """Translate cursorPositionChanged(int,int) into cursorPosition(int,int)""" def __init__(self, widget, row): self._widget = widget self._row = row # Translate cursorPositionChanged into cursor_changed(int, int) widget.cursorPositionChanged.connect(lambda old, new: self.emit()) def emit(self): widget = self._widget row = self._row col = widget.cursorPosition() widget.cursor_changed.emit(row, col) def reset(self): self._widget.setCursorPosition(0) class BaseTextEditExtension(QtCore.QObject): def __init__(self, widget, get_value, readonly): QtCore.QObject.__init__(self, widget) self.widget = widget self.cursor_position = TextEditCursorPosition(widget, self) if get_value is None: get_value = get_stripped self._get_value = get_value self._tabwidth = 8 self._readonly = readonly self._init_flags() self.init() def _init_flags(self): widget = self.widget widget.setMinimumSize(QtCore.QSize(10, 10)) widget.setWordWrapMode(QtGui.QTextOption.WordWrap) widget.setLineWrapMode(widget.NoWrap) if self._readonly: widget.setReadOnly(True) widget.setAcceptDrops(False) widget.setTabChangesFocus(True) widget.setUndoRedoEnabled(False) widget.setTextInteractionFlags( Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse ) def get(self): """Return the raw Unicode value from Qt""" return self.widget.toPlainText() def value(self): """Return a safe value, e.g. a stripped value""" return self._get_value(self.widget) def set_value(self, value, block=False): """Update the widget to the specified value""" if block: with qtutils.BlockSignals(self): self._set_value(value) else: self._set_value(value) def _set_value(self, value): """Implementation helper to update the widget to the specified value""" # Save cursor position offset, selection_text = self.offset_and_selection() old_value = get(self.widget) # Update text self.widget.setPlainText(value) # Restore cursor if selection_text and selection_text in value: # If the old selection exists in the new text then re-select it. idx = value.index(selection_text) cursor = self.widget.textCursor() cursor.setPosition(idx) cursor.setPosition(idx + len(selection_text), QtGui.QTextCursor.KeepAnchor) self.widget.setTextCursor(cursor) elif value == old_value: # Otherwise, if the text is identical and there is no selection # then restore the cursor position. cursor = self.widget.textCursor() cursor.setPosition(offset) self.widget.setTextCursor(cursor) else: # If none of the above applied then restore the cursor position. position = max(0, min(offset, len(value) - 1)) cursor = self.widget.textCursor() cursor.setPosition(position) self.widget.setTextCursor(cursor) cursor = self.widget.textCursor() cursor.movePosition(QtGui.QTextCursor.StartOfLine) self.widget.setTextCursor(cursor) def set_cursor_position(self, new_position): cursor = self.widget.textCursor() cursor.setPosition(new_position) self.widget.setTextCursor(cursor) def tabwidth(self): return self._tabwidth def set_tabwidth(self, width): self._tabwidth = width pixels = qtutils.text_width(self.widget.font(), 'M') * width self.widget.setTabStopWidth(pixels) def selected_line(self): contents = self.value() cursor = self.widget.textCursor() offset = min(cursor.position(), len(contents) - 1) while offset >= 1 and contents[offset - 1] and contents[offset - 1] != '\n': offset -= 1 data = contents[offset:] if '\n' in data: line, _ = data.split('\n', 1) else: line = data return line def cursor(self): return self.widget.textCursor() def has_selection(self): return self.cursor().hasSelection() def selected_text(self): """Return the selected text""" _, selection = self.offset_and_selection() return selection def offset_and_selection(self): """Return the cursor offset and selected text""" cursor = self.cursor() offset = cursor.selectionStart() selection_text = cursor.selection().toPlainText() return offset, selection_text def mouse_press_event(self, event): # Move the text cursor so that the right-click events operate # on the current position, not the last left-clicked position. widget = self.widget if event.button() == Qt.RightButton: if not widget.textCursor().hasSelection(): cursor = widget.cursorForPosition(event.pos()) widget.setTextCursor(cursor) def add_links_to_menu(self, menu): """Add actions for opening URLs to a custom menu""" links = self._get_links() if links: menu.addSeparator() for url in links: action = menu.addAction(N_('Open "%s"') % url) action.setIcon(icons.external()) qtutils.connect_action( action, partial(QtGui.QDesktopServices.openUrl, QtCore.QUrl(url)) ) def _get_links(self): """Return http links on the current line""" _, selection = self.offset_and_selection() if selection: line = selection else: line = self.selected_line() if not line: return [] return [ word for word in line.split() if word.startswith(('http://', 'https://')) ] def create_context_menu(self, event_pos): """Create a context menu for a widget""" menu = self.widget.createStandardContextMenu(event_pos) qtutils.add_menu_actions(menu, self.widget.menu_actions) self.add_links_to_menu(menu) return menu def context_menu_event(self, event): """Default context menu event""" event_pos = event.pos() menu = self.widget.create_context_menu(event_pos) menu.exec_(self.widget.mapToGlobal(event_pos)) # For extension by sub-classes def init(self): """Called during init for class-specific settings""" return def set_textwidth(self, width): """Set the text width""" return def set_linebreak(self, brk): """Enable word wrapping""" return class PlainTextEditExtension(BaseTextEditExtension): def set_linebreak(self, brk): if brk: wrapmode = QtWidgets.QPlainTextEdit.WidgetWidth else: wrapmode = QtWidgets.QPlainTextEdit.NoWrap self.widget.setLineWrapMode(wrapmode) class PlainTextEdit(QtWidgets.QPlainTextEdit): cursor_changed = Signal(int, int) leave = Signal() def __init__(self, parent=None, get_value=None, readonly=False, options=None): QtWidgets.QPlainTextEdit.__init__(self, parent) self.ext = PlainTextEditExtension(self, get_value, readonly) self.cursor_position = self.ext.cursor_position self.mouse_zoom = True self.options = options self.menu_actions = [] def get(self): """Return the raw Unicode value from Qt""" return self.ext.get() # For compatibility with QTextEdit def setText(self, value): self.set_value(value) def value(self): """Return a safe value, e.g. a stripped value""" return self.ext.value() def offset_and_selection(self): """Return the cursor offset and selected text""" return self.ext.offset_and_selection() def set_value(self, value, block=False): self.ext.set_value(value, block=block) def set_mouse_zoom(self, value): """Enable/disable text zooming in response to ctrl + mousewheel scroll events""" self.mouse_zoom = value def set_options(self, options): """Register an Options widget""" self.options = options def set_word_wrapping(self, enabled, update=False): """Enable/disable word wrapping""" if update and self.options is not None: with qtutils.BlockSignals(self.options.enable_word_wrapping): self.options.enable_word_wrapping.setChecked(enabled) if enabled: self.setWordWrapMode(QtGui.QTextOption.WordWrap) self.setLineWrapMode(QtWidgets.QPlainTextEdit.WidgetWidth) else: self.setWordWrapMode(QtGui.QTextOption.NoWrap) self.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) def has_selection(self): return self.ext.has_selection() def selected_line(self): return self.ext.selected_line() def selected_text(self): """Return the selected text""" return self.ext.selected_text() def set_tabwidth(self, width): self.ext.set_tabwidth(width) def set_textwidth(self, width): self.ext.set_textwidth(width) def set_linebreak(self, brk): self.ext.set_linebreak(brk) def mousePressEvent(self, event): self.ext.mouse_press_event(event) super().mousePressEvent(event) def wheelEvent(self, event): """Disable control+wheelscroll text resizing""" if not self.mouse_zoom and (event.modifiers() & Qt.ControlModifier): event.ignore() return super().wheelEvent(event) def create_context_menu(self, event_pos): """Create a custom context menu""" return self.ext.create_context_menu(event_pos) def contextMenuEvent(self, event): """Custom contextMenuEvent() for building our custom context menus""" self.ext.context_menu_event(event) class TextSearchWidget(QtWidgets.QWidget): """The search dialog that displays over a text edit field""" def __init__(self, widget, parent): super().__init__(parent) self.setAutoFillBackground(True) self._widget = widget self._parent = parent self.text = HintedDefaultLineEdit(N_('Find in diff'), parent=self) self.prev_button = qtutils.create_action_button( tooltip=N_('Find the previous occurrence of the phrase'), icon=icons.up() ) self.next_button = qtutils.create_action_button( tooltip=N_('Find the next occurrence of the phrase'), icon=icons.down() ) self.match_case_checkbox = qtutils.checkbox(N_('Match Case')) self.whole_words_checkbox = qtutils.checkbox(N_('Whole Words')) self.close_button = qtutils.create_action_button( tooltip=N_('Close the find bar'), icon=icons.close() ) layout = qtutils.hbox( defs.margin, defs.button_spacing, self.text, self.prev_button, self.next_button, self.match_case_checkbox, self.whole_words_checkbox, qtutils.STRETCH, self.close_button, ) self.setLayout(layout) self.setFocusProxy(self.text) self.text.esc_pressed.connect(self.hide_search) self.text.returnPressed.connect(self.search) self.text.textChanged.connect(self.search) self.search_next_action = qtutils.add_action( parent, N_('Find next item'), self.search, hotkeys.SEARCH_NEXT, ) self.search_prev_action = qtutils.add_action( parent, N_('Find previous item'), self.search_backwards, hotkeys.SEARCH_PREV, ) qtutils.connect_button(self.next_button, self.search) qtutils.connect_button(self.prev_button, self.search_backwards) qtutils.connect_button(self.close_button, self.hide_search) qtutils.connect_checkbox(self.match_case_checkbox, lambda _: self.search()) qtutils.connect_checkbox(self.whole_words_checkbox, lambda _: self.search()) def search(self): """Emit a signal with the current search text""" self.search_text(backwards=False) def search_backwards(self): """Emit a signal with the current search text for a backwards search""" self.search_text(backwards=True) def hide_search(self): """Hide the search window""" self.hide() self._parent.setFocus() def find_flags(self, backwards): """Return QTextDocument.FindFlags for the current search options""" flags = QtGui.QTextDocument.FindFlag(0) if backwards: flags = flags | QtGui.QTextDocument.FindBackward if self.match_case_checkbox.isChecked(): flags = flags | QtGui.QTextDocument.FindCaseSensitively if self.whole_words_checkbox.isChecked(): flags = flags | QtGui.QTextDocument.FindWholeWords return flags def is_case_sensitive(self): """Are we searching using a case-insensitive search?""" return self.match_case_checkbox.isChecked() def search_text(self, backwards=False): """Search the diff text for the given text""" text = self.text.get() cursor = self._widget.textCursor() if cursor.hasSelection(): selected_text = cursor.selectedText() case_sensitive = self.is_case_sensitive() if text_matches(case_sensitive, selected_text, text): if backwards: position = cursor.selectionStart() else: position = cursor.selectionEnd() else: if backwards: position = cursor.selectionEnd() else: position = cursor.selectionStart() cursor.setPosition(position) self._widget.setTextCursor(cursor) flags = self.find_flags(backwards) if not self._widget.find(text, flags): if backwards: location = QtGui.QTextCursor.End else: location = QtGui.QTextCursor.Start cursor.movePosition(location, QtGui.QTextCursor.MoveAnchor) self._widget.setTextCursor(cursor) self._widget.find(text, flags) def text_matches(case_sensitive, a, b): """Compare text with case sensitivity taken into account""" if case_sensitive: return a == b return a.lower() == b.lower() class TextEditExtension(BaseTextEditExtension): def init(self): widget = self.widget widget.setAcceptRichText(False) def set_linebreak(self, brk): if brk: wrapmode = QtWidgets.QTextEdit.FixedColumnWidth else: wrapmode = QtWidgets.QTextEdit.NoWrap self.widget.setLineWrapMode(wrapmode) def set_textwidth(self, width): self.widget.setLineWrapColumnOrWidth(width) class TextEdit(QtWidgets.QTextEdit): cursor_changed = Signal(int, int) leave = Signal() def __init__(self, parent=None, get_value=None, readonly=False): QtWidgets.QTextEdit.__init__(self, parent) self.ext = TextEditExtension(self, get_value, readonly) self.cursor_position = self.ext.cursor_position self.expandtab_enabled = False self.menu_actions = [] def get(self): """Return the raw Unicode value from Qt""" return self.ext.get() def value(self): """Return a safe value, e.g. a stripped value""" return self.ext.value() def set_cursor_position(self, position): """Set the cursor position""" cursor = self.textCursor() cursor.setPosition(position) self.setTextCursor(cursor) def set_value(self, value, block=False): self.ext.set_value(value, block=block) def selected_line(self): return self.ext.selected_line() def selected_text(self): """Return the selected text""" return self.ext.selected_text() def set_tabwidth(self, width): self.ext.set_tabwidth(width) def set_textwidth(self, width): self.ext.set_textwidth(width) def set_linebreak(self, brk): self.ext.set_linebreak(brk) def set_expandtab(self, value): self.expandtab_enabled = value def mousePressEvent(self, event): self.ext.mouse_press_event(event) super().mousePressEvent(event) def wheelEvent(self, event): """Disable control+wheelscroll text resizing""" if event.modifiers() & Qt.ControlModifier: event.ignore() return super().wheelEvent(event) def should_expandtab(self, event): return event.key() == Qt.Key_Tab and self.expandtab_enabled def expandtab(self): tabwidth = max(self.ext.tabwidth(), 1) cursor = self.textCursor() cursor.insertText(' ' * tabwidth) def create_context_menu(self, event_pos): """Create a custom context menu""" return self.ext.create_context_menu(event_pos) def contextMenuEvent(self, event): """Custom contextMenuEvent() for building our custom context menus""" self.ext.context_menu_event(event) def keyPressEvent(self, event): """Override keyPressEvent to handle tab expansion""" expandtab = self.should_expandtab(event) if expandtab: self.expandtab() event.accept() else: QtWidgets.QTextEdit.keyPressEvent(self, event) def keyReleaseEvent(self, event): """Override keyReleaseEvent to special-case tab expansion""" expandtab = self.should_expandtab(event) if expandtab: event.ignore() else: QtWidgets.QTextEdit.keyReleaseEvent(self, event) class TextEditCursorPosition: def __init__(self, widget, ext): self._widget = widget self._ext = ext widget.cursorPositionChanged.connect(self.emit) def emit(self): widget = self._widget ext = self._ext cursor = widget.textCursor() position = cursor.position() txt = widget.get() before = txt[:position] row = before.count('\n') line = before.split('\n')[row] col = cursor.columnNumber() col += line[:col].count('\t') * (ext.tabwidth() - 1) widget.cursor_changed.emit(row + 1, col) def reset(self): widget = self._widget cursor = widget.textCursor() cursor.setPosition(0) widget.setTextCursor(cursor) class MonoTextEdit(PlainTextEdit): def __init__(self, context, parent=None, readonly=False): PlainTextEdit.__init__(self, parent=parent, readonly=readonly) self.setFont(qtutils.diff_font(context)) def get_value_hinted(widget): text = get_stripped(widget) hint = get(widget.hint) if text == hint: return '' return text class HintWidget(QtCore.QObject): """Extend a widget to provide hint messages This primarily exists because setPlaceholderText() is only available in Qt5, so this class provides consistent behavior across versions. """ def __init__(self, widget, hint): QtCore.QObject.__init__(self, widget) self._widget = widget self._hint = hint self._is_error = False self.modern = modern = hasattr(widget, 'setPlaceholderText') if modern: widget.setPlaceholderText(hint) # Palette for normal text QPalette = QtGui.QPalette palette = widget.palette() hint_color = palette.color(QPalette.Disabled, QPalette.Text) error_bg_color = QtGui.QColor(Qt.red).darker() error_fg_color = QtGui.QColor(Qt.white) hint_rgb = qtutils.rgb_css(hint_color) error_bg_rgb = qtutils.rgb_css(error_bg_color) error_fg_rgb = qtutils.rgb_css(error_fg_color) env = { 'name': widget.__class__.__name__, 'error_fg_rgb': error_fg_rgb, 'error_bg_rgb': error_bg_rgb, 'hint_rgb': hint_rgb, } self._default_style = '' self._hint_style = ( """ %(name)s { color: %(hint_rgb)s; } """ % env ) self._error_style = ( """ %(name)s { color: %(error_fg_rgb)s; background-color: %(error_bg_rgb)s; } """ % env ) def init(self): """Deferred initialization""" if self.modern: self.widget().setPlaceholderText(self.value()) else: self.widget().installEventFilter(self) self.enable(True) def widget(self): """Return the parent text widget""" return self._widget def active(self): """Return True when hint-mode is active""" return self.value() == get_stripped(self._widget) def value(self): """Return the current hint text""" return self._hint def set_error(self, is_error): """Enable/disable error mode""" self._is_error = is_error self.refresh() def set_value(self, hint): """Change the hint text""" if self.modern: self._hint = hint self._widget.setPlaceholderText(hint) else: # If hint-mode is currently active, re-activate it active = self.active() self._hint = hint if active or self.active(): self.enable(True) def enable(self, enable): """Enable/disable hint-mode""" if not self.modern: if enable and self._hint: self._widget.set_value(self._hint, block=True) self._widget.cursor_position.reset() else: self._widget.clear() self._update_palette(enable) def refresh(self): """Update the palette to match the current mode""" self._update_palette(self.active()) def _update_palette(self, hint): """Update to palette for normal/error/hint mode""" if self._is_error: style = self._error_style elif not self.modern and hint: style = self._hint_style else: style = self._default_style QtCore.QTimer.singleShot( 0, lambda: utils.catch_runtime_error(self._widget.setStyleSheet, style) ) def eventFilter(self, _obj, event): """Enable/disable hint-mode when focus changes""" etype = event.type() if etype == QtCore.QEvent.FocusIn: self.focus_in() elif etype == QtCore.QEvent.FocusOut: self.focus_out() return False def focus_in(self): """Disable hint-mode when focused""" widget = self.widget() if self.active(): self.enable(False) widget.cursor_position.emit() def focus_out(self): """Re-enable hint-mode when losing focus""" widget = self.widget() valid, value = utils.catch_runtime_error(get, widget) if not valid: # The widget may have just been destroyed during application shutdown. # We're receiving a focusOut event but the widget can no longer be used. # This can be safely ignored. return if not value: self.enable(True) class HintedPlainTextEdit(PlainTextEdit): """A hinted plain text edit""" def __init__(self, context, hint, parent=None, readonly=False): PlainTextEdit.__init__( self, parent=parent, get_value=get_value_hinted, readonly=readonly ) self.hint = HintWidget(self, hint) self.hint.init() self.context = context self.setFont(qtutils.diff_font(context)) self.set_tabwidth(prefs.tabwidth(context)) # Refresh palettes when text changes self.textChanged.connect(self.hint.refresh) self.set_mouse_zoom(context.cfg.get(prefs.MOUSE_ZOOM, default=True)) def set_value(self, value, block=False): """Set the widget text or enable hint mode when empty""" if value or self.hint.modern: PlainTextEdit.set_value(self, value, block=block) else: self.hint.enable(True) class HintedTextEdit(TextEdit): """A hinted text edit""" def __init__(self, context, hint, parent=None, readonly=False): TextEdit.__init__( self, parent=parent, get_value=get_value_hinted, readonly=readonly ) self.context = context self.hint = HintWidget(self, hint) self.hint.init() # Refresh palettes when text changes self.textChanged.connect(self.hint.refresh) self.setFont(qtutils.diff_font(context)) def set_value(self, value, block=False): """Set the widget text or enable hint mode when empty""" if value or self.hint.modern: TextEdit.set_value(self, value, block=block) else: self.hint.enable(True) def anchor_mode(select): """Return the QTextCursor mode to keep/discard the cursor selection""" if select: mode = QtGui.QTextCursor.KeepAnchor else: mode = QtGui.QTextCursor.MoveAnchor return mode # The vim-like read-only text view class VimMixin: def __init__(self, widget): self.widget = widget self.Base = widget.Base # Common vim/Unix-ish keyboard actions self.add_navigation('End', hotkeys.GOTO_END) self.add_navigation('Up', hotkeys.MOVE_UP, shift=hotkeys.MOVE_UP_SHIFT) self.add_navigation('Down', hotkeys.MOVE_DOWN, shift=hotkeys.MOVE_DOWN_SHIFT) self.add_navigation('Left', hotkeys.MOVE_LEFT, shift=hotkeys.MOVE_LEFT_SHIFT) self.add_navigation('Right', hotkeys.MOVE_RIGHT, shift=hotkeys.MOVE_RIGHT_SHIFT) self.add_navigation('WordLeft', hotkeys.WORD_LEFT) self.add_navigation('WordRight', hotkeys.WORD_RIGHT) self.add_navigation('Start', hotkeys.GOTO_START) self.add_navigation('StartOfLine', hotkeys.START_OF_LINE) self.add_navigation('EndOfLine', hotkeys.END_OF_LINE) qtutils.add_action( widget, 'PageUp', widget.page_up, hotkeys.SECONDARY_ACTION, hotkeys.TEXT_UP, ) qtutils.add_action( widget, 'PageDown', widget.page_down, hotkeys.PRIMARY_ACTION, hotkeys.TEXT_DOWN, ) qtutils.add_action( widget, 'SelectPageUp', lambda: widget.page_up(select=True), hotkeys.SELECT_BACK, hotkeys.SELECT_UP, ) qtutils.add_action( widget, 'SelectPageDown', lambda: widget.page_down(select=True), hotkeys.SELECT_FORWARD, hotkeys.SELECT_DOWN, ) def add_navigation(self, name, hotkey, shift=None): """Add a hotkey along with a shift-variant""" widget = self.widget direction = getattr(QtGui.QTextCursor, name) qtutils.add_action(widget, name, lambda: self.move(direction), hotkey) if shift: qtutils.add_action( widget, 'Shift' + name, lambda: self.move(direction, select=True), shift ) def move(self, direction, select=False, n=1): widget = self.widget cursor = widget.textCursor() mode = anchor_mode(select) for _ in range(n): if cursor.movePosition(direction, mode, 1): self.set_text_cursor(cursor) def page(self, offset, select=False): widget = self.widget rect = widget.cursorRect() x = rect.x() y = rect.y() + offset new_cursor = widget.cursorForPosition(QtCore.QPoint(x, y)) if new_cursor is not None: cursor = widget.textCursor() mode = anchor_mode(select) cursor.setPosition(new_cursor.position(), mode) self.set_text_cursor(cursor) def page_down(self, select=False): widget = self.widget widget.page(widget.height() // 2, select=select) def page_up(self, select=False): widget = self.widget widget.page(-widget.height() // 2, select=select) def set_text_cursor(self, cursor): widget = self.widget widget.setTextCursor(cursor) widget.ensureCursorVisible() widget.viewport().update() def keyPressEvent(self, event): """Custom keyboard behaviors The leave() signal is emitted when `Up` is pressed and we're already at the beginning of the text. This allows the parent widget to orchestrate some higher-level interaction, such as giving focus to another widget. When in the middle of the first line and `Up` is pressed, the cursor is moved to the beginning of the line. """ widget = self.widget if event.key() == Qt.Key_Up: cursor = widget.textCursor() position = cursor.position() if position == 0: # The cursor is at the beginning of the line. # Emit a signal so that the parent can e.g. change focus. widget.leave.emit() elif get(widget)[:position].count('\n') == 0: # The cursor is in the middle of the first line of text. # We can't go up ~ jump to the beginning of the line. # Select the text if shift is pressed. select = event.modifiers() & Qt.ShiftModifier mode = anchor_mode(select) cursor.movePosition(QtGui.QTextCursor.StartOfLine, mode) widget.setTextCursor(cursor) return self.Base.keyPressEvent(widget, event) class VimHintedPlainTextEdit(HintedPlainTextEdit): """HintedPlainTextEdit with vim hotkeys This can only be used in read-only mode. """ Base = HintedPlainTextEdit Mixin = VimMixin def __init__(self, context, hint, parent=None): HintedPlainTextEdit.__init__(self, context, hint, parent=parent, readonly=True) self._mixin = self.Mixin(self) def move(self, direction, select=False, n=1): return self._mixin.page(direction, select=select, n=n) def page(self, offset, select=False): return self._mixin.page(offset, select=select) def page_up(self, select=False): return self._mixin.page_up(select=select) def page_down(self, select=False): return self._mixin.page_down(select=select) def keyPressEvent(self, event): return self._mixin.keyPressEvent(event) class VimTextEdit(MonoTextEdit): """Text viewer with vim-like hotkeys This can only be used in read-only mode. """ Base = MonoTextEdit Mixin = VimMixin def __init__(self, context, parent=None, readonly=True): MonoTextEdit.__init__(self, context, parent=None, readonly=readonly) self._mixin = self.Mixin(self) def move(self, direction, select=False, n=1): return self._mixin.page(direction, select=select, n=n) def page(self, offset, select=False): return self._mixin.page(offset, select=select) def page_up(self, select=False): return self._mixin.page_up(select=select) def page_down(self, select=False): return self._mixin.page_down(select=select) def keyPressEvent(self, event): return self._mixin.keyPressEvent(event) class HintedDefaultLineEdit(LineEdit): """A line edit with hint text""" def __init__(self, hint, tooltip=None, parent=None): LineEdit.__init__(self, parent=parent, get_value=get_value_hinted) if tooltip: self.setToolTip(tooltip) self.hint = HintWidget(self, hint) self.hint.init() self.textChanged.connect(lambda text: self.hint.refresh()) class HintedLineEdit(HintedDefaultLineEdit): """A monospace line edit with hint text""" def __init__(self, context, hint, tooltip=None, parent=None): super().__init__(hint, tooltip=tooltip, parent=parent) self.setFont(qtutils.diff_font(context)) def text_dialog(context, text, title): """Show a wall of text in a dialog""" parent = qtutils.active_window() label = QtWidgets.QLabel(parent) label.setFont(qtutils.diff_font(context)) label.setText(text) label.setMargin(defs.large_margin) text_flags = Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse label.setTextInteractionFlags(text_flags) widget = QtWidgets.QDialog(parent) widget.setWindowModality(Qt.WindowModal) widget.setWindowTitle(title) scroll = QtWidgets.QScrollArea() scroll.setWidget(label) layout = qtutils.hbox(defs.margin, defs.spacing, scroll) widget.setLayout(layout) qtutils.add_action( widget, N_('Close'), widget.accept, Qt.Key_Question, Qt.Key_Enter, Qt.Key_Return ) widget.show() return widget class VimTextBrowser(VimTextEdit): """Text viewer with line number annotations""" def __init__(self, context, parent=None, readonly=True): VimTextEdit.__init__(self, context, parent=parent, readonly=readonly) self.numbers = LineNumbers(self) def resizeEvent(self, event): super().resizeEvent(event) self.numbers.refresh_size() class TextDecorator(QtWidgets.QWidget): """Common functionality for providing line numbers in text widgets""" def __init__(self, parent): QtWidgets.QWidget.__init__(self, parent) self.editor = parent parent.blockCountChanged.connect(lambda x: self._refresh_viewport()) parent.cursorPositionChanged.connect(self.refresh) parent.updateRequest.connect(self._refresh_rect) def refresh(self): """Refresh the numbers display""" rect = self.editor.viewport().rect() self._refresh_rect(rect, 0) def _refresh_rect(self, rect, dy): if dy: self.scroll(0, dy) else: self.update(0, rect.y(), self.width(), rect.height()) if rect.contains(self.editor.viewport().rect()): self._refresh_viewport() def _refresh_viewport(self): self.editor.setViewportMargins(self.width_hint(), 0, 0, 0) def refresh_size(self): rect = self.editor.contentsRect() geom = QtCore.QRect(rect.left(), rect.top(), self.width_hint(), rect.height()) self.setGeometry(geom) def sizeHint(self): return QtCore.QSize(self.width_hint(), 0) class LineNumbers(TextDecorator): """Provide line numbers for QPlainTextEdit widgets""" def __init__(self, parent): TextDecorator.__init__(self, parent) self.highlight_line = -1 def width_hint(self): document = self.editor.document() digits = int(math.log(max(1, document.blockCount()), 10)) + 2 text_width = qtutils.text_width(self.font(), '0') return defs.large_margin + (text_width * digits) def set_highlighted(self, line_number): """Set the line to highlight""" self.highlight_line = line_number def paintEvent(self, event): """Paint the line number""" QPalette = QtGui.QPalette painter = QtGui.QPainter(self) editor = self.editor palette = editor.palette() painter.fillRect(event.rect(), palette.color(QPalette.Base)) content_offset = editor.contentOffset() block = editor.firstVisibleBlock() width = self.width() event_rect_bottom = event.rect().bottom() highlight = palette.color(QPalette.Highlight) highlighted_text = palette.color(QPalette.HighlightedText) disabled = palette.color(QPalette.Disabled, QPalette.Text) while block.isValid(): block_geom = editor.blockBoundingGeometry(block) block_top = block_geom.translated(content_offset).top() if not block.isVisible() or block_top >= event_rect_bottom: break rect = block_geom.translated(content_offset).toRect() block_number = block.blockNumber() if block_number == self.highlight_line: painter.fillRect(rect.x(), rect.y(), width, rect.height(), highlight) painter.setPen(highlighted_text) else: painter.setPen(disabled) number = '%s' % (block_number + 1) painter.drawText( rect.x(), rect.y(), self.width() - defs.large_margin, rect.height(), Qt.AlignRight | Qt.AlignVCenter, number, ) block = block.next() class TextLabel(QtWidgets.QLabel): """A text label that elides its display""" def __init__(self, parent=None, open_external_links=True): QtWidgets.QLabel.__init__(self, parent) self._display = '' self._template = '' self._text = '' self._elide = False self._metrics = QtGui.QFontMetrics(self.font()) policy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Minimum ) self.setSizePolicy(policy) self.setTextInteractionFlags( Qt.TextSelectableByMouse | Qt.LinksAccessibleByMouse ) self.setOpenExternalLinks(open_external_links) 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 text != self._template: self._display = text # Qt overrides def setFont(self, font): self._metrics = QtGui.QFontMetrics(font) QtWidgets.QLabel.setFont(self, font) def resizeEvent(self, event): if self._elide: self.update_text(event.size().width()) with qtutils.BlockSignals(self): self.setText(self._display) QtWidgets.QLabel.resizeEvent(self, event) class PlainTextLabel(TextLabel): """A plaintext label that elides its display""" def __init__(self, parent=None): super().__init__(parent=parent, open_external_links=False) self.setTextFormat(Qt.PlainText) class RichTextLabel(TextLabel): """A richtext label that elides its display""" def __init__(self, parent=None): super().__init__(parent=parent, open_external_links=True) self.setTextFormat(Qt.RichText) git-cola-4.6.1/cola/widgets/toolbar.py000066400000000000000000000441661457126473700176540ustar00rootroot00000000000000from functools import partial from qtpy import QtGui from qtpy.QtCore import Qt from qtpy import QtWidgets from ..i18n import N_ from .. import icons from .. import qtutils from . import defs from . import standard from .toolbarcmds import COMMANDS TREE_LAYOUT = { 'Others': ['Others::LaunchEditor', 'Others::RevertUnstagedEdits'], 'File': [ 'File::QuickOpen', 'File::NewRepo', 'File::OpenRepo', 'File::OpenRepoNewWindow', 'File::Refresh', 'File::EditRemotes', 'File::RecentModified', 'File::SaveAsTarZip', 'File::ApplyPatches', 'File::ExportPatches', ], 'Actions': [ 'Actions::Fetch', 'Actions::Pull', 'Actions::Push', 'Actions::Stash', 'Actions::CreateTag', 'Actions::CherryPick', 'Actions::Merge', 'Actions::AbortMerge', 'Actions::UpdateSubmodules', 'Actions::Grep', 'Actions::Search', ], 'Commit@@verb': [ 'Commit::Stage', 'Commit::AmendLast', 'Commit::UndoLastCommit', 'Commit::StageModified', 'Commit::StageUntracked', 'Commit::UnstageAll', 'Commit::Unstage', 'Commit::LoadCommitMessage', 'Commit::GetCommitMessageTemplate', ], 'Diff': ['Diff::Difftool', 'Diff::Expression', 'Diff::Branches', 'Diff::Diffstat'], 'Branch': [ 'Branch::Review', 'Branch::Create', 'Branch::Checkout', 'Branch::Delete', 'Branch::DeleteRemote', 'Branch::Rename', 'Branch::BrowseCurrent', 'Branch::BrowseOther', 'Branch::VisualizeCurrent', 'Branch::VisualizeAll', ], 'Reset': [ 'Commit::UndoLastCommit', 'Commit::UnstageAll', 'Actions::ResetSoft', 'Actions::ResetMixed', 'Actions::RestoreWorktree', 'Actions::ResetKeep', 'Actions::ResetHard', ], 'View': ['View::DAG', 'View::FileBrowser'], } # Backwards-compatibility: Commit::StageUntracked was previously # exposed as Commit::StageUntracked. RENAMED = { 'Commit::StageAll': 'Commit::StageUntracked', } def configure(toolbar, parent=None): """Launches the Toolbar configure dialog""" if not parent: parent = qtutils.active_window() view = ToolbarView(toolbar, parent) view.show() return view def get_toolbars(widget): return widget.findChildren(ToolBar) def add_toolbar(context, widget): toolbars = get_toolbars(widget) name = 'ToolBar%d' % (len(toolbars) + 1) toolbar = ToolBar.create(context, name) widget.addToolBar(toolbar) configure(toolbar) class ToolBarState: """export_state() and apply_state() providers for toolbars""" def __init__(self, context, widget): """widget must be a QMainWindow for toolBarArea(), etc.""" self.context = context self.widget = widget def apply_state(self, toolbars): context = self.context widget = self.widget for data in toolbars: toolbar = ToolBar.create(context, data['name']) toolbar.load_items(data['items']) try: toolbar.set_toolbar_style(data['toolbar_style']) except KeyError: # Maintain compatibility for toolbars created in git-cola <= 3.11.0 if data['show_icons']: data['toolbar_style'] = ToolBar.STYLE_FOLLOW_SYSTEM toolbar.set_toolbar_style(ToolBar.STYLE_FOLLOW_SYSTEM) else: data['toolbar_style'] = ToolBar.STYLE_TEXT_ONLY toolbar.set_toolbar_style(ToolBar.STYLE_TEXT_ONLY) toolbar.setVisible(data['visible']) toolbar_area = decode_toolbar_area(data['area']) if data['break']: widget.addToolBarBreak(toolbar_area) widget.addToolBar(toolbar_area, toolbar) # floating toolbars must be set after added if data['float']: toolbar.setWindowFlags(Qt.Tool | Qt.FramelessWindowHint) toolbar.move(data['x'], data['y']) def export_state(self): result = [] widget = self.widget toolbars = widget.findChildren(ToolBar) for toolbar in toolbars: toolbar_area = widget.toolBarArea(toolbar) if toolbar_area == Qt.NoToolBarArea: continue # filter out removed toolbars items = [x.data() for x in toolbar.actions()] # show_icons is for backwards compatibility with git-cola <= 3.11.0 show_icons = toolbar.toolbar_style() != ToolBar.STYLE_TEXT_ONLY result.append({ 'name': toolbar.windowTitle(), 'area': encode_toolbar_area(toolbar_area), 'break': widget.toolBarBreak(toolbar), 'float': toolbar.isFloating(), 'x': toolbar.pos().x(), 'y': toolbar.pos().y(), 'width': toolbar.width(), 'height': toolbar.height(), 'show_icons': show_icons, 'toolbar_style': toolbar.toolbar_style(), 'visible': toolbar.isVisible(), 'items': items, }) return result class ToolBar(QtWidgets.QToolBar): SEPARATOR = 'Separator' STYLE_FOLLOW_SYSTEM = 'follow-system' STYLE_ICON_ONLY = 'icon' STYLE_TEXT_ONLY = 'text' STYLE_TEXT_BESIDE_ICON = 'text-beside-icon' STYLE_TEXT_UNDER_ICON = 'text-under-icon' STYLE_NAMES = [ N_('Follow System Style'), N_('Icon Only'), N_('Text Only'), N_('Text Beside Icon'), N_('Text Under Icon'), ] STYLE_SYMBOLS = [ STYLE_FOLLOW_SYSTEM, STYLE_ICON_ONLY, STYLE_TEXT_ONLY, STYLE_TEXT_BESIDE_ICON, STYLE_TEXT_UNDER_ICON, ] @staticmethod def create(context, name): return ToolBar(context, name, TREE_LAYOUT, COMMANDS) def __init__(self, context, title, tree_layout, toolbar_commands): QtWidgets.QToolBar.__init__(self) self.setWindowTitle(title) self.setObjectName(title) self.setToolButtonStyle(Qt.ToolButtonFollowStyle) self.context = context self.tree_layout = tree_layout self.commands = toolbar_commands def set_toolbar_style(self, style_id): style_to_qt = { self.STYLE_FOLLOW_SYSTEM: Qt.ToolButtonFollowStyle, self.STYLE_ICON_ONLY: Qt.ToolButtonIconOnly, self.STYLE_TEXT_ONLY: Qt.ToolButtonTextOnly, self.STYLE_TEXT_BESIDE_ICON: Qt.ToolButtonTextBesideIcon, self.STYLE_TEXT_UNDER_ICON: Qt.ToolButtonTextUnderIcon, } default = Qt.ToolButtonFollowStyle return self.setToolButtonStyle(style_to_qt.get(style_id, default)) def toolbar_style(self): qt_to_style = { Qt.ToolButtonFollowStyle: self.STYLE_FOLLOW_SYSTEM, Qt.ToolButtonIconOnly: self.STYLE_ICON_ONLY, Qt.ToolButtonTextOnly: self.STYLE_TEXT_ONLY, Qt.ToolButtonTextBesideIcon: self.STYLE_TEXT_BESIDE_ICON, Qt.ToolButtonTextUnderIcon: self.STYLE_TEXT_UNDER_ICON, } default = self.STYLE_FOLLOW_SYSTEM return qt_to_style.get(self.toolButtonStyle(), default) def load_items(self, items): for data in items: self.add_action_from_data(data) def add_action_from_data(self, data): parent = data['parent'] child = data['child'] child = RENAMED.get(child, child) if child == self.SEPARATOR: toolbar_action = self.addSeparator() toolbar_action.setData(data) return tree_items = self.tree_layout.get(parent, []) if child in tree_items and child in self.commands: command = self.commands[child] title = N_(command['title']) callback = partial(command['action'], self.context) tooltip = command.get('tooltip', None) icon = None command_icon = command.get('icon', None) if command_icon: icon = getattr(icons, command_icon, None) if callable(icon): icon = icon() if icon: toolbar_action = self.addAction(icon, title, callback) else: toolbar_action = self.addAction(title, callback) toolbar_action.setData(data) tooltip = command.get('tooltip', None) if tooltip: toolbar_action.setToolTip(f'{title}\n{tooltip}') def delete_toolbar(self): self.parent().removeToolBar(self) def contextMenuEvent(self, event): menu = QtWidgets.QMenu() tool_config = menu.addAction(N_('Configure Toolbar'), partial(configure, self)) tool_config.setIcon(icons.configure()) tool_delete = menu.addAction(N_('Delete Toolbar'), self.delete_toolbar) tool_delete.setIcon(icons.remove()) menu.exec_(event.globalPos()) def encode_toolbar_area(toolbar_area): """Encode a Qt::ToolBarArea as a string""" default = 'bottom' return { Qt.LeftToolBarArea: 'left', Qt.RightToolBarArea: 'right', Qt.TopToolBarArea: 'top', Qt.BottomToolBarArea: 'bottom', }.get(toolbar_area, default) def decode_toolbar_area(string): """Decode an encoded toolbar area string into a Qt::ToolBarArea""" default = Qt.BottomToolBarArea return { 'left': Qt.LeftToolBarArea, 'right': Qt.RightToolBarArea, 'top': Qt.TopToolBarArea, 'bottom': Qt.BottomToolBarArea, }.get(string, default) class ToolbarView(standard.Dialog): """Provides the git-cola 'ToolBar' configure dialog""" SEPARATOR_TEXT = '----------------------------' def __init__(self, toolbar, parent=None): standard.Dialog.__init__(self, parent) self.setWindowTitle(N_('Configure Toolbar')) self.toolbar = toolbar self.left_list = ToolbarTreeWidget(self) self.right_list = DraggableListWidget(self) self.text_toolbar_name = QtWidgets.QLabel() self.text_toolbar_name.setText(N_('Name')) self.toolbar_name = QtWidgets.QLineEdit() self.toolbar_name.setText(toolbar.windowTitle()) self.add_separator = qtutils.create_button(N_('Add Separator')) self.remove_item = qtutils.create_button(N_('Remove Element')) self.toolbar_style_label = QtWidgets.QLabel(N_('Toolbar Style:')) self.toolbar_style = QtWidgets.QComboBox() for style_name in ToolBar.STYLE_NAMES: self.toolbar_style.addItem(style_name) style_idx = get_index_from_style(toolbar.toolbar_style()) self.toolbar_style.setCurrentIndex(style_idx) self.apply_button = qtutils.ok_button(N_('Apply')) self.close_button = qtutils.close_button() self.close_button.setDefault(True) self.right_actions = qtutils.hbox( defs.no_margin, defs.spacing, self.add_separator, self.remove_item ) self.name_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.text_toolbar_name, self.toolbar_name ) self.left_layout = qtutils.vbox(defs.no_margin, defs.spacing, self.left_list) self.right_layout = qtutils.vbox( defs.no_margin, defs.spacing, self.right_list, self.right_actions ) self.top_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.left_layout, self.right_layout ) self.actions_layout = qtutils.hbox( defs.no_margin, defs.spacing, self.toolbar_style_label, self.toolbar_style, qtutils.STRETCH, self.close_button, self.apply_button, ) self.main_layout = qtutils.vbox( defs.margin, defs.spacing, self.name_layout, self.top_layout, self.actions_layout, ) self.setLayout(self.main_layout) qtutils.connect_button(self.add_separator, self.add_separator_action) qtutils.connect_button(self.remove_item, self.remove_item_action) qtutils.connect_button(self.apply_button, self.apply_action) qtutils.connect_button(self.close_button, self.accept) self.load_right_items() self.load_left_items() self.init_size(parent=parent) def load_right_items(self): commands = self.toolbar.commands for action in self.toolbar.actions(): data = action.data() try: command_name = data['child'] except KeyError: continue command_name = RENAMED.get(command_name, command_name) if command_name == self.toolbar.SEPARATOR: self.add_separator_action() continue try: command = commands[command_name] except KeyError: continue title = command['title'] icon = command.get('icon', None) tooltip = command.get('tooltip', None) self.right_list.add_item(title, tooltip, data, icon) def load_left_items(self): commands = self.toolbar.commands for parent in self.toolbar.tree_layout: top = self.left_list.insert_top(parent) for item in self.toolbar.tree_layout[parent]: item = RENAMED.get(item, item) try: command = commands[item] except KeyError: continue icon = command.get('icon', None) tooltip = command.get('tooltip', None) child = create_child(parent, item, command['title'], tooltip, icon) top.appendRow(child) top.sortChildren(0, Qt.AscendingOrder) def add_separator_action(self): data = {'parent': None, 'child': self.toolbar.SEPARATOR} self.right_list.add_separator(self.SEPARATOR_TEXT, data) def remove_item_action(self): items = self.right_list.selectedItems() for item in items: self.right_list.takeItem(self.right_list.row(item)) def apply_action(self): self.toolbar.clear() style = get_style_from_index(self.toolbar_style.currentIndex()) self.toolbar.set_toolbar_style(style) self.toolbar.setWindowTitle(self.toolbar_name.text()) for item in self.right_list.get_items(): data = item.data(Qt.UserRole) self.toolbar.add_action_from_data(data) def get_style_from_index(index): """Return the symbolic toolbar style name for the given (combobox) index""" return ToolBar.STYLE_SYMBOLS[index] def get_index_from_style(style): """Return the toolbar style (combobox) index for the symbolic name""" return ToolBar.STYLE_SYMBOLS.index(style) class DraggableListMixin: items = [] def __init__(self, widget, Base): self.widget = widget self.Base = Base widget.setAcceptDrops(True) widget.setSelectionMode(widget.SingleSelection) widget.setDragEnabled(True) widget.setDropIndicatorShown(True) def dragEnterEvent(self, event): widget = self.widget self.Base.dragEnterEvent(widget, event) def dragMoveEvent(self, event): widget = self.widget self.Base.dragMoveEvent(widget, event) def dragLeaveEvent(self, event): widget = self.widget self.Base.dragLeaveEvent(widget, event) def dropEvent(self, event): widget = self.widget event.setDropAction(Qt.MoveAction) self.Base.dropEvent(widget, event) def get_items(self): widget = self.widget base = self.Base items = [base.item(widget, i) for i in range(base.count(widget))] return items class DraggableListWidget(QtWidgets.QListWidget): Mixin = DraggableListMixin def __init__(self, parent=None): QtWidgets.QListWidget.__init__(self, parent) self.setAcceptDrops(True) self.setSelectionMode(self.SingleSelection) self.setDragEnabled(True) self.setDropIndicatorShown(True) self._mixin = self.Mixin(self, QtWidgets.QListWidget) def dragEnterEvent(self, event): return self._mixin.dragEnterEvent(event) def dragMoveEvent(self, event): return self._mixin.dragMoveEvent(event) def dropEvent(self, event): return self._mixin.dropEvent(event) def add_separator(self, title, data): item = QtWidgets.QListWidgetItem() item.setText(title) item.setData(Qt.UserRole, data) self.addItem(item) def add_item(self, title, tooltip, data, icon): item = QtWidgets.QListWidgetItem() item.setText(N_(title)) item.setData(Qt.UserRole, data) if tooltip: item.setToolTip(tooltip) if icon: icon_func = getattr(icons, icon) item.setIcon(icon_func()) self.addItem(item) def get_items(self): return self._mixin.get_items() class ToolbarTreeWidget(standard.TreeView): def __init__(self, parent): standard.TreeView.__init__(self, parent) self.setDragEnabled(True) self.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly) self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) self.setDropIndicatorShown(True) self.setRootIsDecorated(True) self.setHeaderHidden(True) self.setAlternatingRowColors(False) self.setSortingEnabled(False) self.setModel(QtGui.QStandardItemModel()) def insert_top(self, title): item = create_item(title, title) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.model().insertRow(0, item) self.model().sort(0) return item def create_child(parent, child, title, tooltip, icon): data = {'parent': parent, 'child': child} item = create_item(title, data) if tooltip: item.setToolTip(tooltip) if icon: icon_func = getattr(icons, icon, None) item.setIcon(icon_func()) return item def create_item(name, data): item = QtGui.QStandardItem() item.setEditable(False) item.setDragEnabled(True) item.setText(N_(name)) item.setData(data, Qt.UserRole) return item git-cola-4.6.1/cola/widgets/toolbarcmds.py000066400000000000000000000221171457126473700205130ustar00rootroot00000000000000from .. import cmds from .. import difftool from .. import guicmds from ..widgets import archive from ..widgets import browse from ..widgets import compare from ..widgets import createbranch from ..widgets import createtag from ..widgets import dag from ..widgets import diff from ..widgets import editremotes from ..widgets import finder from ..widgets import grep from ..widgets import merge from ..widgets import recent from ..widgets import remote from ..widgets import search from ..widgets import stash COMMANDS = { 'Others::LaunchEditor': { 'title': 'Launch Editor', 'action': cmds.run(cmds.LaunchEditor), 'icon': 'edit', }, 'Others::RevertUnstagedEdits': { 'title': 'Revert Unstaged Edits...', 'action': cmds.run(cmds.RevertUnstagedEdits), 'icon': 'undo', }, 'File::QuickOpen': { 'title': 'Quick Open...', 'action': guicmds.open_quick_repo_search, 'icon': 'search', }, 'File::NewRepo': { 'title': 'New Repository...', 'action': guicmds.open_new_repo, 'icon': 'new', }, 'File::OpenRepo': { 'title': 'Open...', 'action': guicmds.open_repo, 'icon': 'folder', }, 'File::OpenRepoNewWindow': { 'title': 'Open in New Window...', 'action': guicmds.open_repo_in_new_window, 'icon': 'folder', }, # 'File::CloneRepo': { # 'title': 'Clone...', # 'action': guicmds.spawn_clone, # 'icon': 'repo' # }, 'File::Refresh': { 'title': 'Refresh...', 'action': cmds.run(cmds.Refresh), 'icon': 'sync', }, 'File::FindFiles': { 'title': 'Find Files', 'action': finder.finder, 'icon': 'zoom_in', }, 'File::EditRemotes': { 'title': 'Edit Remotes...', 'action': editremotes.editor, 'icon': 'edit', }, 'File::RecentModified': { 'title': 'Recently Modified Files...', 'action': recent.browse_recent_files, 'icon': 'edit', }, 'File::ApplyPatches': { 'title': 'Apply Patches...', 'action': diff.apply_patches, 'icon': 'diff', }, 'File::ExportPatches': { 'title': 'Export Patches...', 'action': guicmds.export_patches, 'icon': 'save', }, 'File::SaveAsTarZip': { 'title': 'Save As Tarball/Zip...', 'action': archive.save_archive, 'icon': 'file_zip', }, # 'File::Preferences': { # 'title': 'Preferences', # 'action': prefs.preferences, # 'icon': 'configure' # }, 'Actions::Fetch': {'title': 'Fetch...', 'action': remote.fetch, 'icon': 'download'}, 'Actions::Pull': {'title': 'Pull...', 'action': remote.pull, 'icon': 'pull'}, 'Actions::Push': {'title': 'Push...', 'action': remote.push, 'icon': 'push'}, 'Actions::Stash': {'title': 'Stash...', 'action': stash.view, 'icon': 'commit'}, 'Actions::CreateTag': { 'title': 'Create Tag...', 'action': createtag.create_tag, 'icon': 'tag', }, 'Actions::CherryPick': { 'title': 'Cherry-Pick...', 'action': guicmds.cherry_pick, 'icon': 'cherry_pick', }, 'Actions::Merge': { 'title': 'Merge...', 'action': merge.local_merge, 'icon': 'merge', }, 'Actions::AbortMerge': { 'title': 'Abort Merge...', 'action': cmds.run(cmds.AbortMerge), 'icon': 'undo', }, 'Actions::UpdateSubmodules': { 'title': 'Update All Submodules...', 'action': cmds.run(cmds.SubmodulesUpdate), 'icon': 'sync', }, 'Actions::ResetSoft': { 'title': 'Reset Branch (Soft)', 'action': guicmds.reset_soft, 'icon': 'style_dialog_reset', 'tooltip': cmds.ResetSoft.tooltip(''), }, 'Actions::ResetMixed': { 'title': 'Reset Branch and Stage (Mixed)', 'action': guicmds.reset_mixed, 'icon': 'style_dialog_reset', 'tooltip': cmds.ResetMixed.tooltip(''), }, 'Actions::RestoreWorktree': { 'title': 'Restore Worktree', 'action': guicmds.restore_worktree, 'icon': 'edit', 'tooltip': cmds.RestoreWorktree.tooltip(''), }, 'Actions::ResetKeep': { 'title': 'Restore Worktree and Reset All (Keep Unstaged Changes)', 'action': guicmds.reset_keep, 'icon': 'style_dialog_reset', 'tooltip': cmds.ResetKeep.tooltip(''), }, 'Actions::ResetHard': { 'title': 'Restore Worktre and Reset All (Hard)', 'action': guicmds.reset_hard, 'icon': 'style_dialog_reset', 'tooltip': cmds.ResetHard.tooltip(''), }, 'Actions::Grep': { 'title': 'Grep', 'action': grep.grep, 'icon': 'search', }, 'Actions::Search': { 'title': 'Search...', 'action': search.search, 'icon': 'search', }, 'Commit::Stage': { 'title': 'Stage', 'action': cmds.run(cmds.StageOrUnstage), 'icon': 'add', }, 'Commit::AmendLast': { 'title': 'Amend Last Commit', 'action': cmds.run(cmds.AmendMode), 'icon': 'edit', }, 'Commit::UndoLastCommit': { 'title': 'Undo Last Commit', 'action': cmds.run(cmds.UndoLastCommit), 'icon': 'style_dialog_discard', }, 'Commit::StageModified': { 'title': 'Stage Modified', 'action': cmds.run(cmds.StageModified), 'icon': 'add', }, 'Commit::StageUntracked': { 'title': 'Stage Untracked', 'action': cmds.run(cmds.StageUntracked), 'icon': 'add', }, 'Commit::UnstageAll': { 'title': 'Unstage All', 'action': cmds.run(cmds.UnstageAll), 'icon': 'remove', }, 'Commit::Unstage': { 'title': 'Unstage', 'action': cmds.run(cmds.UnstageSelected), 'icon': 'remove', }, 'Commit::LoadCommitMessage': { 'title': 'Load Commit Message...', 'action': guicmds.load_commitmsg, 'icon': 'file_text', }, 'Commit::GetCommitMessageTemplate': { 'title': 'Get Commit Message Template', 'action': cmds.run(cmds.LoadCommitMessageFromTemplate), 'icon': 'style_dialog_apply', }, 'Diff::Difftool': { 'title': 'Launch Diff tool', 'action': cmds.run(difftool.LaunchDifftool), 'icon': 'diff', }, 'Diff::Expression': { 'title': 'Expression...', 'action': guicmds.diff_expression, 'icon': 'compare', }, 'Diff::Branches': { 'title': 'Branches...', 'action': compare.compare_branches, 'icon': 'compare', }, 'Diff::Diffstat': { 'title': 'Diffstat', 'action': cmds.run(cmds.Diffstat), 'icon': 'diff', }, 'Branch::Review': { 'title': 'Review...', 'action': guicmds.review_branch, 'icon': 'compare', }, 'Branch::Create': { 'title': 'Create...', 'action': createbranch.create_new_branch, 'icon': 'branch', }, 'Branch::Checkout': { 'title': 'Checkout...', 'action': guicmds.checkout_branch, 'icon': 'branch', }, 'Branch::Delete': { 'title': 'Delete...', 'action': guicmds.delete_branch, 'icon': 'discard', }, 'Branch::DeleteRemote': { 'title': 'Delete Remote Branch...', 'action': guicmds.delete_remote_branch, 'icon': 'discard', }, 'Branch::Rename': { 'title': 'Rename Branch...', 'action': guicmds.rename_branch, 'icon': 'edit', }, 'Branch::BrowseCurrent': { 'title': 'Browse Current Branch...', 'action': guicmds.browse_current, 'icon': 'directory', }, 'Branch::BrowseOther': { 'title': 'Browse Other Branch...', 'action': guicmds.browse_other, 'icon': 'directory', }, 'Branch::VisualizeCurrent': { 'title': 'Visualize Current Branch...', 'action': cmds.run(cmds.VisualizeCurrent), 'icon': 'visualize', }, 'Branch::VisualizeAll': { 'title': 'Visualize All Branches...', 'action': cmds.run(cmds.VisualizeAll), 'icon': 'visualize', }, 'View::FileBrowser': { 'title': 'File Browser...', 'action': browse.worktree_browser, 'icon': 'cola', }, 'View::DAG': {'title': 'DAG...', 'action': dag.git_dag, 'icon': 'cola'}, } # 'Rebase::StartInteractive': { # 'title': 'Start Interactive Rebase...', # 'action': lambda: app().activeWindow().rebase_start(), # 'icon': None # }, # 'Rebase::Edit': { # 'title': 'Edit...', # 'action': lambda: cmds.rebase_edit_todo(), # 'icon': None # }, # 'Rebase::Continue': { # 'title': 'Continue', # 'action': lambda: cmds.rebase_continue(), # 'icon': None # }, # 'Rebase::SkipCurrentPatch': { # 'title': 'Skip Current Patch', # 'action': lambda: cmds.rebase_skip(), # 'icon': None # }, # 'Rebase::Abort': { # 'title': 'Abort', # 'action': lambda: cmds.rebase_abort(), # 'icon': None # } git-cola-4.6.1/contrib/000077500000000000000000000000001457126473700147015ustar00rootroot00000000000000git-cola-4.6.1/contrib/README.md000066400000000000000000000031311457126473700161560ustar00rootroot00000000000000# Git Cola Accessories ## Bash shell completion The [git-cola-completion.bash](git-cola-complation.bash) script can be sourced by `.bashrc` or `/etc/bash_completion.d` to provide completion for `git cola` on the command-line. Git Cola's bash completion script requires that you have Git's [git-completion.bash](https://github.com/git/git/blob/master/contrib/completion/git-completion.bash) setup via your `.bashrc`. Git Cola's completion script is a plugin / extension to Git's `git-completion.bash`. ## Zsh shell completion * The [_git-cola zsh completion script](_git-cola) is a completion script for `zsh`. This script is only able to offer completions for the dashed `git-cola` command. Completions for `git cola` are not currently available. To use it, copy `_git-cola` to the location where you keep your zsh completion scripts (ie. `mkdir -p ~/.config/zsh/completion && cp _git-cola ~/.config/zsh/completion`) and then add the directory to zsh's `$fpath` in your `~/.zshrc` before initializing the completion system using `compinit`: # ~/.zshrc shell completion setup fpath=(~/.config/zsh/completion $fpath) autoload -U +X compinit compinit ## macOS-related files The [darwin](darwin) directory contains resources for creating Mac OS X git-cola.app application bundles. ## Windows-related files The [win32](win32) directory contains packaging-related utilities and resources for the Windows installer. If you're developing git-cola on Windows then you can use the `cola` and `dag` helper scripts to launch git-cola from your source tree without needing to have python.exe in your path. git-cola-4.6.1/contrib/_git-cola000066400000000000000000000076551457126473700164770ustar00rootroot00000000000000#compdef git-cola #description zsh completion for git-cola # # The recommended way to install this script is to make a copy of it as a # file named '_git-cola' inside any directory in your fpath. # # For example, create a directory '~/.config/zsh/completion', # copy this file to '~/.config/zsh/completion/_git-cola', # and then add the following to your ~/.zshrc file: # # fpath=(~/.config/zsh/completion $fpath) __git-cola_common_options () { # these can't be prefixed _arguments '--help[Show help]' \ '--icon-theme=-[specify an icon theme name or directory]:theme:(dark light default)' \ '--theme=-[specify a GUI theme name]:theme:(dark light default)' \ '--prompt[prompt for a repository]' \ '--repo=-[open the specified git repository]:repository:_files -/' \ '--version[print version number]' } _git-cola_refs () { typeset -a refs local ref if git rev-parse HEAD >/dev/null 2>&1 then for ref in $(git for-each-ref --format='%(refname:short)') do refs+=(${ref}) done (( $#refs )) && _describe -t refs 'refs' refs fi } _git-cola-am () { __git-cola_common_options _arguments \ '*:patches:_files -g "*.patch"' } _git-cola-archive () { __git-cola_common_options _arguments \ ':ref:_git-cola_refs' } _git-cola-cola () { __git-cola_common_options _arguments \ '--status-filter=-[status path filter]:path:_files' } _git-cola-dag () { __git-cola_common_options _arguments \ '--all[show all branches]' \ '*:refs:_git-cola_refs' } _git-cola-diff () { __git-cola_common_options _arguments \ '*:refs:_git-cola_refs' } _git-cola-find () { __git-cola_common_options _arguments \ ':path:_files' } _git-cola-grep () { __git-cola_common_options _arguments \ '*:path:_files' } _git-cola-merge () { __git-cola_common_options _arguments \ ':ref:_git-cola_refs' } _git-cola-rebase () { __git-cola_common_options _arguments \ '--autosquash[move commits that begin with squash!/fixup!]' \ '--autostash[automatically stash/stash pop before and after]' \ '--fork-point[use "merge-base --fork-point" to refine upstream]' \ '--onto=-[rebase onto given branch instead of upstream]:ref:_git-cola_refs' \ '--preserve-merges[try to recreate merges instead of ignoring them]' \ '--root[rebase all reachable commits up to the root(s)]' \ '--strategy=-[use the given merge strategy]:strategy:(recursive resolve octopus ort ours subtree)' \ '--verify[allow pre-rebase hook to run]' \ '--continue[continue]' \ '--abort[abort adn check out the original branch]' \ '--skip[skip current patch and continue]' \ '--edit-todo[edit the todo list]' \ ':ref:_git-cola_refs' \ ':ref:_git-cola_refs' } _git-cola-tag () { __git-cola_common_options _arguments \ '--sign[annotated and GPG-signed tag]' \ ':tag name:' \ ':ref:_git-cola_refs' } _git-cola () { local curcontext="$curcontext" state line typeset -A opt_args _arguments -C \ ':command:->command' \ '*::options:->options' \ case $state in (command) #breaks if defined outside the func local -a subcommands subcommands=( 'about:about git-cola' 'am:apply patches using "git am"' 'archive:save an archive' 'branch:create a branch' 'browse:browse repository' 'clone:clone repository' 'cola:start git-cola' 'config:edit configuration' 'dag:visualize branch history' 'diff:view diffs' 'fetch:fetch remotes' 'find:find files' 'grep:grep source' 'merge:merge branches' 'pull:pull remote branches' 'push:push remote branches' 'rebase:interactive rebase' 'recent:edit recent files' 'remote:edit remotes' 'search:search commits' 'stash:stash and unstash changes' 'tag:create tags' 'version:print the version' '--help-commands:show available sub-commands' ) _describe -t commands git-cola subcommands ;; (options) local funcname funcname=_git-cola-$line[1] if type $funcname | grep -q 'shell function' then $funcname else __git-cola_common_options fi ;; esac } _git-cola "$@" git-cola-4.6.1/contrib/darwin/000077500000000000000000000000001457126473700161655ustar00rootroot00000000000000git-cola-4.6.1/contrib/darwin/.gitignore000066400000000000000000000000151457126473700201510ustar00rootroot00000000000000/git-cola.py git-cola-4.6.1/contrib/darwin/Info.plist000066400000000000000000000041671457126473700201450ustar00rootroot00000000000000 CFBundleExecutable git-cola CFBundleName Git Cola CFBundleDocumentTypes CFBundleTypeOSTypes **** fold disk CFBundleTypeRole Viewer CFBundleIconFile git-cola.icns CFBundleIdentifier com.justroots.git-cola CFBundleInfoDictionaryVersion 6.0 CFBundleName git-cola CFBundlePackageType APPL CFBundleShortVersionString 0.0.0 CFBundleSignature Cola CFBundleVersion 0.0.0.0 CFBundleSupportedPlatforms MacOSX LSHasLocalizedDisplayName NSAppleScriptEnabled CFBundleGetInfoString Copyright NSHumanReadableCopyright Copyright NSMainNibFile MainMenu NSPrincipalClass NSApplication NSHighResolutionCapable NSDesktopFolderUsageDescription Access Git repositories in the Desktop/ folder. NSDocumentsFolderUsageDescription Access Git repositories in the Documents/ folder. NSDownloadsFolderUsageDescription Access Git repositories in the Downloads/ folder. NSNetworkVolumesUsageDescription Access Git repositories on network volumes. NSRemovableVolumesUsageDescription Access Git repositories on removable volumes. NSFileProviderDomainUsageDescription Access Git repositories from a file provider. git-cola-4.6.1/contrib/darwin/PkgInfo000066400000000000000000000000101457126473700174340ustar00rootroot00000000000000APPL????git-cola-4.6.1/contrib/darwin/git-cola000077500000000000000000000006331457126473700176140ustar00rootroot00000000000000#!/bin/sh # $0 = Contents/MacOS/git-cola # macos = Contents/MacOS macos="$(dirname "$0")" # contents = Contents contents="$(dirname "$macos")" # resources = Contents/Resources resources="${contents}/Resources" # Setup PATH for git-osx-installer and other common locations PATH="${resources}/bin:${PATH}:/usr/local/bin:/usr/local/git/bin" export PATH exec python "${contents}/Resources/bin/git-cola" --prompt git-cola-4.6.1/contrib/darwin/git-cola.icns000066400000000000000000006161131457126473700205520ustar00rootroot00000000000000icnsKTOC His32s8mkil32 vl8mkit32F(t8mk@ic08ic09is32܀ f  T V " ]9 [ +1e ޠm6u WO|s & 1@1 B5=1 1 ?8>1{3?9 (9=32>6>A6<1,?8:;2 A:=1>Z2=;:: 1+9=1 vkU57:9 9-97@6t{`V4< 37":=1=fqC6: 5==;=1;i_>5<1 ?}D#"<<3 *::8:=12=7=10@1"*" ,"(" # +%)"{$(' &(##($),#(#*%&'" ,&(#0G)'&' # &("d]C!"&& & '$*(cnNE ) #&''"0Tc0!($()'(#-WuL *#'" 1n1''$%'(#$'$'#"*"s8mk%- t3v;|V5)}8COҢ-"7Y+zpil32 v#e  ?-@+K+]+'X+;W+>P+>w+>"+>+>]+>k ]+>^[+?M(++ UeV RTy)S{F+*Q+*IU+* +*0!'+*+*` O+)t9k,*,)+)+),*, ,.0 >;= >8:9= >9:;:9=$>8;:9=#>899;:9=A."?=<9;:9=?7>/*2=9;:9=>8<8=/*>9;:9=>8;:;8> ;:9=>8;: 9< =9;:9=?8;: ;9=,$>8; :9=@6;:;8?(%>788;:9=;5?8;:;9<,!2#@>=9;:9=5DF.>7;:(;9=+A,+=9;:9=5ae.@9:9:;9=,<<,/<9;:9=5,H2f:97;=9;9=+>:2?8;;9;2pBQ<;3=:9=+>:6)>8;:9<B=UME4>7=,?7>* <9;:9=,iJUG<99<*=9:=;8>:B9=5^AO97>7?- @7<8::8::9=27?6L/?2 1<9;::;:9=<_On[4<9;:9=-WLM8 ;:9=9YM,B!>8;:9=9-5@8=(&;9;:9=C;8;9>?>9::9=<::;8::9==9:;:9= =9:;:9==9=<;<* +%+ +$'$+ *%'&'%+)%'&&'%+)$%&''$+-#*('%&'%++#($ %)%&'%++$(%(% (%&'$++$'%'$* )%&&'$++$'&&'%* *$'&&'$++$'&%("*$('&'%+,"(&'%) )$%%''%+' ,$'&'!'+*(%&'%+!13+#'&O'%(!+"!(%&'%+!OT-%&%&&%'!('"#'&&'$+/5V&%#')%'%'!*%%*%&t_}.?(')%&'!)%'(%&'$+0)C:2 *$(!*$)! (%&'%+Y7D4(%&' )%&()()%&'%+"M.=% #*$)#+$'%&'$*#+"w9*$ %'&'%+)M=_J)%'&&'%+F::% )%&&'%*&G:-)%''%+&!,#) )%&'$+1'%'%(+(%&'$+*%''%&'$++$'$+ +$'&'$+ +%&$++&+l8mk X; |a a  a a d&a  ya  {a  |a  |P<=:;==:9;:;9<-:9:;::3  '&7<9:;9<-:9:;::3  %:;9<-:9:;::4 9:;9<-:9:;::3 9:;9<-:9:;::3 !<9:;9<-:9:;:;34:;9<-:9:;0=9;:;9<-:9:;9=";9:;9<-:9:;9= 8:;9<-:9:;9=3:;9<-:9:;9=6:;9<-:9:;9=:;9<-:9:9<-=8;:;9=-:9:99 4;:;:;9=-:9:9<* 4;:;:;9=-:;9; 4::;:;9<-:9: 4::;:;9<-:9:9;(  4;:;:;9<-:9:   4::;:;9<-:9:;8=3 3::;:;9=-:9:;9=>. 4:;9<-:9:;9==:0 4::;:;9<-:9:;9=>8<. 4::;:;9<-:9:;9==9:;. 4;:;:;9<-:9:;9==8;9<- 4::;9:;:;9<-:9:;:;9==9:;9<-  4::<<;<;99;:;9<-:9:;979;:;9==9;:;9<-  37.**.5<<9:;9<-:9;:;97=?@?;7:;9=>9;::;9<, -<:;9<-:9::;9;@3..07?9: ;9==9;:;9<- 9:;9=-:9::;9=8-WxrK.;;9: ;9==9;:;9<-8:;9<- 9:;9=4F99:9: ;9==9;:;9<,;9:;8=)+<9;:9<5MȒ8<: ;9==9;:;9<-*<9:;9< 9:9;9u2..;->8;: ;9==9;:;8>:9:<-;9:;7@,h&A>@;4p2>8;: ;9==9;:9 0;9:;7.9::;8>4*E594>5Z/>6;;: ;9==9;:9<1&=9;:779:9;;g1=8<;8;7J3>;:7: ;9==9;:9<.!>8;:8': 9<9V4;:;:90><66;@9: ;9==9;:9<-!=8;:;7<9;;7?1~,C3::;9<>,0['69<3PÄ:9>9:;: ;9==9;:;9=:9: ;9<*=9;:6G97H=5@/?7;:9=1;:9;: ;9=>9;:;2'<9;:;8=(&-<9;9::3D=0a);<:5Q6<9:<3k?8<8;: ;9==9;:9=!9:/;9<.-<9;99?*P<44`k*D95B.v/@5?0s1=<9;: ;9==9;:;9;7;:;9<.%-<9;:8@79C,-C4=7=-|.@7;9G27: ;9==9;:9:"8:;9<-&-<9;;7<7>.x/;889<=i0>8:;3=?;9: ;9==9;:;:<0*;:;9<.'-<9;;:7@.|.D8>@(A9::;6D*j0>8;: ;9==9;: 9;=4+$"*3;<9:;9<.%-<9;;9=3[6472/,@8;7@).>8;: ;9==9;: ;:9;<=><;99;:9<.#-<9;:8?0WIb/>8;8@++@8;: ;9==9;:;:9889:;:;9;-!-<9;::;70<::8@+*A7;: ;9==9;:;;:;9<.-<9;9;:2vЧ_,=::8@+*A6;: ;9==9;:;9<.-<9;9:>//76-2@9:8?+)A6;: ;9==9;:9<.-<9;:8??<=@=8;8@+)A6;: 9=>9;:;9<.-<9;:779879;7@,)A6;::;: ;8=<9;:;9<.-<9;:;::;;9A,)A6;:;:879;: ;:@8:;9<.-<9;:8=()A6;:;79>@;7:;9;) 9:;9<.-<9;:;8?/~,@7;::7?;0.7?8:;9<5;:;9<.-<9;:8=3]3=8;:9?-9d|K.=9:9< 9:9<.-<9;:8>&w^2=9:=-u1=7:9<,<9:;9<.-<9;;8C,rQ6:<0饋,B9:9:1;9:;9<.'-<9;;5C(~7;>-B/-.H'=8;::9<-=9;:;9<.&-<9;;8=4/5?.q+:?@@5E6<9:;9=":9:;9<.%-<9;:8=@9>2->963;5K:;9:;9=7:;9<.$-<9;:97:9@y4?7=C4KC6;9:;9<3:;9<-#-<9;:;9;:~"?77)MD6=9;:;9=6:;9<."-<9;;7@-uE@QqE5=8;::;9=!;9:;9<.-<9;::;9C5=7;:97<:;9< 8:;9<.-<9;;6>&~*B6<:;9< 6:;9<.-<9;::=34<8;:9;,  :;9;/ -<9;:9>=9;: ;9;9* #5<9:;9<0 -<9;:89;: 99<=;::<=:9;:;9;/-<9;:;:9:9:;:;9;/-<9;:;;:;:;9;0-<9;:9p Tpp  p   kp ~ Np   xp xQp Ҭp p p o p n q }^ 0Y ]SKm *b } 'YS W  \>ˁ\?Jl joic08PNG  IHDR\rf$iCCPICC Profile8UoT>oR? XGůUS[IJ*$:7鶪O{7@Hkk?<kktq݋m6nƶد-mR;`zv x#=\% oYRڱ#&?>ҹЪn_;j;$}*}+(}'}/LtY"$].9⦅%{_a݊]hk5'SN{<_ t jM{-4%TńtY۟R6#v\喊x:'HO3^&0::m,L%3:qVE t]~Iv6Wٯ) |ʸ2]G4(6w‹$"AEv m[D;Vh[}چN|3HS:KtxU'D;77;_"e?Yqxl+@IDATx mGU&}{Iޔ),6a#ڦE$l_ #;ahKTN/(!y 2psjT}yȩUkZUvq42bdP^_R*GQqڵ7رmv n,Ņ/|h\|taᓝNxE0+zv3 kd. @G⑀SBCף۷K~arzF4Y(WַZnq4E-bTdӱp{mqj0ځ^|G$0j.BLv}l>a  ޕnn'*q{GJ}P-`Z:zz}xrHv^{bnB]vq)Lzt*pczv1d>Zb#RcjiP*k_}ѣ6uF…nF ^_n]J?WoJ׎;%(~ %^(ԟ9^Vxllө}_qȑ?@Dy /?ړz~)e]+vzW ZrӉCPnYa(?ѽߌτJ~]l\eז,,-}`N#s!J`\fiN)?{ݗzbz凣Fh_X BQ1y릛Fn`1nƅ֍.n7z͙nZ\ h4i⼠~G U\:g/ae۶uΝZ@jz1>Aq}Z \H0 FGm)uJ7#>7 dwaG U^Lm_9Ǟ *?z7ݸ7$y;9({cv.J5ڙ4G#D5j.K)ߍo~7?bs.TНrab,l0[KkH^[kaq4B fwTFyO~$z4'p*"?Seߵ]ejl=9/fi9pNv$Ձќ@_ب8&klW83GxhP9!@u=n8@s>/N1jκWaJ:?\K`s6OեZ7r05Riد ^ lyh$0L|_Ԥ}'ɇM>Æ7KCV#N >bXX7}ю|5C)48:?=v_J)[|6,6#!Bըp${9ps , H=jΟBnï_Ɯ:Z&3J<@y}!|H ƎA(4g׌v :ܣ(tϟsj== hRphf<y }xs6~mC Du}YQpnOʯ^[ISF Egȗ0fď9tO3jm<p{K3! <^3)I?!f#8^&)s<;8:E9s$xDRY_xO>NWRR^d4k{_I);c8ᜧ儑m@Ձht0y5Rʿ=('KV^3>->T>fW{5(y 7jk?;'}Hgh$u\>w&KZ?`oIyI STc6L T %4m# Ĕv8'7p;GӒ=QpveNT6&6zg@ǾN$yd 05u Ep 2t ?lc H]#S1gt@ l=;=) Ӹk7|R&NQqC}&LS<4?$p|LF{>4 G<;`lugZu#oqrOqj۷m{e;w?T_)/U:ScS'y)h^Xw`!~s#^YVcv G {2֨rtn\|~ !Ɖ?2gVΏ<T̿Sj/{6ي{?/MYMZ79 /n(|}t0Nή>~:F \$ѣ[7n@kwW71C#/4pYh6hұ1y)-9'0'3!v fu}G o.skcrqas6hv61)}“2Ofp#՛Ajך8 Kn@ :o7st;/a+?&0 MsYM#Env4Fe|rQprr0?ͯ]R[PH'R lF4ՌDU/PrB1%Wﷳ* $lȗCG ˌM.H۱}[fiwڋD^Flup#40OFW`$p% `LÌ~#U&rֲi04}>,7a~Ձ=fU)B/t\KXn],`yn-ͬp>h$iF7ۆmP#NVVV!mHG vI 8BEMBx6 'I#䜀19-*1WFw xOw^dN.C{.߉;͕s+Nga~~8'}sHoVD˦R`o4i3B1{TtlF/puaC^Zm5WwNHP$ svWe+T6^RL)Bh+Ta~n!aF穭iw; ` "\;:EoQR:qՇc%Y6h*bi Lb$p l>pbQbò*oW%!6_@:LOO1S~{;hUQq~$zriP;g֬q müT#*$rF+3*C]/ley(vC0xz+Kr )aqw>cpO f{ŒR~ DDŽ&xz~^}X= H&1189yxObNW( Sa+[ݦ\pT!hfco5/J)|w@@:[^ 4K1zڣ|J9ۿ{w-z~hGX= s+%׭[H:PMcv;$q61271 {JRNE hCy0<)yJ1%Dq&, qYHF03jL2)Cor۰UrJ,RځM +su ~pihc'"Df0TlzM +['HoRBün>M؜_%LK4F @:nfǰp0Տ50rʦ`OM %cmrxgI:o۲azLIHoTjl.B=e *ن+tF^ȯB18zw -+ 7_(\ݮb&3[IC?zUs`4N j$Qb[d3M8nwİ ψAg{,w>F#/; S~=ԉo}MqϞ~~p^LU= L]}:z1;Jlz"D: q\-_;3~# O`F#ܡ!6>KLmlX}݁ۆGw >j?R?33{n焟~=9R 鱬z2RBmçppsWz+1b qܹȕ p| L$ f P߀K BqF?!_O9Os ĵAk G3Kf{yK}Vjj +]VITŤMBQ IűMX+e2<ֺFu /;<F-cٸJ~"z}NI{sAψk׾h֭?MM_W[u#XCps5I0Pӈ|҄𬛴ƔwH8QN8pφ`Ttjb򪏵KbB5r3ATp̕6HC+KK'|/.~M~Sb{s<3j@)Ъ0AY0,} )0~Fd [kpX#F{bmʯ;`~Wlţ, ÑCqFbx%9F6. ;zm4Sh#xx /tkx-L0f)0bMXGҠqBe+IHqm#1x m BcB*\hXULQ2CUAVnk9Cz _EJ_4npDUNjskݺ}Sh_QJT rhQNpMnYZ \8Y;FmH1o~o&Kge+**JvXGY/ #~'3sn6VwrNRp=idڳtVRz`M/g ]^eɚ[!!4i輽RaA^ .)?Ïyh{J{}%JVR 5d%\r^a{&M sZ:ρ01G_0.@=[e#Nbrc_Z^h2Pv,9aJr CX<@B m; Ub"\sq.)?ak`=U  [>|0T*Cwug~$Vz?^ΐݙ2t6>>;T ~T|RSϗՑsV,KiVNYCnKbIhC/p WK:\sCRb`{1)?$]HM>"d4'' E"zt&bW׬T*_z?CWE9t8jZߘ^ћZi<)-!K pǏ O p13ln.-G榑WŃ'cy@t7)w:ꖮ El*3Tls0Z ֜1|_n⑵q(\pfݏSJwk/b{&Yb.` 1 vGx{( ̽r$9gOCaƌmƥF%&W‚ϯ %m .95dRϞ%[f{+2݌V/e31TmhboGQegmՊX\m̆eJ:|_ը8|l~-ύ11FsG~E3RL~̗Mp M^N&;aL͗Ř'SQk~ w%s([.^B(S`+ ,L=U8˃=:'H˦(V 9 ] m:b>M> AawEyq1*4`8 sBϤInڇfn%HQN'|2iZ А|#lK~_شY&zRرc7l2"+$0Z_K}tc&H;,hj#٪i0#GMLSx؈s=$p^9J>ܬLb7jsrdM\Jl C$$r?S6pFZ* 4.{\Ͽ=rz~^ ?3UU1XtNJCn'XHoqfc Wvȣٳq=  ,HKCT,֑JiB{WZMK8&?ӱd,VxJCȅ0i$p4p# `$ \ @J=?` .[0}0 V0ųjJ1ȋW V -=;ѫ 1,ra[ 9kwmq)ncRe*i+J,̰r0!/827gH2xqz x 7\s{R~ ]\Y0Y#B!0☒z.!\ Q/NEMP D@=lZ.danݱKŔ3RˇZ^MuChMlb(VN ߴ qT̟znufjg V \翚^; <:YѯW(UtHj+ax?9G' ͆x r!r9ttRwUϩesl|bJkx?I״, &oNXXS>24wK@(>ڒ+K+ ;޽a fu|mRϽp<{dϥ>~5V{.U6+Qh`U |uü˨7ʰ .+M~X)C0]? tqL*5+̹ k3<7HxŐ=<>y8<a g!i\FZO|\"(g['+/\-e<Pc,f IX!\pd>1 kmqXwvE8 3OOrr|zb{;K[^ l/&,Ldx&ٓ&Uii 'QNS#}v>Op8u~w|gRQ V_X* '+]AoTV BE̐#Q_jR7K\kZ>k2EX06^|0Q& 9]B( fC=mK&DZ , 9Yj6'}c V0'=w OgH/_ٽˎ7lztBTeSqK!pU!jx!7Gw%qS BiEAhz Q%F^y\Ӏg0P?k:n'V[{o6ZNag+ qAfÌJ2/aaZJŠ8Yy>xt;ڛ,t!"TlR/7o{UTA)CӟWYash[faąᄧKR*Aӿ@<IhhgJCR J@=Mμ$`ZF ?i+!F`p'X : P}( F19j#{0H)z~Ï*`NX`r[aL*4j}k!ɧ5/HS|iO>zL>Bx;\Lp+0"ɇ&ǟ؛cxI^nsX#K3K>$_-uG sFB Sdd>;1}n 6מ7  \K}6MV.tAd/bӊwȢkV>/h Q%^|Wм<>6㸮V̛R΋g1%P<9}G<w^t)1w60o%rrXG\B:qa>&ʆN xNF#p0ĿJwq8υ欻eR~շM>N Th+A o.<Ŗb 'my)fz7~UhML\C|3lW^Fvj~4$w:5l&|#-r%)O^"\G׏Θx 'v~zWw#:7"ܟͥZv([& <[x\SĽ5W#`„P|'ɸ2 ťe6?b4mgyk-eӥR0pц 5lJhC^ܤ՜qs% f1h`$P?#8Rf2[{ +alUPŐW`Ƌ*z m b)Fa 7! Qc =vgJ7p]xY8>?IYF %Axb9'h$%hц =Ⳙ_>)dBHKvǠnފ9s{lumouuaJu`輀U# &fXX>Sy4a< ej`p{VxEiÒx T}{3Cp|s3_~tu'fe|@#69"< ;8!/s>YAz 0|&{(móh9ff=:83tK*p0\De}Qy@Rd L0G7 th0;QOM`$0vCp%"rh   m~u D2„aw &ta8iqZs1W6NƪF$ s*hRo\p{+,A1Z/m9wV) SJaLE~<~:$l/O8}p 'Ya e`B cMv̗&piL[Z UHxv  '_K}ԡ]P툓G+>pr";x6"(\Y-G Ix N|gU؋DRu-[{ne`fW\7oS_XX4*H [42g_$p KI' UZ1dh&\c WП Ä`x^ :S @J?қ2yjl:xRw[P C0%;[M:ӎ4,o)!<9QXoCFr]S5*/.ZaLMM=u޽oǧa+[x#,t(i9`#KAM B<'lLvX 'Xiϗ1\&/U[h/ DF\Lɚ_K}Cr{Z\D.U,҄w y #QxZBjwfx 5!-qh q -}>% 0^6C~Ӊ.-Fe<u;9➀qa0Y[Zv߲ukЕ20,YaŤ4;*V&~^]X)ueganC0Aiﳲ5c_L㠛#6̋FmxvMT9%t7No~䳀_|l^Y}aXP 3N\/RTT=0&i'c <0UO˃O c ^WWlXqsdJ%:Vo|Ǯ[6f9pS3\#PH1tgF 5`#er /9f ~C YB_qBwҊ>4y|6(' D3{:T8:7؋=o : ZrX(nE.iRt⪢/+lni1'PxSEӧ42>7;&vضc.A#kNr$89 4I#H N5&W.dҐpB _4 f%P&72Xa|@sa\:̑oHa;,tFp{>>a{o~v\+6i"4M;C0=L4!OKQ)|a$~ӡO EXW zDz^bηnI7,F,l$ρ T'~#~?80ơvr1yL\p[d KKxrQf1c-O3yh{bOr'yaM@ 0fT4#.cXai_Bv^&_0/rtJB8B7)ײ^+`  =ohMi6`$@8$ʲo88F2j瀟uFYMDg.%Z4 f&{! c5;F D-B{ 7y8)& ^N"Q>)AQ7~ki{U Ő&4(̥_C8+[,T )%{6vLce|<W!q u:h&6^1+ %50G#`6'095"P_RK[B-]Z˦?)q1j,'hȁFe-B6\9Ex8|~^]\,񛟭De>/0B"6xA QfmU,mPKrNlT cV .aZYޞ6ˆ A`v|0>l9HyZM퉣];߶a㆗`WC#0`,ɒ,kb+X`#.ausw`bpgsړR1b7aXsPJlX^ lCpIØ,7rPF@*qͽJ|G'q껹ҫ%eԋ H$YIZ Vያ} 4\ӡ5a9/sGol9$_yg>aH\ؐAcz>/߱] 6X7,+L%R|cblssu tq6f ALI/9Z"&9t*N`'4QX͉91h/%#o$p2 @J_{R~l) #+&½1 &r(&t y[ ` hR~sKB7a?XQ/Aif1a£,+>}*05bm4IGX|Il:EE­ℐEiYb 9T`#ZZwa܈5 %-1j$:5d,"%p (,(CFk%#0Ͱp O|CHx]N i$ם['Rg=?|8o8-P 3,K4f*t( (T|B>Y^l0SL|#X--f~eKCHT[᫰GpP7Mvg:оbǎ_ɱ:Zg221 FA#B%r ϑ <€E%@D1xD0n/QҖC< 8>ģiO&m @_%&aGia~y~wׯb2m-X(S#(Y&4?}C:_ p::FmG0 -c UGfă>bk)/^AUPj . t0,-j|O^EKap@D l0GDp94Y1;?>VH7 D&k0,G>I̛/c̽_ ZR38{7!omboo2 H)so Gz{y~&04Lϒ YCiJ *e[Ca1³i$oE'\btLig4|q VܲCzrfSJme>&1za}`$p徽N]{K4OLZ/עbw[(ֱDUfX,w: 8rێvB\g[aP)w”IG0\OxP,4DL;;[͐7 yCή(~vۥޛ^Lg,WfaV zM(ED(Mh"|@IDATO h$<}KCig4VJfӦ4e:lyxji4y^YүR ; ;URP#^![wz-F;}G>9du&wXxlxK5B#Za\]MIvX4ZCdToX-}m|l 3f=Uת7YhG(tbr*fF3zX CO~`T)4P>. zKZ܈;v|7R7,z~lxǒJl VKˬ=5L- (,<0l2F0ږ?`_a0a,>̱ HŸy e= <4>aކLxh Q=.`$Jsg:t)x4*/gC?v]_('˥F_p`Z .NoV+ZsOB$nn(4-*U8nE>y |.M96<:/4/B@#po77HGEp5),ݑ^QR~ +ZL,) % (~RAe\Wlnn>Ց ]ﮯ}%l?{O;J<.ӹ ^~ݺui֖~n 78l%l̕˳rIs- '(!\257*Y>"2Fͨ} FT87f9췽󳠳Ner *h㈩3 N.a,~%ZuL~jB!FaK atdIS4ͤc!S-F|KSv.]FV ޲v~8+ȼb6pNzaY]D5F][>'g9z 1wX@c<СCKw՗Vz06d,v9IuU>o^u7)_+&o*`ف_֫W1=Ņަmý;s$ž_ 2>*3;ҟp|.\X/™jHa oi,ć~HOcar{[x-$eH ̦[$_hӽRKrvdօڿ+kfBظS c6߾|"~xy6ަ[o6{2O1N /s.>BϝH$̅$qtDCYZkoۥB{z]hX!q˕L)Ǘ4~*FzB<ń{w@WyoxTW~7ۏS}nnA+pt&*S|$iUC1GE~p4&aBe_~<n2&x //= 3I ,4qm%m ݏOGPis?q1dzmک6j$8G$pB8 wx0^UFZv -NRPJxOzQ0G#9{s}QTMTذlS^:<5?5?(FQA@9l/+BXH!b ZJ@| 7€!LCXIDɇzy µl}S@5{~pTZeqHDá0JFfEWQ葨'D3Z4)*^ B5ll[4 0!*_h.5Sx*at3^^xeWsC| QCފ1/c3/jYV& NrF3n16,-LG<qN=S=395KxS@GCiFlKNy '.![~ݰWxB`Vv`\?Zꗬ]wá#sh?PD{]qBz[(½Y%3?Ma+`Q&_rc?z5؜"&&P?^ KEV4F'QiǥQopDfJ4je~E&~͐4Ug,/ij|e)T(&K| c dFmqx)/L²u"ao,1 .6~/C nsю-[^h~eSķCS*/jf)?&ݣsċo&~u8z8{hw#QD0X,LODkMk׀v)*l;7D).:!T /t20. ѣH)N=|#,|Hf!aa+ GC,{yOǦa1:5<.]dH&z&n,ð6Q{]w=#); Ƨv9BpRp#_:>w[_fuNuI5&ۼ$yw ,nv$V~ HC[䦒78KJ/%[6CՉ'cs[2d3蹻ǣʷ<6~*?7@[h-7!L̬ 6D[ =ёٿAÁKm1*`$ >hL @ژi0C)O'EI@ ZTs[͟lq6.X fc6 Ni4+R>!l'0tQa4/ªuvp|CHM;Y!;zg٨W &bTybE<vz21aXƳ0`r_߻~r;ģ? 3Bh:'aXk9R舘N\}Df}GCr_Ywqdήqcڿu? ,g}[hb> ld|ʽ\#W#7'&r/&}?8&=Њ /-LOM>Un #C[IP䌂ߔnX>YQqZ0,㵿/4Uoَ@%4h hŨco~m;vꂙE۰_OSr 5`68n(<]O(Dk~A|Xȉ-xڄ KClbx4bQ)>dWHA'kU"bid 9PfsSȇSSG3 1ASo.tZ3MAu}2 ~۳Y,2!(zw%&`iCaxFIFhx4#;;-ȐA!! 㱸W4>[,uc3xPG dy#Y?>wM.^4v:#qCRM^{ZcH 6H1̄XOHPᢐg@m{[wal?*GG|"/^v9^ AhiиJcɦ׻3CG ǗuQ<>8ϐe\н?NޢW$hzn jf P]^yaxTĒa/0:xr.G@xIJ=Be9eZe—Mhbpqg)ܻ2+z~ӕ+9d+pu\ԴfU/a˗|e-eQB # {Qjyj/.S[X\l ] e_CrxnIKG4f;!e\ $2 .`Ss1ys9pq7Ӫs"Iy,}7̋hE a!OKCq)vpxXah}r0c0<RxP+BBDmx#3LͧtgÌ!>L ߐAt=7{=/\@бP^Tb_b"Dֈ4ql:=Lu3fϖS&J qFfEc`.>sce,qmeCZuҰ-?ZMW$۰ *,1̅"ɩ9J WSJ!M}6Aj,#rFRN_Qz|CZ3-L{*Qs~ X^rpv!GCʨiz}XSܶ}hTܤ]8ba!$򥂳ᆠ"sq.;a\:C2yJRm60*=Q;GDo1DGaZ.`eяy&naV87 /i`-'xx*>ڟ8x\ҌR-Nrn2Bc! CP0ccս E29nƋ*JMX+ߺm.C\;O.v3"(S0mDT?^cP>N5S3їGﻣEsek&cJ {[7D?3w *\ w/_gp˕lI0ySp/R-\ل7paXNq&yx7[)'h`*t'9 Z< ˗A!JŢq8ɑ0vVMOM=;Ʒ lPM^Z!'XMjI"LT) X=gKoiJR~? :/Vjv(?8likP&g67D/1>M ᱭy@{ 3DLJGGc~fF/p--A6 qcpqa%?[7Fjw @($a:UL:@)v* 1ti0\G8q0ensدύK-7j篥I[@+]i4PY;=4`J(]g$+~xFvxOlܛ_0KKaX6Uq˂NiX!n@|ϬoE|ԾyO\hUu| 04_$@LLFSxe4ߋ [vO xb ௌ,/!x }?Ja*ӤH,ؙ7 qnШ(.92?Yn⥼Y\}XX)7y( nػhxd -V)?S4!{9Ii2ôrióSaIv3dq_Ʈ5ɧm&<Эa hf"uĉ4AsINْdrKي/tC_~]mCD\w ӥw?kK_loljc#ko+KbQsׂEm78?7G~w]8sm rp׉h±hc/"4|$:WEs/}^4#/>Zo81G}3o q F&;`ʝ+PVxn7T7QȶJ@x($&! Q,SǢ₯1O_Gʰ 7imTwV<ͳ%SOAz+ξAܨx-ÛA'G6qsQ}ba~GC;+½dF;%Fz=̄ =_4n=~OҸ;øz2 Ԗ^{}4~Y>U{0 !t̀O,#p1st1:ZI7l@Ohe h-l|ն"w񓍀DIXv6.s~fB<{^ѝf~hN~V\81xPyv/e X^La"rfxxNU0pM6CfjW&;pɣ֠z7~;/ƥ_m5:4lA8xĽ@Wp{l):/ @;38chNTXm]Iy,'vƞ^F7%=67C܏ pFw(,߈C3:SsxATZsiޅt ܡb!1׀ IrT`Vð‚q֟<rq H(OP}WH aP,7daX" нܪV;/7X/.i9OݱepCg[E<Ԅ&LHSUaXxDpr#P+tPq7/{~*˵ 4d_>pn<\XԱh`>`x +ͱQPBsPqx>W`k0ܨ 8o:' k&cc 0䰿?+{df68\"JDoWиw[qT!Z1BNFcQiO"Ӏ>Dndpm=hh b0 +g@(\:kVR.~ "Ġ LQ{-5{bm oxI˽\\MB%1-FF~5$VKOЭĊZ~3 _aPy_I|lЂhM'cKccw;zq;p-% Klx5q xCH- 2lsi- 4- ϣ#?;>tOt柌5R]Wco}1oB`o6h ?F!lФ.:!='x11w-`#f@8py׀|,\JN%ұ_&!.5\DX;㿈ϔ V_q5,5}!9n{25B[1 B>0\)(?hͯ5o}v4F ûw $uq2^A1GڥҁTȲG{ynGgLT0=j\>f`Q12:_sC^rQ8ڍwq< c5mM:aKcxxȕ8육Zp^{Cc6{畸jYɶlZu_1Xɑ@>i% ^pJw=OH/\&^<Lw"1)(=™|ŧ'LDf :ayaaMOÃt2dGp>,p)VOzV4'u Adp J,e0Y9y ҈N;D 0 ʦr( J`dcirOT ~0i8*__ [{lre2+ .jYM/@jY51⧘՟n’Rh}u6};1Xo46m{#8(k<+$:?rh`Om v35l ЪPrt LV'#9kȯ[ tl$MίAuHG(uv 2`p5FO#iÕA~1 X!V"GSԴ2Jn]Hj_BҸP0 `a2i˯qWpꯦ|h\*!bKÎy^͚twky\QOtʫ֟{ҹ\A|N_āDxrb嫟ng?7[o3;0ɍ0ΥȑN`崬LPԐ5\CU?XezN;±0rώ_ȿQF޴gOȹı4pC]}fvc0^ Dr>FmH dr &`͟qĎj~3PO"0?2j?b)\xbaM&= /pc1747oǑfJ8Zr> &nxL:#f++>rҥyUq O&,~EZ&@DZj!;1H6p(;cP-hz!JOZ°u ճj{̌L[#y@p5jGtE/^f)%v (9\A]J,b%#%e J?Gc0qGӀGjŗAG|^$ ؒMP7/9fNysиJO>O:CbG @/&A%_,6x)2'k/(c1v0CΎf4wh)W( [@ ղ:81ۧ-*MI?c!?1s~smT.7od(02_0h5,0FǙ'V1yܛk [~ bE 6L+Q'+]v~ Fk<2#C0Y@}{ X>}Ȍͦ+d?Y-%,$9 83EJ'5633WwqO()t ׀0tkЦD _$ҡ4mhqn8mhhy# 5(#n3/[mߋgE}sS1+:XY՞f.6:Un }<VGJ4^mMJD mo+VO.SC?w3w`4юn54N8x^}p&rr*I/3#cyMkpLK}3 ؗAw4-s"%7^g7"6x[pشg|"uT͢U+g$=f f#`Kߜ1Soy5N J/_+IeZ/aԮyP?~i4\] ?4%~8"E) 'ײYĉG]&k?ʬŵ =/6 $`eJ9 纹Q݁l99W Яfi>=i\#!1%F~ X޼i3F=alx,jT}1ߘ `ƍ"'A3+EHZ)e dO#*; );N3xa#9(eӻN7)a:M4;nf/ 7n O(C"_ )sk5~ iW `lFa!IO\~8Gp߽/ow=kL@Tar"c7/_nno"GnP_wYϙ64FzSP9>Z2Cؘ? |%ZGܸ#Ao!RMy`bj1Iv&pJߠ4#R!謄4TcP>D؁V}%j`mG 6n^_}$͇KRsؼSKxxI<? _U'  {5,X@| =̄0Sє4 ʍ* SWH- ]c~ (p/vHl ?އ 41(40WpQE姝e]$LͲ~o9?kOrv,9p-%-a#:=RTfC=? S_(b8b|W[t5? (]G1%!\up&ə4yUhAXZl̑ &u_:r $ee+b,NihW87Hj.nk=? ģ0jW7[B>n?k&?N8<^1r !38vmEV(a.9]zّϑ>ڈ[.:I#%溿 aQ,*hM[0kQ_/C\>__k^Ks&}EA O֏ft*|i8qMB~L? $.!~_T*q~a_>%2]tGq>\%/Q p#/n%DPs _ZQ `Y a{cr3!ܳf"`\T7 S+K|OeG~3 6 I.绥_[7B~IjX5h $mU|8s8h-m[|٫ݚk\?_z"33x3Wz="g:m% d$؃{~K򒗙O^ns0j+Ʒa +xB HQX٩/MI{X$I iLa_k%~7kW1KJ+)) Wx4B 8J!EѼؒŭyp-"q&}$dděq?*90~.ES/j:ZK #1()O^󜿂f=s~,g8' 83e+ڵ3Uv$}AwxrnNfɨ1!?;{D=3:n8 +OD?`M̦n??!~ܴI9K4CK 4N6w6qpRM0j'BPi! 1ώN48].M> _Alj, xzz ImFq9έUC@;H6Ln?Q65Ge1(X}U0x3v2[$f?!<ܺ[f3XI7#(0Rղ?~Qnyk~Bڜ.aȷش9xw驏b>ّ9x ځCpW:(7?thOcd^l 4./#~@~X[ óKH ,z1 V+/L!@%w tL>l79s(j\ӑ)ˆ$)JOMAF gG 7)eNa|83ܕSi$dT0$#;^ c:.;sIH)v 1(d/߇yqЅ"q>XT #w]Nm0 89lYJE*-xT{,l'@Y{5 ဍzO ~AdO=#C¯Ƒ݆DFNkh? &.p'$Y}\OA/1̀-a:<CpMŇ ԍ[;IDAT1Ő?$LyNbH;7^mq1G0FOˁ/RbQu-ap^6%J^nY^_'k^F~&Fֆv%oƥq0$ ɩ$4N0&HȎ2g~9$^,S諹ĤZr*.c|3\0:ICRquHd<-ae,_p?iFs i.|$vz$G~ϑb0;6\ˁ^b-JVf}aX~v2#$wG^;G~_7,h'/ظNvu'/a4C|4ӸXN_6?/YSK"^2I>Kk<%S-I֯'n)q?t;K.-Bd(s#_bt(- '8ɥ& jДsF_(_ I&"''/\I5WȴK?~qkbO_ۯ/iH*`iIWNR] as#HQX\B ⾒s;c'uˆ')j\.RO΃r>;e۶mWݻn_E$|fe?ub۲ͭlk%.V>5rQGCu$ɰd^$\cJs 햴ӭFa+hg[qO~le~AOg}[߰|@'T]&G0,e1Xh429>v--0=3ӶLr= Ƶh8j}ۮ.0H> bOʚ%nqiy%@?oi:^_(:h>5Ը[.Cm}ݎ|ܷ( &/ћoA 6C#.fol+Il0ǡxF!;_8M25Isx\h>ߖOr"o P[^&o}njnϱ 0]3՘ |3<Ȁdofʍ^=(+c׼# ~eG r(Ĉct^iz” ձdd {m!Q']flƼ{GPMbwѡvTgp/4mxN'hl}SS_􉉗[|R8o[Gɽ+#2bL1LG&I_zTmXgi|SATyύfm.03Gp"xjU*Bxh= 2o]b?q)^z}$;KK3n(>z Wޯ_^ %af^׬7u } -/Wz3)LG-42I26 8P8wb~όCޥxk5&>$ˡ _ &xF?, r$}S-'g17sxl1L6 UU9+emA\VS0F>,^ӡ+/l 6u73@ H k5EPE_@ãcAZiq_ro [EO 2jq)]xC6rggO}?#Mh-O,!Fk>S\w.3?ZKt ø7`Gx8&l!;/x%UY]߆,!rmO;{۶{)xLEeƏkjrEx^vE~>)N|;kćPI1_?o׸0 6c( !~Ş{k`^b&=J.%}!Xlk~hspOM>8CH/ e`x{Y&@9H RXHיi}vc&p f`oq!߈Q|a3DmBƜ;kF渑,rVcNqϛM7%x-h$fmpe`ESf+CTc! XG\$q,ۖ 쏴+6Lvk6[Čs#h[IcG"Ziʗ|,5HyZJ粩P n.7!>'K9?Fkm{k=_tdXǓaIU D|P5 鞀yK0$RŁ|s^yYQ Lf[of.6PeybƬL_zN1棣 z29&'_}͢yڛcf|d!"lL;A,J<ڟ?N;;?37W!GbɁ2BG`o3`fۭ]bq yg p˪ao.A`Q#04̥B9d%'#O3-*L`"1fRCw7wd*Wn9k[۵97)+LTWb*JE X`-l݁r&~CbOM } ϓ.#6~YËGw~&˰,0J'WDjrn.o6۱"ȣMBdl#å♭᱋6Ӳ eB>*a*F?ͺ MOtqdj [tcn$]im#`Nc&=MK {݁au'w[|@wۗN`F񶧰YG~}|,fx-٤"R? t Gm:1 $isinj5BFg]v%Ҏɂ#xJ~ܻk%\>G:siA(IWˀUtۭCL\\r"g0I,Rhؼ'#~߭dIFG}zMg֭oך?Y0ĞNƬDm Ġߨ @xg#.6TloSˆ؟ˆ@ث~OGz총 v禞O8NL)^l0>`2l?:֏!@FBm J䯎;[axong_EܖQ9e=cuoҍX,)" Do67epK8l*$oz&$FF~s]8燐kdyt<vloO 'o",vWd*69N^LbPۮLLL3NAC/P1NxB Q{Lf*09'n?GNR;S_i?S:>dY_v'L[+RLIC]eNݘmr57exy(MUМs*_dꔎ@DC;JDc+*auf7rz Q)OE.FC#r al|FP~{44HX€ fț s/lݶ*Bg8j\nUxGd1*wv?h/bs~PнI,!ϵ]fW,C|2##`>pwqi b(#7Fy?ȥkY k@J\iƥaY* kGpѥpQzj- ~.v 2"L(=Hv0(e@=k^oFn|P3൯7sEc{"~B4cXru\Բ0PKƯGC]\Ec F\+M.!^_ٿG{:Vow4Ra ;xpM&`Uwj462[:\XN=`2H C)>*)kG7 r טK a7M7IO0{LEI4x3I U6HǑ__}߇U`.VTRWaFɨVp2 矌K7{޻っÏ=f)1; t:6 }^l4H{l60:3֦%l p߀8s2_I)AHBi{OI} ӓ(sdC=+>2:kƇծi2PΏx/"~/ZR{\$2% Nvsn#U?JJ~|NK_l=%?5\س$db[ 9Ü 6@sN!8u9F޾ɴwl¨̵:@p@iә!c'? )XE mt]׾ Ϸ?2aIG{iMU:= f"H؏MRM #u2qHM+dѹ{߇0 d1eʟUC^]SꫳOmܴ#[kۏ>4xB9݁& d8<{e `Xn!f ;zSX{$6"|NCQ $4Yׄ1.7Wb@";?i?F .(;(麻KQamߜsNf޽""0iD"_KOXx||g&O;m'jE\xb"`OF/IRn?GRO& !w~\'XGe~aI6GsL1X7_wTKf d ~I@ɯ QJ D{7}wC駐ȭ>dO?چNBEs_o].?WvWoCb ojw-{,Z-)c/Y6V> L\q/Nd:%b]$aHEӡUq5?5l5_'bL^.t{bOէ^Ub^ ڏ@v-k4S3?1K~֍lbcf_BGۑ7/<(Fa7V(9ӓH+1֎"*pbbUM]iBR0;>i.WX| %t(~/&cͯB>[]͛7SSluI/_i4~YKnr@ Ic$; d Wtvg@"6JB.|sn?(;n}Οl@ۂ'MLcN1W^hg|(!h5gg{ʾ._CE9$+"eQV"P`Xu74.A_yGk9`g-۳P&Zk,-&@mHǠ{wFhG<ϗ ]S/72-5ͻm?0Gwi24A[v~qQ;d6IJ+<}76pGk/de^P\9Ke_53maY/-„t%\3qP1p:k̐܁ R =3 _ٷ>ڑs?ả(ЙP7Ԣv Xa{MZ:%ԉ#r(23Sasݲe+_&G4'XRH=-B} 6w ":I\u3z{M)Xs?ޫ5?𜟯E~E7Wt)#U{ 5tgLk xFGv=(FַHaa$~ DP:lEWy7B8F}x'>-W?i~N7 4Idx?7EW^Ǵ`ڿi?/Q(2>|O(B_%>p`+>ӾJz r.$Qm=ʮ@i/dV0u"gd}V" vp{}Jf,.[x'}iQxVV*iiQ<F=\K|!nXpݺ/Mr^W矂,XK*t‡ɩ3*'?A;yoAo_cEEDO` O6%T&Wu&{1RX86ͻnJ~NN2i5n#![;3ڡcv^ɵnk|14Cۻ`PTéK)H\`Q?^kŋ 7F_Zl+S%<  eA ,vSh[ ԑ~;3,F_يG;~x/A NtE(/*Lt!nb)~@{.武|3AT`;g/66ڙvp1|'S#;Y|d]{~:<+,뀆(ax@OMe/zڹgjGdž-/dhA{Nht90YS]6@WVŘt?&lI8kf`j1P.Jmv੝Vb;ww'z8_XrK¹ [8"O I?^p+S@0 8˥ҹ}O>ZsB Z?-E)ڷ[A+{^ d5~$\9߹(?WU'9\}, ᝘ U0*EL@GXq&؁Ɲc. K\Jpd✵p7AmxV {3߂0 f>|>r}+Vb٪^5O4]lI,Z5a?cRjqTR^?;AFVr-`]C}֬YVjݱO";,=Bw٥#.'2L?dߴ_b\2;at&fL)9eY?И>*wVk{ڦFȹK# W]6貋Ў /^it1OLc?ʎ ?IKiFa{Z!/n娩j0ǚ|ahǎ>syDd`'<1JshLBH4[*q׊d' lz}gkF{Qo. ;_\p&9l@4]I`N5oj1^´iU*34N;z f`X3 ҈i5K v%LBl~L%.d3g ͭLGقy:up$0Z`ׂ蟚igf13QיHL}[s˷k|5~a%\⎈sJU۱#?iz{L@fgJlبdg _?̷/q2B30R ַ2DJ3ߕf| ٦Q?cG[BB&t '= tƷ'qoN3ABOS%y2sM8hJtD,#9$j\}")0$Q-:<>av%G󬾄5R)K?HO+1o7hGDQ9f0װ"L`|<1ȷ5=}.`$N.tq#~+2Lah~%'U%<=nozRL?k~Cȇvo0}+fL^%>8f!ӎ:HbWuF}] HΙB& r4PgSŕ͏sXiq^~l%i_e}⪈-L`YՎ쇫->WG~k¥BΏb|#pl!^Eܷ&f|W~N0zOd&0{h& {mOX:!  [:xd2B`}\ _§Qp Kq%R+ְX:SN\_x@|_;_r@N[ml B#8̳`w l<%\$V2k WÒnͩ IM3]@!>>\2uÏ~槄pl׀LfZ p&\9"Lj=? bp_v%8f\ l!B^Lsiݹ͇ }GfI2s]V |v$,fT*b CN`OZ DA0䊞0O@7h: K s9uD?B%CWå7LEyR!#?ˆ?Å\P Ixp_@ 4 2.rr%`zd |IB/gf@,t"QWo vdYy ?GFoWقXb p9.#B'@ѽic, 'ILJp|]RV?Rp6pdBrt5^n`vHf#1\AR_ ;<&~+ai2šZu/ 횦iJ,ťaf=n?{uͯB> Z;`^iL@. v&0J,3yGO7;V{>ĥP뇫/4M%2߇“%ngT|..O<Ǵ.;48R g_3ՋqKE?&Uodacl5):0GOO1(N̓/Iex@_pUGHEH&vw@;wqX'ZVX8aũ%aa|{z%:D4#@j_T؀,L7wQL 3m:'Pi0i~>N3ܧWXVs~N%VoVਏuu8̀<ڌ W",&_.Τ&c 83!/Ka!3jV{p*1"fu Ġ" D*6,]_%DjAI#luk,p!{P!wHzJ!̋l}~'>Wi6`2=T1O@ D<I' K:Xd-,◌ O' @]⧿GMa:V@_H~ nt&6=.Ub''LN ӏe\v>ncNRØi3fhէԒ'lɴߩ\z<850t ; AUbGBJ<ɬ:ªK>*qK(0 1&.}%pqU_Tw}di~o Vk5yw{8"L',|YV[ q ^&Yb>Ξ !I:y;Z8:5~әETBJ>IS+.e[,ͻCBCW!S(|[o0w5vlp:`*'0=J@p?£;h_HX*M2?.FyWzsCVo@_X[G5`GR@m5Q" X xIuBNsjs_ hczOs// xuu]pk<bBcў@hTor&@E>I{za xҹ\bSB }ѕ+ iEf|GY{*10=Ӑ0^/XZqCv%~}C^-U"Νg~j;8$0f!6{Ub!4 0'HOLe? / O&;0c 1px(xw |(ש/-]B$0T\JzGewbOZ;8vu)L@$"'=[p D ч$d(x6 _?jz߇c n95sHO|<'# =a=.5׀,-*1gJL&p3 xu>[||B ygPTwŞݶπ,ͦ#L ;ϐMu3B&ɂ7|-RVUD+j6T3bi#?4ϟ%6^bd50nŞ2(l;St;LĜacQȰli`) $ryeK۷w ̀, mܓvWnNH>ѓ)4AM|s<oruJ5K\tww 0N^#@46,aәS?,٦|tU}:HՅe "8@ x7 p[lbq޻yKܨLπQKh.żր}P,?2bn436 \dWn!c\i|; ٍs{qˎl46 kUR Rm|[&"H}&jbՓ+V"32K+Kf' C}D`7kc7(rF?;{;jd.tҳ0]J50`KW `޵Kz3\.S kZpadvd3nnJ`VݴoϞնjZ02A;5 ŵÒ}_¾IENDB`ic09҉PNG  IHDRx$iCCPICC Profile8UoT>oR? XGůUS[IJ*$:7鶪O{7@Hkk?<kktq݋m6nƶد-mR;`zv x#=\% oYRڱ#&?>ҹЪn_;j;$}*}+(}'}/LtY"$].9⦅%{_a݊]hk5'SN{<_ t jM{-4%TńtY۟R6#v\喊x:'HO3^&0::m,L%3:qVE t]~Iv6Wٯ) |ʸ2]G4(6w‹$"AEv m[D;Vh[}چN|3HS:KtxU'D;77;_"e?Yqxl+@IDATxMeWu_D8QY N U覜.f 1@YIԳ- 6 aRK9#@  )t8>cZ{s{aG8{ow{gJ|pqvvؑ*+]C? {Ftl偛ꁚ7g]~-+*})Ƹ{6^ u<<>93)ɽA`h#T:jpp=syOv{bOmAn)Wo&`sӕCy_ ,{w_ܹGww}аӕ~;,Ϋ[;{%{%K#l{woxǏk-_쁚;e[y y`|/H>|[g73|U 69"OQPWg\8m0Oʲ'?8;Ƴ w xmo 3>`^ AHO2g_['tyA ]SS2l)=em_)73MS'C+9R%ןf'Pg#%Tlo=?{|? (EJx`v%{dzCMf`|-6J| tt`;wvNnh<=P>( '}{nO/ ;u\\&ď0޾'H~H6.zC8vÉ}Yyy

sٟ/@7r r<2t̴[z#Pӟ xڣN!O<=PzRV~?s.׌W53qA8nC6p;DHWҪ l-$(*lwO/; zL<:gi#z mBl.f~:vJ6r^@yyxm-#?=M;P#:R3dZ3.kh#ܛ|솇:C >?߽{ p}}wK* @%'?wP$ IᗀK\rm m֜a89e+vQ:6?{ϟ190LV<)n%8@f\?p*Os\8 xn_h6E&噀&y0RT(yE_޷yBJ}'OL纜kwR&7t<"#mˑm v"w7\SyyeO"rls1u#a4s_b]T40:^>X-Ӕ葊L@{E틁O֦~AFq-)ly{@3}Ohi0-ʢQ[83sRI93JV ?-uH66228S(IYܔqB9Sy6y0lY>2Za ʙ2xq)0$:v>$[`]`2,}tͳm܋gQ}TFT—g>)HyErɿő~lyDH* OP\ :d v`;:3,sX5FX *7>agLΑefbd @>G@y`@Q:to?"?>+Q[EUPpV_sx3D:ؙFTh쁞H$lroBvF:D?7g陀[?X·U* 쑪zAm=XE2<Ru#W2\NѫeV,F.ʕħR :;O *42&`C#y\ x_׬M(VnXm UPW#p*7$e٦ti6sJ\ 0ml{) (._I%|CU#d=D IC#̹$xrbsO嘃Gn`(sѾ SzmQia[``{'1W^[@{㟵IAK\3OכP>/Ayfx!1K]@hWT]/s;em"-Dn0ݻ+$Q6[xj"D{euH !N"Љ"]MBTFifq =)A4ۺ% %+Etr#H?әbԑ^r e{S_[Ibyz=[<}[= :s`!:H%G YAG j9CZVpB qƍ^x9ץC{ : FmT.kEF;ABe/~t=& ˪ry{=\苼JZ[{0l'>R1A0ұl3,C|\K2pN5Ce5GiCџ% y7J N9͹'e~0mFԑ UpӸi]1b7̧֮jOy`Zy@z CW(P@!D#oWݢaؓɾm#L/Ph3|=PW}V^[_<0J8:`9 CTsdɼpFDz$;њ(&Gy46ėN0%>2$hЧrNoA|ھ+J}خ#K׹ e{y=/.y ~{- Ia*+f s\~Ώ6vf .At%Hg2uӬ52v['瞡=nd)G/گ^m3cU+׹_EWr7R@e\.S}k,\V9Ӈ>ǜ3F.9 "K9pm;Xs!e|_x8A7(%l kUB<&L@Np%@)|򘿮m(y1oG$\'*4=L0h:,\BLz.K϶,Cj`a8ل< eݣ^hluFiO;`mvx~;@>t==PWgկ\ +`VDZh7֑ EA( zYmrrY3j b͘,-(QD)IRTsk|.UW2/dY!̅]Rtmu -mo٨L%rsGO%i}NZ6^<Zz`/kiYVx[|ha-u10/c&:]M65% W)c'=JjoЄȵ K̼+`#Fk%R:,07ぺf^Zu] {W(/.;M39 mq %w広(rT>vd;pWH.(r>ZY.wȮІ-k8X͚+:ңhm 9FQ:6'pi~Zu7⿼{g20H*)8'XuRM#rq"Q:esxvq!{-m\/>xʡa,C墝X14"u :Q.4cyEPֈ.ntwD=P2<]i&@Wx -XӤ=p':D$@n.$(hN=Z0 Ʋe!lK֊v{s$JAʡ>`ynL#}āRT^80FO2" ;]7ぺf^Z7<3S?[_}޶ E,nJaGr4$F8@VaK|Yh0GoA83y.x#|f kt^F9[7.Q~4K$Klݏ rܚ,fɷ{}wT|T )ʷܮ9I!ȁ% CA688NѯiLm) k<ۮ2.ڬ+l hhȓ#+*e,- O9;3sK9]!҃z4hN[J3_uU{@}3௤SGuGofA`U?\MvJ@xW;ܺu hUYAr/,dwX<@ɦ-)!G<5B&^ڄ`[ z|dF&d+N b (V>ۦPW;}3fW<}x6߇KG^"V̟׋~W/K;e:KZїLhG5UȘcpTu([h뙒2r$Ue)M ǢLmX^61cXNvO_Y^kmՖmxʅvb`(̗틁!a9P 亏ԡU>{8p#26=lQjsvE[K;Yh,3ŧ4#0 ۶ycc5gxHtg^vB~p sv{x?O_ֶ+/^Ǣ*MttKƩfH4h"/J9ٓ::eMe}V )E=KGrr)3=ed}1 ^ΐpm/,?ex o.͌гvՕi̜Uܾ*_/lՆngLkx8ic9rLFF?"G9[26m7wnKOO?N<@p\#7A R/&y$gtϴ_ hQ 7 Y ˬ/kDEI5|r>BG>^)6. z.DKٴ75f !Gy.͚CZ{L{blOn_#Z_xG+/|s*[ݫB!u{x]o#?}IyA|qZe(h~.4YvRm\Q+a7 mަ/8@!V|p}fCrdOglӣfQ+dR2X8Vϸ-$CxاW^>zѾ6mH6mJqkaL?dz#MI/qʛ}g+‘o|al M6cPbZ?#8K=ےt6ݶil˾,g.AVy|ۻMmeYwG~ϋyQtr)XWRY$otgK<ՓwL6 f_03<.YRKd  yDRqOL#Ze!6!1-B !5ayA^H.E,nwnK-hyj TT:ւWxڟ+0 Ƣ)ء89X+<^? RdS*[j7|,H[[.g?A~I!O}|h|sHmz67'iy1z>﫧y_/[y!kBheQ{b6_좃ΚNrB3B_) m8Lc;/dAu<˲E?JSߎZoZ-a'/Jv}IjkC|z9MY+vfٙGefGg|G)Gw35ơ"O8mm%`UЫpSmɖƷvK}RW@m[O5~??#E uI:9g :rT,Ѫ?j۟%:bm>6#;rqݒ-lD,gZz3,ESmf-+'%f gIzCY,+_X;΋L,%!7^yO{:NS\B_=VM>V8Su S,QeyyMsX3o.s T:c}sHpsFsh/4ïUSuqÞ ʕ`2uُXF`2<4ϛ Y".dƷQ򕣆iJcy`@Q}垿XD3m/v|{5e-\g:T$AKG\ڂjm~PoPZ+经/~75:SIg%J}u eˮu2Q6&r:dc彜(݋: 8aۤ!졌]%>ڜe9V$ptd] dϼ_hVi#TA3.h'u冭LMz繯-z#ܙ&`.٠Y, P!DQA-"I:٦ ZS@-GDM3=Pzt4or!p{<*W@a!kx?gk]Z ~6ҚWyWZu}Ӟ h=?%L[hz.p[COlw1 ei1Jz3=f]-'f< * |kelY!~ qnlC=n{p6?7+T`pu H)[ Ld`30q:X3~rоŋ'61|jJ ?'jpo5$PιtK0:t:mB!zH3\1c;r._W"yn>^;ra[(r<-(E+0* Bg<:Y lK'KЬ7z_KD"坘R5^Rj6 ]4Hʢ#W NoI ^ӈV)ۗmcMDMWg h/X[icȑd+:m5y no+qo\=-.,ȇh[;(QRfwGc Ly^hWܞCe|zt]gv|ߵgFHߧ^0/^~`߃@??/ZXXd5bk=o,rGisy h8S[7up]5tq??䲽z_{j³{oW|Ӷ!w§YV Xד`X!JѿQ6&hT k:23fq.s  bK=a3t2<Ðf!?пA/[F> <]m4|^:b4/xƂIu )| !^̳hLڐl HڳZDfAR<:Ʀww~aOs0[d>eB, 9/Yf ]57EB#ΣJZbcyH0-2/kg-Xo <O}lcIGvI=a{^Ԅlտm3E 9ܲ*ߒsX/~>vϔyP~M/e=!P۸`Jx^{W>IFCbغOm(ՑmjA:#AVn}k^h l#pfgUe Oo4_|<~g|0~o~KY(XW߳ Eugܼ FYAgLeF8?DMH$ zaG3vr _Z_^oww?ꀼ贾ݿ{wH}.>sr 3-: )c̄L%lKEfve~D6e4󃯚SҮ_<_̒va1=/d. c)/Th/9gI:s[ƃ绿7Q?G9V幞y8SyNeCt[9A+x.Ce6CsY%W<@}GBv; em.yxz ?/>Byh1@2 țCzgXR,Nnllav&]*x u={v?>T8G~ -.'s~'%SO%cեuT:,mI$E52v?V#+m ,ow@IDAT5o7}[yۧKj>g*??'XNbqՅ :X䑝rg+GOe,.G7J3[o#WOH[^ƍKG` 0C&ip?) =4QvOܦ!=?%<>RfrW7mm!Vg ?k}1E*/Jc) 7BcHP G.X̱E.u@4l%^RőETPt=SIY~k%Iɘ_SSۿ|>8բW0q+eeX)GZp-*S4JPG[|{w礿hzx_}Wo<> ~3w[,Ml}z_ hH,@yQ\A'%:4kh$9أl55q~E޻e>1u%(DGOSM8NW-4H}1õYD }u~\ /$Z0b 24)#GC1N.zY t[!aW>~ޣ^^VvԙsJP%}sLJ2 ̟А 71<':"*ͼJR)n(_\z& |zJ[n n ,O좀kCٲxఀ22ͼPƒpE5\c2"پ[mAmK B]:0&"Мy|i' O'ϴcTX]'y! y ݢt˥_ ߯ܥs2%` \ǂf݄zКjΗϗZ<,/jz̭n#Z2pر[dA,{clƯP}ܾ&޺mQ whyO+M֘ jB'}eEP޵<)c5Q[҄iCZF]^\@n'{)  ys0Y6-1= @NX3v.w"| 8,oͽ~$߅W?>woc/XjpNY!ak!!+ƺr d/El xs/'SzW^66w׿L^еj{gvFX0\ dˢ 9>޲)G.$VPg^mLĴp?3rV_^tp>X4ѧ - =, ^~Ɩэ,Pٺ̱m6,Y+׳V/T=I,1BB/4]qYtzNp fCeVz6{Cu[h ̰;ΰz v%%9oT(F_Zn:3$A/;\35oS9G`֣~E^AHXuXs ?<98#oPV8`.`~4#[nwi|dn} 0|'˷cn$$"T*z Ej9BhiQe4 X<%[ #3m}ڔ1E2-~\?QyWGj]nu=$S6Isk?粤Wey 6@'vruEȱ_Boإu=`MW@mg6,JQOckI},³`+e!sc:]ȑ.4^KѢijA/ ۔a!-H c*:e#Pza<S_ tu/72&.g<>ob-)<9rcז~vC9Z ̯_y0ym|x=sZ HoQfO -wVLpҸ9XZ=#-3Z0/~Ƅ~t#GBָx'h!d}ŦQo9Ix2>;}h>@)!qq@<ty|l=;L\xC;[C>r;ݢW 1Wo6pJzV{5x=suuhփzڟMX$Wa5E?./)+d ˳Y-ExLM%,A{])鳪%-:[74lF; \s>>ܸ-Adܴ5It~ g`XYzX"~aM.^W t)i㦤]otW\CmQwq/5=/<鵘xvV'x8 *:$<0f.Ih96pl Xhd>M@wꀏ䩿kM0Hs$RaGk92l1cH9L jКڴndn7uL"٢ɲ]~~WpqO8>M8-Z}Iž"fp9 p«\QSi{1I؅~PΔ#C%Tsg}@-^ -6x9Ϟ\޳GNhHHprja»OM?E s2cXra<'Gd;W7Ƿ|mUу^ E¶ <\~geؓ.@LCY܋ʣRI^ d{qR Z$Pj:t)7MP b6g]XcY rizbP& |FIŃ_PDZ~;A,ZE;Ң\Hv0~43^ۀ̟oG9Y!l.Q^J2w jm ,58>ҮZgšLz4L EG,<B%hQu\K |CK.sy uUϔޟ*2n W|8SrJpgZBibjܸY6)ϺT%G}?=>22l+-َ-pEnQJ?}t @W,k#N7 M'2' {yB);U{E Ѓ+]?mN8NI=@{z/!Y2~kRgX3\8Cr2:$y]DXXȜڮ4\[r菺mr /g{7v۞zeOG͛cr_APp7ӓ0϶<$gGGMrz6\F(Bz+PR|ECth ag^|%KL@K8^ф-H>91'opMZ1}`Ģ&?G_Yw$VH{˶ 2Y, lpX9b"K/]ݒ7]7K5ЯfA/}) \.$#z8rư,qd%#Ɲ_m@Gyji#dR|7H:_W2 nv+u+Ϟ^^ t)e?[ 'vc68nMf$oOedM>щGLexS QɋX>, gy1ztE|`S՝;;XgFqOG3BXD@1-Mh3,05,YV9^0VgiMHħ%q#m`xMI@mNr[4͸O3Hԋ.sSRtu2lov`mG4ּXw B9A.Uy닻/OpȗN} 7C% nD+|Ns#"C=N9>SbvR``b53>sn5Zd![9X?`2cߨjF ̧A&"R\$62!]i8˱zt-X0Im0c,3wv)dmEtmK:BO.9Oa*˒$^Իṟ6?{&oJsEy4'D2R ̼@GUqgtÓqYw Im%# ڬ#eK߭?{.Yc @d:_oxOq6˙sM虱c=n׭G2'ݮ3ɦs[%Р\ԳcrS^\RT.?}6~x* |bܹiߚ~>&vC3k"-ɴ.by;~a֨@<>LG3Leegl&`9i '~qiFLLi2\ֈ˶%<NҐͶQX=OԕYgW&ytd3[ՓAoW?Os‰> <\ϴ`3?S>' .grr-ti *BF~XȌV5WiWԧh.3k Hmބ,tz_?[fk/'3\O 4c&p L92;qD3./Qŋ$3$ %tnu] L$-fna |Y֢g#ѽ['?~yˌU{@BAHK"C*r%_яɴh;\ #|!˺-Y&x€ ]. f5/r>]kQL_`H>kM,0d9TA^$(s:rч4Ӛ>Cse;D.\V][6cAU73r+4ksNg9?S4JI[%ʮeg׹VòlAT^5rB;R/&:#e7ó4Ѯ]޸$oBsCCξ[]7.kΔ> ) #^=ndn4 J!MҨNTE3.(LO=ttXSȇW%! Ǯr2ߏjy3ۗcq)%O43Wo$ɋސDcCLsa86)/-l.QoWx,r pg7> I]zM>:ȽGDOwEϽgKc0ӚKGݲIRs2a:"gJ\2DԱ4])Qd8r1'm 9Ʌ<ٞ媦d< c{|o|o~큠 }ۿ7} $(3gS<|=l!o,,EԘ.IhCbzhNyQ2ްig8F\4lgV!l_~uzZNX`cP{,v,wCm0`٦LQXX Y#ci-'X)"۩zN)kr,O-el!g]h~Tz3 `Sy_$L z3 u˅9f5T|'y=Nr/#d5)X fyK¶}XGF:39P_-F{gyV~WL xq0:dl :B4Ё,[<y3G.CmVu63w>;,3TTqC8` <-qb>~J}YWy$3u k4e{O3O$OL-3? & rOLmR8:$KE)#9vl!Y[ti ,M ,d^pZ),jQv`or 0=Y#c#x]}G j")CA1ԇ%/x-1.\1,.n[g{^qc7f|cz?-Vx%c} ).u[>:l!YHaT>*[}&~@G]$~;`K/{Yg߬&A\LI& "L?_G&~I*XTyQ.,CǐZs 5nc,E __|*v@C4n ,C0l>6fm {v%ch 8cӼH7yŕӴ7WYgP%K Zxfg˷$0l hPJ~ mhseoot+ ^}^WS-bȏd<"OyL0K`Y3 Ю ܴcҕ\řܶq)?scW voыIwͶ ,00k1[ :/?o`x4(ɔIFN4#/HRڹ \ %KB"|9s/-xߕv goo_\i h3_Q1-OH-A/.>i~ 4 Ȯ4LL)\ ?x \/K7k^\3}.:Š(c]DhvW9$oƫat*)ξgf/vw\z< };^(}9uql[N3Z`2Rll8*m`XLr(޾1 MY"4βDe*rSkEt_v姯m (Bt^j (ޮ;O̟ A$b !c$d1/5 ofeU&uJ[urT͚\y` 0nK7tp>ŒقjQd#/`VWcGH?8(s_kIRb4yXfkɰ<.Ձmt`P,acHiQzoև=/%^2f;@o,QhYsx6{WXv[1Y TWb 6j֣(LqeYԡ xά*cs=8BJŎ 6V ]ҟ8fn$#0h ;nrg2*WI3a}/jkNFFJGQ7,!ᣏU&:2g G1 Y5Qj,!_S\6ۚq=\_ϭCjCa>Tۃ-x2`)dha#yG1G/[,*d)1 -yu0<[t7,bPTipiyyKL-4!,Ӝ2\z`ĩ&:ue ɚ<2c{ rN«]0 Yhw;5NW>mv@/']Kf`jܦ?-{50WQ'L!s  &la $ތ/rM!:`Ո>Yzcm? h$xIGͮ-i}=؀v[o}ao~<-IL »GZ-Q҃?}TrMGa8zuB5^ Kg{'6`aUCv|UؠZɂjr DY^>[nt.4KƷOxI_}5^-=ZD2c@{Pk`߱ bzȈ&R}\2 ƪꔱO#L| ~drhq\psgy)}!ۃ4z zvﯞ ʵ- _#7:'8 8n+gKLc ʅ{xx˂$u,Iz6{ Fx8k릵4\ h2E^] ۲>]#?_{{-ۓUbLL:n8&G8yf~H`v(/p1 h.dsʡ:Xph בlϹJNrcGX0`_|۔}jd“c߽w~_£KlԪcP>d~xByLQ6UA[gcIy&.gSuLQ낭#yO@}6ghqoβ@m>9lu*_{о~ՏI V(`:A\*d1Aɡ˹'8/TpڪXH2,Q}N𑃇2«6Bn $yEe[.L೥f#d3_Oq]=ߟ(=~yfnyor`׻0{sR'!ǜ:9AGg}K'-1n)KOuCć `4#XA#1nSSIxȆRvGFmLm \ʒ.$Fn:m[Ph~>_\!LT+y6WrSzϿLZѩљ?()`q0N2Q S{LS÷Snh{ d:pjw Z$ZYy~QFQcj:NBrmŖC_4 w?i@̓Pvn(P9&28*&>=!\SP\g-=ŋUAUC'JLLw=c\(8Լ>,w al_iiҟq=g/m~6`y|>bSGZ$6q\\FVw8_e eù`JjJZG'2,/ke<_igOY([RɍF_loØǂ.+2-x.1/DpiAD0!bŔ`A93洭H178B`#gnt#Sl[j2h޶UJA͉~MլoBHq;쏋]-\I:<ǀ/t;퀱ojF}\wC+N~tL1ǔLw5ײđ LW3RƩ.yY&v7\n ^ZƒQ2DK{"$նf[&},H7=:@m8/QH=|2ǺKׇ;Ρ->smY%:y̷|gHqܐoZ;{=qfS_\杔}}r"">9Ǔc оy}{_sjUyR8z}/wϯ| YmIy|_͋%8'zƻwޛ6NB|:D,+svmXx1x^P߱0aˉ^:ڣѩ)Ԧ=f7>ڞ|jk q!-_t-{Azgߔ8f{2LU#DSGI?ٙc!+&6ի}r1J\l:cDtq$\O-8~l_7<]Xc/4wƷg_8>6oĈ6scgCX]pD'NthP9Q8&Nzu$2Oc1ihfQhwWpߞtu^g_84iJVÿ|Ǐ{e$4ߛ~@{KK[~u~w{g7_2̱Qϑ=OV\ŀb3 ùsmy$BCJ/9#&qC=Â.c Ԫ+ݡx_?gyh)qi䌝/(}gv{h:wǽ q::ug3uT45z+xߣzmPty^9t_s00Z`{o9`w>ȭ܏UUo~~mhݵ)W:.~*_WC0v -2͘o^zXyI}>2rј~au|ǨGtC2Wo:7mſ0,Sq|^ޞ?;?x qi8Gʾڔ]/ovuB*qxa"1o>yc{tsI/P$'d |xOwo>ZﭱQV$ ޸HOJ cxٸk0w^*>vis6FymBs\Ux5vWێ[" 9Zdߨv2u]#N18[1V|y[،oGW>>6^]7֗U=_)}}X"*)$k ړU<[8YWȽZ7{ˈ%&=ʽnLW~W{w]^ꂮǏ n_ !\?uulhl&6ʓlߠr :{$X'yUG|s3?Ƙ9h'pQ=>:aWwxjLpA1D_S=Qh>,軞8c kJQXwlJfcKuף㍊mƛ^%OS~"e*Hg>߳V# z@;Ҭ; _ 48ǝg$'봽nK~6}Aʎўkzٸf6[9=ʡҼʞXJݿ'sRAoJ{=FǨDZHަ9*+?]}c`!:jq_ k}i=WU=u}n|=Wf,r^SKKO\#Rs,SUq9Ȼφ~|5IZ͜}϶ܾg߿¸Yz/>yXlp ubTN'9r/s'9v/s_l/Ilqq95^.i2GmwzMպ,}Op~ >kZ;üz49\8}_*:cbSqױ̨Σ~|pYe\}f9. Ã7t7ǀN?#k+I~<~?>}7:6TߐFs9֓b?HN`5ߚտ:o%x%`=6GyVߎ/n;ԥ cr6c^{l&>J\%O0@xÂ潡Xu6~M{Wx+~cy7x]ssFsMW{_Uyg 9rz{5u&?N쀶xٟw --M7fmV GXD>5Hֿ{N;8Tđ'9+^iQS׹|nSmHtj;LXwEޠΏxݧ#t!&o=z+pzx~S9sU5lwc>|ފ(񩵯 >rvΩ^#iX7mIs-d6#1(K˫X+: |<7mG0ߞAgNW7uC/(":㝏)>ya.*=/nZ Ǐɋw?{2wU\J}#u{~"\bGf+4r߿?]/U7_UOzYVݶw`]qQrkq?9^ž Q j̓4Fps_Y,J]nry:ri6سܮ;׻7ș0sgi(u*h\s9|&^)q3hs[hȿG)%ĥȂrAx6ԯ^ct>>Ï~ {c-EG"M@~{@ :뷎5]bNr|3Je{ P }1:VnO5].9OxuxO@'})0!?_}Oˍztݎ:}Ϊ䂲jk998_9Aq_92ʱWY'\wjr'N8z+> wɡNJ/Me^ǩO{o8oy^cnW Wj2:y|wXZd/l<+WvPY+MC|Ί<*@L"sm w1bR>xq;bݯ+Wt_} G@IDAT`/sz9쏗c/=ub1V\?qĬrx٤uscF}W_q .&3qUb .uGq^6y/TϹ CʩznkmX+U,o~_| %W%˜o|ܞP0: M@@i/|}* 0zV{{^~mSXc\Jbŧv6tz3u8A~F~0ٰ=^nwo¨Kml?%+Bc]7"6 Z83Ͼх^seSL$qneWLfÜg:kt.O[ygPDX3g/Z96ԔC_,f_gߗwaf\EJu\a#Oo#c{ut@Ȇuէ^,;V\w${Qr1?E.+7lKg%kxg}3䑹E8^F_.۾wkIs>>̿o7XLz؞r?۷Nll4%~ яu86փ>3kYy|+>Tj .ZsAV#ݪ@Nf,mXzhp;_F16M70\|q?^n>Cs&;z3+B[+js"Wt{G? EKV~l%кEGOsz}?wl:1z2Vow}C>vf2U5{bo7>۟w_I-ʮ-:F:_66D)+T;O0MNʠVSp팩 1=yDx[~uQ=K!YdI3˜?H+2Ǟz%Q@_q?jW5#=sc"H3d+kJ),ONsU.3Ksn_K=1~^.{h?trq㵧`-,hWnO &{i'I{^pƨ͒s`:nMqܱQ#;Ə S,KS~Dt={60^"Fkltב^ ϸ{uKqS~[ 3vcfDpq5>r.XX}!YHZf˱G xeDM髄_ѽ6 +};7;l@noOx)̱~Jܐ]mm Ҝ7 (udzj'TaR3!: dcl*[0s}}rMEoVx8mXk6W q|onH9m̑z?=,fQ:{ّS^a-cM_oLsWvV[Vo/V%9}F^r%F׉^#`qa3K|GG^ 'ax_7>`AX;c&Tا/L-ݣ#<1H0^gpX%6Uyv\?SA[XhDq4Պo1#}*+Zcb8"k&c O:O"#zSÖx$v|Dw'N Xb[*e2q\=K{sٻ#R}wu9Ȳ:">/߶`C'} xOW~A>ʯre&W_s7O;ce}7:u7U-x.2yԉY\}s/#CfmٌScx3W6A}sCWu5G|:G]w,F|qB+Uzy[7G#?|hN?y.myŷtŃxfaNFl7}іX'+ *o\zl1H?u^e+xʫ⭯X*Octp0C}iU;c+TY^ϡl}DOy3>۷7|2|C(U5wd8I;,6Z}Q'lEmh[dP #ڴb_~]m8է W>f^eea(A_Y嚑K3cNy[Q}e{x8:Nx$!'< ه-w̋l}J[y1Ym<5>:#2c&nuW(c͞?Vq=L[.*=|a˜c'(~}}z)̖˞ 'U7wtuɃs?έ+ ㉳S aԜ` _[ NkF·{ALa6I;UL椯ŭ<jq{)&zmJXۊǶpu^37>{k{>׃lkςZ#xЋd8oN3 )v.p[c-ͽBߚe'8Ívܱs/#cNO_՞ 1rAE|L Oce,Z;19m5r8yjH9¿Ж-LBڗ 51Į>f=QV`n{3"u>M2'1`,Ol'y8Gnu:گ.՗涿|oeFHʬ!KM+”c_l4말=^?ΛN[1|b :z̤~b7,8W]/z9u4xcUTNb]l`>h2Ɔo͹#(2'uɣwU?nի7jޥI)~'x` ܜy%`hI5 n:n2n$>{lqR{c|XHGz &qmO2+_VQ֬d(?4UzɗJF[Gh#Xړ3vzj/l)e6Ox5O ubx%ߣ,.>말y?)Y]ewT jE?bW+SpruCobgmsn?_>؃]nx3 Ť%YTW9 geϾُn\8G/q0~j=Jox1mKRrV35PRd\Gqx%Gzqf~04#:Ys6%%=^f|+9[d=ǎd,>}"'٩ӎ<%fՌ9M@;WHx}︘!?, TΥ1}A_g-l9ۥ/A+ü{uZcmO_:2}dS5KI!u6>S݌:wlr"aX[>KO;dhZzlu[@Y< ~=c7 >>>~fpX^U,k+Xsf X*Kpݳp(٣UU-xz 07~/sMLB_gIe+< 0:_gϼ#{0?Era.x6}m1uʃOZ"dLhӯ)8À͍.\E2Y0L{ kf ǽ1ݿU2Ir5cu?c$SzV&hr쳑;(O~-GE͹x=jo2NMh3Aji؇7W#=ӯ>A#w]NZDiX(Xmu+ﰻ] cZ᫷s`cȭ-J#Vt23g6{-컦rU$AT.s8+#c;Vg,G#>{sg:Q7~Y/HSa*v|Z۫9Z3koUyrK7G +̆5d'DZz_pXRdWdy«}y65%e1Hl+jͬ5kY}C6^lx,s_N|@囀G`;r=؇?-HdsKf\,-SI-Wi V+{eP1{iHȸ+򷇬yhh,ΨWc"WqPW14guB>ipm~oKx/ Yy15kn)~枙=wƟor8z% L,F/zFf{Ҟ` FG}g+p|٫C>Θb|:^\2rgp~Ĩcp+"M+eѿGs|sQLpشF~}ѻ?rO6tUVt>ObO]|ZFXs$E9^VzwFc\9KyY#&`sNΓqoĬu/ΪK5aI/9Y=W->[暼Qή1Ng_J&_{dnrR Ʒm/owi / شJ}5b3)o_'#5geҫ)sqw'ǪK&'9'6ssUg2b]sǪsˉ_׃5HV̵+]3 Hcfao6z'^jF٪+Qq]ˍ|v K1cLg}s}bv:xps8@o;'B[ЮvFM%mxlwMxmr[V;.{ fmvh,gl%v"vqiI {<+7=m/gW>1='1/; Wӆ^7Bw#8Vv_cvl6F߱p267{ /I#)Kz'YJ|;/=t^)Қb}dϝ~f|M.As׭}2m_dE]C8S|IJ|pd$= {ŞsOP"QMHκs3GVf]Vh-1^uJ{zEkE+[0#׳An;Gǹ(7[Yx .-,NG BodGq"#;Wl |:b7])[xǾ9CkЀu>t='1Hpߵ5^c%DyU+d]~}qU b@Kf i%bd4j6|&uJƽﵹ?'`@/'_m8(qs4׬)kD$߰f/JtW8ѥm/غ>\܉>߳2+]jci)fzQhv*l,&`<}^ xUoq,ʃ>󧐶ѻXJXNXYz{]5>;E'_ͿbC)z1gTs9u暨wKȎGDML+A?_R)5->y/xԎ$ \Q4s‘xO]wn׏W6|lpIj˘7ևl{acmRSMyW{e =h`#?yJ#:R_f]ɺs$&?x?=O:F^:|_ ؘA}XqlwSZy(̺( <&8:~1|/p(}3E>'vYqilřS\z^"+/휜26?ec1fĭe>^H<EG.3[K/rbf8_gpMĊ9y GLortNm&~xgI' _rU {ץ E͞;>VFzt\DFw'xe#9|͹ ۜ>׎#bQ_Au1מkI>ؾgb ʏؾ_aE7x6e`_}z^ڔ=O[%s}8am~Pq_)'F-[\-w.4}F=f0>8JĊr2qJ.~z9Ce6q7=rNW{em3+'>5>-*uyou@>6θ@m'R}_e;JlsE;A7,8c|:~-r [M8UO79e~|V8o[YndmKoCi(~ڎ.[FN?b~,z](ϸ3oNl0sOduNAҬ<:7F|su]D=uՈw,zY Ss>NW 7D&6Y9-mG3n[++2:xu@Q 5rJRk\ַcSkR끶|z!A1753Ljkh}~se4s§ٟ6Fnt>'_<9Ǘѽ&ix_gQPһU!EBi{ܱp%+=s+7䐜g SwaG: 7~" O]O%ܴ$y͉qɚ[I;{;UWSOͬla6@\G8ד^C#92=s>8vzOIo^֣f:B`Yt\Ω*0YXz|>gkU}OŝhD-56.Eq![_앻ڼ'+)udcF~)b2g% O + $N% Mt4G7CA-]r~j%SrXc50pyH2)ڇczK.+#ޠc W8>Qq8ӎjuUz9:X4tr2=T]_`1%W['`$ak5ϳ~E:;?4jl)}ϡ0LCոHuaA_8Jġ%s> <r9kLV B/ &5Nb&^wX{`3gd稊T]AGr>gS9U)xiȃ59bS9%?L&58񻪱38W$8 J=vLlxBk:bwTШ5a:ټt'ا_$:/Sp (UoՓc &^b,4=l50׏.zLnCmi_yɈ~Ē_9:Y"itгs$Sy|u.Eޯ''8|kLc<˓ȏc%ogD_RGoH5[g v+[?*qw6\ʾ=:e@(VsEG0+Cx'7sϾ1wx#}yYF=ޏZ^L1'1w<󷰖X#frWb\9$J cNMYxNx<艅8+gĮB.;u^F'. :k?[Fk"bBYk}^G]9;I4in܋5O!_sWD2cgV4U"<ʞaA~{sxBqbWGA5O~p_q^yo\Zo;|K/l67->9*5\ ؒ"4dWȬgօɵnJVĵ-1pɻ"+,8oL͓g٬GEZ8D]7>xCgpg??w @`l?۰gs1NA_97 o 6tNk[to{ +:k@7m~<'.w×7VTGܨJF6E;PO٧ϾĈxq 2֨9>}*gΉy`霞'>4}?X1H qTmbK^XKj6xIs}p:\.Xsf2αcکsL^}m}n99]uE2xiy*8^yy97o}W n/>qP{z~w>7>w^Qē}ᙻ@Hm'xJ^ ud6f9RIJr=J#~y>lqpwJϵ}Xu]9j~Xo̔;sgo/_,Xfg'R+}%٨7WeW:t>?'?LvfҾZ3v&{.Lθ5^jw opTY>6sܥ ]Χ2j08繦诳J:d9,el'h$|eN_4Az8Z9j? ؉8_wq-Ͻ7>Uk8G0Yَr+ۊc7.\Gf\#B|k.,j*mVz X7m>puֆ>ᶾ>77 BRԲqaFv1u!;j1 a䟹bwړ{xo簿ZuD_sS9{q;~>u=ǟdqc]v;hh^<| $@răd 3 -X3W{:">ءwvz3<^%xk/'m:8 ;qO<;~U?΃Jˮ~m^ t߻]k8:$}D_}vgv٧{Z+7n~kJztx[ۦ?_;(נ)VX=2ދ)g+&Ձ7:[?I}o,eX'߽y<<~ sf WWn7#csKŚpNR&?xs|p 7e<k52?Zǭs:`je=j5vѯ]_7*cMϥy̞^̝sdv}Ǜ}1 p{%_V{ֻ߉BWen>Z.Wx9 .lt/|taKz:+J%Ƴq99AS8qu|syo2n~T{xOj= Bw/I^/NV{Avq .a"qeFLx'05 Yz\.KojLů9tDxu1w^YlsZx_||'6)ǖ\uѿ/lǓ'[I Qu-EL-3gΩI;V[>,hz|f24.קFxG>o~o=#Vk[5ξd5w29 Rj ]_U٦|JGN_8"p:ўy>o~ébjJfm]]g-Y5^G%ʼnq\I\p f`?2#>>$u=p@Y| /s'NsjN eRNBq"aJ8؂8꾕]a03M=<33{s>zz@&N؂]i/$p8% }\NTܒO f%k6cy*8n][t"iG֟*Kaʧqr<^F"՞"=uo$0\lЭԄiF+8u8wsyϝ綛%B% nƾy=}Rʳ} N jfn=0P%n[Yx(\|x}m CP?9oM˾ `N$|// 8 lUF QqqWK !_G:S,FXӚeFT?>72nLo DU_h+'Ge(9'6Y1+R&bCcn^<;H/4\0Oj+-zױgxcfƳ| xMJgպf&>?~瞱Oݾ@h͓{bPUT&`qmׇ5:Fv<gV.]+2a5 `198Bv| CS+2FS+~ub \W^|/^ zgQ[[$MU5zF(>}`gnpv;Fz5v63ESZ3G;NNt43]pXAjB"HwM2棾p_V1)ͷ|9Q4R4#laFlme~3~uA䑙3^ul¨IDdq2vmAJ?>Lz>|"$cnƧ+>{|V:fm+^YkV)V}jS?=^t#Lambcܱ۾6o7$8ؓ^#;Whۚ |e اc4ɤ.խ ًԱj e.6{9f]海I+H}'N~Odb9셕*+b0 L2XuUڔ8y֚Y񒷙'yb#b,=hO٪S%y\QgA uYpÐM;7GB2\'1Q_#KiZVȪde6鰷`r?nw>kGWىзXh8e\dV1EV K%^jO|e7~pIt\wMVN qTAG{ Q'JÛzӇ۟^K:ANR=Xc:1Zzԋ+)S4Ș;X+hzQƝçs0x1\g@`!wX<qp%M1OY3CܞW?=5|pĻI.Ob܊3cN|'8y<>~;yO|Y{xg>\\#=u*?slm92X7\Kܬ6%h?KϬ+oVR{fמ;ssߛsSTGoUN8،Fl.>|p> 04OZ%IF9n4@o$G/ay=}֕ШuSD sVqu;{k/ˏ4O98:R?8>,hmݪy&@͇mƟyQMQuuj{=[o _;OB/cfi9;Vzɿfݛ8ۥhWvnjC:fe¬a99v.][ߌ®_ϥ]]\}ӱR^õV`>]V8:-V~p|Ԇo' 'r6Op̢bǽzSꕺt{L@>6oZ22uu:i[>AάE Rb8s\p7}ʺ{nULjW &j9O):VLfȹ~܏o~7; w~w\\όr:v=/_nnwJw-kw]~<\{]+Wf(& KUKڀ{9üڳ^KKvp}eG+KK9sK~N1ydV'فU\|8{|ݝO/$(WAmaXO^-ѵt77>oWp-Wo #df=zm>t8tDU~o]f4?/ Y3H"{D//&sƝ;Q%d/ɡ~]IЖ9W/GO_/c 4xWqxdm1[OOοT?_'9%#>?v7R fLn' mO}=j <}4gpl񇃾l픵ņ:_۹Id4ƒ,aOq;}WYYSra}h siLIw}pAXD:Ժ"Fys{c7<J{N/>[U΋PdY}ey]#;XdX~ۇ>?fwM wLBx7ye2ɳ~zp#/~lKO齉q?I6Z '7/9|_n㟧O{j+33΅e5_r΅6~9.G_O0''eK~=ώs Lų2}[%iG wFi:;>>zGt>Np=U%j{ 6ZgM\|s(A\qk|IupμĢiN4ql{:D:wߐZmqǚ]zro=L4&cJx0ŋdoοr8W[r4>!> zjÿ7׉EG]Uo%}Lk@IDAT6t*a=V_"Ż#Wah>Bi+fzsf#7:~S=5z}mǠ.豾G̐ˆ9GEU;Z0&jp4Oc1M{J@rO& Psw7J?>x 7;9E5X-uuN $-[wz"= &1W}!wm~beѩQr{ɧndJUo{Cϼ99Nj~ȬQ7?N_K/{m)L`ORhMJBc+#ZտOۇq_?ux/߇{Ȗˍ7p3oO{8rS?qLv,-TsޥI\~zoI^e9LW?lG>Z}cǥ{_+#㹔QKx2J{D"|Ğ(*;2'MgF.2̪.P}vֳV¹ZYsd]1917'pO RֻFi<6Pzj[m\um\SPuY)*aYx}?j׷KO|ǑUQ*cyW]t^t0V8 ŏǭc&Pi ҢS}F:|Kgx؏şn)Ý> F#:|$8FNڠud:1)5ؠsM7\76t{~VsC1>N`|S ѭVcsg\+?O}"g#v}xcr$*HvsyU;j_w#Wpox*7Mc>>-GMѶ_x?yE6ewuJ$q}#s棆Fp8ʐyQǬʣ?݆F "{}^m.]D1Np{a*/+3_#c0u_غ=0k爜#џ[6_s8z=n?Gj> ?cgeZ+k.C+Dk/l君>6x6UYzm|,1^͵t]yպ/KXtywɃ ߲.`G7Ql.P^b6G֊k6W~ ' R%^>Ogo=_OnH\ k)^_nѷapU~0x8̩d6NAM038ol C<ӰiK蓑>pO zOzJ}:8Nlṅ'F={'dzKkHmܝ]kSzɪ[\sΨإ9uq_1'VP:ƎwG[a/s)\Tn"wǯ ɺ @?y?sb)IɅ895vJ`q>O}׃7>x?O|+oYKES_?pߛO?}&̘V=jXu׶ℿbuX%Ӄwv?OMNK뾽/ܰ]%caua(앧lքq+'{Gz? Fc7.w"x_'y gUrɝ,s4儮7ў\8JeM|/NfX&Jnz}G) #y/F۽o[y6%8Qz?5U w}œ/&nrtkVʒ@Mvps._?~?Շ?1gRy0s_7+osķ| !>gXVNrJ^^ac6BE1N5@Kl5˵>AF\Wp4 kD{l-ceNjh{986d壶Kךy(Sgq1Npg*×>3LGee1S.e{pi\k~M1pD4*֒dGnpi.$9AedL?97U899|hѸNr)D\<2 xZ }YO귶\'N^z~d财qrڱoAIyo=l9K 62&ɯÇ6>O֖ 6F;?]aVU^Yz=K~Α[g]ae"8P bFGq;:U&T=nVs=p G'S#ד8WmƦ>8_Xflr,iD<rIwr?3~[ҬJ z$γ3F>/}U[Z3c8qj\ړ4gCOOypDI !¼%ɤ?Wi&`Z7~oO~۾e{_~-6F}ƛ ?A?綯μ/h4Gb#őq \w1ƛCCY]K|2R'" ^Qϙ%S N#cqZjrˁ!3Wpu|_y&,Y ukSwYԓ>'qOEH؉wӫ½^J K @'O6횾J+OK;;m^aO.cFU<9ʔH\8Aͷ޲^[GsOߙ ! :[xއޛ4h"E!9~pN,2_Ͷ{N?𵛷ru`SoVpwK(1ݿ;/ڕMsO<ʧY#WC3z$z$")eᱲJ1rzLp* =| p_>3IZ[Dɢ^ T߸cjpa)%ee\Wڝ񧁷>̛}"ӔN=cxՋ뫟Jxy4=jGe簏}'<ݼ3DX\? Y˜je= fTua"j=G/l/sg:V èU̺:!5ؠKYlcSR^PT5̃qi29|~ZhgpkFO&C'G}˴AN0b1q`'Pi;hr_p?ۂsevlPp/XjG~Wt(^5:*4zބ>ȅ]`ΜCV^L՛/W$5/'7ud>ĞCsL V J^u==-TJ6eSy}>;8 žtK.uګ}SRzMt{|!귭@Mk=]#3΄nY`W`_1D﹤aeťW^VKXj~N9}7=, _0v`օbD`qҢ<S _'*)c O~$۴1~)wMg~M_쐸^͌#[Yj$[m&Z >LwTzbI0[Uߌc fM;g,tJ9/̔ъ]1䒼0y [ρsswt^̳Hѥ<:}x0#]cŮ:~vv ++۷G*kMӼغشÕ~F{CW4̸Ɖ>2蕱ӫ[YꈎKUg77}E(jT3!LJc3\qٿ'jT9a(mG_6W(mʏ*N'mr^C 2>;jV~EGhD3?箃c-QD)[2ƷsKc7q3[%25y"S_8;ow_*z{`ĵ {jw̬zLQCB]ǽcǨ2ѱ!GlҏxҺ7 7lo犷s힕= Y"%sP1aE8["(N,d}9WOLl쮒n L@s  qIz}d|5Fڗ7ZU r&>]S=} [9]-4[}EVlYkΑ@8`v3*O#mğug]nκηs*V @JtU` "MA$X1*xЀgqR25LI AQŒ3c:5u'>9g~Kݡwλz.k+'s3ۦ^/[=-P.$`2BmA{5p/ncW=,C\1flPu{Pd|Ƣؑ=VaK>/ǮrWYM@b-Ɓ>]ƻa$ÜÆ\ 2{ >r=j| ~yPLf}95l#35>Vλpe,WPs*@y#vCPkؾv`VAuwpzKόyIR8u ͸cԄ3oÇμr7Q"җ8j;sۇE{ֆ/rmEWv&+az/D`WK=K$KkRw,myPGJ1.\z%cUfGbnoW{#)M3_EN,cu[%բ, QxRAXz4…%C?[\U扠r0uUѧjL3x}I/ 8Kx:wыaIy,v-ݧ%q=nu .\{W"j¢I#~duEFz`9DHFϞAo+Gr_9wNݎ"9v3``!8: ' Hw[aEwIO_'ݦg g/$BZ q6U_>`M\-0^ב\^ԢSd'%_ųGXOnW6W{ݣGܼwsWTlz/ZD+X_iY巺oxX$:`FUir (xLiw'ύ+0ZΒZgS+F,[1klrQ!o מ91cڊKN`e؍Wa1 Ы8$3*Vfpe=n}}R[ d-Ŕf.^p%r?3oY?|!MҀͬr mDZ^bK^#9[\us*'0ySGTq؈iշR+b75Kz3W"ݛ̧MgĨmduFŒ5f;Ȗ5v=$( ^`SYK5Q_)yYjЋW<iwTMNY&rpݶq(7B5'VE;l=#in.H@ jG3 94oW+~$sO11&0dξ˂xz`|?_wq3rVv=Bs=+^sb!/lFq06>s;CSYg?m+KA o=#򊥇()?% 6Ʊע3Wn] 0yv,e [ɭy ;ь{JRk]7렾ckCOe.9ieYB=7^}TzcGYdom_&R?tZ+d]gCɎd#ILYEI@_9ˁ +aTK-:_vƱ_(KhޜwݡeV;q_^nؗ"Y^45B绍$ݑWw_?3>ǹx]Ӳc:o@u=^_n>Aqy Srf8:G6Xcf3n=̧oocUH.ErV6b-sT3R ]㐋O;ihoveT t#/]xhȰLG>(&n7ܓ gnHN~Nc,hɽ3+mUևQU]lN>[|<Wig@B}*9M2Kz[0s{0g1u?^0ec Ucܫչ-窡,n/9:NtaO,D[p1,68U^{DbXs},c.Yx#"C_Wa$'`Ԧ21:9zh#/}fn%ŢcE(5{Z '[-ǀNvPD>]2>{jT-n9::߱ύOzb꾎ެu>"]ˬZy?],mlsV|UxLX+AhO6֭7z_u(Vq09(,AU үycR/WY)Za"qu ǚĔDZ[%*O՟DqPXHt&WaI.#BPv]?q瘜FyqJ\If6ۈ [#" osدqNwGwȧF#'9Lk<1r:^zwL5']}:A7]znxb֓XO_JvMd qug1볡kJ}+uf3'z.|G}r埽O@ O ј+DǸ3cpf;g u#^}4n}r˂Wh9җFڄY9F#6.1&Uk-ތ9v?uz\2}QE># ȊyoAtIvl#Z&uzU߅8櫀㮢sM+sVRv0JsݘsZ8٬.Vzs?g^Z?o+^lZqޠzۥuz޴>z2r99}fTƾ݇6rc1ƥcu#vݫk^.%c6H3?-`O?걻:},@9;h$8BؿG]S4z/޸~%pWhߣʜwp$Ew)E5s ;Ie>i9s 3-Wyrrr5A6Vb+Wojӻ:] -_Aj~k:qƦ,5Ֆ&,'qw'ޕ/e6ԬCy%1y_uCq!{XF0~XS*QfawVe!zEϰ+|-O>78~[@2s>jOvue[}l VȴK>}u,O8zc㌏O%3(e"(Of\>gŎB(up< \<.^} ƳZ_%LR}2)~K;?;vlǻ.˹W,˽vm\ߺ^tnX2ŸF!K}vZ~tl5%K\O_>O\9vfzMc8@O=].Kd`}F9kh㌵g/Oex|cb i}j ~]ص&y06T/yA^t+|ȼֳ {8QK?^ GUhވ/~QzsC2NٴOE*wz]A?{֧vOWϣ_s᏶u|Unb7߿\ي9's/Oo}my˵!}u&>:A<ٛI>aá?TNb{N>q3{zʚegb9"gg_]Ƭ_ma_H=s|q&g0JXJ&o|^"/m;Y4z]6mXX{xC`Oyuc\ g`.BbG2K˙ß/,-x)io/E+1?#YTV#Z>xz $#=# VVc#Iȶy"QN1ݿXucU#9J-8Y2r91(bOz>aޒ;06#m Ug]x S;}`ͽisqS^ l$I{uBuq8Y۬Yg[?їq"+'ưȥJݹ:9NlŮ< 5xrw U=/|KMilvl[Z0Vdu(_d#Gơ1~m3ʣw[7c}\9mч` /o rV Җp#R}_XQ4XhdX.N&-b57S2:z`~E?{e;cv;T6HN~pqeOpgit9x?ߑx_ǃ7_8њX[.xM;]P_3DCcR8%APlHl"=`:E[߱|nwļ^۾py|r៿iHaXgG2QMLƅm?< :/wO[#ߴ &p;~yyBx;+LD_Md-6֟qt:j\y}p\ϼ:^>g\az*U}>rU}0Ҋ"+6F{,U#!'q72՞E-ڨ[YZA oP^~둿巜my/Vp_ϳ1Ԋ] kɘ:tk}1F'c57y˧AbHcSv5%kYG4[}V&}ꑞxuwܿQ ENGV$01v^ W~͟lj74+h"+\ɟ]_gR:Q_k`ܥ:~i}-")lVV;轾t%|N΁;skZ5 3ɝwۣ'7vbU =nЃ .5@(sӤz  R|=vy%'3/zޞ6FKltrj=_E ohu|gWGn}k/{t>bzEXw2fa/s\JRPvfN63Tw]s1ǐ8{BVy_̆z# <#u]w[ֈ:(7sW*u\N)K-/lW-= 3ކǝmKwQZLYh$:B:N]k5!YJB9ыM|Ǡk:Rrwc1EƘljV.?pa|n߂w6O~a5-8U0tk{e޸<y4?~j*TwoebG 4[u1ЇGؚHvr;?hnf4CXqd]6t5#8Ne.YdRz>pc ^ٖ y =9^@[k*{OzU!ճֺ۵mR?9"bV?}E {c*6FcXVfpq@|WyN0ُ}ۙq~>\?8hOk^dѽ3wgrHb:v+I~n$zW޵>י̟_Q!c1>F_%co.ܝCQ3o׼+q|7Tn`s,պt~CZoqQ._|-,ǹ>X ^93D:̕1QfT86P Z=s9_FbsmV9֧sxzܕ%cM-`'˖L=l_< B%f M8G~5!9v;iB zt~١"'Ύ0\ VOUw>U|a"}Zj52H3GYjS78+ 9Yۚˁ/Q=-m!BടJ[ԉcPZ9[AFٗ\"YK9sazLѳ 16E~MUX:b/}~nnN]Ș6\]3+1c[lK\5.2!y3[5~o]u^<7t87QPP DRz$DRM2xm}}nb6('sc4zz?#> Y(s1;֖^Ɠ'_6}|x/rf_JVάS8VW5b1ͭ9bfLڛ mX.s]c0՛g^9"e5im 2&~z1RQ&9ޞżVq8R' I@ržngÑ?qiy݃{hܹZ|?eԾ׹NHg}jXuv@fIo]>0gtjpʐGNY{Ǖ/,]r z5Y1m<_Ob>cpͧc _p}LEx9o痆LbU&GY$Uu~W/}3\<~=UϯB^7ٴ"N:C$̣?wf>1>z3Wd!d꣩#Vw|^̳m8K9nO#u>>{ۖzb|.|4f_NTzqf3p>~:bjcg^`isq4ptlyCI9Gzu<]m}: _E:^7ŒxcI߁4L_ȶ:qXG_ #Y'N}ǟEyG."A85|g ͈>c~+/:_U6~iY6|]^?Gg\š`UWÀl{G%Ijew4T@)\xN`f<Pm|ǀMyc^D/־cA/ݯ{(2g~^?vnX ~%ќ9pn/_}«/c5ou%=>ZY[- +┈q^X{|OvڻDnrчCڻ&nuM\_4\x y/oP۽1O # |.^S8zQ?wyt_{Q9Kq;ktd#%s[bX6fǏ ;oߺG0r⌝=b<wg#{#H5j z( ̊gzd@IDAT"t/2F^Cauw}b<\k|:֫cnŦ^DW3YzkG63 _tO__CԼ_}e#[ fyG\Cq{ }l6~N-7"q_"+ˮJH>業v3Oܻ;X j\l @'@}9TcrEA̳]~'l<%/Rh]G}:7?'^ضmч].h#&үV?s0q,~8ts 3Hd䯑̶c]bBgo^-JڃqF_~kj̻ >Ȍ1bTmgV,K$گ\>lxը\:R+/cgƱJ`QcpCKDzlZ}ݥo*z;H깰e;._?j`MZ'j횀}mǹ B_rkoGֻVe>E{y2.$}ouvD$po|۟6Ol8 xcy9r Bg3i"YT GDZ$^ᪿ? KBC,ħm=F5:d.<"HcG6s󰕟X9 G[EY:ƉPk\=VZ>!;^WW[4X1.x4GSBtb#?-qCNK*g^[EWt,c~-r/@}4ۥ/$~^mԩ7Aֳx,ˬlq29:Ex;G6;}:o›j>v s> |ԏG3㓾Sv^8m] ^ҙ`K;?;x|EWy r[IOz+ĿSE[>#sh#Sc#^"xAw*N|`ÖV){; l+LوW2}cDz|ZfSmˋm͙BxMg5uv"29⬁kX ~ v{䃋J=H;c[G(U۝}6BrSa!:6bu Aj&vޠ?^Qub{_dh=ARXm<=N_wDže݉?ɟ=֊ :=%'êXZUbgyq:N:MNfnWX,w"39^g:2+."mO?7p=L_s6x-/,ÞX84vJ\*,>t=lIv˰Ʀl2M>RǪ?+rSc4`㌅7[3|:?fϩ=v%ٔ|pܠFƧ!S:5_u3GIK4& x\aq{*G^px'^s'Fd6G^/X8 6=;NWl*8%5Nۼ5=ZǾ0Sv7-WgMg*]Z0Ԝq*,}e ͑{O~]wQBۋZ\{Q:6H8JPK>i'?=֟o3!6233ƅˉ 2Z.˝ ._o]ױ!+:eI\0f~93}P}7XF.9}2#`.#㴪QT^Ȋ0%9&BC;nk xʡ=ȈcxěcB1faeۢ߶Tj*Q7˙0޽77 q~n O̟I֋3_Yyh?bS?SmSw^کSܵkYVmɮDX3rn:c${kǨ7V$؄no|?o]dOx@~@(X$^%3(;+-`fAkׂwy~y5ycc S%ѮW:_wI׵$o䙀#<=8fN>W]mXKJx38f|%xa$d IEn{纕cn@P!#5UGMq|F/fW=y(^>$\|,;_lgٰϤpVm֜GwmCw_ZGHaf:Se6Wy:q;Goc/o cGէ2{[c9<#<=6<{K. ϝ(rPOaz&ˆf[u+} vx;hkgkca<{=~W6x"?BIJM{NxOpKKAiWU=i >QϬ᪵ed-1f>Ĝxø>J_w~H{hK&G6V{|5tE?>- =[ / n딵JG/辞>m*x.ni:c0@fff/ &޻xup9cyNriƙY:?o}vo?[uew~;SYRoK azqYGy(,z x߼i]HCH6h4m;c[.+\ge%CKD'jrrzZ1'V#z_FTF=>!ھj~^'xa܌gx'Q5K3?0b{oh9^;&}m>#b/!>2xdf!9lED`;7],gz$>5[۸`w#EK)BR͋T|e.?&P2pm-Y$ƥhw~\?p~u3ܙ]ONkLn_x]\`֭(󈓋\jpX;^M~<]F11o1ȷ29kH.ۗ7,w-oc=3RNnKE Z5F"͑j~!U;9/ZdŞx 8JEtR}R(L98__?4Gkģ[x˞N|$D˂^3~E{h}o(bn ̽jmX@iJQquyzۋ?;'lWO&xkё+ Q"Ci auQFAGp֜-~8A_؎jED>xt)Ic^ 嘬'~.IogV/iuOT8XӇkhoKO'65ӗ372"|Ȍg:},Y~t?ǺV?hH?|۸3`.NL{ѧ xKDX=LOZL6Zuy|8\jܶ۝9ިkFָ+9Umf^dYFTk K@+M_=ܵ3Cz@"adκOj܍(O~+u… -c0 z+ g<:ǯbJݑJU|}\b1o9oyLW;^Ĉc^Ov|*vS B؋xTY4q}wyV5}V}KƋÛMl2xT_Ap?\wAu?5"W5,ϻ処QkE̿Td!9& xVӸmH+?zfX],7[0v͉w^̱C=¹G'۲\[+GIRoEn<c@{Jq/ O<ه?q_};u!zbߝZ=pngCWo׏%<ü*g=4QSO1ݮ .3օ6OT=fʖ'0#y۶.j >BXwdY*WGdߢ_~8ӧm9?8Qh"ڸ$ٔA'HO5FeSsk+cW~DZ>wYt,GoI>FnF>cz-OE'ycw^sf͚6H/'))k+L=1<frocW,gy;sȰ=Y=WtW/W/ڍ919G_bĞw%oi+,1XX,Ȋ-u" f/WbֻO Z҃~x~;7ܛ-nG6ؤc6>Y0diۥDZPr٣<}~rv }Y?s;uۥ׮^طqnqAXI#>jZ;a.xc>jXual];EI}qbI͍yk/VvnoG'kBy~߁e|e7k׳szªx(?6vϘJkur폨'ℏ&xGrǝf{׸Bx3 d>m @35>o}61i9!r; 1w)bca -gIQ 1=[޷~o.tNi5ԟ{ual׌ ~L@6SXd'aԱ?k}5CF oHqFO H+Ep19ªSp`m{/N{Fm{TZQM5vy{暾nkrwE[#W)x_s}te=wuFm.Ñ+ hcoܵw췣׾WqNljX"2Q]w~W-ǣtXKZFv#3qdzcVC4A#m}e-XB̷*Qn'w:p-8o~!q Od9vm7V~\AwYZmy ^{%?o#6zq O9u݉Q ק|c˜YКH>l}_݉5OԽQΰ=3>׽Fǎ%obtCmqs{Z$g۞~;웙8rdƌ:!V{1zf6sǶNȠǡmrvYM5P |G3򌢋F39vrJXA~Ge+۶X?ԇGp ü)g|WuU Wx\Y"ײNj&XoObќ}tբ{~Ԙ%V=b_?twcoPܿo?_{4q%+\"[*Z^_{}ɤ5 {E],`#>mc :N96Lq\G2[ݼ0ʀL99'6wzլqXX'.5YpU;s$ζv}/bʍFߘ:ayo~Y9"H,U7%Ї ]!(Z%ُÀnP}*]3spNek}QYFl?7oX %KVxg'跤}k\Qd]1 .b\Ok0~ ¸i?0ګ<|cj9*}rCq*Z{k/hk{.a?Kg f92a-Nmہ$K?]]]'9T;q]٣bz_ɿi>>Uwq|){RZyI2Tb}1K_:.E6!YGfaY4QhS|cD~{͟X(VYueO_G9ߨߡl9TaJ=gz?pvix^{`|^clJ׸]Kױbn1uQl}m[oa;&qtxkqݟre̍罕/k$z5^bƗ:}챟4~Ƽ p^O ?.0}6E1xYl.ي|eԌ.7"kz}g6~So5Ȭ19κys'^x`nkƧn:ΣsQgRT1fQJqޱzd?~vBX޼q8L)*#Zwb\'I1+Vڱ9>+7ʌͨXA3g֧?sx'gE\6x逾Y|ҩM aSL=V+2 &F6e<`eRoL1#kXhlW1.h-bԅD-:;Y IQAa9GJ7ӛ2ݕD,Rf )e^5F|ϻ-sa3={_P Ƚ4Et!sܗE%ϢGaLÖG|_1Xؑ/yty/~CX;cͷb]QwH`wo~ 'q8A-qvcks~i#6Krq]rko5:8cN/,ڊ(`3d,ԡlF>Xto[6}w3+th_My,(|˥$da|+/7yL>i-q#,wvO - [ż/k"C[߱<_OYgw׈o??/꧗+>TlyfIzv,(;}Focɿ"Jժ񁬛r#;V FK3+{%wYX)gHr<:;z5'G0:姸j 'Vq?%&meaG} Y*<*\B\-8tb+wlW0g9т[1bCl>;>N JgU1L|krEz^ڮUچ-30O%gk֫$Qb52x~˅#>>NOs0VƗ?u%ߺ2޶<\_ޟ{,_#mmx,y/$$'U 7 oHvcRt֟=u0oצr>B^y)BTT{_>g-zt̥W*γR:?z_uW1~TGߛy)9Yrsˠ vF>ymA}]# {kx_ug:wۊOιuvGXOF>lEu;w#sk#g Ƌ {^}im5p;k ALs`hK?Drȥm>̱wbys'^/$:6ޓb,y7FƴΫm4WX5moG!}mujt\F9ʼn@wO; ==37ktRuv,'X+u|tی̗(:w"^7vu^}Vi?e,]-a>s[y.K}([_po}]3gM{gM6W\Ƿ,W1 c[_ddnF c>zӇ~qb)&I_͜yɂ"λr >5j 9 YYv8I$gOX_JҰ/c#+g˦<Ul|y _?gX5+mF-y;,cm+8e~w c"e]lUJss> 7z|=nۙvhfk#7(q,9zMס<'e>o'gnYy@B}[xxo W)U?M7V>iVj>V/X*^bsQl͞zڟxfY|xzvTbg43q'`qWw;V\.},x:K 6ٖXs|lܚӸ1K&ǩA*q`nMm{sY CױGDXdxXm™8Y")m *~yRct)s}u'Xlgq,K~|oow Tox6gk[os1Rх<˺  Ұ9m"Z1bc9"jdbb{\F_F|+n},q'xHk="nM!ߊ): u-W|qݕ}z@h!X䲏Ԧ2ʅp,Hdsn^)9o{ݩ=Z$UȪZ߱O`㿎 MÖlfUc͎8^yIt!Rms4bV^٪tLox@+QͳZΧ,:n>bx6+/׋ rwWheٌT_̓qnΰjۓ+unn7 |Ο9!}y`Ѭl]G?ZOa_.0}\bnڣƄ>{|`hƐٱȉGݻZGÑ sNYuUMLwkAzyLeXs꜃Qo><}Hj~Lg Mp&hxRoѩ/{x26c͌YwO6>Q3:ǚv|@>${γ$(Q•#疷X*n~pGʳ@#<*Ύ6d#6nF4h?2OK~8'qL۩O$t89SK<ݾ^ʶےaQ%&VV#Bp"USrC[}dvV쀇?z;̤Sʌ6{/䉋э7m){}F"YN#swMe'}}i-3_¦Ž +C8H#dL,8GfF. ҉MË̊Q;WOo+M%9Bd$gdž]}z|6'# 7e5W?›< 苻"|umٿrL<GV5ID ?.8X0GNly "ok'y\4 Wd!үOeŶnYڋG1ª<}9n1"eGFUl`$7 `;7qɾ?=5êi/V&Lǡ-SEoٕ$|9{KnIť?cL\VNXXtznw g<35J!UB]ЕSq}ǫ2'eg|u}@5k)&Y1+os~"hy*iL1vqo{t<0`Ne56OG&V21ţ⇯"W˿?ƞYEԎ>b.,i.kBYjX77JbF?m(nVs,A2W@&gKP_{7~WӋ'c-ǺAk٬D ՙX(Ԭbc[,*Ix@-qi[r}ǿ )]KN4{W;1NgԝF~ `skM4q:[*lA+}-KnrH `Qc$h[LָP_є}"9>ˑXm=V/k+/7} Nl}su_'^ʫ9о-'cm+'5QNzq^d\qklUGqJ_%V?&fuDn#+蝇K/+Q=M<QaL&n#hm+;aI\ŝS`V~ۓ{tD^eB9첎1lɻU%<6sYoKfǏ J%gK,h|D 7"\$L.6v]oDSm@t[gf>l#8'"§Q{t,c?+V~9nloc(m$Yӧjjr{^-vOi?:Mσ$"kTzfjnʭ7sDZ/ik_c7o;!}h!.|1㪕u{ODclX5-bO=2+lUԕM$W_^]-n|,wMgz#Q5Ӿ]x#5>rO9 *c<\dc7%s7:s򿱧7O389VPdSR*.Q[q7JcX6v{|tc eLSgi%wӋ[0Nd>Bu+mƯ|TrȖ{M#.;޻[}v=/(H!XBD *J% cC aPȌUAe c!,c;L\XT'TRIefQ{;woϹgzz]k}ǚs,Wwi"~.WtU~'rgТmY̸LH㴺Y?%mL_j1-|Z9mnx%d2^pmPp察U|rL ]՟ד}𐐾L$J Y..8N>_u#sMlÖmќp `U\k?ˉn 厪2)Dsl#yKȊ2!%-8,_ {u,J dko^, ^|s-N>|e?5mJb`,ϋ%:z討;Ȉ 9@'4CJ-s*KxeZS =Nhw=yxn˾HnwOusn[1(sl83qakN RD8@8i0Af`A%R.C$O \tU޷/[򢗵ÉEQY.PRY$AG2D~ 8`I5-GZvIe|taE<}fzb~-un{@rOꏥq, Iiۘkj<^`+p<՗mB1ilWXk4[lQIkuik!1aڬHYLId붏 ҳ 㻭f/ _R8Veoފe-[ւE'{姄_sҪysF]T Je6[w}׷LG>Ϸ-f{Yv h?!stWJVKd H٦#N`"C]y՟>87~J<]Tr <χt4^~Z \LEz`8 urʱr063N[hHSټ66/'0Lֽr=h؁9G!Ħmpʇz>H}&@IDAT#[Jt~֗6]k^1 VY0Jz~e@bhto"B#wPcc'K\^6sU?Y'{æ閂\Ky"D/iu}dKk z},Ӗ[Z67v+ryLen! h|t<0ϸu(-}/4mߖ:m-a2mS'Ǘ8.mT!eOUG/ؕI'&Wj'(Eg}zܩ$b~~D %s d5֦\6~6Wr=0WغqM|lI:slQcZwXx/rn+lH.U׻+{*e+v^}6jW;ӟ'.wo B%NJ(:nԢ& e9_IB ]k'91VsA~Ъ!˷h/vHXn9!Ғ!qm̦߾M2mc[6 lqyI11DzQX-ڢDX±uwrv;O\Z=VkG/Ľ3F3lo&\6Sy*>3\]KZJ%XZN߿IMh>3N̑3C LߖR |:ϣ-ElMoOved{ܾrŤnyN,'Q8nRf@$]H }ۄM$ ds]W~wښ?e@7"i&dW._-B<}MFn*Xu^R>\϶)爟-V1ˇĴm*IqXv=iowgSOM/ZU[R{-|$('Y,R=ucgY{22˅lABPzm5~aC], N y&3<4| dbŒk{_}⻿c?g H|s?F;_4xP6! I'{4ױv%T~Y|0r`o-m̵a1RBuzz%?5G`Xb+U9e ,@(oh3f+v5yIq*\S¿]^sHzP~PklrA^K~·OO]XySm#^@LBm]xkoP-l!(nDtkOH9c6[0;QXne[kq{>Gs8-sیK)pTw-QYWmފ 4 i5'ۧ?w۩N?9tm|W[R.23-m*g%]R(_X k`!>@X_oGX;Pu+mڣv+w~ڟ"8*bge$"O.^t' Օr=> p8P[֧hM'tki3/s{~ImYh1k*۱)/\>Are_]_AWӕ6g BtASN9 m)i%6t&uk?6]_Y2Nߜv^voCÎl0'{zŏuvG,/>mhQB \4\C2~롙jL̄ݭzR'u^ƪnwU_bP{ݳCdC@.:rA [$M2!ifD.iYRsђ 4I>96/Þavtٱt%? eR[Ox}#7x;@1}oNq龃f*1tGedDI*BCFKϦ\k9k:%_1]?>J+ ;;7BVmtI|}әO#Owwx:鯘vNʋÌғmiגy%YJe^_z/17x^n+Gy_^*3}4߼ dSaoSG]=*.KMd*:KP3hToy=dDϴVs3fpޤ%7uɈvHIz_~Տ7[yNZk=|-grʃӂXߋ]e\GzcL{+y%'.OvBn0:]{g}thM?Khot7tʣodܭXC۹8UgTjשu?l,Tz֦x>KuNK1\"f_2#c^2fܿzydsYx{ IzPY[fe#gؔ{D^8=xJ7v+ߑ@jS}[;ܣpQH}ޯG+iM\ni>oS.y/ےq3]:g:e$q42VU|S6Z|{]ޖ|x.%Π5I@Xo7J!7Mq=M|%P {vzb}tөOFҳOGK>f_ۺ!y/ym7_s^W6~>?W)sǥ/kreT^:}t5v.{a, jfw83M8Cŵdcyۆ^С[$D/N|J9Rq<x0YU[t`gzs!2bTBp<^kZ/kK`v_y}I./?CkmnKIv*m>5w3 KƯLg'nP}tۏcjT&BIMH)'~q塒j,VJ'yHqxMxG]Bq0c;mYPߥCR\tKWl  C:z蠋r%eh6mY7 (G*}V# m"!O~wN,kIOQSQuN\8@3o/"xqs<)ǠxKgA.NίWw@WnL.˦t%W˃X6q}IV_{c?!|~wy:xNtڹ+_9yÑ.(z>BI(1SWrP[X|d$ii#Tn=㫬LJi\:h</+~njq+&yts-߮ȑ#ƘMlu_/)_ɘ1/MsH% "x͕򊳔dʓ8hɛPLLz g;'ɦqr#.~tyÊvԂ6' {{96Kz`Kxr I_R"\@| muppDzXi\I%GjxWmsms*ӗ0=~MŅfQ.gͶbIŴW&'T#ݔ+-/Q24'\앍+ѩ>GCl9WΝ]x00rjV`eY%l: d]?O|Vҕ?te.=mO Oȃ[yasWLw| nkۿ'U6=ьm>8#8JDnDZ=4[UOtB^~rXY)}c#?5W+t0Z_4BGKt-Zz#j+c xvķmɯ~^XwS^^{̖5Wz l@S>`z?T5CeE %J,D9Qoy5]_*/A}} 櫬¸R?Lޖ?]e8boQC޸o$[hRBnE#-G(W8GyS<iz23G&hP~x# 2\HnoFR- \cu)g>F+ih~YR%893%s}y<5f굓_O˂y{o1љ1Ux o?I%2<墁<:KFGQ9b^0}{c:L]Ow;w_ '\Gц K@,9Qa._L18*uDSBTGPo%=&RɅ|$yaSxZ3C~!S='rʲ`2&pɘ,zЕX%lwTG.=-cu~ʩx?r=,Z}I:Qtq"1K\ue3}k1Z#jBk-%eEJ=_4+G^OuDz kk aO$o>No<y2?vIL?{%kmd[0<׌O&>v(g~B>Wu;-_8NQo3##M$6l\}l_~؇+Bj8bV;X ,ʤ`DJH3De#%M: $T=cQ^Y?6T{="aC7nwt|BJzqQ8` 1|r,6]kQy,|Μ}߸!":h13#O}P^Kͽe}aMx1,ROn]-2X3- ɖ)hH2^hlK_U?ΓH?t QW3GE '7td҉{Y&s\oz5~(`@=8n}Bf,pFQ@'93i.rԝ+)*tzuկ10>'szbw8Ģr4r]e|fȃ.䙇Y_ug-#JiCv#đ.ƶ640-Vc;_Ϸë_+/ dtXIWw JL)3EXUux* u4J;Y=?'Ķ.}Jcx~ Q=M1CV/wÎwW|1R[ Yij!rfCw8m՘K,U2 rE/̇&sBZưG"$H 2lrThTnmd+֓~dIPA"/$,ny_sd̓>ro}<]- rN@y0''LL&ԑ. YLd_6K~Ib2*["Z2JeE?l?aDz(ҕfcƑ|_)88. Weo?tqo3GC4Y?WZ+%G#-ZZ7#99a"rq_7c}.!Jl}oVO5 -f+:⋦!<0};e:CY噏Jj:V𔋯'<޿ۿq_#q5󝀲ޥ7zi䉥 >SRPec9:M#Y+B)WѢV[z~|C[C>oOnD7u wnl9g@P,jK ,h@W/d=ݦkh4^`K\h2c6hKDeb26mz߷5qoX !-t\hRk'Y,YM<1 ySwmZ:%aځm {_vm51l_~ rт5myT_Mrz.v#@l ް+N1@UT"cJ(x\%$ 3 xԱ<=!`JLeQFQxJсF]\VgwM\*wV+"h\ϡzq7 ›Ng4I'}&hK2inOyKN ?2[cO\Ǫ}|a?G#)xvJC{x|]B*~$<}:}h^1D'eYcC%ɫnQl;p)E(*4妛T7(Nlcz%qVn2k$WrQ2N^/7MU냁od+O]^B`|S*t^ٲ5y!'ʲhc|{zN/W|,n#k*N[E^@FY]:v,zђ)nVqGTjS*@~E^}ے-gǻ}c}GRgJ$@ ]T;ˉf\[%g|D un٘6;;ϟ_\ )\eMz,HyR:!-AX(. . Bm{4aFi};YIJJ RLDS߀K Zn+5p_Hg B xwONϬ湁^r %rQVNY@ n&~.Jn6gh{Ra[>եH7M Mv$?vfw51crz4˓tSAzZmo4/4>2ű E,Fn^g~el/'_ Є/CF%%9ʒtuz٤<#;m|"gX1g#}M:e=vcc|;yeӬtJ3ZšmЬi;yG r|uUޔϷ?6~1 <`[eF񞀇_d32x_TɓFbRd/LST%DX7 :}w{M+ //qr;WQSig\^]hw":J9Fw(,6Fsq5~GAO]*[#vBߚI(4rqh-r`_'.Z/qCK*>Z&MtᏏB hh2i_vv4.{8Q:䢵Z0=? qco̫[!Z1f: |@\<=gU?=/]{olOnT<XBۖdU~}]skҫ]}4>%e(, %drqi*׿:f#3a.,3\ȇqG3noDP: (OE?x'^sw' &zo o+oI5OO}іg?狪/ ȕ~zڟ%G]3 `vќ{eA\{gά> 8ĈQ_z;ӫN{~b_YiÓ]8ۖZv~O;7$w0if1ĽX~E0;I;o1ubk{R{31hE ˰8~k| ZP_\m)e=NJsbuV4L+ lgQ.G^}aXz/>6z*/۰4G=jyAj1DYZ/ֿ,HLSӧN}7WrpmsTf!ےYp %H' ^y cPܧY}1b%GϷMDm#uY*KamK~1MG>~j|}!}ڋ'2r~dz?0_S?YWdDe_mXWRy&]0\Z9njJ3AqcZW7]$ )#e" |HN h aa5[jcMRŨejFsl!=v y< 2`Irco81E@OJyZ,x9=ϜďEIKn|çt:?RAOOO~r-?No+{XP!sڟ6~N L]z|mSă;[˯MO⥱=#l;.ؤcDN9k#kKXg)#[~o;qjgy0V}>V~"ʣ96բ"=L{/L0 XlYHLק3Bhm+K~@VfI6R:ڊl!=%d|\ƃjExXʱXo1q!rWi1,'Gx1/ydž,16yia"q<췕m7=E1P MYJl!%5:yV3[{|ڛy}O?mbKB.|d:1 6Dh`(WRs^?IR ]SV%mX2DMys}g~\X_1մ` $8P#G7Q("6hGƀ/У$S /nuzoWqKxm>Nmׅ: cvo٭Z, B"_P]X"̙UjZ_P4+&HV[˶l Ke!'dSO]y~Tۧ|'X7yc{k,[G5bWRt:RΣ[zhK6s,VG D/)[״I#궡zbS~կ5n}T,ԭ_{aSm䄮x(q[2'-q_OJݩW'ORw% g@0?+6]/^7d=(SK>袘J6Kinkϯ-1>ϯDkiמd̛6'ܤ_dyaKZ_5. iAĢq/njj~_!#JP1')PrLv/yХc@GUf;BZ-}uROƯoG+ґ]WDw }75$8Il#G.>etrw>#$/نoDhQI|BOJpgcG[qp{m<WWHE)o@xrK8,&"z;rX#Z ҂'þ7~\/Wme '2C_rbJ!z=7@˝Nz|+ĥ7`ei@DWpQpC]rG\GN-[1/|[,|l.r%;`˖(_54[56"ukǦu3vOm xqӝ.E4]ErxQo[H8]z#N^<β :gEBnP/#h; GWV)߁_;;=MՁWĘt(LSTw#Kkr/HY;М%Ms[N5c.9䦇lcYzw %ŕq˟:8uiI=c׬} {,# P,^EY'Z欗/|G ٤-dn.);bIz6B`DR4ag{('$@sE$;+|3n|/¡cR/o*Gq݃ ahhy /\gvYD酶G;$`@O:!#N 3o|V7nʘT$ Usi5+h,) -ےc,H5Ϛ7y@O4^F/s69J lX1ӥO^_T1ʞ[% #Po/ aiBBYhY.ſ뻾e7gr-8䱊)BsMʄm *oib,<g [{3VJ'*!v9?b舯2cҜ^-)Pl@GΒl-\m/.ZEC7EU"wk[BI]lʂy+) `qB.f,Ͳu))WO/wڇ~,ne *ԶrxYk˒@&um%g|UyNbN 3qYc/TzHcJ4EeG#Utu` M8D+(𿕮dUوe HR̵]r[E3yk'=%,9^sơOn|ܺ}۴{KY k8EE $/-G4/)!o!4rcNO߫ S+baKѦQ-zYxWSBWrY˯}nyK`ݪ͒WczPGt6zj1h)XC<{uiDmSBrI`F]^_2f, .EO5GoOT߈ @,zA"b. 9F0RwwŇ?0h]jb%@6ۧl|Ħqr\-ŢmF=caq ZN=}\d`cQ{T֕_yrzՃU_V^99m9_:$:=MkO +8,J.ǢdxGY|ZQ,|X؉Mi[Zc h/:$>C#Ǿr_;[TwTrԚ9o䏘䫝q?'gno|rC>Xc\8(rlz3O3.rK[ . D+1v_~?_3_,';׍:t|UWF$uIZx0r/˸z~QWyed,분wĢmlw]׮Mp}$鲦?w| hӴW>JsW LCz/1 NYȩ)-C/au|D^dYn݌bɅ96Q62쯾7_$]Et%}Ty39/ݢk{ޘx[1y9: Ѓ+<ASnDCXMls9 A̦n}- ,`/y+ >2/K6e:;LOf,x]Mů`ͷub nhcUI(oo7d'YŊ|BPК3Wɶh8k)&큑i}YJ}l[7>?CGd'Ջ?Ճ\H1]7\,t^XKKXsnTzuNK{Fd9-Oبe E66w}IY5pxJlQ_50zWvy҃Kox>E|7%g\ecچ1!HGCiNy' MK l=oP}.w[=%)x]1\NԥՆbڶ𶋕1Jj֬h[>b1+g%cgyE^Cė(YrβбxSg]93̛x[60oJvjӗ_^US>:Ѣ";6 QZ ,мH ll؇a/ȓcC_{SN !k;dשFkO}\Y}+oBY$k\;C ~bx9QXUf{N_~C[~BCMH:N\:K |Տ-Ek##j J,,\Э-yKe|X≆Y9<ʕ@QrlHvpbO^{gʮwW+W_[eeDJF>r֍~/n;|"+H:DZM7n|&;)}ɏ#8NrF@;zL8와< W:, Jgl ŵ::+随^~MrdW%%%IL3Vm過^g[9c"Dُ̃N.^.gYčԎM~ez. wh(Y֔+nƕ1(4"=<1D {QVK6/ZSY!UGݨ#Y' `JN\Zj5,Z(M'$1ۅniaXѳM~֠ Ge#K.TV8e$l)f 2td69N2BOPWc%nЭ_7s,E`,Ee# %L$`= `ab",/},¢Dʋ]i:%N˱/F9%r#ncU4薊cϷoұcۏMic]%Z}ڂn*?);Fax(C_ukȴ5a|GF֢.?Zom?GG}D`c8 wʂS@{Y,2&'гS=v_G62,9D.N` g*6Ry(i_Dr'RSG.4] qSNK[=n9.!^:gt IlM1:f{2s_"7(l`Sd}cqv=禇Ϝ:^XAIߴ `Z'S ǃܼ\2,lF!m%ب-cƐDb‰7te4H8?E0lKޭ_r Ѝ$mnYن"l-L,ID$g]xⓠneIl OBD,?'}+ݑC'$GiDqsxBe)H'TKii  >ueeE j[}4)<2!I 偳n 2!lA[ԕcu#Y{ ^ػo6av#&7*V-˻G{=˴8 ,t3]eeiУdN&qIٟ=mWDkqZ5dWЂ?m};Ol,)JXKN>i26Jlͪff9gOV'j}ɏܨ=%^DAw`g']K>)9m?/lImLHfY<'b&hՐ 9ˈoOCNI{ zۿ1HYqG1w`D& mj,,B*[,؁vYteÉ8%혴Dt/BI]N:/Z"ctG~+s$ϋ'[Tz#'gYsBN^!u璌 Zص~]|.#P9N럭 *[>PV;2:}5$H[^X ~z_sJ'#\u=9j!C :=waz,,Q O-8`@Elf\|̒Zo:G7a> i,oi:9>ofI)幦8ٖ墬R曲#˴ekA[is/K~t寫~>WKQgqFnmL3JmKJ\8wYr,*Yʛ|r%:|K⣏~1~ǹh /Үu.0'!Ҕ*4UFa:vLA\jYpLAYY?u]/XȐg,ctl3KfU?]9 GG3#ccX]+ .\lZ$ɢjf)6-/,,-R[?Qp- >T"SQ$i锗|X7m{ Ⱥmgh|__˷-;ၿ-x=}"PNo<4v YJUelh%eHI>E 4,Uz9_ɦtR!"+|lehe-bi}YuRF>e;^]PI8AwUW0i!y͛?NCxFnX 3= 8'R<<bX"\/MmLMes}:!CZuGX]k ?Y*Ckw6nKk>D?,TPs='kI.Gu H/T**ɝ7LYYp^]^lAm99fQQ+c5(7> E xWy&@o dͪ`DgAM]eZe|Szk[\7ciotyc`]nkM.hE)dLŽEjJ;ʳ/F ]V+y<5˺'r5A4|Ѱۮuו-0naoD`cS噀='66#dr. /ol(!^L|{z_ϲ,Z JbZ%={9uϒ}oWG+gym+,x}\\F~}7$wnnDx0' 3ZNs{< 0 QΩmc!AdZdz9$کza ׼`n@k$A@Gm9|Q/9DGyFk9}-&M=6WvieGmDx a{c-򞀝򞀋&@lyQfrl l2}>tʥ})fhQbA?zv8՛sBRgo&х/gS>m98 ,ڔ}܆l[%ڨ2ɖ{ߣ毷qOF~E`idd.wNrAG@'}EueAy1Ҝ)] FP]ϽQd,e yIRHDT7qRu.>QlFl~`rCkT~fK7;c>>#g[|DH#7uL)B{!ksd2[ַTw mi؊mC^;r*uudrrqr}f)Cln_1N%1OF~3F`<p3o =y_'/xQeYAu9]bQ_I>ew_@̡1C֓6C6lOo-qUFTJV#~2iͿ, ×^/Ѓg+koa^v/cÐ#Z@TWBqâe\o`cW7?ʕ 6[*:XOl>Y%zPq"F{]=>|)ڑYʭMC 궿_-k[Dp7s4ZG86X}EpZ 3,yS[J}4,X-ѫ/ڥ@h7^} jT^g;m^+}B`J88lGl;>Ͳ\ǭ"1;7û&B> x,ǒ-qTB:dDnK2'Gȗ79g]{K 1<ǔz[N_7ro⊗qa[q!\N=%Yr|Ͽa>WDh!K&'@D-1<%y>zrU$N(_%%GzC[3EYO\[.e):*T{/!azzش? .fo]|F9t /qnC%G~_yD{#7{37{ #0~8 r/^ܗeij7075dzGt,/=೹Ʀ}n#ytO⫬V!@Snl)8ȓ/s[5)Y_TD-I'Ii9;÷\u)PVWwWzl,/oOYN|o ސ( +UgȺ{zPdZMZ+rڔ12]$c-cJF}gh_%2bBiзiOqKe~xטq;X^ĉszY 3b/ d棺a2efj/{'2pzmĆdݨ/)d߈)G\Zȷ8֋JvU`De:EOJ90}|y|?id2ta=Av7iO 6~g"d=m7Z:jIMqn?5~_o{KdU8&9iX6h~ۿ8lY>{x1:Ϥ,U"[V@DчlZ!&!tmc+tFNVHojClR ǽur߰womkm#Xy1F1r1zg|_Ŀ}#LU;pj9['b̈́!AGٗgWtOs{=˭m_5J2q7p' dI(!ˣۉ%Sq"P{sQm un|]'.^%4)h Db۲$֊6?ӕ|\?3!x÷K˶1VD=zdѳc7,w3`MN\GW-YQOC_/kCE4VB8zQ'-rgOccdVLBv-RBC$o'ݭE(>ɳOA9[qQv80,m#>(_}J[HwU*pmz_m˾E;`L&"$E7.3%e-ff$ܟ3keO̾seE)˧Z;GǏNX{$U?Y;^髷a 0O*Nj@8϶Fv !_}9z;K{bN,&S]fJ9! ćXDF$@Xgb9oF\ʑc-Kܶ_mkf\R|Ƙum]__ڡA@ܤOƺC@?j%t?_Ji)H8H)6& )R_Ajn_f-tDq]u&j b)"ֱ?lG/`Ͱ5`Xۥ|kycגǍqFW$xw@$xzXD$r(]v vo=Dw~߳/yl{\1)}eDǔ'98>}HM'٢ʅ#P+_V ?-vKJ:F2xrNb# :Mxplm> ;ezh!):-Xn{ 1ŏc ;C>F}ݞ|uBܬϻFW =!Ϩtz$I U6X{R5=f?Ds>%%b+|[B3ٓ\uFރMd2}юl}[em?mH]V"P+7qoAAʽ' \V1E52)bc ibD>YW2xE&^lozUm5}  ~ѡ7ۋGv%Znq?]>\ۿXD~{68Uf#͹x e~Nv )l.[vg{B<ߒ\~](A*oY/km~+msKOYwK{Ͽ%?ƣsB; F3YB芬˳q/2DDYQQs,yqy6󸥹mmQG+)c[/|?mZaugԮZ!ps=7_ȂF]?' HKdf\$Ch5sYc&G.&[^b"mYg4W1\:ǰ$@~N+ϓsM`ܦ+ znSPImKhφ ?dy臧()6 ўK2f9eljP5-~`XB|hO(mwo@h$PMe>>Ic_o`]ܚMKx.܎Ͼx-u?XB J&KB8|LAqxOH]doҺ#Z-HN,崹_jU2a=>X'6$h\e iyl{nۂM_UV8@8M蓀(4Q7qd<#7- ¥Մi>-~sFۭH#`h Q1dr[c/aKՙc!pp:VPfRۻJHK!$I* Ć ĉoʳ.s;e59B ?Vf _꧷~W7R [VC!P{S|Sgmw|"8&4Y,;CLz#v8 mtiHG +?/?Z1p<[e^'mgfJ$-5U(&j`$mꌳL+ PeDgRDmXx&tkSyN-ߔW>>%C'Ǡ}-/Yϱ-%ѳE?r!P*Bpk(Q)?'gO;!ĶEArSIr%tjٷt'vXcs;2mϳ>Ѣx̌5co@XZ FV1?'tfIOesݵhr~CJ)ه"cgzmMնu^أkD\kZ>J@!W1+B`@@{v+ltOd܆ܤnE;1z֥,Lَ֋oX/ {z!w1|ٖ׆?YuձxjmP+B !0+g=Z2i#mtQdcY&ҠF YKE(Ɂl5ӞG k3G}0qL4[z!}¿u}ՏÇJB L *Hz޽; HP6&8(ǟrlC䪿91D>Ks%W}b3*IGRC}Q+^'Yz(sok_v@!0!Пdwo,\]*S pI] *hOtԪ4Q1 w_.mrNrTbbGV/_d͓Q[VW5g?U. 7CV .^VDZWڞoO$@zʤcjK.g VI 'rLۋG.ZO5&_ɿCa\y!P5ୡ+B0 huܿr' +$ -*eM"…An}eh]v&∔ۑ9}t3qhr}_oX)mm B!P__Y"p^{pqZnt;%QjӦ&5/,զ'M:mzȏO$ WU. w@3(Q!p c?oU{B?&Ψd C&Jjus앏mM?; 1c}+}lJ_0\+QR!P7ὅ(Dž@!PKi.@gҶxG|ܮ9TN(Rut4uԙTU @Gpu!H.vE+& Ԗ+gvXDƒBhEu>x(cpy(L㙴]]~xI!L.1qat}M'Z| ~p(f$%V9;_^# l9mypnösI5OzGA|+h!h[߯SƑzN79J"X"T]e*Yn?M\9*c\iGVk zuM';i#T 𡐮8+`@oԻڞ=')h]L2xڂ!q! &$Ʊ^RTOV:Y B!P_}E.nlgwo=1 I&_/hviSVZ}L^rkL@p~`Ty!1cb@B_L@hB&mBs!Ɵ54n֭Nn-_+kҚjPT\ j='P{os|4mݹIC&mYfkKxؖAhm;]K:G@Mk=[1saa  IDAT,8khIENDB`icnV Bffgit-cola-4.6.1/contrib/git-cola-completion.bash000066400000000000000000000052531457126473700214130ustar00rootroot00000000000000# git-cola extensions for Git's git-completion.bash script # # This script must be sourced *after* Git's git-completion.bash script. # Source git.git's git-completion.bash and then source this script from # your ~/.bashrc in order to activate the completions. # # Completion is provided for "git cola ..." and "git dag ..." via the # _git_cola() and _git_dag() functions. # See git.git's contrib/completion/git-completion.bash for more details. __git_cola_common_options="--icon-theme --prompt --repo --theme --version" __git_cola_subcommands_list= __git_cola_common_opts () { __gitcomp "$__git_cola_common_options $1" } _git_cola () { __git_has_doubledash && return if test -z "$__git_cola_subcommands_list" then __git_cola_subcommands_list=$( git cola --help-commands | grep '^ [a-z]' | grep -v cola | cut -d' ' -f5) fi local subcommand=$(__git_find_on_cmdline "$__git_cola_subcommands_list") case "$prev" in --repo) return ;; esac if test -z "$subcommand" then __gitcomp " $__git_cola_subcommands_list $__git_cola_common_options --amend --help-commands --status-filter " return fi case "$subcommand" in am) return ;; dag) _git_dag "$@" return ;; archive|diff|merge) __git_complete_revlist __git_cola_common_opts ;; grep) # do nothing ;; pull) __git_cola_common_opts --rebase ;; rebase) case "$prev" in --exec) return ;; --whitespace) __gitcomp "nowarn warn fix error error-all" return ;; --strategy) __gitcomp "resolve recursive octopus ours subtree" return ;; --strategy-option) __gitcomp "ours theirs patience diff-algorithm=patience diff-algorithm=minimal diff-algorithm=histogram diff-algorithm=myers ignore-all-space ignore-space-at-eol ignore-space-change renormalize no-renormalize rename-threshold= subtree= " return ;; esac __git_complete_revlist __git_cola_common_opts " --abort --autostash --autosquash --committer-date-is-author-date --continue --ignore-date --ignore-whitespace --edit-todo --exec --force-rebase --fork-point --merge --no-autosquash --no-ff --no-stat --onto --preserve-merges --quiet --rerere-autoupdate --root --skip --stat --stop --strategy --strategy-option --update-refs --verbose --verify --whitespace " ;; tag) case "$cword" in 3) # do nothing ;; *) __git_complete_revlist ;; esac ;; *) __git_cola_common_opts ;; esac } _git_dag () { __git_has_doubledash && return if test "$prev" = "--max-count" then return fi __git_cola_common_opts --max-count __git_complete_revlist } git-cola-4.6.1/contrib/svg.tidy000066400000000000000000000011341457126473700163720ustar00rootroot00000000000000// Config file for [HTML Tidy](html-tidy.org) to properly format SVG markup // The main goal is to split elements attributes to separate lines, useful in comparing in diffs // Documentation: http://api.html-tidy.org/tidy/tidylib_api_next/tidy_config.html // Credit goes to [blalasaadri](https://stackoverflow.com/users/2382246/blalasaadri), who asks the question and find the solution themself. // https://stackoverflow.com/questions/25447006/adding-line-breaks-between-attributes input-xml: yes output-xml: yes add-xml-decl: yes indent: auto indent-attributes: yes indent-spaces: 4 hide-comments: yes git-cola-4.6.1/contrib/win32/000077500000000000000000000000001457126473700156435ustar00rootroot00000000000000git-cola-4.6.1/contrib/win32/README.md000066400000000000000000000010351457126473700171210ustar00rootroot00000000000000Windows Tips ============ * git-cola is tested on Git for Windows. * 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/Python27/python.exe" git-cola-4.6.1/contrib/win32/cola000077500000000000000000000023301457126473700165050ustar00rootroot00000000000000#!/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/Python312" \ "/c/Python311" \ "/c/Python310" \ "/c/Python39" \ "/c/Python38" \ "/c/Python37" \ "/c/Python36" \ "/c/Python35" \ "/c/Python34" do if test -d "$python" then PATH="$python":"$PATH" exec "$python/python.exe" "$COLA" "$@" fi done exit 1 git-cola-4.6.1/contrib/win32/dag000077500000000000000000000011211457126473700163170ustar00rootroot00000000000000#!/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-4.6.1/contrib/win32/git.bmp000066400000000000000000003171501457126473700171350ustar00rootroot00000000000000BMh6(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-4.6.1/contrib/win32/git.ico000066400000000000000000000537261457126473700171370ustar00rootroot0000000000000000f 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-4.6.1/contrib/win32/gpl-2.0.rtf000066400000000000000000000400701457126473700174400ustar00rootroot00000000000000{\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-4.6.1/contrib/win32/pynsist-preamble.py000066400000000000000000000002541457126473700215140ustar00rootroot00000000000000import os pythondir = os.path.join(installdir, 'Python') # noqa path = os.environ.get('PATH', '') os.environ['PATH'] = os.pathsep.join([pythondir, pkgdir, path]) # noqa git-cola-4.6.1/contrib/win32/run-pynsist.sh000077500000000000000000000002471457126473700205200ustar00rootroot00000000000000#!/bin/sh rm -rf build/nsis && make all && make doc && make htmldir="$PWD/share/doc/git-cola/html" install-doc && pynsist pynsist.cfg && rm -r share/doc/git-cola/html git-cola-4.6.1/docs/000077500000000000000000000000001457126473700141715ustar00rootroot00000000000000git-cola-4.6.1/docs/.gitignore000066400000000000000000000000161457126473700161560ustar00rootroot00000000000000/_build /html git-cola-4.6.1/docs/Makefile000066400000000000000000000053761457126473700156440ustar00rootroot00000000000000prefix ?= $(CURDIR) docdir ?= $(prefix)/share/doc/git-cola htmldir ?= $(docdir)/html mandir ?= $(prefix)/share/man/man1 # DESTDIR = # External commands INSTALL ?= install MKDIR_P ?= mkdir -p RSYNC ?= rsync SED ?= sed RSYNC_FLAGS = -r --delete --delete-excluded RSYNC_FLAGS += --exclude=.buildinfo --exclude=.gitignore RSYNC_CMD = $(RSYNC) $(RSYNC_FLAGS) SPHINXOPTS = -a 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: all help clean html man dirhtml pickle json .PHONY: htmlhelp qthelp latex changes linkcheck doctest .PHONY: install install-files install-html install-man # The default target of this makefile is... all:: html man help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " man to make manual pages" @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/doctrees _build/man _build/html/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) _build/man dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest install: install-files install-html install-man install-files: $(MKDIR_P) $(DESTDIR)$(docdir) $(INSTALL) -m 644 *.html $(DESTDIR)$(docdir) $(INSTALL) -m 644 *.rst $(DESTDIR)$(docdir) install-html: install-files html $(MKDIR_P) $(DESTDIR)$(htmldir) $(RSYNC_CMD) _build/html/ $(DESTDIR)$(htmldir)/ install-man: man $(MKDIR_P) $(DESTDIR)$(mandir) $(INSTALL) -m 644 _build/man/git-cola.1 $(DESTDIR)$(mandir) $(INSTALL) -m 644 _build/man/git-dag.1 $(DESTDIR)$(mandir) git-cola-4.6.1/docs/_static/000077500000000000000000000000001457126473700156175ustar00rootroot00000000000000git-cola-4.6.1/docs/_static/.gitignore000066400000000000000000000000001457126473700175750ustar00rootroot00000000000000git-cola-4.6.1/docs/_templates/000077500000000000000000000000001457126473700163265ustar00rootroot00000000000000git-cola-4.6.1/docs/_templates/.gitignore000066400000000000000000000000001457126473700203040ustar00rootroot00000000000000git-cola-4.6.1/docs/conf.py000066400000000000000000000061621457126473700154750ustar00rootroot00000000000000import os import sys try: import furo except ImportError: furo = None try: import sphinx_rtd_theme except ImportError: sphinx_rtd_theme = None try: import rst.linker as rst_linker except ImportError: rst_linker = None # Add the source tree and extras/ to sys.path. srcdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) extrasdir = os.path.join(srcdir, 'extras') sys.path.insert(0, srcdir) sys.path.insert(1, extrasdir) extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinxtogithub', ] master_doc = 'index' html_theme = 'default' # {package_url} can be provided py jaraco.packaging.sphinx but we # expand the value manually to avoid the dependency. package_url = 'https://gitlab.com/git-cola/git-cola' project = 'Git Cola' # Link dates and other references in the changelog if rst_linker is not None: extensions += ['rst.linker'] link_files = { '../CHANGES.rst': dict( using=dict(GH='https://github.com', package_url=package_url), replace=[ dict( pattern=r'(Issue #|\B#)(?P\d+)', url='{package_url}/issues/{issue}', ), dict( pattern=r'(?m:^((?Pv?\d+(\.\d+){1,2}))\n[-=]+\n)', with_scm='{text}\n{rev[timestamp]:%d %b %Y}\n', ), dict( pattern=r'PEP[- ](?P\d+)', url='https://www.python.org/dev/peps/pep-{pep_number:0>4}/', ), ], ) } # Be strict about any broken references nitpicky = True # Preserve authored syntax for defaults autodoc_preserve_defaults = True # Get the version from cola/_version.py. versionfile = os.path.join(srcdir, 'cola', '_version.py') scope = {} with open(versionfile) as f: exec(f.read(), scope) version = scope['VERSION'] # The short X.Y version. release = version # The full version, including alpha/beta/rc tags. authors = 'David Aguilar and contributors' man_pages = [ ('git-cola', 'git-cola', 'The highly caffeinated Git GUI', authors, '1'), ('git-dag', 'git-dag', 'The sleek and powerful Git history browser', authors, '1'), ] # Sphinx 4.0 creates sub-directories for each man section. # Disable this feature for consistency across Sphinx versions. man_make_section_directory = False # furo overwrites "_static/pygments.css" so we monkey-patch # "def _overwrite_pygments_css()" to use "static/pygments.css" instead. def _overwrite_pygments_css(app, exception): """Replacement for furo._overwrite_pygments_css to handle sphinxtogithub""" if exception is not None: return assert app.builder with open( os.path.join(app.builder.outdir, 'static', 'pygments.css'), 'w', encoding='utf-8', ) as f: f.write(furo.get_pygments_stylesheet()) # Enable custom themes. if furo is not None and hasattr(furo, '_overwrite_pygments_css'): furo._overwrite_pygments_css = _overwrite_pygments_css html_theme = 'furo' elif sphinx_rtd_theme is not None: extensions += ['sphinx_rtd_theme'] html_theme = 'sphinx_rtd_theme' git-cola-4.6.1/docs/git-cola.rst000066400000000000000000001274061457126473700164340ustar00rootroot00000000000000======== git-cola ======== SYNOPSIS ======== ``git cola [options] [sub-command]`` DESCRIPTION =========== Git Cola is a sleek and powerful Git GUI. OPTIONS ======= ``--amend`` ----------- Start `git cola` in amend mode. ``--prompt`` ------------ Prompt for a Git repository. Defaults to the current directory. ``-r, --repo `` --------------------- Open the Git repository at ``. Defaults to the current directory. ``-s, --status-filter `` -------------------------------- Apply the path filter to the status widget. ``--version`` ------------- Print the `git cola` version and exit. ``-h, --help`` -------------- Show usage and optional arguments. ``--help-commands`` ------------------- Show available sub-commands. SUB-COMMANDS ============ am -- Apply patches. archive ------- Export tarballs from Git. branch ------ Create branches. browse ------ Browse tracked files. config ------ Configure settings. dag --- Start the `git dag` Git history browser. diff ---- Diff changed files. fetch ----- Fetch history from remote repositories. 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. remote ------ Create and edit remotes. search ------ Search for commits. stash ----- Stash uncommitted modifications. tag --- Create tags. version ------- Print the `git cola` version. CONFIGURE YOUR EDITOR ===================== The editor used by `Ctrl-e` is configured from the Preferences screen. The following environment variables are consulted when no editor is configured. If defined, the first of these variables is used: * `GIT_VISUAL` * `VISUAL` * `GIT_EDITOR` * `EDITOR` The `*VISUAL` variables are consulted before the `*EDITOR` variables so that you can configure a graphical editor independently of the editor used by the Git CLI. *Pro Tip*: Configuring your editor to `gvim -f -p` will open multiple tabs when editing files. `gvim -f -o` uses splits. `git cola` is {vim, emacs, textpad, notepad++}-aware. When you select a line in the diff or grep screens and press any of `Enter`, `Ctrl-e`, or the `Edit` button, you are taken to that exact line. The editor preference is saved in the `gui.editor` variable using `git config `_. The following are some recommend editor configurations. * Neovim + Neovim-Qt .. sourcecode:: sh git config --global core.editor nvim git config --global gui.editor 'nvim-qt --nofork' * Vim + gvim .. sourcecode:: sh git config --global core.editor vim git config --global gui.editor 'gvim -f' * Sublime Text .. sourcecode:: sh git config --global gui.editor 'subl --wait' KEYBOARD SHORTCUTS ================== `git cola` has many useful keyboard shortcuts. Many of `git cola`'s editors understand vim-style hotkeys, e.g. `{h,j,k,l}` for navigating in the diff, status, grep, and file browser widgets. `{d,u}` move down/up one half page at a time (similar to vim's `ctrl-{d,u}`). The `space` and `shift-space` hotkeys are mapped to the same operations. `Shift-{j,k,d,u,f,b,page-up,page-down,left,right,up,down}` can be be used in the diff editor to select lines while navigating. `s` is a useful hotkey in the diff editor. It stages/unstages the current selection when a selection is present. When nothing is selected, the diff hunk at the current text cursor position is staged. This makes it very easy to review changes by selecting good hunks with `s` while navigating down and over hunks that are not going to be staged. `Ctrl-u` in the diff editor reverts unstaged edits, and respects the selection. This is useful for selectively reverted edits from the worktree. This same hotkey reverts the entire file when used from the status tool. `Ctrl-s` in the diff editor and status tools stages/unstages the entire file. You can see the available shortcuts by pressing pressing the ``?`` key, choosing ``Help -> Keyboard shortcuts`` from the main menu, or by consulting the `git cola keyboard shortcuts reference `_. 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 main 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. The `Control-{1, 2, 3, ...}` hotkey gives focus to a specific tool. A hidden tool can be re-opened using the `Tools` menu or the `Shift+Control-{1, 2, 3, ...}` shortcut keys. The Diff editor can be focused with `Ctrl-j`. The Status tool can be focused with `Ctrl-k`. The Commit tool can be focused with `Ctrl-l`. .. _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 ergonomic 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 `Diff` viewer. Double-clicking a file stages its contents, as does the `Ctrl-s` shortcut key. `Ctrl-e` opens selected files in the configured editor, and `Ctrl-d` opens selected files using `git difftool `_ Additional actions can be performed using the right-click context menu. Drag and Drop ------------- Files can be dragged from the `Status` tool onto other applications. Some terminals will treat a drag with multiple files by separating them with newlines, which is less amenable for pasting command-line arguments. To avoid this issue, hold down `Alt / Option` when dragging from the `Status` tool. The drag and drop payload will no longer contain local file URLs -- it will contain plain text that is amenable for use on a command-line. Note: if drag and drop is not working and you are on Wayland then you may need to ``export QT_QPA_PLATFORM=wayland`` in your environment. 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 are available through the right-click context menu. Different actions are available depending a file's status. Stage Selected ~~~~~~~~~~~~~~ Add to the staging area using `git add `_ Marks unmerged files as resolved. Launch Editor ~~~~~~~~~~~~~ Launches the configured visual text editor Launch Difftool ~~~~~~~~~~~~~~~ Visualize changes using `git difftool`. Revert Unstaged Edits ~~~~~~~~~~~~~~~~~~~~~ Reverts unstaged content by checking out selected paths from the index/staging area Revert Uncommitted Edits ~~~~~~~~~~~~~~~~~~~~~~~~ Throws away uncommitted edits Unstage Selected ~~~~~~~~~~~~~~~~ Remove from the index/staging area with `git reset `_ Launch Merge Tool ~~~~~~~~~~~~~~~~~ Resolve conflicts using `git mergetool `_. Delete File(s) ~~~~~~~~~~~~~~ Delete untracked files from the filesystem. Add to .gitignore ~~~~~~~~~~~~~~~~~ Adds untracked files to to the .gitignore file. .. _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. The "Copy Diff" action at ``Alt + Shift + C`` copies the selected lines to the clipboard. The ``+``, ``-`` and `` `` diff line prefixes are stripped from each line when copying diffs using the "Copy Diff" action. Staging content for commit -------------------------- The ``@@`` patterns denote a new diff hunk. Selecting lines of diff and using the `Stage Selected Lines` command will stage just the selected lines. Clicking within a diff hunk and selecting `Stage Diff Hunk` stages the entire patch diff hunk. 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. Diff Against Commit (Diff Mode) ------------------------------- *Diff Mode* allows you to selectively unstage and revert edits from arbitrary commits so that you can bring these edits back into your worktree. You can use the diff editor to unstage edits against arbitrary commits by using the ``Diff > Against Commit... (Diff Mode)`` menu action. You can exit *Diff Mode* by clicking on the red circle-slash icon on the Status widget, by using the ``Diff > Exit Diff mode`` menu action, or by clicking in an empty area in the `Status` tool. COMMIT MESSAGE EDITOR ===================== The 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 sign-off to the bottom of the commit message:: Signed-off-by: A. U. Thor Invoking this action is equivalent to passing the ``-s`` option to `git commit `_. Signing-off on commits is a common practice in projects that use `Developer Certificate of Origin `_ attestations in their contribution process. 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. Create Signed Commit -------------------- Tell `git commit` and `git merge` to sign commits using GPG. Using this option is equivalent to passing the ``--gpg-sign`` option to `git commit `_ and `git merge `_. This option's default value can be configured using the `cola.signcommits` configuration variable. Prepare Commit Message ---------------------- The ``Commit -> Prepare Commit Message`` action or `Ctrl-Shift-Return` keyboard shortcut runs the `cola-prepare-commit-msg` hook if it is available in `.git/hooks/`. This is a `git cola`-specific hook that takes the same parameters as Git's `prepare-commit-msg hook `_ The hook is passed the path to `.git/GIT_COLA_MSG` as the first argument and the hook is expected to write an updated commit message to specified path. After running this action, the commit message editor is updated with the new commit message. To override the default path to this hook set the `cola.prepareCommitMessageHook` `git config` variable to the path to the hook script. This is useful if you would like to use a common hook across all repositories. BRANCHES ======== The `Branches` tool provides a visual tree to navigate branches. The tree has three main sections: `Local Branches`, `Remote Branches` and `Tags`. Branches are grouped by their name divided by the character ``/``. For example, in a repo with the following list of branches:: branch/feature/foo branch/feature/bar branch/doe The branches widget will display the following hierarchy:: branch - doe + feature - bar - foo The current branch is decorated with a star icon. If the current branch has commits ahead or behind the remote then an up or down arrow will be displayed alongside a number showing the number of commits. Actions ------- Various actions are available through the right-click context menu. Different actions are available depending on the selected branch's status. Checkout ~~~~~~~~ The checkout action runs `git checkout [] `_. Merge into current branch ~~~~~~~~~~~~~~~~~~~~~~~~~ The merge action runs `git merge --no-commit [] `_. Pull ~~~~ The pull action runs `git pull --no-ff [] [] `_. Push ~~~~ The push action runs `git push [] [] `_. Rename Branch ~~~~~~~~~~~~~ The rename branch action runs `git branch -M [] `_. Delete Branch ~~~~~~~~~~~~~ The delete branch branch action runs `git branch -D [] `_. Delete Remote Branch ~~~~~~~~~~~~~~~~~~~~ The remote branch action runs `git push --delete [] [] `_. APPLY PATCHES ============= Use the ``File -> Apply Patches`` menu item to begin applying patches. Dragging and dropping patches onto the `git cola` interface adds the patches to the list of patches to apply using `git am `_. You can drag either a set of patches or a directory containing patches. Patches can be sorted using in the interface and are applied in the same order as is listed in the list. 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 patches are applied by placing patch sets into alphanumerically-sorted directories. CUSTOM WINDOW SETTINGS ====================== `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 by disabling the `Save Window Settings` option in the `git cola` preferences. DARK MODE AND WINDOW MANAGER THEMES =================================== Git Cola contains a ``default`` theme which follows the current Qt style and a handful of built-in color themes. See :ref:`cola_theme` for more details. To use icons appropriate for a dark application theme, configure ``git config --global cola.icontheme dark`` to use the dark icon theme. See :ref:`cola_icontheme` for more details. On macOS, using the ``default`` theme will automatically inherit "Dark Mode" color themes when configured via System Preferences. You will need to configure the dark icon theme as noted above when dark mode is enabled. On Linux, you may want Qt to follow the Window manager theme by configuring it to do so using the ``qt5ct`` Qt5 configuration tool. Install ``qt5ct`` on Debian/Ubuntu systems to make this work.:: sudo apt install qt5ct Once installed, update your `~/.bash_profile` to activate ``qt5ct``:: # Use the style configured using the qt5ct tool export QT_QPA_PLATFORMTHEME=qt5ct This only work with the `default` theme. The other themes replace the color palette with theme-specific colors. Some systems may require that you override `QT_STYLE_OVERRIDE` in order to use a dark theme or to better interact with the Desktop environment. Some systems provide a theme that you can install:: sudo apt-get install adwaita-qt You can activate the theme using the following environment variable:: # Override the default theme to adwaita-dark export QT_STYLE_OVERRIDE=adwaita-dark `QT_STYLE_OVERRIDE` may already be set in your Desktop Environment, so check that variable for reference if you get unexpected hangs when launching `git-cola` or when the default theme does not follow the desktop's theme on Linux. If you don't want to set this variable globally then you can set it when launching cola from the command-line:: QT_STYLE_OVERRIDE=adwaita-dark git cola The following is a user-contributed custom `git-cola.desktop` file that can be used to launch Git Cola with these settings preset for you:: [Desktop Entry] Name=Git Cola (dark) Comment=The highly caffeinated Git GUI TryExec=git-cola Exec=env QT_STYLE_OVERRIDE=adwaita-dark git-cola --prompt --icon-theme dark Icon=git-cola StartupNotify=true Terminal=false Type=Application Categories=Development;RevisionControl; X-KDE-SubstituteUID=false You may also want to customize the diff colors when using a dark theme:: git config --global cola.color.add 86c19f git config --global cola.color.remove c07067 Please see `#760 `_ for more details. Custom Themes ------------- To create your own custom theme for Git Cola just create a QSS file and put it in ``~/.config/themes/``. You can add as many files as you want. Each file will become an option in ``Menu -> File -> Preferences -> Appearance -> GUI theme``. Some examples can be found here `Qt Style Sheets Examples `_. CONFIGURATION VARIABLES ======================= These variables can be set using `git config` or from the settings. cola.autocompletepaths ---------------------- Set to `false` to disable auto-completion of filenames in completion widgets. This can speed up operations when working in large repositories. Defaults to `true`. cola.autoloadCommitTemplate --------------------------- Set to `true` to automatically load the commit template in the commit message editor If the commit.template variable has not been configured, raise the corresponding error. Defaults to `false`. cola.blameviewer ---------------- The command used to blame files. Defaults to `git gui blame`. cola.blockcursor ---------------- Whether to use a "block" cursor in diff editors. The block cursor is easier to see compared to a line cursor. Set to `false` to use a thin "line" cursor. Defaults to `true`. cola.browserdockable -------------------- Whether to create a dock widget with the `Browser` tool. Defaults to `false` to speedup startup time. cola.checkconflicts ------------------- Inspect unmerged files for conflict markers before staging them. This feature helps prevent accidental staging of unresolved merge conflicts. Defaults to `true`. cola.defaultrepo ---------------- `git cola`, when run outside of a Git repository, prompts the user for a repository. Set `cola.defaultrepo` to the path of a Git repository to make `git cola` attempt to use that repository before falling back to prompting the user for a repository. cola.dictionary --------------- Specifies an additional dictionary for `git cola` to use in its spell checker. This should be configured to the path of a newline-separated list of words. By default, `git cola` searches for `dict/words` and `dict/propernames` dictionary files in `~/.local/share` and `$XDG_DATA_DIRS`. If `$XDG_DATA_DIRS` is undefined or set to an empty value then `/usr/local/share` and `/usr/share` are searched for dictionary files. Dictionary files are newline-separated and contain one word per line. cola.expandtab -------------- Expand tabs into spaces in the commit message editor. When set to `true`, `git cola` will insert a configurable number of spaces when tab is pressed. The number of spaces is determined by `cola.tabwidth`. Defaults to `false`. cola.gravatar ------------- Use the `gravatar.com` service to lookup icons for author emails. Gravatar icons work by sending an MD5 hash of an author's email to `gravatar.com` when requesting an icon. Warning: this feature can leak information. Network requests to `gravatar.com` are disabled when set to `false`. Defaults to `true`. cola.fileattributes ------------------- Enables per-file gitattributes encoding and binary file support. This tells `git cola` to honor the configured encoding when displaying and applying diffs. A `.gitattributes` file can set the ``binary`` attribute in order to force specific untracked paths to be treated as binary files when diffing. Binary files are displayed using a hex-dump display. .. sourcecode:: sh # Treat *.exr files as binary files. *.exr binary cola.fontdiff ------------- Specifies the font to use for `git cola`'s diff display. cola.hidpi ---------- Specifies the High DPI displays scale factor. Set `0` to automatically scaled. Setting value between 0 and 1 is undefined. This option requires at least Qt 5.6 to work. See `Qt QT_SCALE_FACTOR documentation `_ for more information. .. _cola_icontheme: cola.icontheme -------------- Specifies the icon themes to use throughout `git cola`. The theme specified must be the name of the subdirectory containing the icons, which in turn must be placed in the inside the main "icons" directory in `git cola`'s installation prefix. If unset, or set either "light" or "default", then the default style will be used. If set to "dark" then the built-in "dark" icon theme, which is suitable for a dark window manager theme, will be used. If set to an absolute directory path then icons in that directory will be used. This value can be set to multiple values using, ``git config --add cola.icontheme $theme``. This setting can be overridden by the `GIT_COLA_ICON_THEME` environment variable, which can specify multiple themes using a colon-separated value. The icon theme can also be specified by passing ``--icon-theme=`` on the command line, once for each icon theme, in the order that they should be searched. This can be used to override a subset of the icons, and fallback to the built-in icons for the remainder. cola.imagediff.[extension] -------------------------- Enable image diffs for the specified file extension. For example, configuring `git config --global cola.imagediff.svg false` will disable use of the visual image diff for `.svg` files in all repos until is is explicitly toggled on. Defaults to `true`. cola.inotify ------------ Set to `false` to disable file system change monitoring. Defaults to `true`, but also requires either Linux with inotify support or Windows with `pywin32` installed for file system change monitoring to actually function. cola.refreshonfocus ------------------- Set to `true` to automatically refresh when `git cola` gains focus. Defaults to `false` because this can cause a pause whenever switching to `git cola` from another application. 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 options sub-menu. cola.logdate ------------ Set the default date-time mode for the DAG display. This value is passed to `git log --date=`. See `git log(1) `_ for more details. cola.maxrecent -------------- `git cola` caps the number of recent repositories to avoid cluttering the start and recent repositories menu. The maximum number of repositories to remember is controlled by `cola.maxrecent` and defaults to `8`. cola.mousezoom -------------- Controls whether zooming text using Ctrl + MouseWheel scroll is enabled. Set to ``false`` to disable scrolling with the mouse wheel. Defaults to ``true``. cola.dragencoding ----------------- `git cola` encodes paths dragged from its widgets into `utf-16` when adding them to the drag-and-drop mime data (specifically, the `text/x-moz-url` entry). `utf-16` is used to make `gnome-terminal` see the right paths, but other terminals may expect a different encoding. If you are using a terminal that expects a modern encoding, e.g. `terminator`, then set this value to `utf-8`. cola.readsize ------------- `git cola` avoids reading large binary untracked files. The maximum size to read is controlled by `cola.readsize` and defaults to `2048`. cola.resizebrowsercolumns ------------------------- `git cola` will automatically resize the file browser columns as folders are expanded/collapsed when ``cola.resizebrowsercolumns`` is set to `true`. cola.patchesdirectory --------------------- The default directory to use when exporting patches. Relative paths are treated as being relative to the current repository. Absolute paths are used as-is. Defaults to `patches`. cola.safemode ------------- The "Stage" button in the `git cola` Actions panel stages all files when it is activated and no files are selected. This can be problematic if it is accidentally triggered after carefully preparing the index with staged changes. "Safe Mode" is enabled by setting `cola.safemode` to `true`. When enabled, `git cola` will do nothing when "Stage" is activated without a selection. Defaults to `false`. cola.savewindowsettings ----------------------- `git cola` will remember its window settings when set to `true`. Window settings and X11 sessions are saved in `$HOME/.config/git-cola`. cola.showpath ------------- `git cola` displays the absolute path of the repository in the window title. This can be disabled by setting `cola.showpath` to `false`. Defaults to `true`. cola.signcommits ---------------- `git cola` will sign commits by default when set `true`. Defaults to `false`. See the section below on setting up GPG for more details. cola.startupmode ---------------- Control how the list of repositories is displayed in the startup dialog. Set to `list` to view the list of repositories as a list, or `folder` to view the list of repositories as a collection of folder icons. Defaults to `list`. cola.statusindent ----------------- Set to `true` to indent files in the Status widget. Files in the `Staged`, `Modified`, etc. categories will be grouped in a tree-like structure. Defaults to `false`. cola.statusshowtotals --------------------- Set to `true` to display files counts in the Status widget's category titles. Defaults to `false`. cola.tabwidth ------------- The number of columns occupied by a tab character. Defaults to 8. cola.terminal ------------- The command to use when launching commands within a graphical terminal. `cola.terminal` defaults to `xterm -e` when unset. e.g. when opening a shell, `git cola` will run `xterm -e $SHELL`. `git cola` has built-in support for `xterm`, `gnome-terminal`, `konsole`. If either `gnome-terminal`, `xfce4-terminal`, or `konsole` are installed then they will be preferred over `xterm` when `cola.terminal` is unset. The table below shows the built-in values that are used for the respective terminal. You can force the use of a specific terminal by configuring cola accordingly. cola.terminalshellquote ----------------------- Some terminal require that the command string get passed as a string. For example, ``xfce4-terminal -e "git difftool"`` requires shell quoting, whereas ``gnome-terminal -- git difftool`` does not. You should not need to set this variable for the built-in terminals cola knows about -- it will behave correctly without configuration. For example, when not configured, cola already knows that xfce4-terminal requires shell quoting. This configuration variable is for custom terminals outside of the builtin set. The table below shows the builtin configuration. .. code-block:: text Terminal cola.terminal cola.terminalshellquote -------- ------------- ----------------------- gnome-terminal "gnome-terminal --" false konsole "konsole -e" false xfce4-terminal "xfce4-terminal -e" true xterm "xterm -e" false cola.textwidth -------------- The number of columns used for line wrapping. Tabs are counted according to `cola.tabwidth`. .. _cola_theme: cola.theme ---------- Specifies the GUI theme to use throughout `git cola`. The theme specified must be one of the following values: * `default` – default Qt theme, may appear different on various systems * `flat-dark-blue` * `flat-dark-green` * `flat-dark-grey` * `flat-dark-red` * `flat-light-blue` * `flat-light-green` * `flat-light-grey` * `flat-light-red` If unset, or set to an invalid value, then the default style will be used. The `default` theme is generated by Qt internal engine and should look native but may look noticeably different on different platforms. The flat themes on the other hand should look similar (but not identical) on various systems. The GUI theme can also be specified by passing ``--theme=`` on the command line. cola.turbo ---------- Set to `true` to enable "turbo" mode. "Turbo" mode disables some features that can slow things down when operating on huge repositories. "Turbo" mode will skip loading Git commit messages, author details, status information, and commit date details in the `File Browser` tool. Defaults to `false`. cola.color.text --------------- The default diff text color, in hexadecimal #RRGGBB notation. Defaults to "#030303":: git config cola.color.text '#030303' cola.color.add -------------- The default diff "add" background color, in hexadecimal #RRGGBB notation. Defaults to "#d2ffe4":: git config cola.color.add '#d2ffe4' cola.color.remove ----------------- The default diff "remove" background color, in hexadecimal #RRGGBB notation. Defaults to "#fee0e4":: git config cola.color.remove '#fee0e4' cola.color.header ----------------- The default diff header text color, in hexadecimal #RRGGBB notation. Defaults to "#bbbbbb":: git config cola.color.header '#bbbbbb' commit.cleanup -------------- Configure whether commit messages should be stripped of whitespace and comments. Valid values are ``strip``, ``whitespace``, ``verbatim``, ``scissors`` or ``default``. The ``default`` mode uses the ``whitespace`` mode when committing through Git Cola and the ``strip`` mode when committing using the ``git commit`` command-line. * ``strip`` - Strip leading and trailing empty lines, trailing whitespace, commentary and collapse consecutive empty lines. * ``whitespace`` - Same as strip except ``# commentary`` is not removed. This is the ``default`` behavior when committing through `Git Cola`. * ``verbatim`` - Do not change the message at all. * ``scissors`` - Same as whitespace except that everything from (and including) the line found below is truncated, if the message is to be edited. "#" can be customized with ``core.commentChar``:: # ------------------------ >8 ------------------------ Scissor-lines and all following lines are removed. Changing the mode to ``whitespace`` can be useful when you always want to keep lines that begin with comment character ``#`` in your log message, even when committing using the command-line ``git commit``. On the contrary, if you always want to always strip comments, even when committing through Git Cola, then configure ``commit.cleanup`` to ``strip``. Please see the `git commit cleanup mode documentation `_ for more details. core.commentChar ---------------- Commit messages can contain comments that start with this character. Defaults to ``#``. Please see the `git config documentation `_ for more details. core.hooksPath -------------- Hooks are programs you can place in a hooks directory to trigger actions at certain points in git’s execution. Hooks that don’t have the executable bit set are ignored. By default the hooks directory is ``$GIT_DIR/hooks``, but that can be changed via the ``core.hooksPath`` configuration variable The ``cola-prepare-commit-msg`` hook functionality and Cola's Git LFS detection honors this configuration. Please see the `git hooks documentation `_ for more details. gui.diffcontext --------------- The number of diff context lines to display. gui.displayuntracked -------------------- `git cola` avoids showing untracked files when set to `false`. gui.editor ---------- The default text editor to use is defined in `gui.editor`. The config variable overrides the VISUAL environment variable. Defaults to `gvim -f -p`. gui.historybrowser ------------------ The history browser to use when visualizing history. Defaults to `gitk`. 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. 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. ENVIRONMENT VARIABLES ===================== GIT_COLA_ICON_THEME ------------------- When set in the environment, `GIT_COLA_ICON_THEME` overrides the theme specified in the `cola.icontheme` configuration. Read :ref:`cola_icontheme` for more details. GIT_COLA_SCALE -------------- .. Important:: `GIT_COLA_SCALE` should not be used with newer versions of Qt. Set `QT_AUTO_SCREEN_SCALE_FACTOR` to `1` and Qt will automatically scale the interface to the correct size based on the display DPI. This option is also available by setting `cola.hidpi` configuration. See the `Qt High DPI documentation `_ for more details. `git cola` can be made to scale its interface for HiDPI displays. When defined, `git cola` will scale icons, radio buttons, and checkboxes according to the scale factor. The default value is `1`. A good value is `2` for high-resolution displays. Fonts are not scaled, as their size can already be set in the settings. 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. VISUAL ------ Specifies the default editor to use. This is ignored when the `gui.editor` configuration variable is defined. 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.:: mkdir -p ~/.config/git-cola && echo en >~/.config/git-cola/language Alternatively you may also use LANGUAGE environmental variable to temporarily change `git cola`'s language just like any other gettext-based program. For example to temporarily change `git cola`'s language to English:: LANGUAGE=en git cola To make `git cola` use the zh_TW translation with zh_HK, zh, and en as a fallback.:: LANGUAGE=zh_TW:zh_HK:zh:en git cola CUSTOM GUI ACTIONS ================== `git cola` allows you to define custom GUI actions by setting `git config` variables. The "name" of the command appears in the "Actions" 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). If ```` contains slashes (``/``) then the leading part of the name, up until the final slash, is treated like a path of sub-menus under which the actions will be created. For example, configuring ``guitool.Commands/Util/echo.cmd`` creates a ``Commands`` menu inside the top-level ``Actions`` menu, a ``Util`` menu inside the ``Commands`` menu and an ``echo`` action inside the ``Commands`` sub-menu. guitool..background ------------------------- Run the command in the background (similar to editing and difftool actions). This avoids blocking the GUI. Setting `background` to `true` implies `noconsole` and `norescan`. 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 sub-dialog. 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. Defaults to 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. guitool..shortcut ----------------------- Specifies a keyboard shortcut for the custom tool. The value must be a valid string understood by the `QAction::setShortcut()` API. See https://doc.qt.io/qt-6/qkeysequence.html#toString for more details about the supported values. Avoid creating shortcuts that conflict with existing built-in `git cola` shortcuts. Creating a conflict will result in no action when the shortcut is used. SETTING UP CREDENTIAL HELPERS ============================= Git has robust support for automatically handling credentials. The recommended approach is to use SSH keys and an SSH agent, but any of the core Git Credentials helpers will get used automatically by Git Cola. See https://git-scm.com/doc/credential-helpers for more details. SETTING UP GPG FOR SIGNED COMMITS ================================= When creating signed commits, `gpg` will attempt to read your password from the terminal from which `git cola` was launched. The way to make this work smoothly is to use a GPG agent so that you can avoid needing to re-enter your password every time you commit. This also gets you a graphical passphrase prompt instead of getting prompted for your password in the terminal. Install gpg-agent and friends ----------------------------- On Mac OS X, you may need to `brew install gpg-agent` and install the `Mac GPG Suite `_. On Linux use your package manager to install gnupg2, gnupg-agent and pinentry-qt, e.g.:: sudo apt-get install gnupg2 gnupg-agent pinentry-qt On Linux, you should also configure Git so that it uses gpg2 (gnupg2), otherwise you will get errors mentioning, "unable to open /dev/tty". Set Git's `gpg.program` to `gpg2`:: git config --global gpg.program gpg2 Configure gpg-agent and a pin-entry program ------------------------------------------- On Mac OS X, edit `~/.gnupg/gpg.conf` to include the line,:: use-agent This is typically not needed on Linux, where `gpg2` is used, as this is the default value when using `gpg2`. Next, edit `~/.gnupg/gpg-agent.conf` to contain a pinentry-program line pointing to the pinentry program for your platform. The following example `~/.gnupg/gpg-agent.conf` shows how to use pinentry-gtk-2 on Linux:: pinentry-program /usr/bin/pinentry-gtk-2 default-cache-ttl 3600 This following example `.gnupg/gpg-agent.conf` shows how to use MacGPG2's pinentry app on On Mac OS X:: pinentry-program /usr/local/MacGPG2/libexec/pinentry-mac.app/Contents/MacOS/pinentry-mac default-cache-ttl 3600 enable-ssh-support use-standard-socket Once this has been set up then you will need to reload your gpg-agent config:: echo RELOADAGENT | gpg-connect-agent If you see the following output:: OK Then the daemon is already running, and you do not need to start it yourself. If it is not running, eval the output of ``gpg-agent --daemon`` in your shell prior to launching `git cola`.:: eval $(gpg-agent --daemon) git cola SHELL COMPLETIONS ================= Git Cola provides shell completions for zsh and bash. The completion scripts and instructions are included in Git Cola's `contrib` directory. * `Shell completion scripts `_ * `Setup instructions `_ WINDOWS NOTES ============= Git Installation ---------------- If Git is installed in a custom location, e.g. not installed in `C:/Git` or Program Files, then the path to Git must be configured by creating a file in your home directory `~/.config/git-cola/git-bindir` that points to your git installation, e.g.:: C:/Tools/Git/bin SSH Agents for Key-based Authentication --------------------------------------- You may need to setup ssh-agent in order to use SSH key-based authentication on Windows. It has been reported that starting OpenSSH agent in Windows Services and adding the key using Powershell are necessary in order to get things working. Please see the following links for more details. https://stackoverflow.com/questions/18683092/how-to-run-ssh-add-on-windows FIPS SECURITY MODE ================== `FIPS Security Mode `_ is available in newer versions of Python. These include Python 3.9+ and the patched Python 3.6 used by CentOS8/RHEL8 (and possibly others). Git Cola uses the ``hashlib.md5`` function and adheres to the FIPS security mode when available. Git Cola does not use the MD5 value for security purposes. MD5 is used only for the purposes of implementing the ``cola/gravatar.py`` Gravatar client. LINKS ===== Git Cola's Git Repository ------------------------- * `Primary repository _`. * `Mirror repository _`. Git Cola Homepage ----------------- https://git-cola.gitlab.io/ git-cola-4.6.1/docs/git-dag.rst000066400000000000000000000051331457126473700162410ustar00rootroot00000000000000======= git-dag ======= SYNOPSIS ======== ``git dag [options] [] [[--] [...]]`` DESCRIPTION =========== `git-dag` is an advanced Git history visualizer that presents ``git log``'s powerful features in an easy to use graphical interface. OPTIONS ======= ```` -------------------- Show only commits in the specified revision range. When no ```` is specified, it defaults to ``HEAD`` (i.e. the whole history leading to the current commit). ``origin..HEAD`` specifies all the commits reachable from the current commit (i.e. ``HEAD``), but not from ``origin``. For a complete list of ways to spell ````, see the Specifying Ranges section of `gitrevisions(7) `_ (``man gitrevisions``). ``--prompt`` ------------ Prompt for a Git repository instead of using the current directory. ``-r, --repo `` --------------------- Open the git repository located at ````. Defaults to the current directory. ``--version`` ------------- Print the version number and exit. ``-h, --help`` -------------- Show usage and optional arguments. Log Arguments ============= The ``Log`` text field allows you to pass arguments to `git log`. This can be used to filter the displayed history, for example entering `main -- Makefile` will display only commits on the `main` branch that touch the `Makefile`. The `Log` text field lets you interactively edit and replace the ``[] [[--] [...]]`` arguments that were initially specified on the command-line. CONTEXT-MENU ACTIONS ==================== The right-click menu can be used to perform various actions. All actions operate on the selected commit. You can create branches and tags, cherry-pick commits, save patches, export tarballs, and grab files from older commits using the context menu. DIFF COMMITS ============ You can diff arbitrary commits. Select a single commit in either the list view or the graph view and then right-click on a second commit. A menu will appear allowing you to diff the two commits. SHORTCUTS ========= You can run commands using dedicated shortcuts. Select a single commit and then press `Ctrl-Alt-c` to copy sha1 or `Ctrl-d` to run diff tool. You can read more about hotkeys from 'keyboard shortcuts' window or context menu. CONFIGURATION 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 git-log(1) for details. git-cola-4.6.1/docs/hotkeys.html000066400000000000000000000210271457126473700165470ustar00rootroot00000000000000 Keyboard shortcuts


    Commit
Ctrl + Return : Commit staged changes
Ctrl + Shift + Return : Prepare commit message hook
Ctrl + S : Stage / unstage selected files
Ctrl + Shift + S : Stage / unstage all files
Alt + A : Stage modified files
Alt + U : Stage untracked files
Ctrl + U / Alt + Shift + R : Revert the selected lines, or the diff hunk beneath the text cursor when nothing is selected, from the worktree
Ctrl + Shift + U : Launch an external editor to edit the selected lines, or the diff hunk beneath the text cursor when nothing is selected, and then revert unstaged changes using the edited diff
Ctrl + Z : Revert uncommitted changes
Ctrl + Shift + M : Merge branches
Ctrl + m : Amend last commit
Ctrl + Shift + C : Cherry pick
    Actions
Ctrl + B : Create branch
Alt + B : Checkout branch
Ctrl + T : Find files
Alt + G : Grep
Alt + D : Show diffstat
Alt + E : Export patches
Alt + Shift + S : Stash
Ctrl + Enter : Apply Stash
Ctrl + Backspace : Pop Stash
Ctrl + Shift + Backspace : Drop Stash
Ctrl + Backspace : Delete untracked files
Alt + Shift + F : Toggle paths filter
Alt + R : Start/continue interactive rebase
Ctrl + R : Refresh
? : Keyboard shortcuts
    Editing
Enter / Ctrl + E : Launch editor
Space : Open using default application
Shift + Space : Open parent directory
Ctrl + Alt + C : Copy Commit ID
Ctrl + Shift + E : View / edit recently modified files
Ctrl + # : Focus tools
Ctrl + Shift + # : Show and hide tools
# is 1 for commit, 2 for status, 3 for diff, etc.
Ctrl + Space : Display autocomplete options
Ctrl + Shift + # : Show and hide tools
# is 1 for commit, 2 for status, 3 for diff, etc.
    Remotes
Ctrl + P : Launch the Push dialog
Ctrl + Shift + P : Launch the Pull dialog
    Diff
S : Stage or unstage the selected lines, or the diff hunk beneath the text cursor when nothing is selected
Ctrl + Shift + S : Launch an external editor to edit the selected lines, or the diff hunk beneath the text cursor when nothing is selected, and then stage or unstage the edited diff
Ctrl + D : View diff using `git difftool`
Ctrl + F : Search diff for matching text
Ctrl + G : Search diff for the next text match
Ctrl + Shift + G : Search diff for the previous text match
Alt + Shift + C : Copy Diff to clipboard (strips diff +/- prefixes)
Ctrl + Shift + D : View directory diff using `git difftool --dir-diff`
Shift : Hold Shift to select text when moving the cursor with H, J, K, L and Arrow keys
Space / Shift + Space : Page Down / Page Up
0 (Zero) : Move cursor to the start of the line
$ (Shift + 4) : Move cursor to the end of the line
G G : Move cursor to the start of the diff
Shift + G : Move cursor to the end of the diff
    Browser actions
Ctrl + Shift + H : View history
Ctrl + Shift + D : View diff against predecessor
    Navigation
H : Move left/collapse
J / Alt + J : Move down
K / Alt + K : Move up
L : Move right/expand
Ctrl + J : Focus the Diff Editor
Ctrl + K : Focus the Status tool
Ctrl + L : Focus the Commit summary, Grep query, DAG query, ...
git-cola-4.6.1/docs/hotkeys_de.html000066400000000000000000000201601457126473700172140ustar00rootroot00000000000000 Tastenkürzel
    Version
Ctrl + Return : Vorgemerkte Änderungen versionieren
Ctrl + Shift + Return : Prepare commit message hook
Ctrl + S : Ausgewählte Dateien vormerken
Ctrl + Shift + S : Stage / unstage all files
Alt + A : Geänderte Dateien vormerken
Alt + U : Alle neuen Dateien vormerken
Ctrl + U / Alt + Shift + R : Revert the selected lines, or the diff hunk beneath the text cursor when nothing is selected, from the worktree
Ctrl + Shift + U : Launch an external editor to edit the selected lines, or the diff hunk beneath the text cursor when nothing is selected, and then revert unstaged changes using the edited diff
Ctrl + Z : Nicht versionierte Änderungen verwerfen
Ctrl + Shift + M : Merge branches
Ctrl + M : Letzte Version nachbessern
Ctrl + Shift + C : Einzelne Version übernehmen
    Befehle
Ctrl + B : Neuen Zweig erstellen
Alt + B : Zweig wechseln
Ctrl + T : Find files
Alt + G : Suchen
Alt + D : Vergleichsstatistik anzeigen
Alt + Shift + E : Patches exportieren
Alt + Shift + S : Weglegen und zurückholen
Ctrl + Enter : Apply Stash
Ctrl + Backspace : Pop Stash
Ctrl + Shift + Backspace : Drop Stash
Ctrl + Backspace : Delete untracked files
Alt + Shift + F : Toggle paths filter
Ctrl + R : Ansicht aktualisieren
? : Tastenkürzel
    Bearbeiten
Enter / Ctrl + E : Im Editor bearbeiten
Space : Mit der Standardanwendung öffnen
Shift + Space : Übergeordnetes Verzeichnis öffnen
Ctrl + Alt + C : Version kopieren
Ctrl + Shift + E : Kürzlich geänderte Dateien anzeigen/bearbeiten
Ctrl + # : Werkzeuge fokussieren
Ctrl + Shift + # : Werkzeuge anzeigen und verstecken
Ctrl + Space : Display autocomplete options
    Vergleichsansicht
S : Auswahl vormerken; falls nichts ausgewählt ist, siehe H
Ctrl + Shift + S : Launch an external editor to edit the selected lines, or the diff hunk beneath the text cursor when nothing is selected, and then stage the edited diff
Ctrl + D : Mithilfe von `git difftool` ansehen
Ctrl + F : Search diff for matching text
Ctrl + G : Search diff for the next text match
Ctrl + Shift + G : Search diff for the previous text match
Alt + Shift + C : Copy Diff to clipboard (strips diff +/- prefixes)
Ctrl + Shift + D : View directory diff using `git difftool --dir-diff`
Shift : Hold shift to select text when moving around with H, J, K, L and Arrow keys
Space / Shift + Space : Page Down / Page Up
0 (Zero) : Move cursor to the start of the line
$ (Shift + 4) : Move cursor to the end of the line
G G : Move cursor to the start of the diff
Shift + G : Move cursor to the end of the diff
    Browser-Befehle
Ctrl + Shift + H : Verlauf anzeigen
Ctrl + Shift + D : Mit Vorgänger vergleichen
    Navigation
H : Nach links/einklappen
J / Alt + J : Nach unten
K / Alt + K : Nach oben
L : Nach rechts/ausklappen
Ctrl + J : Focus the Diff Editor
Ctrl + K : Focus the Status tool
Ctrl + L : Focus the Commit summary, Grep query, DAG query, ...
git-cola-4.6.1/docs/hotkeys_zh_CN.html000066400000000000000000000176341457126473700176410ustar00rootroot00000000000000 键盘快捷键
    提交
Ctrl + Return : 提交已缓存变更
Ctrl + Shift + Return : Prepare commit message hook
Ctrl + S : 缓存所选项目
Ctrl + Shift + S : Stage / unstage all files
Alt + A : 缓存已更改项目
Alt + U : 缓存未追踪项目
Ctrl + U / Alt + Shift + R : 还原缓存改动
Ctrl + Shift + U : Launch an external editor to edit the selected lines, or the diff hunk beneath the text cursor when nothing is selected, and then revert unstaged changes using the edited diff
Ctrl + Z : 撤销未缓存变更
Ctrl + Shift + M : Merge branches
Ctrl + M : 修正前一次提交
Ctrl + Shift + C : Cherry pick
    操作
Ctrl + B : 建立新分支
Alt + B : 取出分支內容
Ctrl + T : Find files
Alt + G : 搜索
Alt + D : 显示内容差异
Alt + Shift + E : 导出差异
Alt + Shift + S : 缓存
Ctrl + Enter : Apply Stash
Ctrl + Backspace : Pop Stash
Ctrl + Shift + Backspace : Drop Stash
Ctrl + Backspace : Delete untracked files
Alt + Shift + F : Toggle paths filter
Ctrl + R : 重新整理
? : 显示键盘快捷键列表
    编辑
Enter / Ctrl + E : 启动文本编辑器
空白鍵 : 用默认程序打开
Shift + 空白鍵 : 打开上级目录
Ctrl + Alt + C : Copy Commit ID
Ctrl + Shift + E : 查看 / 编辑最近修改的文件
Ctrl + # : 聚焦于工具
Ctrl + Shift + # : 显示/隐藏工具
Ctrl + Space : Display autocomplete options
    差异查看器
S : 缓存所选项目,未选择项目时与H作用相同
Ctrl + Shift + S : Launch an external editor to edit the selected lines, or the diff hunk benath the text cursor when nothing is selected, and then stage the edited diff
Ctrl + D : 使用「git difftool」命令查看内容差异
Ctrl + F : Search diff for matching text
Ctrl + G : Search diff for the next text match
Ctrl + Shift + G : Search diff for the previous text match
Alt + Shift + C : Copy Diff to clipboard (strips diff +/- prefixes)
Ctrl + Shift + D : View directory diff using `git difftool --dir-diff`
Shift : Hold Shift to select text when moving the cursor with H, J, K, L and Arrow keys
Space / Shift + Space : Page Down / Page Up
0 (Zero) : Move cursor to the start of the line
$ (Shift + 4) : Move cursor to the end of the line
G G : Move cursor to the start of the diff
Shift + G : Move cursor to the end of the diff
    「浏览器」窗口操作
Ctrl + Shift + H : 查看变更历史
Ctrl + Shift + D : 与之前版本比较差异
    导航键
H : 左移/折叠
J / Alt + J : 下移
K / Alt + K : 上移
L : 右移/展开
Ctrl + J : Focus the Diff Editor
Ctrl + K : Focus the Status tool
Ctrl + L : 聚焦在 DAG 输入框
git-cola-4.6.1/docs/hotkeys_zh_TW.html000066400000000000000000000177311457126473700176710ustar00rootroot00000000000000 鍵盤快捷鍵
    提交版本
Ctrl + Return : 提交版本提交準備區域中的變更
Ctrl + Shift + Return : Prepare commit message hook
Ctrl + S : 將被選取的項目移入版本提交準備區域
Ctrl + Shift + S : Stage / unstage all files
Alt + A : 將已變更的項目移入版本提交準備區域
Alt + U : 將尚未追蹤其版本的項目移動到版本提交準備區域
Ctrl + U / Alt + Shift + R : 還原尚未移入版本提交準備區域的內容變動
Ctrl + Shift + U : Launch an external editor to edit the selected lines, or the diff hunk beneath the text cursor when nothing is selected, and then revert unstaged changes using the edited diff
Ctrl + Z : 撤銷尚未建立版本提交的內容變動
Ctrl + Shift + M : 合併分支
Ctrl + M : 修正前一次的版本提交
Ctrl + Shift + C : 挑取(cherry pick)
    操作
Ctrl + B : 建立一個新的分支
Alt + B : 取出分支內容
Ctrl + T : 尋找檔案
Alt + G : 搜尋
Alt + D : 顯示內容差異
Alt + Shift + E : 匯出修正
Alt + Shift + S : 珍藏
Ctrl + Enter : Apply Stash
Ctrl + Backspace : Pop Stash
Ctrl + Shift + Backspace : Drop Stash
Ctrl + Backspace : 刪除未納入版本追蹤的檔案
Alt + Shift + F : 開啟/關閉路徑過濾器
Ctrl + R : 重新整理
? : 顯示鍵盤快捷鍵列表
    編輯
Enter / Ctrl + E : 啟動文字編輯器
空白鍵 : 以系統預設的軟體開啟
Shift + 空白鍵 : 開啟上一層目錄
Ctrl + Alt + C : 複製修訂版的SHA-1雜湊值
Ctrl + Shift + E : 檢視/編輯最近修改過的檔案
Ctrl + # : 將焦點移至指定工具
Ctrl + Shift + # : 顯示或隱藏指定工具
對提交版本工具來說 # 為 1、對版控庫狀態工具來說 # 為 2、對內容差異工具來說 # 為 3,依此類推
Ctrl + Space : Display autocomplete options
    內容差異檢視器
S : 將選取的行移入版本提交準備區域,或是當沒有選取任何行時跟 H 效果相同
Ctrl + Shift + S : Launch an external editor to edit the selected lines, or the diff hunk benath the text cursor when nothing is selected, and then stage the edited diff
Ctrl + D : 使用「git difftool」命令檢視內容差異
Ctrl + F : Search diff for matching text
Ctrl + G : Search diff for the next text match
Ctrl + Shift + G : Search diff for the previous text match
Alt + Shift + C : Copy Diff to clipboard (strips diff +/- prefixes)
Ctrl + Shift + D : 使用「git difftool --dir-diff」命令檢視目錄內容差異
    瀏覽器工具內可進行的操作
Ctrl + Shift + H : 檢視變更紀錄
Ctrl + Shift + D : 與過去版本比較內容差異
    導覽按鍵
H : 向左移動/折疊
J / Alt + J : 向下移動
K / Alt + K : 向下移動
L : 向下移動/展開
Ctrl + J : 將焦點移至內容差異編輯器
Ctrl + K : 將焦點移至板控庫狀態工具
Ctrl + L : 將焦點移至提交變更工具
git-cola-4.6.1/docs/index.rst000066400000000000000000000004331457126473700160320ustar00rootroot00000000000000====================== Git Cola Documentation ====================== .. toctree:: :maxdepth: 3 git-cola git-dag thanks Release Notes ============= .. toctree:: :maxdepth: 2 relnotes Indices and tables ================== * :ref:`genindex` * :ref:`search` git-cola-4.6.1/docs/relnotes.rst000066400000000000000000000004651457126473700165630ustar00rootroot00000000000000======== Releases ======== Latest Release ============== :ref:`v4.6.1 ` is the latest stable release. Development version =================== Clone the git-cola repository to get the latest development version: ``git clone https://gitlab.com/git-cola/git-cola.git`` .. include:: ../CHANGES.rst git-cola-4.6.1/docs/thanks.rst000066400000000000000000000116461457126473700162230ustar00rootroot00000000000000Thanks ====== `git-cola` was made possible thanks to the contributions of the following people: * Aaron Boxer * Aaron Cook * Aaron Malpas * Aaron Wolf * Abid Ahmad * Adam Lesperance * Adrien be * Adil * AJ Bagwell * akontsevich * Albert Vaca Cintora * Aleksey Kontsevich * Alexander Preißner * Alex Chernetz * Alex Gulyás * Alexander Kozienko * Alf Eaton * anderben * Andreas Schnederle-Wagner * Andreas Sommer * Andrej Kvasnica * Andrew Chen * Andrew Hemming * Andy O'Neill * armandg * Arthur Coelho * Audrey Yeena Toskin * Audrius Karabanovas * Axel Heider * Balázs Meskó * balping * Barış ÇELİK * Barry Roberts * Bastian Müller * Boris W * Ben Boeckel * Ben Cole * Benedict Lee * Benjamin Somers * Benoît Nouyrigat * Bernd K * Bert Jacobs * Birger Skogeng Pedersen * Björn Ketelaars * Bob van der Linden * Boerje Sewing * Bruno Cabral * 林博仁 (Buo-ren Lin) * cclaus * Charles 101 * Chris Stefano * Christian Jann * Christoph Erhardt * Christopher Meng * Clément Pit--Claudel * Constantine Grantcharov * Daniel Fahlke * Daniel Jay Haskin * Daniel Harding * Daniel King * DasaniT * Dave Cottlehuber * Dave Thomas * David Aguilar * David Bold * David Fernandez * David LeGare * David Martínez Martí * David Roman * Dawid Drozd * Dennis Gilmore * Demodian * deniz1a * Dmitriy Bogdanov * Dmitry Kann * Dmitry Pashkevich * Dorian Marchal * Doug Hoskisson * Drugoy * Efimov Vasily * Eric Drechsel * Eric Wild * Ernst Widerberg * Erop @EgZvor * Erwan Bousse * Fabio Coatti * Fang Pengfei * feinstaub * Felipe Morales * Filip Danilović * Floris Lambrechts * Frank Weber * fu7mu4 * Garoe Dorta * Geoffrey van Wyk * Georg Limbach * geotavros * Gianni Lerro * Giovanni Martins * `Git Hackers `_ * Graham Bartlett * green-eyed-bear * Glen Mailer * Guillaume de Bure * Guo Yunhe * Gyuris Gellért * Harro Verton * Hannes @kannes * hydrargyrum * Igor Galarraga * Igor Kopach * Ilya Tumaykin * Ingo Weinhold * Irfan Baig * Ismael Juma * Iulian Udrea * Ivar Smolin * Jad El Kik * Jacob Gustafson * Jakub Klos * Jan @hanksoff * Jan Šilhan * Jan Tumanov * jakubklos77 * Jakub Szymański * Jakub Wilk * James Geiger * Jason Newton * Javier Rodriguez Cuevas * Jeff Dagenais * Jérôme Carretero * jfessard * JiCiT * Jimmy M. Coleman * Joachim Jablon * Joachim Lusiardi * Joel Barrios * Johannes Löhnert * Johann Schmitz * Jordan Bedwell * Josh Noe * Josh Taylor * Justin Lecher * Kai Krakow * Karl Bielefeldt * Karthik Manamcheri * Kelvie Wong * Kerrick Staley * Kevin Kofler * Kirit Sælensminde * Kisaragi Hiu * Klaas Neirinck * Kurt McKee * Kyle Slane * László Böszörményi * lcjh * Leho Kraav * Lev Zlotin * Louis Rousseau * Libor Jelinek * Lim Ngian Xin Terry * Liviu Cristian Mirea-Ghiban * Luca Ottaviano * Łukasz Wojniłowicz * Luke Bakken * Luke Horwell * Maarten Nieber * Maaaks * Maciej Filipiak * Mahmoud Hossam * Mateusz Kedzior * Matias N. Goldberg * Maicon D. Filippsen * Marcin Mielniczuk * Marco Costalba * Mariusz Jaskółka * Markus Heidelberg * Martin Gysel * Martin Konecny * Matěj Šmíd * Matthew Levine * Matthias Mailänder * Max Harmathy * Melike Kecelioglu * Micha Rosenbaum * Michael Geddes * Michael Homer * Michael Schwarz * Mickael Albertus * Miguel Boekhold * Mike Hanson * MikHulk * Mikołaj Milej * Minarto Margoliono * Mithil Poojary * Mosaab Alzoubi * Muhammad Bashir Al-Noimi * nakanoi * Nanda Lopes * Naraesk * Niel Buys * Nick Todd * Nicolas Dietrich * Nikos Roussos * Noel Grandin * NotSqrt * nyanpasu64 * ochristi * Oliver Haessler * OmegaPhil (Omega Weapon) * Ori shalhon * Owen Healy * Pamela Strucker * Paolo G. Giarrusso * Parashurama Rhagdamaziel * Patrick Browne * Paul Hildebrandt * Paul Weingardt * Paulo Fidalgo * Pavel Borecki * Pavel Rehak * Peer Sommerlund * Peter Dave Hello * Peter Jensen * Peter Justin * Peter Júnoš * Petr Gladkikh * Philip Stark * Pilar Molina Lopez * Pius Raeder * Radek Novacek * Radek Postołowicz * Rafael Nascimento * Rafael Reuber * Raghavendra Karunanidhi * Rainer Müller * Ray Haleblian * RealTehreal * Ricardo J. Barberis * Robbert Korving * Robert Pollak * Rolando Espinoza La fuente * Rustam Safin * Sabri Ünal * Samsul Ma'arif * Scott Field * Sean Allred * Sebastian Brass * Sebastian Oliva * Sergei Dyshel * Sergey Leschina * Shun Sakai * Simon Peeters * Srinivasa Nallapati * Stan Angeloff * Stanisław Halik * Stefan Naewe * Steffen Prohaska * Stéphane Cerveau * Stephen Groat * Suyandi * Sven Claussner * Szymon Judasz * Taylor Braun-Jones * Thiemo van Engelen * Thomas Kiley * Thomas Kluyver * Thomas Thorne * Tom Dobbelaere * Tim Brown * Tim Gates * Tim Schumacher * Trevor Alexander * Tyler Shellberg * Ugo Riboni * Uri Okrent * Utku Karatas * V字龍 (Vdragon) * Vaibhav Sagar * Vaiz * vanderkoort * Ved Vyas * Victor Gambier * Victor Nepveu * Victorhck * Ville Skyttä * Virgil Dupras * Vitor Lobo * v.paritskiy * waterzch * Wolfgang Ocker * wm4 * WNguyen14 * wsdfhjxc * Xie Hua Liang (xieofxie) * yael levi * YAMAMOTO Kenyu * Yi EungJun * Zauber Paracelsus * Zeioth * Zhang Han * 0xflotus git-cola-4.6.1/extras/000077500000000000000000000000001457126473700145475ustar00rootroot00000000000000git-cola-4.6.1/extras/README.md000066400000000000000000000012561457126473700160320ustar00rootroot00000000000000# extras The extras directory contains third-party code that is used by Git Cola. ## sphinxtogithub Git Cola uses [sphinx-to-github](https://github.com/michaeljones/sphinx-to-github) for massaging the output of the [Sphinx](https://github.com/sphinx-doc/sphinx)-generated documentation. ## qtpy The license and author information for the [QtPy](https://github.com/spyder-ide/qtpy) library is included in the [qtpy/](qtpy) directory. ## polib The `cola.polib` Python module is a copy of the [MIT-licensed](LICENSE.polib) [polib](https://github.com/izimobil/polib) library. The license for [polib](https://github.com/izimobil/polib) is included in the [polib](polib) directory. git-cola-4.6.1/extras/polib/000077500000000000000000000000001457126473700156545ustar00rootroot00000000000000git-cola-4.6.1/extras/polib/LICENSE000066400000000000000000000020521457126473700166600ustar00rootroot00000000000000Copyright (c) 2006-2015 David Jean Louis. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. git-cola-4.6.1/extras/qtpy/000077500000000000000000000000001457126473700155445ustar00rootroot00000000000000git-cola-4.6.1/extras/qtpy/AUTHORS.md000066400000000000000000000014601457126473700172140ustar00rootroot00000000000000# Authors ## Original Authors * [pyqode.qt](https://github.com/pyQode/pyqode.qt): Colin Duquesnoy ([@ColinDuquesnoy](https://github.com/ColinDuquesnoy)) * [spyderlib.qt](https://github.com/spyder-ide/spyder/commits/2.3/spyderlib/qt): Pierre Raybaut ([@PierreRaybaut](https://github.com/PierreRaybaut)) * [qt-helpers](https://github.com/glue-viz/qt-helpers): Thomas Robitaille ([@astrofrog](https://www.github.com/astrofrog)) ## Current Maintainers * Daniel Althviz ([@dalthviz](https://github.com/dalthviz)) * Carlos Cordoba ([@ccordoba12](https://github.com/ccordoba12)) * C.A.M. Gerlach ([@CAM-Gerlach](https://github.com/CAM-Gerlach)) * Spyder Development Team ([Spyder-IDE](https://github.com/spyder-ide)) ## Contributors * [The QtPy Contributors](https://github.com/spyder-ide/qtpy/graphs/contributors) git-cola-4.6.1/extras/qtpy/CHANGELOG.md000066400000000000000000001665451457126473700173760ustar00rootroot00000000000000# History of changes ## Version 2.4.1 (2023-10-23) ### Issues Closed * [Issue 462](https://github.com/spyder-ide/qtpy/issues/462) - Release QtPy 2.4.1 * [Issue 458](https://github.com/spyder-ide/qtpy/issues/458) - Typo causes failed QWebEngineScript with PySide6 In this release 2 issues were closed. ### Pull Requests Merged * [PR 459](https://github.com/spyder-ide/qtpy/pull/459) - [pre-commit.ci] pre-commit autoupdate, by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci) * [PR 456](https://github.com/spyder-ide/qtpy/pull/456) - [pre-commit.ci] pre-commit autoupdate, by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci) * [PR 455](https://github.com/spyder-ide/qtpy/pull/455) - PR: Fix bug when importing from `PySide6.QtWebEngineCore/QtWebEngineWidgets` (`QWebEngineScrip` vs `QWebEngineScript`) , by [@damonlynch](https://github.com/damonlynch) In this release 3 pull requests were closed. ---- ## Version 2.4.0 (2023-08-29) ### Issues Closed * [Issue 453](https://github.com/spyder-ide/qtpy/issues/453) - Release QtPy 2.4.0 * [Issue 447](https://github.com/spyder-ide/qtpy/issues/447) - Type hints not working for `qtpy` specific imports ([PR 450](https://github.com/spyder-ide/qtpy/pull/450) by [@wkrasnicki](https://github.com/wkrasnicki)) * [Issue 442](https://github.com/spyder-ide/qtpy/issues/442) - Some compatibility issues when using latest PyQt6 or PySide6 (6.5+) ([PR 448](https://github.com/spyder-ide/qtpy/pull/448) by [@dalthviz](https://github.com/dalthviz)) * [Issue 439](https://github.com/spyder-ide/qtpy/issues/439) - qtpy.uic.loadUiType failing for PySide6 ([PR 440](https://github.com/spyder-ide/qtpy/pull/440) by [@JaRoSchm](https://github.com/JaRoSchm)) * [Issue 432](https://github.com/spyder-ide/qtpy/issues/432) - Add compatibility layer for keywords arguments of `QFileDialog ` `get*` class methods ([PR 433](https://github.com/spyder-ide/qtpy/pull/433) by [@Czaki](https://github.com/Czaki)) * [Issue 423](https://github.com/spyder-ide/qtpy/issues/423) - Fix flaky importlib error on Ubuntu Python 3.7 conda CI job ([PR 425](https://github.com/spyder-ide/qtpy/pull/425) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 383](https://github.com/spyder-ide/qtpy/issues/383) - Add extra packages available for PyQt to CI for testing ([PR 446](https://github.com/spyder-ide/qtpy/pull/446) by [@dalthviz](https://github.com/dalthviz)) * [Issue 345](https://github.com/spyder-ide/qtpy/issues/345) - Use pre-commit to automatically format code with Black and imports with isort ([PR 451](https://github.com/spyder-ide/qtpy/pull/451) by [@Czaki](https://github.com/Czaki)) In this release 8 issues were closed. ### Pull Requests Merged * [PR 451](https://github.com/spyder-ide/qtpy/pull/451) - PR: Setup pre-commit and format all code with Black, by [@Czaki](https://github.com/Czaki) ([345](https://github.com/spyder-ide/qtpy/issues/345)) * [PR 450](https://github.com/spyder-ide/qtpy/pull/450) - PR: Update README with information on Pyright/Pylance integration and add CLI subcommand to help generate the related config, by [@wkrasnicki](https://github.com/wkrasnicki) ([447](https://github.com/spyder-ide/qtpy/issues/447)) * [PR 449](https://github.com/spyder-ide/qtpy/pull/449) - PR: Improve enum to flags aliasing for PyQt6 and PySide6 > 6.3 and `QFileDialog` static methods kwarg compatibility, by [@dalthviz](https://github.com/dalthviz) * [PR 448](https://github.com/spyder-ide/qtpy/pull/448) - PR: Restore `QtWidgets.QFileDialog.Options` access as `QtWidgets.QFileDialog.Option` alias (PyQt6), by [@dalthviz](https://github.com/dalthviz) ([442](https://github.com/spyder-ide/qtpy/issues/442)) * [PR 446](https://github.com/spyder-ide/qtpy/pull/446) - PR: Test using `PyQt` extra packages, by [@dalthviz](https://github.com/dalthviz) ([383](https://github.com/spyder-ide/qtpy/issues/383)) * [PR 445](https://github.com/spyder-ide/qtpy/pull/445) - PR: Add mappings for deprecated `QDropEvent` `pos` and `posF` methods, by [@dalthviz](https://github.com/dalthviz) * [PR 444](https://github.com/spyder-ide/qtpy/pull/444) - PR: Restore `Qt.ItemFlags` access as `Qt.ItemFlag` alias (PyQt6), by [@dalthviz](https://github.com/dalthviz) * [PR 443](https://github.com/spyder-ide/qtpy/pull/443) - PR: Update bindings upper bound version to 6.5 and ignore `DeprecationWarning` (CI), by [@dalthviz](https://github.com/dalthviz) * [PR 440](https://github.com/spyder-ide/qtpy/pull/440) - PR: Replace custom implementation with loadUiType from PySide6, by [@JaRoSchm](https://github.com/JaRoSchm) ([439](https://github.com/spyder-ide/qtpy/issues/439)) * [PR 438](https://github.com/spyder-ide/qtpy/pull/438) - PR: Make `exec()` for PySide2, by [@StSav012](https://github.com/StSav012) * [PR 437](https://github.com/spyder-ide/qtpy/pull/437) - PR: Make `QMenu.addAction` and `QToolBar.addAction` compatible with Qt6 arguments' order, by [@StSav012](https://github.com/StSav012) * [PR 434](https://github.com/spyder-ide/qtpy/pull/434) - PR: Enable more tests on CI, by [@Czaki](https://github.com/Czaki) * [PR 433](https://github.com/spyder-ide/qtpy/pull/433) - PR: Add wrapers to fix argument name in `QFileDialog` `get*`methods, by [@Czaki](https://github.com/Czaki) ([432](https://github.com/spyder-ide/qtpy/issues/432)) * [PR 431](https://github.com/spyder-ide/qtpy/pull/431) - PR: Rename `utils.py` to `_utils.py` to make it private, by [@StSav012](https://github.com/StSav012) * [PR 425](https://github.com/spyder-ide/qtpy/pull/425) - PR: Make CI jobs much faster & less flaky w/Mamba, 1-pass solve & other tweaks, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([423](https://github.com/spyder-ide/qtpy/issues/423)) * [PR 424](https://github.com/spyder-ide/qtpy/pull/424) - PR: Add `QEnum` macro for PyQt bindings, by [@phil65](https://github.com/phil65) * [PR 422](https://github.com/spyder-ide/qtpy/pull/422) - PR: Use static calls of `exec_` elsewhere where needed, and test them, by [@StSav012](https://github.com/StSav012) * [PR 421](https://github.com/spyder-ide/qtpy/pull/421) - PR: Symmetrize `QDateTime.toPython` and `toPyDateTime`, etc., by [@StSav012](https://github.com/StSav012) * [PR 420](https://github.com/spyder-ide/qtpy/pull/420) - PR: Symmetrize `path` and `location` of `QLibraryInfo`, by [@StSav012](https://github.com/StSav012) * [PR 419](https://github.com/spyder-ide/qtpy/pull/419) - PR: Add missing issue closed for v2.3.1 changelog entry, by [@dalthviz](https://github.com/dalthviz) * [PR 387](https://github.com/spyder-ide/qtpy/pull/387) - PR: Improve import modularity between `QtGui`, `QtWidgets` and `QtOpenGL*` related modules, by [@DaelonSuzuka](https://github.com/DaelonSuzuka) In this release 21 pull requests were closed. ---- ## Version 2.3.1 (2023-03-28) ### Issues Closed * [Issue 416](https://github.com/spyder-ide/qtpy/issues/416) - Release QtPy 2.3.1 * [Issue 412](https://github.com/spyder-ide/qtpy/issues/412) - How to catch QtBindingsNotFoundError ([PR 413](https://github.com/spyder-ide/qtpy/pull/413) by [@cbrnr](https://github.com/cbrnr)) * [Issue 405](https://github.com/spyder-ide/qtpy/issues/405) - Remove patch that "may be limited to `PySide-5.11a1` only" * [Issue 402](https://github.com/spyder-ide/qtpy/issues/402) - `QTextStreamManipulator` has no `exec` method on PyQt5/6 * [Issue 394](https://github.com/spyder-ide/qtpy/issues/394) - Differences in QEvent subclass APIs in PyQt6 cause attribute and/or type errors * [Issue 390](https://github.com/spyder-ide/qtpy/issues/390) - QtBindingsNotFoundError is not raised correctly (from None) in __init__ ([PR 391](https://github.com/spyder-ide/qtpy/pull/391) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 389](https://github.com/spyder-ide/qtpy/issues/389) - Make `QtWidgets` and `QtGui` modules compatible with `PySide6`/`PyQt6` import locations for `PySide2`/`PyQt5` ([PR 410](https://github.com/spyder-ide/qtpy/pull/410) by [@StSav012](https://github.com/StSav012)) * [Issue 386](https://github.com/spyder-ide/qtpy/issues/386) - Add official support for Python 3.11 ([PR 392](https://github.com/spyder-ide/qtpy/pull/392) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) In this release 8 issues were closed. ### Pull Requests Merged * [PR 417](https://github.com/spyder-ide/qtpy/pull/417) - PR: Add compatibility mappings between bindings for all children of `QSinglePointEvent`, by [@StSav012](https://github.com/StSav012) * [PR 414](https://github.com/spyder-ide/qtpy/pull/414) - PR: Skip QtPositioning tests on Conda Qt >=6.4.3 where its not included, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) * [PR 413](https://github.com/spyder-ide/qtpy/pull/413) - PR: Make `QtBindingsNotFoundError` also inherit from `ImportError`, by [@cbrnr](https://github.com/cbrnr) ([412](https://github.com/spyder-ide/qtpy/issues/412)) * [PR 410](https://github.com/spyder-ide/qtpy/pull/410) - PR: Improve compatibility for `QtWidgets` and `QtGui` modules between Qt5 and Qt6 bindings, by [@StSav012](https://github.com/StSav012) * [PR 408](https://github.com/spyder-ide/qtpy/pull/408) - PR: Add mappings for QMouseEvent methods, by [@StSav012](https://github.com/StSav012) * [PR 407](https://github.com/spyder-ide/qtpy/pull/407) - PR: Remove patch that may be limited to PySide-5.11a1 only, by [@StSav012](https://github.com/StSav012) * [PR 404](https://github.com/spyder-ide/qtpy/pull/404) - PR: Don't make `QTextStreamManipulator.exec_` on PyQt5/6, by [@StSav012](https://github.com/StSav012) * [PR 401](https://github.com/spyder-ide/qtpy/pull/401) - PR: Unskip PySide2 5.15 on Python 3.11 with Conda on CIs, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) * [PR 398](https://github.com/spyder-ide/qtpy/pull/398) - PR: Make warning usage consistant and refine messages, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) * [PR 397](https://github.com/spyder-ide/qtpy/pull/397) - Simplify CI script following Qt 5.15.6 feedstock update, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) * [PR 393](https://github.com/spyder-ide/qtpy/pull/393) - PR: Fix `LibraryLocation` -> `LibraryPath` renaming due to deprecation with Qt6, by [@StSav012](https://github.com/StSav012) * [PR 392](https://github.com/spyder-ide/qtpy/pull/392) - PR: Add Python 3.11 to CIs/tags & overhaul CI config, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([386](https://github.com/spyder-ide/qtpy/issues/386)) * [PR 391](https://github.com/spyder-ide/qtpy/pull/391) - PR: Use raise from None when raising QtBindingsNotFoundError in __init__, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([390](https://github.com/spyder-ide/qtpy/issues/390)) In this release 13 pull requests were closed. ---- ## Version 2.3.0 (2022-11-07) ### Issues Closed * [Issue 384](https://github.com/spyder-ide/qtpy/issues/384) - Release QtPy 2.3.0 * [Issue 381](https://github.com/spyder-ide/qtpy/issues/381) - Add QtPdf, QtPdfWidgets ([PR 382](https://github.com/spyder-ide/qtpy/pull/382) by [@jschueller](https://github.com/jschueller)) * [Issue 375](https://github.com/spyder-ide/qtpy/issues/375) - Test PySide6 6.4.x ([PR 376](https://github.com/spyder-ide/qtpy/pull/376) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 373](https://github.com/spyder-ide/qtpy/issues/373) - PySide6 6.4.0 support - `AttributeError: Cannot reassign members` when aliasing enum values ([PR 374](https://github.com/spyder-ide/qtpy/pull/374) by [@astrofrog](https://github.com/astrofrog)) * [Issue 367](https://github.com/spyder-ide/qtpy/issues/367) - Import behaviour if no Qt bindings are installed ([PR 379](https://github.com/spyder-ide/qtpy/pull/379) by [@dalthviz](https://github.com/dalthviz)) * [Issue 134](https://github.com/spyder-ide/qtpy/issues/134) - QScintilla Support ([PR 372](https://github.com/spyder-ide/qtpy/pull/372) by [@dgoeries](https://github.com/dgoeries)) In this release 6 issues were closed. ### Pull Requests Merged * [PR 382](https://github.com/spyder-ide/qtpy/pull/382) - PR: Add `QtPdf` and `QtPdfWidgets`, by [@jschueller](https://github.com/jschueller) ([381](https://github.com/spyder-ide/qtpy/issues/381)) * [PR 380](https://github.com/spyder-ide/qtpy/pull/380) - PR: Enable more qt6 tests, by [@jschueller](https://github.com/jschueller) * [PR 379](https://github.com/spyder-ide/qtpy/pull/379) - PR: Raise error when no bindings are found at `__init__`, by [@dalthviz](https://github.com/dalthviz) ([367](https://github.com/spyder-ide/qtpy/issues/367)) * [PR 378](https://github.com/spyder-ide/qtpy/pull/378) - PR: Try PySide6 on conda, by [@jschueller](https://github.com/jschueller) * [PR 376](https://github.com/spyder-ide/qtpy/pull/376) - PR: Expand the CI test matrix with Qt/bindings 6.4 and fix tests with PyQt 5.9, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([375](https://github.com/spyder-ide/qtpy/issues/375)) * [PR 374](https://github.com/spyder-ide/qtpy/pull/374) - Don't re-assign Qt.MouseButton.MiddleButton on PySide6, by [@astrofrog](https://github.com/astrofrog) ([373](https://github.com/spyder-ide/qtpy/issues/373)) * [PR 372](https://github.com/spyder-ide/qtpy/pull/372) - PR: Add `Qsci` to the imports, by [@dgoeries](https://github.com/dgoeries) ([134](https://github.com/spyder-ide/qtpy/issues/134)) In this release 7 pull requests were closed. ---- ## Version 2.2.1 (2022-10-03) ### Issues Closed * [Issue 369](https://github.com/spyder-ide/qtpy/issues/369) - Release QtPy 2.2.1 * [Issue 365](https://github.com/spyder-ide/qtpy/issues/365) - Additions needed for PySide6/PyQt6 support (`QFontMetricsF.width`, `QLineEdit.getTextMargins` and `QtWidgets.QUndoCommand`) ([PR 366](https://github.com/spyder-ide/qtpy/pull/366) by [@random-developer](https://github.com/random-developer)) In this release 2 issues were closed. ### Pull Requests Merged * [PR 368](https://github.com/spyder-ide/qtpy/pull/368) - PR: Add missing `self` for `QtBindingsNotFoundError` definition, by [@dalthviz](https://github.com/dalthviz) * [PR 366](https://github.com/spyder-ide/qtpy/pull/366) - PR: Aliased `QUndoCommand`, provided `QLineEdit.getTextMargins()` and `QFontMetricsF.width()`, by [@random-developer](https://github.com/random-developer) ([365](https://github.com/spyder-ide/qtpy/issues/365)) * [PR 363](https://github.com/spyder-ide/qtpy/pull/363) - PR: Fix typo in Qt flags in Readme, by [@Czaki](https://github.com/Czaki) * [PR 362](https://github.com/spyder-ide/qtpy/pull/362) - PR: Fix various minor typos found with Codespell, by [@luzpaz](https://github.com/luzpaz) * [PR 361](https://github.com/spyder-ide/qtpy/pull/361) - PR: toPython helpers for QDate and QTime, by [@bob-schumaker](https://github.com/bob-schumaker) * [PR 360](https://github.com/spyder-ide/qtpy/pull/360) - CI: Ensure conda-forge channel usage when testing with conda, by [@dalthviz](https://github.com/dalthviz) In this release 6 pull requests were closed. ---- ## Version 2.2.0 (2022-08-10) ### Issues Closed * [Issue 359](https://github.com/spyder-ide/qtpy/issues/359) - Release QtPy 2.2.0 * [Issue 352](https://github.com/spyder-ide/qtpy/issues/352) - Deprecation Warning for Enum Access ([PR 353](https://github.com/spyder-ide/qtpy/pull/353) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 351](https://github.com/spyder-ide/qtpy/issues/351) - `PySide6.QtSvgWidgets` not exposed * [Issue 302](https://github.com/spyder-ide/qtpy/issues/302) - Compat shiboken and sip like Qt.py ([PR 354](https://github.com/spyder-ide/qtpy/pull/354) by [@zjp](https://github.com/zjp)) * [Issue 61](https://github.com/spyder-ide/qtpy/issues/61) - Add documentation for methods or helpers that are specific to qtpy ([PR 357](https://github.com/spyder-ide/qtpy/pull/357) by [@dalthviz](https://github.com/dalthviz)) In this release 5 issues were closed. ### Pull Requests Merged * [PR 358](https://github.com/spyder-ide/qtpy/pull/358) - PR: Fix PyQt6 typing import for Qt, by [@tlambert03](https://github.com/tlambert03) * [PR 357](https://github.com/spyder-ide/qtpy/pull/357) - PR: Add initial `Methods, helpers and QtPy namespace specifics` section to the README, by [@dalthviz](https://github.com/dalthviz) ([61](https://github.com/spyder-ide/qtpy/issues/61)) * [PR 354](https://github.com/spyder-ide/qtpy/pull/354) - PR: Add wrapper around sip/shiboken isdeleted/isvalid (compat.py), by [@zjp](https://github.com/zjp) ([302](https://github.com/spyder-ide/qtpy/issues/302)) * [PR 353](https://github.com/spyder-ide/qtpy/pull/353) - PR: Add note to readme about use with Pyright, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([352](https://github.com/spyder-ide/qtpy/issues/352)) * [PR 350](https://github.com/spyder-ide/qtpy/pull/350) - PR: Restore `WEBENGINE` constant in `QtWebEngineWidgets`, by [@ccordoba12](https://github.com/ccordoba12) * [PR 346](https://github.com/spyder-ide/qtpy/pull/346) - PR: Add workaround for `mode` argument in QTextCursor.movePosition (PySide6), by [@rear1019](https://github.com/rear1019) * [PR 344](https://github.com/spyder-ide/qtpy/pull/344) - PR: Add missing imports and modules, by [@DaelonSuzuka](https://github.com/DaelonSuzuka) In this release 7 pull requests were closed. ---- ## Version 2.1.0 (2022-05-02) ### New features * New CLI to get mypy arguments and check QtPy version ### Important fixes * Remove Python 3.6 support * Fix `QT_API` environmental variable handling so new processes get the correct value when `Qt_API` is not initially set * Change try order for bindings in case the `QT_API` environmental variable is not set i.e `PyQt5 - PySide2 - PyQt6 - PySide6` ### Issues Closed * [Issue 342](https://github.com/spyder-ide/qtpy/issues/342) - Change bindings `try order` to follow QtPy `v1.x` convention ([PR 343](https://github.com/spyder-ide/qtpy/pull/343) by [@dalthviz](https://github.com/dalthviz)) * [Issue 338](https://github.com/spyder-ide/qtpy/issues/338) - Release QtPy 2.1.0 * [Issue 336](https://github.com/spyder-ide/qtpy/issues/336) - Segfaulting tests on PyQt6 + Windows on both Py3.7 and 3.10 (no conda) probably due to PyQt 6.3.0 ([PR 335](https://github.com/spyder-ide/qtpy/pull/335) by [@dalthviz](https://github.com/dalthviz)) * [Issue 332](https://github.com/spyder-ide/qtpy/issues/332) - Remove `QHeaderView` patch ([PR 334](https://github.com/spyder-ide/qtpy/pull/334) by [@dalthviz](https://github.com/dalthviz)) * [Issue 327](https://github.com/spyder-ide/qtpy/issues/327) - Missing `QtCore.Qt.MidButton` alias for `QtCore.Qt.MouseButton.MiddleButton` with PyQt6 ([PR 328](https://github.com/spyder-ide/qtpy/pull/328) by [@dalthviz](https://github.com/dalthviz)) * [Issue 323](https://github.com/spyder-ide/qtpy/issues/323) - Fix test suite failing at collection on Python 3.10 in Pytest 7.x ([PR 324](https://github.com/spyder-ide/qtpy/pull/324) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 297](https://github.com/spyder-ide/qtpy/issues/297) - Drop Python 3.6 support ([PR 329](https://github.com/spyder-ide/qtpy/pull/329) by [@dalthviz](https://github.com/dalthviz)) * [Issue 265](https://github.com/spyder-ide/qtpy/issues/265) - Investigate and (hopefully) resolve segfaults and other issues in UIC tests ([PR 335](https://github.com/spyder-ide/qtpy/pull/335) by [@dalthviz](https://github.com/dalthviz)) * [Issue 216](https://github.com/spyder-ide/qtpy/issues/216) - Support type hints and mypy ([PR 337](https://github.com/spyder-ide/qtpy/pull/337) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) In this release 9 issues were closed. ### Pull Requests Merged * [PR 343](https://github.com/spyder-ide/qtpy/pull/343) - PR: Change bindings `try order` to be `PyQt5, PySide2, PyQt6, PySide6`, by [@dalthviz](https://github.com/dalthviz) ([342](https://github.com/spyder-ide/qtpy/issues/342)) * [PR 341](https://github.com/spyder-ide/qtpy/pull/341) - PR: Add workaround for `mode` argument in QTextCursor.movePosition (Pyside2), by [@rear1019](https://github.com/rear1019) * [PR 340](https://github.com/spyder-ide/qtpy/pull/340) - PR: Fix bug with environ handling, by [@larsoner](https://github.com/larsoner) * [PR 337](https://github.com/spyder-ide/qtpy/pull/337) - PR: Add command line support for Mypy, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([217](https://github.com/spyder-ide/qtpy/issues/217), [216](https://github.com/spyder-ide/qtpy/issues/216)) * [PR 335](https://github.com/spyder-ide/qtpy/pull/335) - PR: Fix uic skipped tests and PyQt 6.3.0 segfaulting tests, by [@dalthviz](https://github.com/dalthviz) ([336](https://github.com/spyder-ide/qtpy/issues/336), [265](https://github.com/spyder-ide/qtpy/issues/265)) * [PR 334](https://github.com/spyder-ide/qtpy/pull/334) - PR: Remove `QHeaderView` patch related files, by [@dalthviz](https://github.com/dalthviz) ([332](https://github.com/spyder-ide/qtpy/issues/332)) * [PR 333](https://github.com/spyder-ide/qtpy/pull/333) - PR: Skip import of QOpenGLTime* on architectures where not available, by [@juliangilbey](https://github.com/juliangilbey) * [PR 331](https://github.com/spyder-ide/qtpy/pull/331) - PR: Use QFileDialog.Option to be compatiable with Qt6, by [@frmdstryr](https://github.com/frmdstryr) * [PR 330](https://github.com/spyder-ide/qtpy/pull/330) - PR: Fix typo in constant name, by [@eyllanesc](https://github.com/eyllanesc) * [PR 329](https://github.com/spyder-ide/qtpy/pull/329) - PR: Drop support for Python 3.6, by [@dalthviz](https://github.com/dalthviz) ([297](https://github.com/spyder-ide/qtpy/issues/297)) * [PR 328](https://github.com/spyder-ide/qtpy/pull/328) - PR: Add missing `Qt.MidButton` on PyQt6, by [@dalthviz](https://github.com/dalthviz) ([327](https://github.com/spyder-ide/qtpy/issues/327)) * [PR 326](https://github.com/spyder-ide/qtpy/pull/326) - PR: Add missing `QWebEngineScript` support for PyQt5/6 and PySide2/6, by [@EasyIsrael](https://github.com/EasyIsrael) * [PR 325](https://github.com/spyder-ide/qtpy/pull/325) - PR: Monkey patch `pyside2uic` `UIParser.readResources` for Python 3.9 compatibility, by [@n-elie](https://github.com/n-elie) * [PR 324](https://github.com/spyder-ide/qtpy/pull/324) - PR: Restrict broken Pytest versions to those not affected by the Pytest 7.0.0 import-mode=importlib behavior regression, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([323](https://github.com/spyder-ide/qtpy/issues/323)) In this release 14 pull requests were closed. ---- ## Version 2.0.1 (2022-02-02) ### Issues Closed * [Issue 320](https://github.com/spyder-ide/qtpy/issues/320) - Release QtPy 2.0.1 * [Issue 316](https://github.com/spyder-ide/qtpy/issues/316) - Tests for instance methods alias mapping fix (exec_ vs exec and others) ([PR 317](https://github.com/spyder-ide/qtpy/pull/317) by [@dalthviz](https://github.com/dalthviz)) * [Issue 311](https://github.com/spyder-ide/qtpy/issues/311) - `QtCore.Qt.mightBeRichText` undefined in PySide ([PR 313](https://github.com/spyder-ide/qtpy/pull/313) by [@dalthviz](https://github.com/dalthviz)) * [Issue 306](https://github.com/spyder-ide/qtpy/issues/306) - Qt6: missing unscoped enum values ([PR 314](https://github.com/spyder-ide/qtpy/pull/314) by [@dalthviz](https://github.com/dalthviz)) * [Issue 305](https://github.com/spyder-ide/qtpy/issues/305) - Qt6: exec_ vs. exec ([PR 308](https://github.com/spyder-ide/qtpy/pull/308) by [@kumattau](https://github.com/kumattau)) * [Issue 304](https://github.com/spyder-ide/qtpy/issues/304) - Qt6: QtCharts namespace incompatibility ([PR 315](https://github.com/spyder-ide/qtpy/pull/315) by [@dalthviz](https://github.com/dalthviz)) In this release 6 issues were closed. ### Pull Requests Merged * [PR 319](https://github.com/spyder-ide/qtpy/pull/319) - PR: Promote enum aliases, by [@MatthieuDartiailh](https://github.com/MatthieuDartiailh) * [PR 317](https://github.com/spyder-ide/qtpy/pull/317) - PR: Add missing tests for aliased methods, by [@dalthviz](https://github.com/dalthviz) ([316](https://github.com/spyder-ide/qtpy/issues/316)) * [PR 315](https://github.com/spyder-ide/qtpy/pull/315) - PR: Add `QtCharts` alias for backward compatibility with 1.x, by [@dalthviz](https://github.com/dalthviz) ([304](https://github.com/spyder-ide/qtpy/issues/304)) * [PR 314](https://github.com/spyder-ide/qtpy/pull/314) - PR: Add mapping for missing enum values aliases on `QtCore.Qt`, by [@dalthviz](https://github.com/dalthviz) ([306](https://github.com/spyder-ide/qtpy/issues/306)) * [PR 313](https://github.com/spyder-ide/qtpy/pull/313) - PR: Add missing `QtGui` utility function to `QtCore.Qt` for PySide bindings, by [@dalthviz](https://github.com/dalthviz) ([311](https://github.com/spyder-ide/qtpy/issues/311)) * [PR 312](https://github.com/spyder-ide/qtpy/pull/312) - PR: Add "New features" section for version 2.0 to changelog, by [@ccordoba12](https://github.com/ccordoba12) * [PR 309](https://github.com/spyder-ide/qtpy/pull/309) - PR: Set CI job's timeout to 10 min to force a stalled test to terminate, by [@kumattau](https://github.com/kumattau) * [PR 308](https://github.com/spyder-ide/qtpy/pull/308) - PR: Fix mappings of instance method and slot alias (PyQt6 and PySide6), by [@kumattau](https://github.com/kumattau) ([305](https://github.com/spyder-ide/qtpy/issues/305)) * [PR 307](https://github.com/spyder-ide/qtpy/pull/307) - PR: Add missing imports in QtOpenGL, by [@renefritze](https://github.com/renefritze) In this release 9 pull requests were closed. ---- ## Version 2.0.0 (2021-12-22) ### New features * Add support for PyQt6 and PySide6 with Qt 6 >= 6.2.0 * Add support for QtTextToSpeech. * Drop support for PyQt4, PySide and Python 2. ### Issues Closed * [Issue 300](https://github.com/spyder-ide/qtpy/issues/300) - Release QtPy 2.0.0 * [Issue 286](https://github.com/spyder-ide/qtpy/issues/286) - PySide6 DeprecationWarning of exec_ ([PR 287](https://github.com/spyder-ide/qtpy/pull/287) by [@kumattau](https://github.com/kumattau)) * [Issue 274](https://github.com/spyder-ide/qtpy/issues/274) - SignalInstance, Slot, and Property for Qt6 QtCore * [Issue 270](https://github.com/spyder-ide/qtpy/issues/270) - Port packaging from deprecated legacy builder to current PEP 517 standards ([PR 272](https://github.com/spyder-ide/qtpy/pull/272) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 269](https://github.com/spyder-ide/qtpy/issues/269) - Add CI testing and official support for Python 3.10 ([PR 296](https://github.com/spyder-ide/qtpy/pull/296) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 267](https://github.com/spyder-ide/qtpy/issues/267) - Coveralls shows 0 coverage despite coverage report and runner output looking fine ([PR 268](https://github.com/spyder-ide/qtpy/pull/268) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 258](https://github.com/spyder-ide/qtpy/issues/258) - Compatibility with `QtWidgets.QOpenGLWidget` vs `QtOpenGLWidgets.QOpenGLWidget` ([PR 259](https://github.com/spyder-ide/qtpy/pull/259) by [@kumattau](https://github.com/kumattau)) * [Issue 257](https://github.com/spyder-ide/qtpy/issues/257) - Check import behavior for QtCharts module ([PR 260](https://github.com/spyder-ide/qtpy/pull/260) by [@dalthviz](https://github.com/dalthviz)) * [Issue 253](https://github.com/spyder-ide/qtpy/issues/253) - Declare and test support up to Python 3.9 and PyQt6 ([PR 262](https://github.com/spyder-ide/qtpy/pull/262) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 250](https://github.com/spyder-ide/qtpy/issues/250) - Drop Python 2 support ([PR 251](https://github.com/spyder-ide/qtpy/pull/251) by [@dalthviz](https://github.com/dalthviz)) * [Issue 234](https://github.com/spyder-ide/qtpy/issues/234) - distutils.LooseVersion is being deprecated ([PR 266](https://github.com/spyder-ide/qtpy/pull/266) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 233](https://github.com/spyder-ide/qtpy/issues/233) - PyQt6 support ([PR 294](https://github.com/spyder-ide/qtpy/pull/294) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 232](https://github.com/spyder-ide/qtpy/issues/232) - Add support for `QtTextToSpeech` * [Issue 197](https://github.com/spyder-ide/qtpy/issues/197) - QtTest imports are incomplete ([PR 290](https://github.com/spyder-ide/qtpy/pull/290) by [@kumattau](https://github.com/kumattau)) * [Issue 70](https://github.com/spyder-ide/qtpy/issues/70) - Add QHeaderView.setSectionResize for Qt4 layer * [Issue 66](https://github.com/spyder-ide/qtpy/issues/66) - Add documentation for how to run tests ([PR 277](https://github.com/spyder-ide/qtpy/pull/277) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 62](https://github.com/spyder-ide/qtpy/issues/62) - Add to the readme the importance of qtpy when migrating an application ([PR 301](https://github.com/spyder-ide/qtpy/pull/301) by [@dalthviz](https://github.com/dalthviz)) In this release 17 issues were closed. ### Pull Requests Merged * [PR 303](https://github.com/spyder-ide/qtpy/pull/303) - PR: Fix QFileSystemModel for PyQt6, by [@almarklein](https://github.com/almarklein) * [PR 301](https://github.com/spyder-ide/qtpy/pull/301) - PR: Update README.md adding a line for QtPy usefulness when migrating between Qt bindings/versions, by [@dalthviz](https://github.com/dalthviz) ([62](https://github.com/spyder-ide/qtpy/issues/62)) * [PR 299](https://github.com/spyder-ide/qtpy/pull/299) - PR: 'width' needed for PyQt6, by [@stonebig](https://github.com/stonebig) * [PR 298](https://github.com/spyder-ide/qtpy/pull/298) - PR: Make QLibraryInfo.location work for PyQt6, by [@stonebig](https://github.com/stonebig) * [PR 296](https://github.com/spyder-ide/qtpy/pull/296) - PR: Add support for Python 3.10 on CIs and packaging, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([269](https://github.com/spyder-ide/qtpy/issues/269)) * [PR 294](https://github.com/spyder-ide/qtpy/pull/294) - PR: Add minimum version check for Qt6 >=6.2.0, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([233](https://github.com/spyder-ide/qtpy/issues/233)) * [PR 292](https://github.com/spyder-ide/qtpy/pull/292) - PR: Define Qt/binding versions at top level, fix warnings if versions not found, and fix test dir on CIs, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) * [PR 291](https://github.com/spyder-ide/qtpy/pull/291) - PR: Add QtTextToSpeech Module, by [@kumattau](https://github.com/kumattau) * [PR 290](https://github.com/spyder-ide/qtpy/pull/290) - PR: Import all classes in QtTest module., by [@kumattau](https://github.com/kumattau) ([197](https://github.com/spyder-ide/qtpy/issues/197)) * [PR 287](https://github.com/spyder-ide/qtpy/pull/287) - PR: Map exec_ to their non-deprecated alternatives, by [@kumattau](https://github.com/kumattau) ([286](https://github.com/spyder-ide/qtpy/issues/286)) * [PR 282](https://github.com/spyder-ide/qtpy/pull/282) - PR: Update README sponsors section, by [@dalthviz](https://github.com/dalthviz) * [PR 279](https://github.com/spyder-ide/qtpy/pull/279) - PR: Add back legacy PYQT4 and PYSIDE package-level constants for compat, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) * [PR 278](https://github.com/spyder-ide/qtpy/pull/278) - PR: Update gitignore, gitattributes, license, authors and security policy, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) * [PR 277](https://github.com/spyder-ide/qtpy/pull/277) - PR: Add Contributing Guide based on other Spyder projects, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([66](https://github.com/spyder-ide/qtpy/issues/66)) * [PR 276](https://github.com/spyder-ide/qtpy/pull/276) - PR: Fix regression in FORCE_QT_API behavior from merging PySide6 support, by [@tlambert03](https://github.com/tlambert03) * [PR 273](https://github.com/spyder-ide/qtpy/pull/273) - PR: Avoid future deprecations and decrease general technical debt, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) * [PR 272](https://github.com/spyder-ide/qtpy/pull/272) - PR: Upgrade packaging to avoid legacy/deprecated behavior and follow PEP 517, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([270](https://github.com/spyder-ide/qtpy/issues/270)) * [PR 271](https://github.com/spyder-ide/qtpy/pull/271) - PR: Unscoped enums access for PyQt6 and other missing PyQt6 compatibility changes, by [@dalthviz](https://github.com/dalthviz) * [PR 268](https://github.com/spyder-ide/qtpy/pull/268) - PR: Fix and improve Coveralls reporting, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([267](https://github.com/spyder-ide/qtpy/issues/267)) * [PR 266](https://github.com/spyder-ide/qtpy/pull/266) - PR: Use modern packaging instead of deprecated distutils for version parse, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([235](https://github.com/spyder-ide/qtpy/issues/235), [234](https://github.com/spyder-ide/qtpy/issues/234)) * [PR 264](https://github.com/spyder-ide/qtpy/pull/264) - PR: [PyQt6] Add missing tabStopWidth/setTabStopWidth same as PySide6, by [@kumattau](https://github.com/kumattau) * [PR 263](https://github.com/spyder-ide/qtpy/pull/263) - PR: Remove accidentally-duplicated lines of code in QtCore, by [@kumattau](https://github.com/kumattau) * [PR 262](https://github.com/spyder-ide/qtpy/pull/262) - PR: Unify and cleanup CI infra, improve robustness and test Python 3.9 and PyQt6, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([253](https://github.com/spyder-ide/qtpy/issues/253)) * [PR 260](https://github.com/spyder-ide/qtpy/pull/260) - PR: Reorganize `QtCharts` module import and add missing skip validation for `QtNetworkAuth` test with `PyQt6`, by [@dalthviz](https://github.com/dalthviz) ([257](https://github.com/spyder-ide/qtpy/issues/257)) * [PR 259](https://github.com/spyder-ide/qtpy/pull/259) - PR: [PyQt6] Add exec_/print_, and add QOpenGLWidget/QShortcut to QtWidgets, by [@kumattau](https://github.com/kumattau) ([258](https://github.com/spyder-ide/qtpy/issues/258)) * [PR 256](https://github.com/spyder-ide/qtpy/pull/256) - PR: Fix fallback API, by [@benoit-pierre](https://github.com/benoit-pierre) * [PR 255](https://github.com/spyder-ide/qtpy/pull/255) - PR: Add additional Qt modules and more support and tests for PyQt6/PySide6, by [@jschueller](https://github.com/jschueller) * [PR 254](https://github.com/spyder-ide/qtpy/pull/254) - PR: Add QShortcut class to QtWidgets module, by [@kumattau](https://github.com/kumattau) * [PR 252](https://github.com/spyder-ide/qtpy/pull/252) - PR: Remove Qt4 support, by [@jschueller](https://github.com/jschueller) * [PR 251](https://github.com/spyder-ide/qtpy/pull/251) - PR: Drop Python 2, by [@dalthviz](https://github.com/dalthviz) ([250](https://github.com/spyder-ide/qtpy/issues/250)) * [PR 225](https://github.com/spyder-ide/qtpy/pull/225) - PR: Add support for PySide6, by [@jschueller](https://github.com/jschueller) In this release 31 pull requests were closed. ---- ## Version 1.11.3 (2021/12/03) ### Issues Closed * [Issue 284](https://github.com/spyder-ide/qtpy/issues/284) - Warn if using a deprecated and/or unsupported Qt 5 version ([PR 289](https://github.com/spyder-ide/qtpy/pull/289) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) * [Issue 280](https://github.com/spyder-ide/qtpy/issues/280) - import qtpy raise except when only have PyQt4 ([PR 281](https://github.com/spyder-ide/qtpy/pull/281) by [@dalthviz](https://github.com/dalthviz)) * [Issue 261](https://github.com/spyder-ide/qtpy/issues/261) - Add a deprecation warning for unsupported `Qt` versions and bindings (at least `Qt4`: `PyQt4` and `PySide`) ([PR 283](https://github.com/spyder-ide/qtpy/pull/283) by [@CAM-Gerlach](https://github.com/CAM-Gerlach)) In this release 3 issues were closed. ### Pull Requests Merged * [PR 293](https://github.com/spyder-ide/qtpy/pull/293) - PR: Update RELEASE.md for 1.x version, by [@dalthviz](https://github.com/dalthviz) * [PR 289](https://github.com/spyder-ide/qtpy/pull/289) - PR: Add warning for deprecated/EoL Qt5 & PyQt5/PySide2 versions to fix #284, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([284](https://github.com/spyder-ide/qtpy/issues/284)) * [PR 285](https://github.com/spyder-ide/qtpy/pull/285) - PR: Import Callable and MutableMapping in py3compat for Python 2 compat, by [@davvid](https://github.com/davvid) * [PR 283](https://github.com/spyder-ide/qtpy/pull/283) - PR: Add a warning for developers still running legacy Qt4-based APIs, by [@CAM-Gerlach](https://github.com/CAM-Gerlach) ([261](https://github.com/spyder-ide/qtpy/issues/261)) * [PR 281](https://github.com/spyder-ide/qtpy/pull/281) - PR: Catch `PythonQtError` when trying to do alias for `QtDataVisualization` and dev version correction, by [@dalthviz](https://github.com/dalthviz) ([280](https://github.com/spyder-ide/qtpy/issues/280)) In this release 5 pull requests were closed. ---- ## Version 1.11.2 (2021-09-23) ### Issues Closed * [Issue 248](https://github.com/spyder-ide/qtpy/issues/248) - Missing QtDataVisualization ([PR 249](https://github.com/spyder-ide/qtpy/pull/249) by [@dalthviz](https://github.com/dalthviz)) In this release 1 issue was closed. ### Pull Requests Merged * [PR 249](https://github.com/spyder-ide/qtpy/pull/249) - PR: Add handling for QtDataVisualization when missing, by [@dalthviz](https://github.com/dalthviz) ([248](https://github.com/spyder-ide/qtpy/issues/248)) In this release 1 pull request was closed. ---- ## Version 1.11.1 (2021-09-13) ### Issues Closed * [Issue 245](https://github.com/spyder-ide/qtpy/issues/245) - Importing `qtpy.uic` raises an exception ([PR 246](https://github.com/spyder-ide/qtpy/pull/246) by [@dalthviz](https://github.com/dalthviz)) In this release 1 issue was closed. ### Pull Requests Merged * [PR 246](https://github.com/spyder-ide/qtpy/pull/246) - PR: Wrap `pysideuic` and `pyside2uic` imports since they could be unavailable, by [@dalthviz](https://github.com/dalthviz) ([245](https://github.com/spyder-ide/qtpy/issues/245)) * [PR 244](https://github.com/spyder-ide/qtpy/pull/244) - qtpy/tests/test_uic.py: skip if pyside2uic not installed, by [@AndrewAmmerlaan](https://github.com/AndrewAmmerlaan) In this release 2 pull requests were closed. ---- ## Version 1.11.0 (2021-09-03) ### Issues Closed * [Issue 201](https://github.com/spyder-ide/qtpy/issues/201) - Missing QWebEngineProfile from QtWebEngineWidgets ([PR 242](https://github.com/spyder-ide/qtpy/pull/242) by [@dalthviz](https://github.com/dalthviz)) In this release 1 issue was closed. ### Pull Requests Merged * [PR 243](https://github.com/spyder-ide/qtpy/pull/243) - PR: `QtDataVisualization` backward compatibility handling on Windows, by [@dalthviz](https://github.com/dalthviz) * [PR 242](https://github.com/spyder-ide/qtpy/pull/242) - PR: Add `QtWebEngineWidgets.QWebEngineProfile` for PyQt5 and PySide2, by [@dalthviz](https://github.com/dalthviz) ([201](https://github.com/spyder-ide/qtpy/issues/201)) * [PR 228](https://github.com/spyder-ide/qtpy/pull/228) - PR: Rename QtDatavisualization to use uppercase v, by [@antlarr](https://github.com/antlarr) * [PR 219](https://github.com/spyder-ide/qtpy/pull/219) - PR: Add support for QStyleOptionFrameV3 from PyQt4, by [@PierreRaybaut](https://github.com/PierreRaybaut) * [PR 218](https://github.com/spyder-ide/qtpy/pull/218) - PR: Add QtWinExtras module, by [@phil65](https://github.com/phil65) * [PR 209](https://github.com/spyder-ide/qtpy/pull/209) - PR: Add support for QtSerialPort add-on, by [@Stanowczo](https://github.com/Stanowczo) * [PR 205](https://github.com/spyder-ide/qtpy/pull/205) - PR: Add support for the QtPositioning module, by [@avalentino](https://github.com/avalentino) * [PR 202](https://github.com/spyder-ide/qtpy/pull/202) - PR: Add loadUiType implementation for PySide2, by [@avalentino](https://github.com/avalentino) In this release 8 pull requests were closed. ---- ## Version 1.10.0 (2021-08-17) ### Issues Closed * [Issue 238](https://github.com/spyder-ide/qtpy/issues/238) - PySide2 and Python3.9: xml.etree.ElementTree.Element' object has no attribute 'getchildren * [Issue 222](https://github.com/spyder-ide/qtpy/issues/222) - Imported modules are not respected * [Issue 220](https://github.com/spyder-ide/qtpy/issues/220) - MNT: Stop using ci-helpers in appveyor.yml * [Issue 206](https://github.com/spyder-ide/qtpy/issues/206) - DeprecationWarning for getchildren ([PR 224](https://github.com/spyder-ide/qtpy/pull/224) by [@irrcombat](https://github.com/irrcombat)) * [Issue 198](https://github.com/spyder-ide/qtpy/issues/198) - PyQt4-sip==4.19.13 not supported In this release 5 issues were closed. ### Pull Requests Merged * [PR 241](https://github.com/spyder-ide/qtpy/pull/241) - PR: Update setup.py classifiers, by [@dalthviz](https://github.com/dalthviz) * [PR 230](https://github.com/spyder-ide/qtpy/pull/230) - PR: Fix imported modules logic if 'FORCE_QT_API' is empty, by [@hiaselhans](https://github.com/hiaselhans) * [PR 224](https://github.com/spyder-ide/qtpy/pull/224) - PR: Support python 3.9 `custom_widgets` iteration, by [@irrcombat](https://github.com/irrcombat) ([206](https://github.com/spyder-ide/qtpy/issues/206)) * [PR 215](https://github.com/spyder-ide/qtpy/pull/215) - PR: Slight typo fix, by [@altendky](https://github.com/altendky) * [PR 214](https://github.com/spyder-ide/qtpy/pull/214) - PR: Handle QtCore.SignalInstance/pyqtBoundSignal, by [@altendky](https://github.com/altendky) * [PR 208](https://github.com/spyder-ide/qtpy/pull/208) - PR: Move CI to Github Actions, by [@goanpeca](https://github.com/goanpeca) * [PR 204](https://github.com/spyder-ide/qtpy/pull/204) - PR: Add Python 3.9 compatibility for `collections.abc` module, by [@tirkarthi](https://github.com/tirkarthi) * [PR 199](https://github.com/spyder-ide/qtpy/pull/199) - PR: Add support to PyQt4-sip 4.19.13, by [@milanmatic](https://github.com/milanmatic) In this release 8 pull requests were closed. ---- ## Version 1.9.0 (2019-07-23) ### New features * Add the FORCE_QT_API environment variable to keep using the Qt bindings selected with the QT_API variable and avoid switching to the currently imported bindings. This allows to have applications that import PySide and PyQt bindings at the same time (which is possible if both bindings are compiled for the same Qt version). ### Issues Closed * [Issue 195](https://github.com/spyder-ide/qtpy/issues/195) - Errors in the Qt3D modules with PySide2 5.12.4+ and Python 2 ([PR 196](https://github.com/spyder-ide/qtpy/pull/196)) * [Issue 192](https://github.com/spyder-ide/qtpy/issues/192) - Binding Selection Logic ([PR 194](https://github.com/spyder-ide/qtpy/pull/194)) In this release 2 issues were closed. ### Pull Requests Merged * [PR 196](https://github.com/spyder-ide/qtpy/pull/196) - PR: Don't load Qt3D modules for buggy versions of PySide2 ([195](https://github.com/spyder-ide/qtpy/issues/195)) * [PR 194](https://github.com/spyder-ide/qtpy/pull/194) - PR: Add FORCE_QT_API environment variable ([192](https://github.com/spyder-ide/qtpy/issues/192)) In this release 2 pull requests were closed. ---- ## Version 1.8.0 (2019-06-12) ### New features * Add support for several Qt 3D modules. ### Issues Closed * [Issue 172](https://github.com/spyder-ide/qtpy/issues/172) - Support for Qt3D ([PR 191](https://github.com/spyder-ide/qtpy/pull/191)) In this release 1 issue was closed. ### Pull Requests Merged * [PR 191](https://github.com/spyder-ide/qtpy/pull/191) - PR: Add Qt 3D bindings ([172](https://github.com/spyder-ide/qtpy/issues/172)) In this release 1 pull request was closed. ---- ## Version 1.7.1 (2019-05-05) ### Pull Requests Merged * [PR 189](https://github.com/spyder-ide/qtpy/pull/189) - PR: Skip testing PyQt4 and PySide in Python 3.5 * [PR 188](https://github.com/spyder-ide/qtpy/pull/188) - PR: Trivial maintenance tweaks * [PR 187](https://github.com/spyder-ide/qtpy/pull/187) - PR: Avoid deprecated "from collections import MutableMapping" In this release 3 pull requests were closed. ---- ## Version 1.7.0 (2019-03-16) ### New features * Add support for QtCharts. ### Pull Requests Merged * [PR 186](https://github.com/spyder-ide/qtpy/pull/186) - PR: Generate PyPI long description from README.md * [PR 183](https://github.com/spyder-ide/qtpy/pull/183) - PR: Add QtCharts module support * [PR 182](https://github.com/spyder-ide/qtpy/pull/182) - PR: Prevent warnings for equivalent APIs * [PR 176](https://github.com/spyder-ide/qtpy/pull/176) - PR: Don't warn about bindings change if user did not specify a binding In this release 4 pull requests were closed. ---- ## Version 1.6 (2019-01-12) ### New features * Add support for QtQuickWidgets. ### Issues Closed * [Issue 178](https://github.com/spyder-ide/qtpy/issues/178) - Error when import QtCore.__version__ in PySide2 ([PR 180](https://github.com/spyder-ide/qtpy/pull/180)) In this release 1 issue was closed. ### Pull Requests Merged * [PR 181](https://github.com/spyder-ide/qtpy/pull/181) - PR: Restore QWebEngineSettings for PySide2 * [PR 180](https://github.com/spyder-ide/qtpy/pull/180) - PR: Add QtCore.__version__ for PySide2 ([178](https://github.com/spyder-ide/qtpy/issues/178)) * [PR 179](https://github.com/spyder-ide/qtpy/pull/179) - PR: Add QtQuickWidgets In this release 3 pull requests were closed. ---- ## Version 1.5.2 (2018-10-20) ### Pull Requests Merged * [PR 175](https://github.com/spyder-ide/qtpy/pull/175) - PR: Fix tests * [PR 174](https://github.com/spyder-ide/qtpy/pull/174) - PR: Add support for PySide2.QtOpenGL In this release 2 pull requests were closed. ---- ## Version 1.5.1 (2018-09-18) ### Issues Closed * [Issue 170](https://github.com/spyder-ide/qtpy/issues/170) - Can't catch PythonQtError ([PR 173](https://github.com/spyder-ide/qtpy/pull/173)) In this release 1 issue was closed. ### Pull Requests Merged * [PR 173](https://github.com/spyder-ide/qtpy/pull/173) - PR: Make PythonQtError inherit from RuntimeError to be easily catchable ([170](https://github.com/spyder-ide/qtpy/issues/170)) In this release 1 pull request was closed. ---- ## Version 1.5 (2018-08-25) ### New features * Add support for QtLocation, QtMultimediaWidgets, QtQml, QtQuick, QtWebChannel, QtWebSockets and QtXmlPatterns. * Raise an error when trying to use the wrong combination of macOS and Qt versions. ### Issues Closed * [Issue 155](https://github.com/spyder-ide/qtpy/issues/155) - Add warnings for Qt 5.9 in macOS 10.9 and Qt 5.11 and macOS 10.11 ([PR 168](https://github.com/spyder-ide/qtpy/pull/168)) * [Issue 153](https://github.com/spyder-ide/qtpy/issues/153) - Shim PyQt5 ToPyDateTime for compatibility with PySide2 ([PR 169](https://github.com/spyder-ide/qtpy/pull/169)) * [Issue 123](https://github.com/spyder-ide/qtpy/issues/123) - Wrap QWebChannel module ([PR 157](https://github.com/spyder-ide/qtpy/pull/157)) In this release 3 issues were closed. ### Pull Requests Merged * [PR 169](https://github.com/spyder-ide/qtpy/pull/169) - PR: Shim PyQt5 QDateTime.toPyDateTime to QDateTime.toPython for compatibility with PySide2 ([153](https://github.com/spyder-ide/qtpy/issues/153)) * [PR 168](https://github.com/spyder-ide/qtpy/pull/168) - PR: Raise error when trying to use the wrong combination of macOS and Qt versions ([155](https://github.com/spyder-ide/qtpy/issues/155)) * [PR 167](https://github.com/spyder-ide/qtpy/pull/167) - PR: Migrate to CircleCI 2.0 * [PR 163](https://github.com/spyder-ide/qtpy/pull/163) - PR: Add QtLocation * [PR 162](https://github.com/spyder-ide/qtpy/pull/162) - PR: Update readme to remove funding appeal, harmonize with other readmes and minor fixes * [PR 161](https://github.com/spyder-ide/qtpy/pull/161) - PR: Fix pyside2 wheels install * [PR 157](https://github.com/spyder-ide/qtpy/pull/157) - PR: Add more Qt modules ([123](https://github.com/spyder-ide/qtpy/issues/123)) In this release 7 pull requests were closed. ---- ## Version 1.4.2 (2018-05-06) ### Issues Closed * [Issue 150](https://github.com/spyder-ide/qtpy/issues/150) - PySide2-5.11 alpha2 compatibility ([PR 151](https://github.com/spyder-ide/qtpy/pull/151)) * [Issue 144](https://github.com/spyder-ide/qtpy/issues/144) - ValueError: API 'QString' has already been set to version 1 at line 141 in __init__.py file. ([PR 152](https://github.com/spyder-ide/qtpy/pull/152)) In this release 2 issues were closed. ### Pull Requests Merged * [PR 152](https://github.com/spyder-ide/qtpy/pull/152) - PR: Catch ValueError when trying to set sip API ([144](https://github.com/spyder-ide/qtpy/issues/144)) * [PR 151](https://github.com/spyder-ide/qtpy/pull/151) - PR: Add a preventive change for PySide-5.11a2 ([150](https://github.com/spyder-ide/qtpy/issues/150)) * [PR 149](https://github.com/spyder-ide/qtpy/pull/149) - PR: Use Qt official wheels to run tests for PySide2 * [PR 148](https://github.com/spyder-ide/qtpy/pull/148) - PR: Remove internal conda recipe In this release 4 pull requests were closed. ---- ## Version 1.4.1 (2018-04-28) ### New features * Show a warning when QT_API is changed automatically by qtpy. ### Issues Closed * [Issue 145](https://github.com/spyder-ide/qtpy/issues/145) - Raise a warning if QT_API value is changed automatically ([PR 146](https://github.com/spyder-ide/qtpy/pull/146)) * [Issue 142](https://github.com/spyder-ide/qtpy/issues/142) - On OSX qtpy applications are forcing discrete graphics ([PR 143](https://github.com/spyder-ide/qtpy/pull/143)) In this release 2 issues were closed. ### Pull Requests Merged * [PR 147](https://github.com/spyder-ide/qtpy/pull/147) - PR: Add better compatibility with PySide2 * [PR 146](https://github.com/spyder-ide/qtpy/pull/146) - PR: Add a warning if API is changed automatically ([145](https://github.com/spyder-ide/qtpy/issues/145)) * [PR 143](https://github.com/spyder-ide/qtpy/pull/143) - PR: Avoid using PyQt5.Qt, which imports unneeded stuff and forces discrete GPU on OSX ([142](https://github.com/spyder-ide/qtpy/issues/142)) In this release 3 pull requests were closed. ---- ## Version 1.4 (2018-03-11) ### New features * Add support for QtHelp and QtSql * Use already imported bindings ### Issues Closed * [Issue 138](https://github.com/spyder-ide/qtpy/issues/138) - If one binding has already been imported, then qtpy should just use it ([PR 139](https://github.com/spyder-ide/qtpy/pull/139)) * [Issue 135](https://github.com/spyder-ide/qtpy/issues/135) - Add Wrapper for QtSql [feature request] ([PR 136](https://github.com/spyder-ide/qtpy/pull/136)) * [Issue 131](https://github.com/spyder-ide/qtpy/issues/131) - Methods missing from QStandardPaths when QT_API=pyqt4 * [Issue 127](https://github.com/spyder-ide/qtpy/issues/127) - Add Wrapper for QtHelp [feature request] ([PR 128](https://github.com/spyder-ide/qtpy/pull/128)) In this release 4 issues were closed. ### Pull Requests Merged * [PR 140](https://github.com/spyder-ide/qtpy/pull/140) - PR: Pin PyQt5 to 5.9.2 in CircleCI because 5.10 is generating segfaults * [PR 139](https://github.com/spyder-ide/qtpy/pull/139) - PR: If a Qt binding is already imported, then use it. ([138](https://github.com/spyder-ide/qtpy/issues/138)) * [PR 136](https://github.com/spyder-ide/qtpy/pull/136) - PR: Add QtSql wrapper (incl. test) ([135](https://github.com/spyder-ide/qtpy/issues/135)) * [PR 132](https://github.com/spyder-ide/qtpy/pull/132) - PR: Changes to QDesktop split * [PR 128](https://github.com/spyder-ide/qtpy/pull/128) - PR: Add QtHelp Wrapper ([127](https://github.com/spyder-ide/qtpy/issues/127)) In this release 5 pull requests were closed. ---- ## Version 1.3.1 (2017-08-21) ### Bugs fixed **Issues** * [Issue 129](https://github.com/spyder-ide/qtpy/issues/129) - Spurious cache files in PyPI tarball * [Issue 119](https://github.com/spyder-ide/qtpy/issues/119) - Importing qtpy should not raise exceptions In this release 2 issues were closed **Pull requests** * [PR 130](https://github.com/spyder-ide/qtpy/pull/130) - PR: No cache files included in the release tarball * [PR 126](https://github.com/spyder-ide/qtpy/pull/126) - PR: Remove Quantified Code badge because the service doesn't exist anymore * [PR 121](https://github.com/spyder-ide/qtpy/pull/121) - PR: Warn if QHeaderView deprecated methods are used In this release 3 pull requests were merged ---- ## Version 1.3 (2017-08-12) ### New features * Add support for PySide2 and PyQt 4.6 ### Bugs fixed **Issues** * [Issue 124](https://github.com/spyder-ide/qtpy/issues/124) - Typo in readme title * [Issue 111](https://github.com/spyder-ide/qtpy/issues/111) - Update Readme for 1.3 release * [Issue 110](https://github.com/spyder-ide/qtpy/issues/110) - Add tests for untested modules * [Issue 101](https://github.com/spyder-ide/qtpy/issues/101) - Missing: QtOpenGL Module * [Issue 89](https://github.com/spyder-ide/qtpy/issues/89) - QDesktopServices split into QDesktopServices and QStandardPaths * [Issue 57](https://github.com/spyder-ide/qtpy/issues/57) - qInstallMessageHandler <-> qInstallMsgHandler * [Issue 15](https://github.com/spyder-ide/qtpy/issues/15) - Feature Request: PySide2 support In this release 7 issues were closed **Pull requests** * [PR 125](https://github.com/spyder-ide/qtpy/pull/125) - PR: Fix typo in Readme. * [PR 117](https://github.com/spyder-ide/qtpy/pull/117) - PR: Add compatibility for the rename of qInstallMsgHandler to qInstallMessageHandler * [PR 115](https://github.com/spyder-ide/qtpy/pull/115) - PR: Update Readme to reflect that we actually use the PySide2 layout * [PR 114](https://github.com/spyder-ide/qtpy/pull/114) - PR: Update Readme to mention that we now support PySide2. * [PR 113](https://github.com/spyder-ide/qtpy/pull/113) - PR: Add tests for Qtdesigner, QtNetwork, QtPrintSupport, QtSvg and QtTest. * [PR 112](https://github.com/spyder-ide/qtpy/pull/112) - PR: Follow QStandardPaths location in Qt5 for PyQt4/PySide * [PR 109](https://github.com/spyder-ide/qtpy/pull/109) - PR: Add a coveragerc file * [PR 106](https://github.com/spyder-ide/qtpy/pull/106) - PR: Add support for PyQt 4.6 * [PR 102](https://github.com/spyder-ide/qtpy/pull/102) - PR: Add a new QtOpenGL module * [PR 84](https://github.com/spyder-ide/qtpy/pull/84) - PR: Add PySide2 support In this release 10 pull requests were merged ---- ## Version 1.2.1 (2017/01/21) ### Bugs fixed **Pull requests** * [PR 98](https://github.com/spyder-ide/qtpy/pull/98) - PR: Don't use Travis to test macOS because it slows down the entire spyder-ide organization * [PR 97](https://github.com/spyder-ide/qtpy/pull/97) - PR: Update Appveyor badge in Readme because of moving to an org account * [PR 94](https://github.com/spyder-ide/qtpy/pull/94) - PR: Include test suite in sdist In this release 3 pull requests were merged ---- ## Version 1.2 (2017/01/08) ### New features * Add support for QtMultimedia * Use relative imports so its vendored more easily ### Bugs fixed **Issues** * [Issue 83](https://github.com/spyder-ide/qtpy/issues/83) - Include core doc files in PyPi releases * [Issue 78](https://github.com/spyder-ide/qtpy/issues/78) - Request for a new bugfix release * [Issue 75](https://github.com/spyder-ide/qtpy/issues/75) - Missing copyright headers * [Issue 67](https://github.com/spyder-ide/qtpy/issues/67) - uic.loadUiType is missing * [Issue 64](https://github.com/spyder-ide/qtpy/issues/64) - QHeaderView.setSectionResizeMode * [Issue 49](https://github.com/spyder-ide/qtpy/issues/49) - QtMultimedia support In this release 6 issues were closed **Pull requests** * [PR 93](https://github.com/spyder-ide/qtpy/pull/93) - Restore uic full namespace for PyQt5 and PyQt4 * [PR 92](https://github.com/spyder-ide/qtpy/pull/92) - Add missing copyright header in _patch/qheaderview.py * [PR 91](https://github.com/spyder-ide/qtpy/pull/91) - Use star imports in QtSvg again instead of direct ones (reverts PR #55) * [PR 88](https://github.com/spyder-ide/qtpy/pull/88) - PR: Add manifest * [PR 74](https://github.com/spyder-ide/qtpy/pull/74) - Move QStringListModel to QtCore * [PR 71](https://github.com/spyder-ide/qtpy/pull/71) - PR: Use relative imports so its vendored more easily * [PR 65](https://github.com/spyder-ide/qtpy/pull/65) - Introduce renamed methods of QHeaderView in PyQt4 and PySide * [PR 59](https://github.com/spyder-ide/qtpy/pull/59) - Don't install qtpy as a conda package in CircleCI * [PR 58](https://github.com/spyder-ide/qtpy/pull/58) - Remove reference to how qtpy is pronounced in README * [PR 55](https://github.com/spyder-ide/qtpy/pull/55) - PR: Add explicit imports to QtSvg module * [PR 50](https://github.com/spyder-ide/qtpy/pull/50) - Add support for QtMultimedia In this release 11 pull requests were merged ---- ## Version 1.1.2 (2016-08-08) ### Bugfixes **Pull requests** * [PR 54](https://github.com/spyder-ide/qtpy/pull/54) - PR: Fix/ci * [PR 53](https://github.com/spyder-ide/qtpy/pull/53) - PR: Move tests to module so they can be run when installed * [PR 52](https://github.com/spyder-ide/qtpy/pull/52) - PR: Update readme * [PR 51](https://github.com/spyder-ide/qtpy/pull/51) - PR: Add circle ci * [PR 47](https://github.com/spyder-ide/qtpy/pull/47) - Remove PyQt variant symbols from QtCore * [PR 46](https://github.com/spyder-ide/qtpy/pull/46) - del QtWidgets.QStyleOptionViewItemV4 * [PR 45](https://github.com/spyder-ide/qtpy/pull/45) - Allow QT_API values that are not completely in lower case In this release 7 pull requests were merged ---- ## Version 1.1.1 (2016-07-01) ### Bugfixes **Pull requests** * [PR 44](https://github.com/spyder-ide/qtpy/pull/44) - Make qtpy to set the QT_API environment variable In this release 1 pull requests were merged --- ## Version 1.1 (2016-06-30) ### New features * Make importing `qtpy` thread-safe * Add a uic module to make loadUI work for PySide * Add QtTest support for PySide ### Bugfixes **Issues** * [Issue 42](https://github.com/spyder-ide/qtpy/issues/42) - Wrong old PyQt4 version check * [Issue 21](https://github.com/spyder-ide/qtpy/issues/21) - Patch QComboBox with PySide? * [Issue 16](https://github.com/spyder-ide/qtpy/issues/16) - Add loadUI functionality In this release 3 issues were closed **Pull requests** * [PR 43](https://github.com/spyder-ide/qtpy/pull/43) - Don't check PyQt version with qtpy's version for old PyQt versions * [PR 41](https://github.com/spyder-ide/qtpy/pull/41) - `qtpy.__version__` should be QtPy version, not Qt version * [PR 40](https://github.com/spyder-ide/qtpy/pull/40) - Mention qt-helpers in README.md, and add myself to AUTHORS.md * [PR 39](https://github.com/spyder-ide/qtpy/pull/39) - Fix remaining segmentation fault that occurs with the patched QComboBox in PySide * [PR 38](https://github.com/spyder-ide/qtpy/pull/38) - QtTest for PySide * [PR 37](https://github.com/spyder-ide/qtpy/pull/37) - Automatically load custom widget classes when using PySide * [PR 33](https://github.com/spyder-ide/qtpy/pull/33) - Ignore case for QT_API env variable in qtpy submodules * [PR 32](https://github.com/spyder-ide/qtpy/pull/32) - Remove QItemSelectionModel from QtWidgets for PyQt4 and PySide * [PR 31](https://github.com/spyder-ide/qtpy/pull/31) - Add compatibility for QItemSelectionModel * [PR 29](https://github.com/spyder-ide/qtpy/pull/29) - Use ci-helpers (from Astropy) for CI and enable AppVeyor * [PR 28](https://github.com/spyder-ide/qtpy/pull/28) - Make tests.py into proper unit test, and add Qt version info to pytest header * [PR 27](https://github.com/spyder-ide/qtpy/pull/27) - Make sure loadUi is available * [PR 25](https://github.com/spyder-ide/qtpy/pull/25) - Add patched version of QComboBox In this release 13 pull requests were merged --- ## Version 1.0.2 (2016-06-02) ### New features * Add a WEBENGINE constant to QtWebEngineWidgets, which is True if Qt 5 comes with the WebEngine module and False otherwise. ### Bugfixes **Pull requests** * [PR 24](https://github.com/spyder-ide/qtpy/pull/24) - Add constant to QtWebEngineWidgets to see if we are using WebEngine or WebKit * [PR 23](https://github.com/spyder-ide/qtpy/pull/23) - Fix "Prefer `format()` over string interpolation operator" issue In this release 2 pull requests were merged --- ## Version 1.0.1 (2016-04-10) ### Bugfixes **Issues** * [Issue 18](https://github.com/spyder-ide/qtpy/issues/18) - QIntValidator left in QtWidgets, should be in QtGui In this release 1 issues were closed **Pull requests** * [PR 19](https://github.com/spyder-ide/qtpy/pull/19) - Import QIntValidator in QtGui and remove it from QtWidgets In this release 1 pull requests were merged ---- ## Version 1.0 (2016-03-22) * Add QtWebEngineWidgets module for Qt 5.6. This module replaces the previous QtWebKit one. * Import the right objects in QtGui, QtWidgets and QtCore * Add a QtPrintSupport module --- ## Version 0.1.3 (2015-12-30) * Add tests and continuous integration ## Version 0.1.2 (2015-03-01) * First release git-cola-4.6.1/extras/qtpy/LICENSE.txt000066400000000000000000000021311457126473700173640ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2011- QtPy contributors and others (see AUTHORS.md) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. git-cola-4.6.1/extras/sphinxtogithub/000077500000000000000000000000001457126473700176265ustar00rootroot00000000000000git-cola-4.6.1/extras/sphinxtogithub/__init__.py000066400000000000000000000012361457126473700217410ustar00rootroot00000000000000"""Script for preparing the html output of the Sphinx documentation system for github pages. """ VERSION = (1, 1, 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-4.6.1/extras/sphinxtogithub/sphinxtogithub.py000066400000000000000000000240411457126473700232600ustar00rootroot00000000000000#! /usr/bin/env python from optparse import OptionParser import os import sys import shutil import codecs def stdout(msg): sys.stdout.write(msg + '\n') class DirHelper: 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: def __init__(self, open_, path_join, move, exists): self.open_ = open_ self.path_join = path_join self.move = move self.exists = exists class Replacer: """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: """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, 'r').read() for replacer in self.replacers: text = replacer.process(text) self.opener(self.name, 'w').write(text) class Remover: def __init__(self, exists, remove): self.exists = exists self.remove = remove def __call__(self, name): if self.exists(name): self.remove(name) class ForceRename: 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: 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: """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 = str(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: 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: 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: """ 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: """ Layout class that does nothing when asked to process """ def process(self): pass class LayoutFactory: """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): 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, _, 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, _, 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 app.builder.name not in ('html', 'dirhtml'): return if not app.config.sphinx_to_github: if app.config.sphinx_to_github_verbose: stdout('Sphinx-to-github: Disabled, doing nothing.') return if exception: if app.config.sphinx_to_github_verbose: msg = 'Sphinx-to-github: ' 'Exception raised in main build, doing nothing.' stdout(msg) return dir_helper = DirHelper(os.path.isdir, os.listdir, os.walk, shutil.rmtree) file_helper = FileSystemHelper( lambda f, mode: codecs.open(f, mode, app.config.sphinx_to_github_encoding), 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""" app.add_config_value('sphinx_to_github', True, '') app.add_config_value('sphinx_to_github_verbose', True, '') app.add_config_value('sphinx_to_github_encoding', 'utf-8', '') 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', ) parser.add_option( '-e', '--encoding', action='store', dest='encoding', default='utf-8', help='Encoding for reading and writing files', ) 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( lambda f, mode: codecs.open(f, mode, opts.encoding), 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-4.6.1/garden.yaml000066400000000000000000000302651457126473700153730ustar00rootroot00000000000000# Use "cargo install garden-tools" to install garden https://gitlab.com/garden-rs/garden # # # Installation # garden install # Install git-cola to the installation ${prefix} # garden doc # Generate documentation: html + manual pages # garden install docs # Install documentation # # # Variables can be overridden using "-D name=value", e.g.: # garden -D prefix=$PWD/dist install docs # garden -D DESTDIR=/tmp/stage -D prefix=/usr/local install # # # Development # garden test # Run the test suite # garden fmt # Format code using "cercis" # garden html # Generate documentation: html only # garden man # Generate documentation: manual pages only # garden pot # Regenerate git-cola.pot with new translations # garden po # Update .po files with new translations from git-cola.pot # garden pages # Install the pages/ website documentation. # # # macOS # garden macos/app # Build a git-cola.app bundle # # # Related Projects # garden grow pages # Clone the Git Cola homepage # garden grow fedora # Clone the Fedora packaging # garden grow deb # Clone the Debian packaging # garden grow flatpak # Clone the Flatpak packaging trees: git-cola: description: The highly-caffeinated Git GUI path: "${GARDEN_CONFIG_DIR}" url: "git@gitlab.com:git-cola/git-cola.git" commands: doc: ${GARDEN} -vv cmd docs html man -- "$@" dev: ${PYTHON} -m venv --system-site-packages ${env_dir} dev>: - dev/extras - dev/development - dev/build dev/build: ${activate} ${PIP} install --editable '.[build]' dev/development: ${activate} ${PIP} install --editable '.[docs,dev,testing]' dev/extras: ${activate} ${PIP} install --editable '.[extras]' dev/pyqt6: ${activate} ${PIP} install --editable '.[pyqt6]' dev/env: ${activate} "$@" check>: - test - check/fmt - doc check/fmt: garden fmt -- --check fmt: | ${activate} ${CERCIS} --version ${GIT} ls-files -- '*.py' | ${GREP} -v ^qtpy | ${XARGS} ${CERCIS} "$@" html: ${GARDEN} -vv html docs install: | if test -n "${DESTDIR}" then pip_root="--root=${DESTDIR}" export DESTDIR="${DESTDIR}" fi ${PIP} install --disable-pip-version-check $pip_root --prefix=${prefix} "$@" . i18n>: - pot - po macos/app: | ${MKDIR_P} ${cola_app}/Contents/MacOS ${MKDIR_P} ${cola_app_resources} ${PYTHON} -m venv ${cola_app_resources} source ${cola_app_resources}/bin/activate ${PIP} install '.[docs,extras,pyqt6]' ${CP} contrib/darwin/Info.plist contrib/darwin/PkgInfo ${cola_app}/Contents if test -n "${cola_full_version}" then ${SED} -i -e s/0.0.0.0/${cola_full_version}/ ${cola_app}/Contents/Info.plist fi ${SED} -i -e s/0.0.0/${cola_version}/ ${cola_app}/Contents/Info.plist ${CP} contrib/darwin/git-cola ${cola_app}/Contents/MacOS ${CP} contrib/darwin/git-cola.icns ${cola_app}/Contents/Resources ${GARDEN} -vv -D prefix=${cola_app_resources} install ${GARDEN} -vv doc ${GARDEN} -vv -D prefix=${cola_app_resources} install docs man: ${GARDEN} -vv man docs po: | for po in cola/i18n/*.po do ${MSGMERGE} \ --no-wrap \ --no-fuzzy-matching \ --sort-output \ --output-file $$po.new \ $$po \ cola/i18n/git-cola.pot mv $$po.new $$po done pot: | ${XGETTEXT} \ --language=Python \ --keyword=N_ \ --no-wrap \ --omit-header \ --sort-output \ --output-dir cola/i18n \ --output git-cola.pot \ cola/*.py \ cola/*/*.py pages<: doc pages: ${GARDEN} -vv -D prefix=${TREE_PATH}/pages install docs "$@" run: ${activate} ./bin/git-cola "$@" run/qt6: ${activate} QT_API=PyQt6 ./bin/git-cola "$@" test: ${activate} ${PYTEST_CMD} cola test "$@" tox: ${TOX} run "$@" tox/check: ${TOX} run -e check "$@" gitconfig: remote.publish.pushurl: - "git@gitlab.com:git-cola/git-cola.git" - "git@github.com:git-cola/git-cola.git" remotes: BaumiCoder: "https://github.com/BaumiCoder/git-cola.git" DasaniT: "https://github.com/DasaniT/git-cola.git" Mailaender: "https://github.com/Mailaender/git-cola.git" Mithil467: "https://github.com/Mithil467/git-cola.git" NielBuys: "https://github.com/NielBuys/git-cola.git" WNguyen14: "https://github.com/WNguyen14/git-cola.git" abid1998: "https://github.com/abid1998/git-cola.git" achernet: "https://github.com/achernet/git-cola.git" axel-h: "https://github.com/axel-h/git-cola.git" bearsh: "https://github.com/bearsh/git-cola.git" bensmrs: "https://github.com/bensmrs/git-cola.git" bobvanderlinden: "https://github.com/bobvanderlinden/git-cola.git" brccabral: "https://github.com/brccabral/git-cola.git" davvid: "git@github.com:davvid/git-cola.git" dschwoerer: "https://github.com/dschwoerer/git-cola.git" florisla: "https://github.com/florisla/git-cola.git" fu7mu4: "https://github.com/fu7mu4/git-cola.git" gdebure: "https://github.com/gdebure/git-cola.git" github: "git@github.com:git-cola/git-cola.git" guoyunhe: "https://github.com/guoyunhe/git-cola.git" gyuris: "https://github.com/gyuris/git-cola.git" haffmans: "https://github.com/haffmans/git-cola.git" harmathy: "https://github.com/harmathy/git-cola.git" hsoft: "https://github.com/hsoft/git-cola.git" jamie-pate: "https://github.com/jamie-pate/git-cola.git" kenyuy: "https://github.com/kenyuy/git-cola.git" kisaragi-hiu: "https://github.com/kisaragi-hiu/git-cola.git" kneirinck: "https://github.com/kneirinck/git-cola.git" kurtmckee: "https://github.com/kurtmckee/git-cola.git" laerreal: "https://github.com/laerreal/git-cola.git" lah7: "https://github.com/lah7/git-cola.git" living180: "https://github.com/living180/git-cola.git" ljhcage: "https://github.com/ljhcage/git-cola.git" malpas: "https://github.com/malpas/git-cola.git" melkecelioglu: "https://github.com/melkecelioglu/git-cola.git" milestone12: "https://github.com/milestone12/git-cola.git" mmargoliono: "https://github.com/mmargoliono/git-cola" mp-chet: "https://github.com/mp-chet/git-cola.git" nakanoi: "https://github.com/nakanoi/git-cola.git" nandalopes: "https://github.com/nandalopes/git-cola.git" OriShalhon: "https://github.com/OriShalhon/git-cola.git" pilarmolinalopez: "https://github.com/pilarmolinalopez/git-cola.git" quintusfelix: "https://github.com/quintusfelix/git-cola.git" rafaelreuber: "https://github.com/rafaelreuber/git-cola.git" scop: "https://github.com/scop/git-cola.git" sergei-dyshel: "https://github.com/sergei-dyshel/git-cola.git" sthalik: "https://github.com/sthalik/git-cola.git" skunkwerks: "https://github.com/skunkwerks/git-cola.git" takluyver: "https://github.com/takluyver/git-cola.git" thk123: "https://github.com/thk123/git-cola.git" timgates42: "https://github.com/timgates42/git-cola.git" vdragon: "https://github.com/Vdragon/git-cola.git" victorhck: "https://github.com/victorhck/git-cola.git" virtualstaticvoid: "https://github.com/virtualstaticvoid/git-cola.git" wm4: "https://github.com/wm4/git-cola.git" wojnilowicz: "https://github.com/wojnilowicz/git-cola.git" yaellevy: "https://github.com/yaellevy/git-cola.git" deb: description: Debian packaging url: "git@gitlab.com:git-cola/git-cola-debian.git" remotes: davvid: "git@github.com:davvid/git-cola-debian.git" docs: description: Sphinx documentation variables: env_dir: ../env3 commands: clean: rm -fr _build doctest: ${activate} ${SPHINX_CMD} -b doctest . _build/doctest "$@" html: ${activate} ${SPHINX_CMD} -b html . _build/html "$@" man: ${activate} ${SPHINX_CMD} -b man . _build/man "$@" linkcheck: ${activate} ${SPHINX_CMD} -b linkcheck . _build/linkcheck "$@" install: | ${MKDIR_P} ${DESTDIR}${docdir} ${INSTALL} -m 644 *.html ${DESTDIR}${docdir} ${INSTALL} -m 644 *.rst ${DESTDIR}${docdir} # HTML documentation ${MKDIR_P} ${DESTDIR}${htmldir} ${RSYNC_CMD} _build/html/ ${DESTDIR}${htmldir}/ # Manual pages ${MKDIR_P} ${DESTDIR}${mandir} ${INSTALL} -m 644 _build/man/git-cola.1 ${DESTDIR}${mandir} ${INSTALL} -m 644 _build/man/git-dag.1 ${DESTDIR}${mandir} fedora: description: Fedora packaging url: "https://src.fedoraproject.org/rpms/git-cola.git" remotes: git-cola: "git@gitlab.com:git-cola/git-cola-fedora.git" davvid: "git@github.com:davvid/git-cola-fedora.git" flatpak: description: Flatpak packaging url: "git@github.com:flathub/com.github.git_cola.git-cola.git" variables: app-id: com.github.git_cola.git-cola commands: build: flatpak-builder "$@" --user "${prefix}" ${app-id}.yml check: flatpak run --command=flatpak-builder-lint org.flatpak.Builder "$@" --exceptions builddir "${prefix}" install: flatpak-builder "$@" --install --user "${prefix}" ${app-id}.yml run: flatpak run ${app-id} setup: | flatpak remote-add --user --if-not-exists \ flathub https://flathub.org/repo/flathub.flatpakrepo flatpak install --user \ org.flatpak.Builder/x86_64 \ org.kde.Sdk/x86_64/5.15-23.08 \ org.kde.Platform/x86_64/5.15-23.08 \ com.riverbankcomputing.PyQt.BaseApp/x86_64/5.15-23.08 pages: description: "Git Cola's homepage" url: "git@gitlab.com:git-cola/git-cola.gitlab.io.git" remotes: github: "git@github.com:git-cola/git-cola.github.io.git" ls-jad-elkik: "git://github.com/ls-jad-elkik/git-cola.github.io.git" lz-coder: "https://github.com/lz-coder/git-cola.github.io.git" gitconfig: remote.origin.pushurl: - "git@gitlab.com:git-cola/git-cola.gitlab.io.git" - "git@github.com:git-cola/git-cola.github.io.git" commands: build: ${JEKYLL} build --destination build "$@" links: - "https://git-cola.gitlab.io" - "https://git-cola.github.io" commands: commit: git commit "$@" diff: git diff "$@" diffs: git diff --staged "$@" fetch: git fetch "$@" stat: git status --short "$@" status: git status "$@" stage: git add -u "$@" push: git push "$@" pull: git pull --ff-only "$@" # Variables can be overridden externally using "garden -D name=value ...". variables: # Traditional DESTDIR + prefix variables DESTDIR: "" prefix: ${GARDEN_CONFIG_DIR}/dist docdir: ${prefix}/share/doc/git-cola htmldir: ${docdir}/html mandir: ${prefix}/share/man/man1 cola_app: ${TREE_PATH}/git-cola.app cola_app_resources: ${cola_app}/Contents/Resources cola_full_version: $ ./bin/git-cola version --brief cola_version: $ ${SED} -e "s/VERSION = '\(.*\)'/\1/" cola/_version.py is_virtualenv: | $ ${PYTHON} -c ' import os, sys if sys.prefix != sys.base_prefix or os.environ.get("VIRTUAL_ENV"): print("true") ' env_dir: env3 activate: | if test -z "${is_virtualenv}" && test -f "${env_dir}/bin/activate" then source "${env_dir}/bin/activate" fi # External commands and options CERCIS: cercis CP: cp GARDEN: garden GIT: git GREP: grep INSTALL: install JEKYLL: jekyll MKDIR_P: mkdir -p MSGMERGE: msgmerge PIP: pip PYTEST: ${activate} ${PYTHON} -B -m pytest PYTEST_OPTIONS: $ test "$(uname -s)" != "Linux" && printf '%s' --ignore=cola/inotify.py PYTEST_CMD: ${PYTEST} ${PYTEST_OPTIONS} -p no:cacheprovider PYTHON: python3 RSYNC: rsync RSYNC_CMD: ${RSYNC} -r --delete --exclude=.buildinfo SED: sed SPHINX: ${PYTHON} -m sphinx SPHINX_CMD: ${SPHINX} -d _build/doctrees -a TOX: tox XARGS: xargs XGETTEXT: xgettext git-cola-4.6.1/pynsist.cfg000066400000000000000000000075771457126473700154530ustar00rootroot00000000000000# https://pynsist.readthedocs.io/en/latest/cfgfile.html [Application] name=git-cola version=4.6.1 entry_point=cola.main:shortcut_launch icon=cola/icons/git-cola.ico extra_preamble=contrib/win32/pynsist-preamble.py console=false # We might want to pursue shell integration, which would at minimum require a # custom template. https://pynsist.readthedocs.io/en/latest/design.html # [Build] # nsi_template=contrib/win32/pynsist-template.nsi [Python] version=3.9.13 bitness=64 include_msvcrt=true [Shortcut git-dag] entry_point=cola.dag:shortcut_launch icon=cola/icons/git-cola.ico extra_preamble=contrib/win32/pynsist-preamble.py [Command git-cola] entry_point=cola.main:main extra_preamble=contrib/win32/pynsist-preamble.py [Command git-cola-sequence-editor] entry_point=cola.sequenceeditor:main extra_preamble=contrib/win32/pynsist-preamble.py [Command git-dag] entry_point=cola.dag:main extra_preamble=contrib/win32/pynsist-preamble.py # To identify unused DLL files to exclude, we can use Process Explorer. # https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer # Run git-cola and use the Help->Keyboard Shortcut feature and the DAG feature. # Take note of the loaded DLL files under the pythonw.exe process. # This will also include windows and python DLL files. # Sorting the DLL files list under Process Explorer by path will list # the git-cola DLL files first together. # This gives a list of necessary DLLs and the rest can be excluded. [Include] packages=cola pypi_wheels= packaging==21.3 PyQt5==5.15.4 PyQt5-Qt5==5.15.2 PyQt5-sip==12.8.1 pywin32==306 QtPy==2.4.1 send2trash==1.8.2 files=share/ exclude= pkgs/PyQt5/Qt/bin/Qt5Bluetooth.dll pkgs/PyQt5/Qt/bin/Qt5DBus.dll pkgs/PyQt5/Qt/bin/Qt5Designer.dll pkgs/PyQt5/Qt/bin/Qt5Help.dll pkgs/PyQt5/Qt/bin/Qt5Location.dll pkgs/PyQt5/Qt/bin/Qt5Multimedia.dll pkgs/PyQt5/Qt/bin/Qt5MultimediaWidgets.dll pkgs/PyQt5/Qt/bin/Qt5NetworkAuth.dll pkgs/PyQt5/Qt/bin/Qt5Nfc.dll pkgs/PyQt5/Qt/bin/Qt5Positioning.dll pkgs/PyQt5/Qt/bin/Qt5PositioningQuick.dll pkgs/PyQt5/Qt/bin/Qt5PrintSupport.dll pkgs/PyQt5/Qt/bin/Qt5Qml.dll pkgs/PyQt5/Qt/bin/Qt5QmlModels.dll pkgs/PyQt5/Qt/bin/Qt5QmlWorkerScript.dll pkgs/PyQt5/Qt/bin/Qt5Quick.dll pkgs/PyQt5/Qt/bin/Qt5QuickControls2.dll pkgs/PyQt5/Qt/bin/Qt5QuickParticles.dll pkgs/PyQt5/Qt/bin/Qt5QuickShapes.dll pkgs/PyQt5/Qt/bin/Qt5QuickTemplates.dll pkgs/PyQt5/Qt/bin/Qt5QuickTemplates2.dll pkgs/PyQt5/Qt/bin/Qt5QuickTest.dll pkgs/PyQt5/Qt/bin/Qt5QuickWidgets.dll pkgs/PyQt5/Qt/bin/Qt5RemoteObjects.dll pkgs/PyQt5/Qt/bin/Qt5Sensors.dll pkgs/PyQt5/Qt/bin/Qt5SerialPort.dll pkgs/PyQt5/Qt/bin/Qt5Sql.dll pkgs/PyQt5/Qt/bin/Qt5Test.dll pkgs/PyQt5/Qt/bin/Qt5WebSockets.dll pkgs/PyQt5/Qt/bin/Qt5WinExtras.dll pkgs/PyQt5/Qt/bin/Qt5Xml.dll pkgs/PyQt5/Qt/bin/Qt5XmlPatterns.dll pkgs/PyQt5/Qt/bin/concrt140.dll pkgs/PyQt5/Qt/bin/d3dcompiler_47.dll pkgs/PyQt5/Qt/bin/libeay32.dll pkgs/PyQt5/Qt/bin/opengl32sw.dll pkgs/PyQt5/Qt/plugins/audio pkgs/PyQt5/Qt/plugins/generic pkgs/PyQt5/Qt/plugins/geometryloaders pkgs/PyQt5/Qt/plugins/geoservices pkgs/PyQt5/Qt/plugins/mediaservice pkgs/PyQt5/Qt/plugins/platforms/qminimal.dll pkgs/PyQt5/Qt/plugins/platforms/qoffscreen.dll pkgs/PyQt5/Qt/plugins/platforms/qwebgl.dll pkgs/PyQt5/Qt/plugins/platformthemes pkgs/PyQt5/Qt/plugins/playlistformats pkgs/PyQt5/Qt/plugins/position pkgs/PyQt5/Qt/plugins/printsupport pkgs/PyQt5/Qt/plugins/sceneparsers pkgs/PyQt5/Qt/plugins/sensorgestures pkgs/PyQt5/Qt/plugins/sensors pkgs/PyQt5/Qt/plugins/sqldrivers pkgs/PyQt5/Qt/plugins/styles pkgs/PyQt5/Qt/plugins/texttospeech pkgs/PyQt5/Qt/plugins/webview pkgs/PyQt5/QtBluetooth.pyd pkgs/PyQt5/QtDesigner.pyd pkgs/PyQt5/QtQml.pyd pkgs/PyQt5/QtQuick.pyd pkgs/PyQt5/QtQuickWidgets.pyd git-cola-4.6.1/pyproject.toml000066400000000000000000000020741457126473700161600ustar00rootroot00000000000000[project] name = "git-cola" authors = [ {name = "David Aguilar", email = "davvid@gmail.com"} ] classifiers = [ "Development Status :: 6 - Mature", "Intended Audience :: Developers", "Intended Audience :: End Users/Desktop", "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Version Control :: Git", ] description = "A sleek and powerful Git GUI" dynamic = ["dependencies", "optional-dependencies", "version"] license = {file = "COPYING"} readme = "README.md" [project.scripts] cola = "cola.main:main" git-cola = "cola.main:main" git-dag = "cola.dag:main" git-cola-sequence-editor = "cola.sequenceeditor:main" [build-system] requires = ["setuptools>=42", "setuptools_scm[toml]>=3.4.1"] build-backend = "setuptools.build_meta" [tool.cercis] function-definition-extra-indent = false line-length = 88 [tool.pytest-enabler.ruff] addopts = "--ruff" [tool.setuptools_scm] fallback_version = "4.6.1" git-cola-4.6.1/pytest.ini000066400000000000000000000003351457126473700152730ustar00rootroot00000000000000[pytest] norecursedirs=dist build .tox .eggs env* addopts=--doctest-modules filterwarnings= # https://github.com/pytest-dev/pytest/issues/6928 ignore:direct construction of .*Item has been deprecated:DeprecationWarning git-cola-4.6.1/qtpy/000077500000000000000000000000001457126473700142365ustar00rootroot00000000000000git-cola-4.6.1/qtpy/Qsci.py000066400000000000000000000017411457126473700155120ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides Qsci classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.Qsci import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qsci", missing_package="QScintilla", ) from error elif PYQT6: try: from PyQt6.Qsci import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qsci", missing_package="PyQt6-QScintilla", ) from error elif PYSIDE2 or PYSIDE6: raise QtBindingMissingModuleError(name="Qsci") git-cola-4.6.1/qtpy/Qt3DAnimation.py000066400000000000000000000025771457126473700172360ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides Qt3DAnimation classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.Qt3DAnimation import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DAnimation", missing_package="PyQt3D", ) from error elif PYQT6: try: from PyQt6.Qt3DAnimation import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DAnimation", missing_package="PyQt6-3D", ) from error elif PYSIDE2: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide2.Qt3DAnimation as __temp for __name in inspect.getmembers(__temp.Qt3DAnimation): globals()[__name[0]] = __name[1] elif PYSIDE6: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide6.Qt3DAnimation as __temp for __name in inspect.getmembers(__temp.Qt3DAnimation): globals()[__name[0]] = __name[1] git-cola-4.6.1/qtpy/Qt3DCore.py000066400000000000000000000025221457126473700161750ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides Qt3DCore classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.Qt3DCore import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DCore", missing_package="PyQt3D", ) from error elif PYQT6: try: from PyQt6.Qt3DCore import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DCore", missing_package="PyQt6-3D", ) from error elif PYSIDE2: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide2.Qt3DCore as __temp for __name in inspect.getmembers(__temp.Qt3DCore): globals()[__name[0]] = __name[1] elif PYSIDE6: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide6.Qt3DCore as __temp for __name in inspect.getmembers(__temp.Qt3DCore): globals()[__name[0]] = __name[1] git-cola-4.6.1/qtpy/Qt3DExtras.py000066400000000000000000000025441457126473700165570ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides Qt3DExtras classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.Qt3DExtras import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DExtras", missing_package="PyQt3D", ) from error elif PYQT6: try: from PyQt6.Qt3DExtras import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DExtras", missing_package="PyQt6-3D", ) from error elif PYSIDE2: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide2.Qt3DExtras as __temp for __name in inspect.getmembers(__temp.Qt3DExtras): globals()[__name[0]] = __name[1] elif PYSIDE6: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide6.Qt3DExtras as __temp for __name in inspect.getmembers(__temp.Qt3DExtras): globals()[__name[0]] = __name[1] git-cola-4.6.1/qtpy/Qt3DInput.py000066400000000000000000000025331457126473700164060ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides Qt3DInput classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.Qt3DInput import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DInput", missing_package="PyQt3D", ) from error elif PYQT6: try: from PyQt6.Qt3DInput import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DInput", missing_package="PyQt6-3D", ) from error elif PYSIDE2: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide2.Qt3DInput as __temp for __name in inspect.getmembers(__temp.Qt3DInput): globals()[__name[0]] = __name[1] elif PYSIDE6: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide6.Qt3DInput as __temp for __name in inspect.getmembers(__temp.Qt3DInput): globals()[__name[0]] = __name[1] git-cola-4.6.1/qtpy/Qt3DLogic.py000066400000000000000000000025331457126473700163440ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides Qt3DLogic classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.Qt3DLogic import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DLogic", missing_package="PyQt3D", ) from error elif PYQT6: try: from PyQt6.Qt3DLogic import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DLogic", missing_package="PyQt6-3D", ) from error elif PYSIDE2: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide2.Qt3DLogic as __temp for __name in inspect.getmembers(__temp.Qt3DLogic): globals()[__name[0]] = __name[1] elif PYSIDE6: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide6.Qt3DLogic as __temp for __name in inspect.getmembers(__temp.Qt3DLogic): globals()[__name[0]] = __name[1] git-cola-4.6.1/qtpy/Qt3DRender.py000066400000000000000000000025441457126473700165300ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides Qt3DRender classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.Qt3DRender import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DRender", missing_package="PyQt3D", ) from error elif PYQT6: try: from PyQt6.Qt3DRender import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="Qt3DRender", missing_package="PyQt6-3D", ) from error elif PYSIDE2: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide2.Qt3DRender as __temp for __name in inspect.getmembers(__temp.Qt3DRender): globals()[__name[0]] = __name[1] elif PYSIDE6: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide6.Qt3DRender as __temp for __name in inspect.getmembers(__temp.Qt3DRender): globals()[__name[0]] = __name[1] git-cola-4.6.1/qtpy/QtAxContainer.py000066400000000000000000000011661457126473700173340ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtAxContainer classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5 or PYQT6: raise QtBindingMissingModuleError(name="QtAxContainer") elif PYSIDE2: from PySide2.QtAxContainer import * elif PYSIDE6: from PySide6.QtAxContainer import * git-cola-4.6.1/qtpy/QtBluetooth.py000066400000000000000000000012231457126473700170600ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtBluetooth classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: from PyQt5.QtBluetooth import * elif PYQT6: from PyQt6.QtBluetooth import * elif PYSIDE2: raise QtBindingMissingModuleError(name="QtBluetooth") elif PYSIDE6: from PySide6.QtBluetooth import * git-cola-4.6.1/qtpy/QtCharts.py000066400000000000000000000024621457126473700163450ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2019- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtChart classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5 import QtChart as QtCharts from PyQt5.QtChart import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtCharts", missing_package="PyQtChart", ) from error elif PYQT6: try: from PyQt6 import QtCharts from PyQt6.QtCharts import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtCharts", missing_package="PyQt6-Charts", ) from error elif PYSIDE2: import inspect # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import PySide2.QtCharts as __temp from PySide2.QtCharts import * for __name in inspect.getmembers(__temp.QtCharts): globals()[__name[0]] = __name[1] elif PYSIDE6: from PySide6 import QtCharts from PySide6.QtCharts import * git-cola-4.6.1/qtpy/QtConcurrent.py000066400000000000000000000011621457126473700172370ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtConcurrent classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5 or PYQT6: raise QtBindingMissingModuleError(name="QtConcurrent") elif PYSIDE2: from PySide2.QtConcurrent import * elif PYSIDE6: from PySide6.QtConcurrent import * git-cola-4.6.1/qtpy/QtCore.py000066400000000000000000000144711457126473700160140ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2014-2015 Colin Duquesnoy # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtCore classes and functions.""" import contextlib from typing import TYPE_CHECKING from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 from . import QT_VERSION as _qt_version from . import parse from ._utils import possibly_static_exec, possibly_static_exec_ if PYQT5: from PyQt5.QtCore import * from PyQt5.QtCore import pyqtBoundSignal as SignalInstance from PyQt5.QtCore import pyqtProperty as Property from PyQt5.QtCore import pyqtSignal as Signal from PyQt5.QtCore import pyqtSlot as Slot try: from PyQt5.QtCore import Q_ENUM as QEnum del Q_ENUM except ImportError: # fallback for Qt5.9 from PyQt5.QtCore import Q_ENUMS as QEnum del Q_ENUMS from PyQt5.QtCore import QT_VERSION_STR as __version__ # Those are imported from `import *` del pyqtSignal, pyqtBoundSignal, pyqtSlot, pyqtProperty, QT_VERSION_STR elif PYQT6: from PyQt6 import QtCore from PyQt6.QtCore import * from PyQt6.QtCore import QT_VERSION_STR as __version__ from PyQt6.QtCore import pyqtBoundSignal as SignalInstance from PyQt6.QtCore import pyqtEnum as QEnum from PyQt6.QtCore import pyqtProperty as Property from PyQt6.QtCore import pyqtSignal as Signal from PyQt6.QtCore import pyqtSlot as Slot # For issue #311 # Seems like there is an error with sip. Without first # trying to import `PyQt6.QtGui.Qt`, some functions like # `PyQt6.QtCore.Qt.mightBeRichText` are missing. if not TYPE_CHECKING: with contextlib.suppress(ImportError): from PyQt6.QtGui import Qt # Map missing methods QCoreApplication.exec_ = lambda *args, **kwargs: possibly_static_exec( QCoreApplication, *args, **kwargs, ) QEventLoop.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) QThread.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) # Those are imported from `import *` del ( pyqtSignal, pyqtBoundSignal, pyqtSlot, pyqtProperty, pyqtEnum, QT_VERSION_STR, ) # Allow unscoped access for enums inside the QtCore module from .enums_compat import promote_enums promote_enums(QtCore) del QtCore # Alias deprecated ItemDataRole enum values removed in Qt6 Qt.BackgroundColorRole = ( Qt.ItemDataRole.BackgroundColorRole ) = Qt.BackgroundRole Qt.TextColorRole = Qt.ItemDataRole.TextColorRole = Qt.ForegroundRole # Alias for MiddleButton removed in PyQt6 but available in PyQt5, PySide2 and PySide6 Qt.MidButton = Qt.MiddleButton # Add removed definition for `Qt.ItemFlags` as an alias of `Qt.ItemFlag` # passing as default value 0 in the same way PySide6 6.5+ does. # Note that for PyQt5 and PySide2 those definitions are two different classes # (one is the flag definition and the other the enum definition) Qt.ItemFlags = lambda value=0: Qt.ItemFlag(value) elif PYSIDE2: import PySide2.QtCore from PySide2.QtCore import * __version__ = PySide2.QtCore.__version__ # Missing QtGui utility functions on Qt if getattr(Qt, "mightBeRichText", None) is None: try: from PySide2.QtGui import Qt as guiQt Qt.mightBeRichText = guiQt.mightBeRichText del guiQt except ImportError: # Fails with PySide2 5.12.0 pass QCoreApplication.exec = lambda *args, **kwargs: possibly_static_exec_( QCoreApplication, *args, **kwargs, ) QEventLoop.exec = lambda self, *args, **kwargs: self.exec_(*args, **kwargs) QThread.exec = lambda self, *args, **kwargs: self.exec_(*args, **kwargs) QTextStreamManipulator.exec = lambda self, *args, **kwargs: self.exec_( *args, **kwargs, ) elif PYSIDE6: import PySide6.QtCore from PySide6.QtCore import * __version__ = PySide6.QtCore.__version__ # Missing QtGui utility functions on Qt if getattr(Qt, "mightBeRichText", None) is None: from PySide6.QtGui import Qt as guiQt Qt.mightBeRichText = guiQt.mightBeRichText del guiQt # Alias deprecated ItemDataRole enum values removed in Qt6 Qt.BackgroundColorRole = ( Qt.ItemDataRole.BackgroundColorRole ) = Qt.BackgroundRole Qt.TextColorRole = Qt.ItemDataRole.TextColorRole = Qt.ForegroundRole Qt.MidButton = Qt.MiddleButton # Map DeprecationWarning methods QCoreApplication.exec_ = lambda *args, **kwargs: possibly_static_exec( QCoreApplication, *args, **kwargs, ) QEventLoop.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) QThread.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) QTextStreamManipulator.exec_ = lambda self, *args, **kwargs: self.exec( *args, **kwargs, ) # Passing as default value 0 in the same way PySide6 6.3.2 does for the `Qt.ItemFlags` definition. if parse(_qt_version) > parse("6.3"): Qt.ItemFlags = lambda value=0: Qt.ItemFlag(value) # For issue #153 and updated for issue #305 if PYQT5 or PYQT6: QDate.toPython = lambda self, *args, **kwargs: self.toPyDate( *args, **kwargs, ) QDateTime.toPython = lambda self, *args, **kwargs: self.toPyDateTime( *args, **kwargs, ) QTime.toPython = lambda self, *args, **kwargs: self.toPyTime( *args, **kwargs, ) if PYSIDE2 or PYSIDE6: QDate.toPyDate = lambda self, *args, **kwargs: self.toPython( *args, **kwargs, ) QDateTime.toPyDateTime = lambda self, *args, **kwargs: self.toPython( *args, **kwargs, ) QTime.toPyTime = lambda self, *args, **kwargs: self.toPython( *args, **kwargs, ) # Mirror https://github.com/spyder-ide/qtpy/pull/393 if PYQT5 or PYSIDE2: QLibraryInfo.path = QLibraryInfo.location QLibraryInfo.LibraryPath = QLibraryInfo.LibraryLocation if PYQT6 or PYSIDE6: QLibraryInfo.location = QLibraryInfo.path QLibraryInfo.LibraryLocation = QLibraryInfo.LibraryPath git-cola-4.6.1/qtpy/QtDBus.py000066400000000000000000000014001457126473700157450ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtDBus classes and functions.""" import sys from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, QtModuleNotInOSError, ) if PYQT5: from PyQt5.QtDBus import * elif PYQT6: from PyQt6.QtDBus import * elif PYSIDE2: raise QtBindingMissingModuleError(name="QtDBus") elif PYSIDE6: if sys.platform != "win32": from PySide6.QtDBus import * else: raise QtModuleNotInOSError(name="QtDBus") git-cola-4.6.1/qtpy/QtDataVisualization.py000066400000000000000000000024161457126473700205530ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtDataVisualization classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.QtDataVisualization import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtDataVisualization", missing_package="PyQtDataVisualization", ) from error elif PYQT6: try: from PyQt6.QtDataVisualization import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtDataVisualization", missing_package="PyQt6-DataVisualization", ) from error elif PYSIDE2: # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1026 import inspect import PySide2.QtDataVisualization as __temp for __name in inspect.getmembers(__temp.QtDataVisualization): globals()[__name[0]] = __name[1] elif PYSIDE6: from PySide6.QtDataVisualization import * git-cola-4.6.1/qtpy/QtDesigner.py000066400000000000000000000012061457126473700166540ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2014-2015 Colin Duquesnoy # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtDesigner classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: from PyQt5.QtDesigner import * elif PYQT6: from PyQt6.QtDesigner import * elif PYSIDE2: raise QtBindingMissingModuleError(name="QtDesigner") elif PYSIDE6: from PySide6.QtDesigner import * git-cola-4.6.1/qtpy/QtGui.py000066400000000000000000000206601457126473700156450ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2014-2015 Colin Duquesnoy # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtGui classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError from ._utils import getattr_missing_optional_dep, possibly_static_exec _missing_optional_names = {} _QTOPENGL_NAMES = { "QOpenGLBuffer", "QOpenGLContext", "QOpenGLContextGroup", "QOpenGLDebugLogger", "QOpenGLDebugMessage", "QOpenGLFramebufferObject", "QOpenGLFramebufferObjectFormat", "QOpenGLPixelTransferOptions", "QOpenGLShader", "QOpenGLShaderProgram", "QOpenGLTexture", "QOpenGLTextureBlitter", "QOpenGLVersionProfile", "QOpenGLVertexArrayObject", "QOpenGLWindow", } def __getattr__(name): """Custom getattr to chain and wrap errors due to missing optional deps.""" raise getattr_missing_optional_dep( name, module_name=__name__, optional_names=_missing_optional_names, ) if PYQT5: from PyQt5.QtGui import * # Backport items moved to QtGui in Qt6 from PyQt5.QtWidgets import ( QAction, QActionGroup, QFileSystemModel, QShortcut, QUndoCommand, ) elif PYQT6: from PyQt6 import QtGui from PyQt6.QtGui import * # Attempt to import QOpenGL* classes, but if that fails, # don't raise an exception until the name is explicitly accessed. # See https://github.com/spyder-ide/qtpy/pull/387/ try: from PyQt6.QtOpenGL import * except ImportError as error: for name in _QTOPENGL_NAMES: _missing_optional_names[name] = { "name": "PyQt6.QtOpenGL", "missing_package": "pyopengl", "import_error": error, } QFontMetrics.width = lambda self, *args, **kwargs: self.horizontalAdvance( *args, **kwargs, ) QFontMetricsF.width = lambda self, *args, **kwargs: self.horizontalAdvance( *args, **kwargs, ) # Map missing/renamed methods QDrag.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) QGuiApplication.exec_ = lambda *args, **kwargs: possibly_static_exec( QGuiApplication, *args, **kwargs, ) QTextDocument.print_ = lambda self, *args, **kwargs: self.print( *args, **kwargs, ) # Allow unscoped access for enums inside the QtGui module from .enums_compat import promote_enums promote_enums(QtGui) del QtGui elif PYSIDE2: from PySide2.QtGui import * # Backport items moved to QtGui in Qt6 from PySide2.QtWidgets import ( QAction, QActionGroup, QFileSystemModel, QShortcut, QUndoCommand, ) if hasattr(QFontMetrics, "horizontalAdvance"): # Needed to prevent raising a DeprecationWarning when using QFontMetrics.width QFontMetrics.width = ( lambda self, *args, **kwargs: self.horizontalAdvance( *args, **kwargs, ) ) elif PYSIDE6: from PySide6.QtGui import * # Attempt to import QOpenGL* classes, but if that fails, # don't raise an exception until the name is explicitly accessed. # See https://github.com/spyder-ide/qtpy/pull/387/ try: from PySide6.QtOpenGL import * except ImportError as error: for name in _QTOPENGL_NAMES: _missing_optional_names[name] = { "name": "PySide6.QtOpenGL", "missing_package": "pyopengl", "import_error": error, } # Backport `QFileSystemModel` moved to QtGui in Qt6 from PySide6.QtWidgets import QFileSystemModel QFontMetrics.width = lambda self, *args, **kwargs: self.horizontalAdvance( *args, **kwargs, ) QFontMetricsF.width = lambda self, *args, **kwargs: self.horizontalAdvance( *args, **kwargs, ) # Map DeprecationWarning methods QDrag.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) QGuiApplication.exec_ = lambda *args, **kwargs: possibly_static_exec( QGuiApplication, *args, **kwargs, ) if PYSIDE2 or PYSIDE6: # PySide{2,6} do not accept the `mode` keyword argument in # QTextCursor.movePosition() even though it is a valid optional argument # as per C++ API. Fix this by monkeypatching. # # Notes: # # * The `mode` argument is called `arg__2` in PySide{2,6} as per # QTextCursor.movePosition.__doc__ and __signature__. Using `arg__2` as # keyword argument works as intended, so does using a positional # argument. Tested with PySide2 5.15.0, 5.15.2.1 and 5.15.3 and PySide6 # 6.3.0; older version, down to PySide 1, are probably affected as well [1]. # # * PySide2 5.15.0 and 5.15.2.1 silently ignore invalid keyword arguments, # i.e. passing the `mode` keyword argument has no effect and doesn`t # raise an exception. Older versions, down to PySide 1, are probably # affected as well [1]. At least PySide2 5.15.3 and PySide6 6.3.0 raise an # exception when `mode` or any other invalid keyword argument is passed. # # [1] https://bugreports.qt.io/browse/PYSIDE-185 movePosition = QTextCursor.movePosition def movePositionPatched( self, operation: QTextCursor.MoveOperation, mode: QTextCursor.MoveMode = QTextCursor.MoveAnchor, n: int = 1, ) -> bool: return movePosition(self, operation, mode, n) QTextCursor.movePosition = movePositionPatched if PYQT5 or PYSIDE2: # Part of the fix for https://github.com/spyder-ide/qtpy/issues/394 from qtpy.QtCore import QPointF as __QPointF QNativeGestureEvent.x = lambda self: self.localPos().toPoint().x() QNativeGestureEvent.y = lambda self: self.localPos().toPoint().y() QNativeGestureEvent.position = lambda self: self.localPos() QNativeGestureEvent.globalX = lambda self: self.globalPos().x() QNativeGestureEvent.globalY = lambda self: self.globalPos().y() QNativeGestureEvent.globalPosition = lambda self: __QPointF( float(self.globalPos().x()), float(self.globalPos().y()), ) QEnterEvent.position = lambda self: self.localPos() QEnterEvent.globalPosition = lambda self: __QPointF( float(self.globalX()), float(self.globalY()), ) QTabletEvent.position = lambda self: self.posF() QTabletEvent.globalPosition = lambda self: self.globalPosF() QHoverEvent.x = lambda self: self.pos().x() QHoverEvent.y = lambda self: self.pos().y() QHoverEvent.position = lambda self: self.posF() # No `QHoverEvent.globalPosition`, `QHoverEvent.globalX`, # nor `QHoverEvent.globalY` in the Qt5 docs. QMouseEvent.position = lambda self: self.localPos() QMouseEvent.globalPosition = lambda self: __QPointF( float(self.globalX()), float(self.globalY()), ) # Follow similar approach for `QDropEvent` and child classes QDropEvent.position = lambda self: self.posF() if PYQT6 or PYSIDE6: # Part of the fix for https://github.com/spyder-ide/qtpy/issues/394 for _class in ( QNativeGestureEvent, QEnterEvent, QTabletEvent, QHoverEvent, QMouseEvent, ): for _obsolete_function in ( "pos", "x", "y", "globalPos", "globalX", "globalY", ): if hasattr(_class, _obsolete_function): delattr(_class, _obsolete_function) QSinglePointEvent.pos = lambda self: self.position().toPoint() QSinglePointEvent.posF = lambda self: self.position() QSinglePointEvent.localPos = lambda self: self.position() QSinglePointEvent.x = lambda self: self.position().toPoint().x() QSinglePointEvent.y = lambda self: self.position().toPoint().y() QSinglePointEvent.globalPos = lambda self: self.globalPosition().toPoint() QSinglePointEvent.globalX = ( lambda self: self.globalPosition().toPoint().x() ) QSinglePointEvent.globalY = ( lambda self: self.globalPosition().toPoint().y() ) # Follow similar approach for `QDropEvent` and child classes QDropEvent.pos = lambda self: self.position().toPoint() QDropEvent.posF = lambda self: self.position() git-cola-4.6.1/qtpy/QtHelp.py000066400000000000000000000010311457126473700160000ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """QtHelp Wrapper.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtHelp import * elif PYQT6: from PyQt6.QtHelp import * elif PYSIDE2: from PySide2.QtHelp import * elif PYSIDE6: from PySide6.QtHelp import * git-cola-4.6.1/qtpy/QtLocation.py000066400000000000000000000012441457126473700166660ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtLocation classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: from PyQt5.QtLocation import * elif PYQT6: raise QtBindingMissingModuleError(name="QtLocation") elif PYSIDE2: from PySide2.QtLocation import * elif PYSIDE6: raise QtBindingMissingModuleError(name="QtLocation") git-cola-4.6.1/qtpy/QtMacExtras.py000066400000000000000000000015441457126473700170100ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides classes and functions specific to macOS and iOS operating systems""" import sys from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInOSError, QtModuleNotInQtVersionError, ) if sys.platform == "darwin": if PYQT5: from PyQt5.QtMacExtras import * elif PYQT6: raise QtModuleNotInQtVersionError(name="QtMacExtras") elif PYSIDE2: from PySide2.QtMacExtras import * elif PYSIDE6: raise QtModuleNotInQtVersionError(name="QtMacExtras") else: raise QtModuleNotInOSError(name="QtMacExtras") git-cola-4.6.1/qtpy/QtMultimedia.py000066400000000000000000000011161457126473700172060ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides low-level multimedia functionality.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtMultimedia import * elif PYQT6: from PyQt6.QtMultimedia import * elif PYSIDE2: from PySide2.QtMultimedia import * elif PYSIDE6: from PySide6.QtMultimedia import * git-cola-4.6.1/qtpy/QtMultimediaWidgets.py000066400000000000000000000011611457126473700205350ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtMultimediaWidgets classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtMultimediaWidgets import * elif PYQT6: from PyQt6.QtMultimediaWidgets import * elif PYSIDE2: from PySide2.QtMultimediaWidgets import * elif PYSIDE6: from PySide6.QtMultimediaWidgets import * git-cola-4.6.1/qtpy/QtNetwork.py000066400000000000000000000011501457126473700165430ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2014-2015 Colin Duquesnoy # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtNetwork classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtNetwork import * elif PYQT6: from PyQt6.QtNetwork import * elif PYSIDE2: from PySide2.QtNetwork import * elif PYSIDE6: from PySide6.QtNetwork import * git-cola-4.6.1/qtpy/QtNetworkAuth.py000066400000000000000000000021101457126473700173620ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtNetworkAuth classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.QtNetworkAuth import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtNetworkAuth", missing_package="PyQtNetworkAuth", ) from error elif PYQT6: try: from PyQt6.QtNetworkAuth import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtNetworkAuth", missing_package="PyQt6-NetworkAuth", ) from error elif PYSIDE2: raise QtBindingMissingModuleError(name="QtNetworkAuth") elif PYSIDE6: from PySide6.QtNetworkAuth import * git-cola-4.6.1/qtpy/QtNfc.py000066400000000000000000000011651457126473700156260ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtNfc classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: from PyQt5.QtNfc import * elif PYQT6: from PyQt6.QtNfc import * elif PYSIDE2: raise QtBindingMissingModuleError(name="QtNfc") elif PYSIDE6: from PySide6.QtNfc import * git-cola-4.6.1/qtpy/QtOpenGL.py000066400000000000000000000037601457126473700162470ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtOpenGL classes and functions.""" import contextlib from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtGui import ( QOpenGLBuffer, QOpenGLContext, QOpenGLContextGroup, QOpenGLDebugLogger, QOpenGLDebugMessage, QOpenGLFramebufferObject, QOpenGLFramebufferObjectFormat, QOpenGLPixelTransferOptions, QOpenGLShader, QOpenGLShaderProgram, QOpenGLTexture, QOpenGLTextureBlitter, QOpenGLVersionProfile, QOpenGLVertexArrayObject, QOpenGLWindow, ) from PyQt5.QtOpenGL import * # These are not present on some architectures such as armhf with contextlib.suppress(ImportError): from PyQt5.QtGui import QOpenGLTimeMonitor, QOpenGLTimerQuery elif PYQT6: from PyQt6.QtGui import QOpenGLContext, QOpenGLContextGroup from PyQt6.QtOpenGL import * elif PYSIDE6: from PySide6.QtGui import QOpenGLContext, QOpenGLContextGroup from PySide6.QtOpenGL import * elif PYSIDE2: from PySide2.QtGui import ( QOpenGLBuffer, QOpenGLContext, QOpenGLContextGroup, QOpenGLDebugLogger, QOpenGLDebugMessage, QOpenGLFramebufferObject, QOpenGLFramebufferObjectFormat, QOpenGLPixelTransferOptions, QOpenGLShader, QOpenGLShaderProgram, QOpenGLTexture, QOpenGLTextureBlitter, QOpenGLVersionProfile, QOpenGLVertexArrayObject, QOpenGLWindow, ) from PySide2.QtOpenGL import * # These are not present on some architectures such as armhf with contextlib.suppress(ImportError): from PySide2.QtGui import QOpenGLTimeMonitor, QOpenGLTimerQuery git-cola-4.6.1/qtpy/QtOpenGLWidgets.py000066400000000000000000000012751457126473700175750ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtOpenGLWidgets classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: raise QtBindingMissingModuleError(name="QtOpenGLWidgets") elif PYQT6: from PyQt6.QtOpenGLWidgets import * elif PYSIDE2: raise QtBindingMissingModuleError(name="QtOpenGLWidgets") elif PYSIDE6: from PySide6.QtOpenGLWidgets import * git-cola-4.6.1/qtpy/QtPdf.py000066400000000000000000000013251457126473700156270ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtPdf classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: raise QtBindingMissingModuleError(name="QtPdf") elif PYQT6: # Available with version >=6.4.0 from PyQt6.QtPdf import * elif PYSIDE2: raise QtBindingMissingModuleError(name="QtPdf") elif PYSIDE6: # Available with version >=6.4.0 from PySide6.QtPdf import * git-cola-4.6.1/qtpy/QtPdfWidgets.py000066400000000000000000000013701457126473700171560ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtPdfWidgets classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: raise QtBindingMissingModuleError(name="QtPdfWidgets") elif PYQT6: # Available with version >=6.4.0 from PyQt6.QtPdfWidgets import * elif PYSIDE2: raise QtBindingMissingModuleError(name="QtPdfWidgets") elif PYSIDE6: # Available with version >=6.4.0 from PySide6.QtPdfWidgets import * git-cola-4.6.1/qtpy/QtPositioning.py000066400000000000000000000011051457126473700174140ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright 2020 Antonio Valentino # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtPositioning classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtPositioning import * elif PYQT6: from PyQt6.QtPositioning import * elif PYSIDE2: from PySide2.QtPositioning import * elif PYSIDE6: from PySide6.QtPositioning import * git-cola-4.6.1/qtpy/QtPrintSupport.py000066400000000000000000000022351457126473700176100ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtPrintSupport classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtPrintSupport import * elif PYQT6: from PyQt6.QtPrintSupport import * QPageSetupDialog.exec_ = lambda self, *args, **kwargs: self.exec( *args, **kwargs, ) QPrintDialog.exec_ = lambda self, *args, **kwargs: self.exec( *args, **kwargs, ) QPrintPreviewWidget.print_ = lambda self, *args, **kwargs: self.print( *args, **kwargs, ) elif PYSIDE6: from PySide6.QtPrintSupport import * # Map DeprecationWarning methods QPageSetupDialog.exec_ = lambda self, *args, **kwargs: self.exec( *args, **kwargs, ) QPrintDialog.exec_ = lambda self, *args, **kwargs: self.exec( *args, **kwargs, ) elif PYSIDE2: from PySide2.QtPrintSupport import * git-cola-4.6.1/qtpy/QtPurchasing.py000066400000000000000000000014501457126473700172200ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtPurchasing classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.QtPurchasing import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtPurchasing", missing_package="PyQtPurchasing", ) from error elif PYQT6 or PYSIDE2 or PYSIDE6: raise QtBindingMissingModuleError(name="QtPurchasing") git-cola-4.6.1/qtpy/QtQml.py000066400000000000000000000010531457126473700156450ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtQml classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtQml import * elif PYQT6: from PyQt6.QtQml import * elif PYSIDE6: from PySide6.QtQml import * elif PYSIDE2: from PySide2.QtQml import * git-cola-4.6.1/qtpy/QtQuick.py000066400000000000000000000010651457126473700161730ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtQuick classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtQuick import * elif PYQT6: from PyQt6.QtQuick import * elif PYSIDE6: from PySide6.QtQuick import * elif PYSIDE2: from PySide2.QtQuick import * git-cola-4.6.1/qtpy/QtQuick3D.py000066400000000000000000000012111457126473700163530ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtQuick3D classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: from PyQt5.QtQuick3D import * elif PYQT6: from PyQt6.QtQuick3D import * elif PYSIDE2: raise QtBindingMissingModuleError(name="QtQuick3D") elif PYSIDE6: from PySide6.QtQuick3D import * git-cola-4.6.1/qtpy/QtQuickControls2.py000066400000000000000000000012021457126473700177720ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtQuickControls2 classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5 or PYQT6: raise QtBindingMissingModuleError(name="QtQuickControls2") elif PYSIDE2: from PySide2.QtQuickControls2 import * elif PYSIDE6: from PySide6.QtQuickControls2 import * git-cola-4.6.1/qtpy/QtQuickWidgets.py000066400000000000000000000011301457126473700175130ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtQuickWidgets classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtQuickWidgets import * elif PYQT6: from PyQt6.QtQuickWidgets import * elif PYSIDE6: from PySide6.QtQuickWidgets import * elif PYSIDE2: from PySide2.QtQuickWidgets import * git-cola-4.6.1/qtpy/QtRemoteObjects.py000066400000000000000000000011351457126473700176620ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtRemoteObjects classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtRemoteObjects import * elif PYQT6: from PyQt6.QtRemoteObjects import * elif PYSIDE6: from PySide6.QtRemoteObjects import * elif PYSIDE2: from PySide2.QtRemoteObjects import * git-cola-4.6.1/qtpy/QtScxml.py000066400000000000000000000011361457126473700162040ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtScxml classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5 or PYQT6: raise QtBindingMissingModuleError(name="QtScxml") elif PYSIDE2: from PySide2.QtScxml import * elif PYSIDE6: from PySide6.QtScxml import * git-cola-4.6.1/qtpy/QtSensors.py000066400000000000000000000010771457126473700165560ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtSensors classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtSensors import * elif PYQT6: from PyQt6.QtSensors import * elif PYSIDE6: from PySide6.QtSensors import * elif PYSIDE2: from PySide2.QtSensors import * git-cola-4.6.1/qtpy/QtSerialPort.py000066400000000000000000000011571457126473700172050ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2020 Marcin Stano # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtSerialPort classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtSerialPort import * elif PYQT6: from PyQt6.QtSerialPort import * elif PYSIDE6: from PySide6.QtSerialPort import * elif PYSIDE2: from PySide2.QtSerialPort import * git-cola-4.6.1/qtpy/QtSql.py000066400000000000000000000021421457126473700156530ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtSql classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtSql import * elif PYQT6: from PyQt6.QtSql import * QSqlDatabase.exec_ = lambda self, *args, **kwargs: self.exec( *args, **kwargs, ) QSqlQuery.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) QSqlResult.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) elif PYSIDE6: from PySide6.QtSql import * # Map DeprecationWarning methods QSqlDatabase.exec_ = lambda self, *args, **kwargs: self.exec( *args, **kwargs, ) QSqlQuery.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) QSqlResult.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) elif PYSIDE2: from PySide2.QtSql import * git-cola-4.6.1/qtpy/QtStateMachine.py000066400000000000000000000011161457126473700174610ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtStateMachine classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5 or PYQT6 or PYSIDE2: raise QtBindingMissingModuleError(name="QtStateMachine") elif PYSIDE6: from PySide6.QtStateMachine import * git-cola-4.6.1/qtpy/QtSvg.py000066400000000000000000000010531457126473700156530ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtSvg classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtSvg import * elif PYQT6: from PyQt6.QtSvg import * elif PYSIDE2: from PySide2.QtSvg import * elif PYSIDE6: from PySide6.QtSvg import * git-cola-4.6.1/qtpy/QtSvgWidgets.py000066400000000000000000000012561457126473700172070ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtSvgWidgets classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: raise QtBindingMissingModuleError(name="QtSvgWidgets") elif PYQT6: from PyQt6.QtSvgWidgets import * elif PYSIDE2: raise QtBindingMissingModuleError(name="QtSvgWidgets") elif PYSIDE6: from PySide6.QtSvgWidgets import * git-cola-4.6.1/qtpy/QtTest.py000066400000000000000000000014031457126473700160320ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2014-2015 Colin Duquesnoy # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtTest and functions""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtTest import * elif PYQT6: from PyQt6 import QtTest from PyQt6.QtTest import * # Allow unscoped access for enums inside the QtTest module from .enums_compat import promote_enums promote_enums(QtTest) del QtTest elif PYSIDE2: from PySide2.QtTest import * elif PYSIDE6: from PySide6.QtTest import * git-cola-4.6.1/qtpy/QtTextToSpeech.py000066400000000000000000000012701457126473700174740ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtTextToSpeech classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: from PyQt5.QtTextToSpeech import * elif PYQT6: raise QtBindingMissingModuleError(name="QtTextToSpeech") elif PYSIDE2: from PySide2.QtTextToSpeech import * elif PYSIDE6: raise QtBindingMissingModuleError(name="QtTextToSpeech") git-cola-4.6.1/qtpy/QtUiTools.py000066400000000000000000000011461457126473700165150ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtUiTools classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5 or PYQT6: raise QtBindingMissingModuleError(name="QtUiTools") elif PYSIDE2: from PySide2.QtUiTools import * elif PYSIDE6: from PySide6.QtUiTools import * git-cola-4.6.1/qtpy/QtWebChannel.py000066400000000000000000000011161457126473700171220ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtWebChannel classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtWebChannel import * elif PYQT6: from PyQt6.QtWebChannel import * elif PYSIDE2: from PySide2.QtWebChannel import * elif PYSIDE6: from PySide6.QtWebChannel import * git-cola-4.6.1/qtpy/QtWebEngine.py000066400000000000000000000016621457126473700167650ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2014-2015 Colin Duquesnoy # Copyright © 2009- The Spyder development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtWebEngine classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInQtVersionError, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.QtWebEngine import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtWebEngine", missing_package="PyQtWebEngine", ) from error elif PYQT6: raise QtModuleNotInQtVersionError(name="QtWebEngine") elif PYSIDE2: from PySide2.QtWebEngine import * elif PYSIDE6: raise QtModuleNotInQtVersionError(name="QtWebEngine") git-cola-4.6.1/qtpy/QtWebEngineCore.py000066400000000000000000000020351457126473700175710ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtWebEngineCore classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError, ) if PYQT5: try: from PyQt5.QtWebEngineCore import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtWebEngineCore", missing_package="PyQtWebEngine", ) from error elif PYQT6: try: from PyQt6.QtWebEngineCore import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtWebEngineCore", missing_package="PyQt6-WebEngine", ) from error elif PYSIDE2: from PySide2.QtWebEngineCore import * elif PYSIDE6: from PySide6.QtWebEngineCore import * git-cola-4.6.1/qtpy/QtWebEngineQuick.py000066400000000000000000000016511457126473700177600ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtWebEngineQuick classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, QtModuleNotInstalledError, ) if PYQT5: raise QtBindingMissingModuleError(name="QtWebEngineQuick") elif PYQT6: try: from PyQt6.QtWebEngineQuick import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtWebEngineQuick", missing_package="PyQt6-WebEngine", ) from error elif PYSIDE2: raise QtBindingMissingModuleError(name="QtWebEngineQuick") elif PYSIDE6: from PySide6.QtWebEngineQuick import * git-cola-4.6.1/qtpy/QtWebEngineWidgets.py000066400000000000000000000037741457126473700203220ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2014-2015 Colin Duquesnoy # Copyright © 2009- The Spyder development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtWebEngineWidgets classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError, ) # To test if we are using WebEngine or WebKit # NOTE: This constant is imported by other projects (e.g. Spyder), so please # don't remove it. WEBENGINE = True if PYQT5: try: # Based on the work at https://github.com/spyder-ide/qtpy/pull/203 from PyQt5.QtWebEngineWidgets import ( QWebEnginePage, QWebEngineProfile, QWebEngineScript, QWebEngineSettings, QWebEngineView, ) except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtWebEngineWidgets", missing_package="PyQtWebEngine", ) from error elif PYQT6: try: from PyQt6.QtWebEngineCore import ( QWebEnginePage, QWebEngineProfile, QWebEngineScript, QWebEngineSettings, ) from PyQt6.QtWebEngineWidgets import * except ModuleNotFoundError as error: raise QtModuleNotInstalledError( name="QtWebEngineWidgets", missing_package="PyQt6-WebEngine", ) from error elif PYSIDE2: # Based on the work at https://github.com/spyder-ide/qtpy/pull/203 from PySide2.QtWebEngineWidgets import ( QWebEnginePage, QWebEngineProfile, QWebEngineScript, QWebEngineSettings, QWebEngineView, ) elif PYSIDE6: from PySide6.QtWebEngineCore import ( QWebEnginePage, QWebEngineProfile, QWebEngineScript, QWebEngineSettings, ) from PySide6.QtWebEngineWidgets import * git-cola-4.6.1/qtpy/QtWebSockets.py000066400000000000000000000011161457126473700171650ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtWebSockets classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtWebSockets import * elif PYQT6: from PyQt6.QtWebSockets import * elif PYSIDE2: from PySide2.QtWebSockets import * elif PYSIDE6: from PySide6.QtWebSockets import * git-cola-4.6.1/qtpy/QtWidgets.py000066400000000000000000000156131457126473700165310ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2014-2015 Colin Duquesnoy # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides widget classes and functions.""" from functools import partialmethod from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 from . import QT_VERSION as _qt_version from . import parse from ._utils import ( add_action, getattr_missing_optional_dep, possibly_static_exec, static_method_kwargs_wrapper, ) _missing_optional_names = {} def __getattr__(name): """Custom getattr to chain and wrap errors due to missing optional deps.""" raise getattr_missing_optional_dep( name, module_name=__name__, optional_names=_missing_optional_names, ) if PYQT5: from PyQt5.QtWidgets import * elif PYQT6: from PyQt6 import QtWidgets from PyQt6.QtGui import ( QAction, QActionGroup, QFileSystemModel, QShortcut, QUndoCommand, ) from PyQt6.QtWidgets import * # Attempt to import QOpenGLWidget, but if that fails, # don't raise an exception until the name is explicitly accessed. # See https://github.com/spyder-ide/qtpy/pull/387/ try: from PyQt6.QtOpenGLWidgets import QOpenGLWidget except ImportError as error: _missing_optional_names["QOpenGLWidget"] = { "name": "PyQt6.QtOpenGLWidgets", "missing_package": "pyopengl", "import_error": error, } # Map missing/renamed methods QTextEdit.setTabStopWidth = ( lambda self, *args, **kwargs: self.setTabStopDistance(*args, **kwargs) ) QTextEdit.tabStopWidth = ( lambda self, *args, **kwargs: self.tabStopDistance(*args, **kwargs) ) QTextEdit.print_ = lambda self, *args, **kwargs: self.print( *args, **kwargs, ) QPlainTextEdit.setTabStopWidth = ( lambda self, *args, **kwargs: self.setTabStopDistance(*args, **kwargs) ) QPlainTextEdit.tabStopWidth = ( lambda self, *args, **kwargs: self.tabStopDistance(*args, **kwargs) ) QPlainTextEdit.print_ = lambda self, *args, **kwargs: self.print( *args, **kwargs, ) QApplication.exec_ = lambda *args, **kwargs: possibly_static_exec( QApplication, *args, **kwargs, ) QDialog.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) QMenu.exec_ = lambda *args, **kwargs: possibly_static_exec( QMenu, *args, **kwargs, ) QLineEdit.getTextMargins = lambda self: ( self.textMargins().left(), self.textMargins().top(), self.textMargins().right(), self.textMargins().bottom(), ) # Add removed definition for `QFileDialog.Options` as an alias of `QFileDialog.Option` # passing as default value 0 in the same way PySide6 6.5+ does. # Note that for PyQt5 and PySide2 those definitions are two different classes # (one is the flag definition and the other the enum definition) QFileDialog.Options = lambda value=0: QFileDialog.Option(value) # Allow unscoped access for enums inside the QtWidgets module from .enums_compat import promote_enums promote_enums(QtWidgets) del QtWidgets elif PYSIDE2: from PySide2.QtWidgets import * elif PYSIDE6: from PySide6.QtGui import QAction, QActionGroup, QShortcut, QUndoCommand from PySide6.QtWidgets import * # Attempt to import QOpenGLWidget, but if that fails, # don't raise an exception until the name is explicitly accessed. # See https://github.com/spyder-ide/qtpy/pull/387/ try: from PySide6.QtOpenGLWidgets import QOpenGLWidget except ImportError as error: _missing_optional_names["QOpenGLWidget"] = { "name": "PySide6.QtOpenGLWidgets", "missing_package": "pyopengl", "import_error": error, } # Map missing/renamed methods QTextEdit.setTabStopWidth = ( lambda self, *args, **kwargs: self.setTabStopDistance(*args, **kwargs) ) QTextEdit.tabStopWidth = ( lambda self, *args, **kwargs: self.tabStopDistance(*args, **kwargs) ) QPlainTextEdit.setTabStopWidth = ( lambda self, *args, **kwargs: self.setTabStopDistance(*args, **kwargs) ) QPlainTextEdit.tabStopWidth = ( lambda self, *args, **kwargs: self.tabStopDistance(*args, **kwargs) ) QLineEdit.getTextMargins = lambda self: ( self.textMargins().left(), self.textMargins().top(), self.textMargins().right(), self.textMargins().bottom(), ) # Map DeprecationWarning methods QApplication.exec_ = lambda *args, **kwargs: possibly_static_exec( QApplication, *args, **kwargs, ) QDialog.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs) QMenu.exec_ = lambda *args, **kwargs: possibly_static_exec( QMenu, *args, **kwargs, ) # Passing as default value 0 in the same way PySide6 < 6.3.2 does for the `QFileDialog.Options` definition. if parse(_qt_version) > parse("6.3"): QFileDialog.Options = lambda value=0: QFileDialog.Option(value) if PYSIDE2 or PYSIDE6: # Make PySide2/6 `QFileDialog` static methods accept the `directory` kwarg as `dir` QFileDialog.getExistingDirectory = static_method_kwargs_wrapper( QFileDialog.getExistingDirectory, "directory", "dir", ) QFileDialog.getOpenFileName = static_method_kwargs_wrapper( QFileDialog.getOpenFileName, "directory", "dir", ) QFileDialog.getOpenFileNames = static_method_kwargs_wrapper( QFileDialog.getOpenFileNames, "directory", "dir", ) QFileDialog.getSaveFileName = static_method_kwargs_wrapper( QFileDialog.getSaveFileName, "directory", "dir", ) else: # Make PyQt5/6 `QFileDialog` static methods accept the `dir` kwarg as `directory` QFileDialog.getExistingDirectory = static_method_kwargs_wrapper( QFileDialog.getExistingDirectory, "dir", "directory", ) QFileDialog.getOpenFileName = static_method_kwargs_wrapper( QFileDialog.getOpenFileName, "dir", "directory", ) QFileDialog.getOpenFileNames = static_method_kwargs_wrapper( QFileDialog.getOpenFileNames, "dir", "directory", ) QFileDialog.getSaveFileName = static_method_kwargs_wrapper( QFileDialog.getSaveFileName, "dir", "directory", ) # Make `addAction` compatible with Qt6 >= 6.3 if PYQT5 or PYSIDE2 or parse(_qt_version) < parse("6.3"): QMenu.addAction = partialmethod(add_action, old_add_action=QMenu.addAction) QToolBar.addAction = partialmethod( add_action, old_add_action=QToolBar.addAction, ) git-cola-4.6.1/qtpy/QtWinExtras.py000066400000000000000000000014741457126473700170470ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides Windows-specific utilities""" import sys from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInOSError, QtModuleNotInQtVersionError, ) if sys.platform == "win32": if PYQT5: from PyQt5.QtWinExtras import * elif PYQT6: raise QtModuleNotInQtVersionError(name="QtWinExtras") elif PYSIDE2: from PySide2.QtWinExtras import * elif PYSIDE6: raise QtModuleNotInQtVersionError(name="QtWinExtras") else: raise QtModuleNotInOSError(name="QtWinExtras") git-cola-4.6.1/qtpy/QtX11Extras.py000066400000000000000000000014721457126473700166610ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides Linux-specific utilities""" import sys from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInOSError, QtModuleNotInQtVersionError, ) if sys.platform == "linux": if PYQT5: from PyQt5.QtX11Extras import * elif PYQT6: raise QtModuleNotInQtVersionError(name="QtX11Extras") elif PYSIDE2: from PySide2.QtX11Extras import * elif PYSIDE6: raise QtModuleNotInQtVersionError(name="QtX11Extras") else: raise QtModuleNotInOSError(name="QtX11Extras") git-cola-4.6.1/qtpy/QtXml.py000066400000000000000000000010531457126473700156540ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtXml classes and functions.""" from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT5: from PyQt5.QtXml import * elif PYQT6: from PyQt6.QtXml import * elif PYSIDE2: from PySide2.QtXml import * elif PYSIDE6: from PySide6.QtXml import * git-cola-4.6.1/qtpy/QtXmlPatterns.py000066400000000000000000000012631457126473700174000ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides QtXmlPatterns classes and functions.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: from PyQt5.QtXmlPatterns import * elif PYQT6: raise QtBindingMissingModuleError(name="QtXmlPatterns") elif PYSIDE2: from PySide2.QtXmlPatterns import * elif PYSIDE6: raise QtBindingMissingModuleError(name="QtXmlPatterns") git-cola-4.6.1/qtpy/__init__.py000066400000000000000000000245461457126473700163620ustar00rootroot00000000000000# # Copyright © 2009- The Spyder Development Team # Copyright © 2014-2015 Colin Duquesnoy # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) """ **QtPy** is a shim over the various Python Qt bindings. It is used to write Qt binding independent libraries or applications. If one of the APIs has already been imported, then it will be used. Otherwise, the shim will automatically select the first available API (PyQt5, PySide2, PyQt6 and PySide6); in that case, you can force the use of one specific bindings (e.g. if your application is using one specific bindings and you need to use library that use QtPy) by setting up the ``QT_API`` environment variable. PyQt5 ===== For PyQt5, you don't have to set anything as it will be used automatically:: >>> from qtpy import QtGui, QtWidgets, QtCore >>> print(QtWidgets.QWidget) PySide2 ====== Set the QT_API environment variable to 'pyside2' before importing other packages:: >>> import os >>> os.environ['QT_API'] = 'pyside2' >>> from qtpy import QtGui, QtWidgets, QtCore >>> print(QtWidgets.QWidget) PyQt6 ===== >>> import os >>> os.environ['QT_API'] = 'pyqt6' >>> from qtpy import QtGui, QtWidgets, QtCore >>> print(QtWidgets.QWidget) PySide6 ======= >>> import os >>> os.environ['QT_API'] = 'pyside6' >>> from qtpy import QtGui, QtWidgets, QtCore >>> print(QtWidgets.QWidget) """ import contextlib import os import platform import sys import warnings # Version of QtPy __version__ = "2.4.1" class PythonQtError(RuntimeError): """Generic error superclass for QtPy.""" class PythonQtWarning(RuntimeWarning): """Warning class for QtPy.""" class PythonQtValueError(ValueError): """Error raised if an invalid QT_API is specified.""" class QtBindingsNotFoundError(PythonQtError, ImportError): """Error raised if no bindings could be selected.""" _msg = "No Qt bindings could be found" def __init__(self): super().__init__(self._msg) class QtModuleNotFoundError(ModuleNotFoundError, PythonQtError): """Raised when a Python Qt binding submodule is not installed/supported.""" _msg = "The {name} module was not found." _msg_binding = "{binding}" _msg_extra = "" def __init__(self, *, name, msg=None, **msg_kwargs): global API_NAME binding = self._msg_binding.format(binding=API_NAME) msg = msg or f"{self._msg} {self._msg_extra}".strip() msg = msg.format(name=name, binding=binding, **msg_kwargs) super().__init__(msg, name=name) class QtModuleNotInOSError(QtModuleNotFoundError): """Raised when a module is not supported on the current operating system.""" _msg = "{name} does not exist on this operating system." class QtModuleNotInQtVersionError(QtModuleNotFoundError): """Raised when a module is not implemented in the current Qt version.""" _msg = "{name} does not exist in {version}." def __init__(self, *, name, msg=None, **msg_kwargs): global QT5, QT6 version = "Qt5" if QT5 else "Qt6" super().__init__(name=name, version=version) class QtBindingMissingModuleError(QtModuleNotFoundError): """Raised when a module is not supported by a given binding.""" _msg_extra = "It is not currently implemented in {binding}." class QtModuleNotInstalledError(QtModuleNotFoundError): """Raise when a module is supported by the binding, but not installed.""" _msg_extra = "It must be installed separately" def __init__(self, *, missing_package=None, **superclass_kwargs): self.missing_package = missing_package if missing_package is not None: self._msg_extra += " as {missing_package}." super().__init__(missing_package=missing_package, **superclass_kwargs) # Qt API environment variable name QT_API = "QT_API" # Names of the expected PyQt5 api PYQT5_API = ["pyqt5"] PYQT6_API = ["pyqt6"] # Names of the expected PySide2 api PYSIDE2_API = ["pyside2"] # Names of the expected PySide6 api PYSIDE6_API = ["pyside6"] # Minimum supported versions of Qt and the bindings QT5_VERSION_MIN = PYQT5_VERSION_MIN = "5.9.0" PYSIDE2_VERSION_MIN = "5.12.0" QT6_VERSION_MIN = PYQT6_VERSION_MIN = PYSIDE6_VERSION_MIN = "6.2.0" QT_VERSION_MIN = QT5_VERSION_MIN PYQT_VERSION_MIN = PYQT5_VERSION_MIN PYSIDE_VERSION_MIN = PYSIDE2_VERSION_MIN # Detecting if a binding was specified by the user binding_specified = QT_API in os.environ API_NAMES = { "pyqt5": "PyQt5", "pyside2": "PySide2", "pyqt6": "PyQt6", "pyside6": "PySide6", } API = os.environ.get(QT_API, "pyqt5").lower() initial_api = API if API not in API_NAMES: raise PythonQtValueError( f"Specified QT_API={QT_API.lower()!r} is not in valid options: " f"{API_NAMES}", ) is_old_pyqt = is_pyqt46 = False QT5 = PYQT5 = True QT4 = QT6 = PYQT4 = PYQT6 = PYSIDE = PYSIDE2 = PYSIDE6 = False PYQT_VERSION = None PYSIDE_VERSION = None QT_VERSION = None def _parse_int(value): """Convert a value into an integer""" try: return int(value) except ValueError: return 0 def parse(version): """Parse a version string into a tuple of ints""" return tuple(_parse_int(x) for x in version.split('.')) # Unless `FORCE_QT_API` is set, use previously imported Qt Python bindings if not os.environ.get("FORCE_QT_API"): if "PyQt5" in sys.modules: API = initial_api if initial_api in PYQT5_API else "pyqt5" elif "PySide2" in sys.modules: API = initial_api if initial_api in PYSIDE2_API else "pyside2" elif "PyQt6" in sys.modules: API = initial_api if initial_api in PYQT6_API else "pyqt6" elif "PySide6" in sys.modules: API = initial_api if initial_api in PYSIDE6_API else "pyside6" if API in PYQT5_API: try: from PyQt5.QtCore import ( PYQT_VERSION_STR as PYQT_VERSION, ) from PyQt5.QtCore import ( QT_VERSION_STR as QT_VERSION, ) QT5 = PYQT5 = True if sys.platform == "darwin": macos_version = parse(platform.mac_ver()[0]) qt_ver = parse(QT_VERSION) if macos_version < parse("10.10") and qt_ver >= parse("5.9"): raise PythonQtError( "Qt 5.9 or higher only works in " "macOS 10.10 or higher. Your " "program will fail in this " "system.", ) elif macos_version < parse("10.11") and qt_ver >= parse("5.11"): raise PythonQtError( "Qt 5.11 or higher only works in " "macOS 10.11 or higher. Your " "program will fail in this " "system.", ) del macos_version del qt_ver except ImportError: API = "pyside2" else: os.environ[QT_API] = API if API in PYSIDE2_API: try: from PySide2 import __version__ as PYSIDE_VERSION # analysis:ignore from PySide2.QtCore import __version__ as QT_VERSION # analysis:ignore PYQT5 = False QT5 = PYSIDE2 = True if sys.platform == "darwin": macos_version = parse(platform.mac_ver()[0]) qt_ver = parse(QT_VERSION) if macos_version < parse("10.11") and qt_ver >= parse("5.11"): raise PythonQtError( "Qt 5.11 or higher only works in " "macOS 10.11 or higher. Your " "program will fail in this " "system.", ) del macos_version del qt_ver except ImportError: API = "pyqt6" else: os.environ[QT_API] = API if API in PYQT6_API: try: from PyQt6.QtCore import ( PYQT_VERSION_STR as PYQT_VERSION, ) from PyQt6.QtCore import ( QT_VERSION_STR as QT_VERSION, ) QT5 = PYQT5 = False QT6 = PYQT6 = True except ImportError: API = "pyside6" else: os.environ[QT_API] = API if API in PYSIDE6_API: try: from PySide6 import __version__ as PYSIDE_VERSION # analysis:ignore from PySide6.QtCore import __version__ as QT_VERSION # analysis:ignore QT5 = PYQT5 = False QT6 = PYSIDE6 = True except ImportError: raise QtBindingsNotFoundError from None else: os.environ[QT_API] = API # If a correct API name is passed to QT_API and it could not be found, # switches to another and informs through the warning if initial_api != API and binding_specified: warnings.warn( f"Selected binding {initial_api!r} could not be found; " f"falling back to {API!r}", PythonQtWarning, stacklevel=2, ) # Set display name of the Qt API API_NAME = API_NAMES[API] with contextlib.suppress(ImportError, PythonQtError): # QtDataVisualization backward compatibility (QtDataVisualization vs. QtDatavisualization) # Only available for Qt5 bindings > 5.9 on Windows from . import QtDataVisualization as QtDatavisualization # analysis:ignore def _warn_old_minor_version(name, old_version, min_version): """Warn if using a Qt or binding version no longer supported by QtPy.""" warning_message = ( f"{name} version {old_version} is not supported by QtPy. " "To ensure your application works correctly with QtPy, " f"please upgrade to {name} {min_version} or later." ) warnings.warn(warning_message, PythonQtWarning, stacklevel=2) # Warn if using an End of Life or unsupported Qt API/binding minor version if QT_VERSION: if QT5 and (parse(QT_VERSION) < parse(QT5_VERSION_MIN)): _warn_old_minor_version("Qt5", QT_VERSION, QT5_VERSION_MIN) elif QT6 and (parse(QT_VERSION) < parse(QT6_VERSION_MIN)): _warn_old_minor_version("Qt6", QT_VERSION, QT6_VERSION_MIN) if PYQT_VERSION: if PYQT5 and (parse(PYQT_VERSION) < parse(PYQT5_VERSION_MIN)): _warn_old_minor_version("PyQt5", PYQT_VERSION, PYQT5_VERSION_MIN) elif PYQT6 and (parse(PYQT_VERSION) < parse(PYQT6_VERSION_MIN)): _warn_old_minor_version("PyQt6", PYQT_VERSION, PYQT6_VERSION_MIN) elif PYSIDE_VERSION: if PYSIDE2 and (parse(PYSIDE_VERSION) < parse(PYSIDE2_VERSION_MIN)): _warn_old_minor_version("PySide2", PYSIDE_VERSION, PYSIDE2_VERSION_MIN) elif PYSIDE6 and (parse(PYSIDE_VERSION) < parse(PYSIDE6_VERSION_MIN)): _warn_old_minor_version("PySide6", PYSIDE_VERSION, PYSIDE6_VERSION_MIN) git-cola-4.6.1/qtpy/_utils.py000066400000000000000000000121031457126473700161040ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2023- The Spyder Development Team # # Released under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides utility functions for use by QtPy itself.""" from functools import wraps from typing import TYPE_CHECKING import qtpy if TYPE_CHECKING: from qtpy.QtWidgets import QAction def _wrap_missing_optional_dep_error( attr_error, *, import_error, wrapper=qtpy.QtModuleNotInstalledError, **wrapper_kwargs, ): """Create a __cause__-chained wrapper error for a missing optional dep.""" qtpy_error = wrapper(**wrapper_kwargs) import_error.__cause__ = attr_error qtpy_error.__cause__ = import_error return qtpy_error def getattr_missing_optional_dep(name, module_name, optional_names): """Wrap AttributeError in a special error if it matches.""" attr_error = AttributeError( f"module {module_name!r} has no attribute {name!r}", ) if name in optional_names: return _wrap_missing_optional_dep_error( attr_error, **optional_names[name], ) return attr_error def possibly_static_exec(cls, *args, **kwargs): """Call `self.exec` when `self` is given or a static method otherwise.""" if not args and not kwargs: # A special case (`cls.exec_()`) to avoid the function resolving error return cls.exec() if isinstance(args[0], cls): if len(args) == 1 and not kwargs: # A special case (`self.exec_()`) to avoid the function resolving error return args[0].exec() return args[0].exec(*args[1:], **kwargs) return cls.exec(*args, **kwargs) def possibly_static_exec_(cls, *args, **kwargs): """Call `self.exec` when `self` is given or a static method otherwise.""" if not args and not kwargs: # A special case (`cls.exec()`) to avoid the function resolving error return cls.exec_() if isinstance(args[0], cls): if len(args) == 1 and not kwargs: # A special case (`self.exec()`) to avoid the function resolving error return args[0].exec_() return args[0].exec_(*args[1:], **kwargs) return cls.exec_(*args, **kwargs) def add_action(self, *args, old_add_action): """Re-order arguments of `addAction` to backport compatibility with Qt>=6.3.""" from qtpy.QtCore import QObject from qtpy.QtGui import QIcon, QKeySequence action: QAction icon: QIcon text: str shortcut: QKeySequence | QKeySequence.StandardKey | str | int receiver: QObject member: bytes if all( isinstance(arg, t) for arg, t in zip( args, [ str, (QKeySequence, QKeySequence.StandardKey, str, int), QObject, bytes, ], ) ): if len(args) == 2: text, shortcut = args action = old_add_action(self, text) action.setShortcut(shortcut) elif len(args) == 3: text, shortcut, receiver = args action = old_add_action(self, text, receiver) action.setShortcut(shortcut) elif len(args) == 4: text, shortcut, receiver, member = args action = old_add_action(self, text, receiver, member, shortcut) else: return old_add_action(self, *args) return action if all( isinstance(arg, t) for arg, t in zip( args, [ QIcon, str, (QKeySequence, QKeySequence.StandardKey, str, int), QObject, bytes, ], ) ): if len(args) == 3: icon, text, shortcut = args action = old_add_action(self, icon, text) action.setShortcut(QKeySequence(shortcut)) elif len(args) == 4: icon, text, shortcut, receiver = args action = old_add_action(self, icon, text, receiver) action.setShortcut(QKeySequence(shortcut)) elif len(args) == 5: icon, text, shortcut, receiver, member = args action = old_add_action( self, icon, text, receiver, member, QKeySequence(shortcut), ) else: return old_add_action(self, *args) return action return old_add_action(self, *args) def static_method_kwargs_wrapper(func, from_kwarg_name, to_kwarg_name): """ Helper function to manage `from_kwarg_name` to `to_kwarg_name` kwargs name changes in static methods. Makes static methods accept the `from_kwarg_name` kwarg as `to_kwarg_name`. """ @staticmethod @wraps(func) def _from_kwarg_name_to_kwarg_name_(*args, **kwargs): if from_kwarg_name in kwargs: kwargs[to_kwarg_name] = kwargs.pop(from_kwarg_name) return func(*args, **kwargs) return _from_kwarg_name_to_kwarg_name_ git-cola-4.6.1/qtpy/cli.py000066400000000000000000000115211457126473700153570ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The QtPy Contributors # # Released under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provide a CLI to allow configuring developer settings, including mypy.""" # Standard library imports import argparse import json import textwrap def print_version(): """Print the current version of the package.""" import qtpy print("QtPy version", qtpy.__version__) def get_api_status(): """Get the status of each Qt API usage.""" import qtpy return {name: name == qtpy.API for name in qtpy.API_NAMES} def generate_mypy_args(): """Generate a string with always-true/false args to pass to mypy.""" options = {False: "--always-false", True: "--always-true"} apis_active = get_api_status() return " ".join( f"{options[is_active]}={name.upper()}" for name, is_active in apis_active.items() ) def generate_pyright_config_json(): """Generate Pyright config to be used in `pyrightconfig.json`.""" apis_active = get_api_status() return json.dumps( { "defineConstant": { name.upper(): is_active for name, is_active in apis_active.items() }, }, ) def generate_pyright_config_toml(): """Generate a Pyright config to be used in `pyproject.toml`.""" apis_active = get_api_status() return "[tool.pyright.defineConstant]\n" + "\n".join( f"{name.upper()} = {str(is_active).lower()}" for name, is_active in apis_active.items() ) def print_mypy_args(): """Print the generated mypy args to stdout.""" print(generate_mypy_args()) def print_pyright_config_json(): """Print the generated Pyright JSON config to stdout.""" print(generate_pyright_config_json()) def print_pyright_config_toml(): """Print the generated Pyright TOML config to stdout.""" print(generate_pyright_config_toml()) def print_pyright_configs(): """Print the generated Pyright configs to stdout.""" print("pyrightconfig.json:") print_pyright_config_json() print() print("pyproject.toml:") print_pyright_config_toml() def generate_arg_parser(): """Generate the argument parser for the dev CLI for QtPy.""" parser = argparse.ArgumentParser( description="Features to support development with QtPy.", ) parser.set_defaults(func=parser.print_help) parser.add_argument( "--version", action="store_const", dest="func", const=print_version, help="If passed, will print the version and exit", ) cli_subparsers = parser.add_subparsers( title="Subcommands", help="Subcommand to run", metavar="Subcommand", ) # Parser for the MyPy args subcommand mypy_args_parser = cli_subparsers.add_parser( name="mypy-args", help="Generate command line arguments for using mypy with QtPy.", formatter_class=argparse.RawTextHelpFormatter, description=textwrap.dedent( """ Generate command line arguments for using mypy with QtPy. This will generate strings similar to the following which help guide mypy through which library QtPy would have used so that mypy can get the proper underlying type hints. --always-false=PYQT5 --always-false=PYQT6 --always-true=PYSIDE2 --always-false=PYSIDE6 It can be used as follows on Bash or a similar shell: mypy --package mypackage $(qtpy mypy-args) """, ), ) mypy_args_parser.set_defaults(func=print_mypy_args) # Parser for the Pyright config subcommand pyright_config_parser = cli_subparsers.add_parser( name="pyright-config", help="Generate Pyright config for using Pyright with QtPy.", formatter_class=argparse.RawTextHelpFormatter, description=textwrap.dedent( """ Generate Pyright config for using Pyright with QtPy. This will generate config sections to be included in a Pyright config file (either `pyrightconfig.json` or `pyproject.toml`) which help guide Pyright through which library QtPy would have used so that Pyright can get the proper underlying type hints. """, ), ) pyright_config_parser.set_defaults(func=print_pyright_configs) return parser def main(args=None): """Run the development CLI for QtPy.""" parser = generate_arg_parser() parsed_args = parser.parse_args(args=args) reserved_params = {"func"} cleaned_args = { key: value for key, value in vars(parsed_args).items() if key not in reserved_params } parsed_args.func(**cleaned_args) git-cola-4.6.1/qtpy/compat.py000066400000000000000000000127701457126473700161020ustar00rootroot00000000000000# # Copyright © 2009- The Spyder Development Team # Licensed under the terms of the MIT License """ Compatibility functions """ import sys from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, ) from .QtWidgets import QFileDialog TEXT_TYPES = (str,) def is_text_string(obj): """Return True if `obj` is a text string, False if it is anything else, like binary data.""" return isinstance(obj, str) def to_text_string(obj, encoding=None): """Convert `obj` to (unicode) text string""" if encoding is None: return str(obj) if isinstance(obj, str): # In case this function is not used properly, this could happen return obj return str(obj, encoding) # ============================================================================= # QVariant conversion utilities # ============================================================================= PYQT_API_1 = False def to_qvariant(obj=None): # analysis:ignore """Convert Python object to QVariant This is a transitional function from PyQt API#1 (QVariant exist) to PyQt API#2 and Pyside (QVariant does not exist)""" return obj def from_qvariant(qobj=None, pytype=None): # analysis:ignore """Convert QVariant object to Python object This is a transitional function from PyQt API #1 (QVariant exist) to PyQt API #2 and Pyside (QVariant does not exist)""" return qobj # ============================================================================= # Wrappers around QFileDialog static methods # ============================================================================= def getexistingdirectory( parent=None, caption="", basedir="", options=QFileDialog.ShowDirsOnly, ): """Wrapper around QtGui.QFileDialog.getExistingDirectory static method Compatible with PyQt >=v4.4 (API #1 and #2) and PySide >=v1.0""" # Calling QFileDialog static method if sys.platform == "win32": # On Windows platforms: redirect standard outputs _temp1, _temp2 = sys.stdout, sys.stderr sys.stdout, sys.stderr = None, None try: result = QFileDialog.getExistingDirectory( parent, caption, basedir, options, ) finally: if sys.platform == "win32": # On Windows platforms: restore standard outputs sys.stdout, sys.stderr = _temp1, _temp2 if not is_text_string(result): # PyQt API #1 result = to_text_string(result) return result def _qfiledialog_wrapper( attr, parent=None, caption="", basedir="", filters="", selectedfilter="", options=None, ): if options is None: options = QFileDialog.Option(0) func = getattr(QFileDialog, attr) # Calling QFileDialog static method if sys.platform == "win32": # On Windows platforms: redirect standard outputs _temp1, _temp2 = sys.stdout, sys.stderr sys.stdout, sys.stderr = None, None result = func(parent, caption, basedir, filters, selectedfilter, options) if sys.platform == "win32": # On Windows platforms: restore standard outputs sys.stdout, sys.stderr = _temp1, _temp2 output, selectedfilter = result # Always returns the tuple (output, selectedfilter) return output, selectedfilter def getopenfilename( parent=None, caption="", basedir="", filters="", selectedfilter="", options=None, ): """Wrapper around QtGui.QFileDialog.getOpenFileName static method Returns a tuple (filename, selectedfilter) -- when dialog box is canceled, returns a tuple of empty strings Compatible with PyQt >=v4.4 (API #1 and #2) and PySide >=v1.0""" return _qfiledialog_wrapper( "getOpenFileName", parent=parent, caption=caption, basedir=basedir, filters=filters, selectedfilter=selectedfilter, options=options, ) def getopenfilenames( parent=None, caption="", basedir="", filters="", selectedfilter="", options=None, ): """Wrapper around QtGui.QFileDialog.getOpenFileNames static method Returns a tuple (filenames, selectedfilter) -- when dialog box is canceled, returns a tuple (empty list, empty string) Compatible with PyQt >=v4.4 (API #1 and #2) and PySide >=v1.0""" return _qfiledialog_wrapper( "getOpenFileNames", parent=parent, caption=caption, basedir=basedir, filters=filters, selectedfilter=selectedfilter, options=options, ) def getsavefilename( parent=None, caption="", basedir="", filters="", selectedfilter="", options=None, ): """Wrapper around QtGui.QFileDialog.getSaveFileName static method Returns a tuple (filename, selectedfilter) -- when dialog box is canceled, returns a tuple of empty strings Compatible with PyQt >=v4.4 (API #1 and #2) and PySide >=v1.0""" return _qfiledialog_wrapper( "getSaveFileName", parent=parent, caption=caption, basedir=basedir, filters=filters, selectedfilter=selectedfilter, options=options, ) # ============================================================================= def isalive(obj): """Wrapper around sip.isdeleted and shiboken.isValid which tests whether an object is currently alive.""" if PYQT5 or PYQT6: from . import sip return not sip.isdeleted(obj) if PYSIDE2 or PYSIDE6: from . import shiboken return shiboken.isValid(obj) return None git-cola-4.6.1/qtpy/enums_compat.py000066400000000000000000000026561457126473700173130ustar00rootroot00000000000000# Copyright © 2009- The Spyder Development Team # Copyright © 2012- University of North Carolina at Chapel Hill # Luke Campagnola ('luke.campagnola@%s.com' % 'gmail') # Ogi Moore ('ognyan.moore@%s.com' % 'gmail') # KIU Shueng Chuan ('nixchuan@%s.com' % 'gmail') # Licensed under the terms of the MIT License """ Compatibility functions for scoped and unscoped enum access. """ from . import PYQT6 if PYQT6: import enum from . import sip def promote_enums(module): """ Search enums in the given module and allow unscoped access. Taken from: https://github.com/pyqtgraph/pyqtgraph/blob/pyqtgraph-0.12.1/pyqtgraph/Qt.py#L331-L377 and adapted to also copy enum values aliased under different names. """ class_names = [name for name in dir(module) if name.startswith("Q")] for class_name in class_names: klass = getattr(module, class_name) if not isinstance(klass, sip.wrappertype): continue attrib_names = [name for name in dir(klass) if name[0].isupper()] for attrib_name in attrib_names: attrib = getattr(klass, attrib_name) if not isinstance(attrib, enum.EnumMeta): continue for name, value in attrib.__members__.items(): setattr(klass, name, value) git-cola-4.6.1/qtpy/py.typed000066400000000000000000000000001457126473700157230ustar00rootroot00000000000000git-cola-4.6.1/qtpy/shiboken.py000066400000000000000000000011101457126473700164030ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides access to shiboken.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5 or PYQT6: raise QtBindingMissingModuleError(name="shiboken") elif PYSIDE2: from shiboken2 import * elif PYSIDE6: from shiboken6 import * git-cola-4.6.1/qtpy/sip.py000066400000000000000000000010761457126473700154070ustar00rootroot00000000000000# ----------------------------------------------------------------------------- # Copyright © 2009- The Spyder Development Team # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Provides access to sip.""" from . import ( PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtBindingMissingModuleError, ) if PYQT5: from PyQt5.sip import * elif PYQT6: from PyQt6.sip import * elif PYSIDE2 or PYSIDE6: raise QtBindingMissingModuleError(name="sip") git-cola-4.6.1/qtpy/uic.py000066400000000000000000000265771457126473700154110ustar00rootroot00000000000000from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6 if PYQT6: from PyQt6.uic import * elif PYQT5: from PyQt5.uic import * else: __all__ = ["loadUi", "loadUiType"] # In PySide, loadUi does not exist, so we define it using QUiLoader, and # then make sure we expose that function. This is adapted from qt-helpers # which was released under a 3-clause BSD license: # qt-helpers - a common front-end to various Qt modules # # Copyright (c) 2015, Chris Beaumont and Thomas Robitaille # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the # distribution. # * Neither the name of the Glue project nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Which itself was based on the solution at # # https://gist.github.com/cpbotha/1b42a20c8f3eb9bb7cb8 # # which was released under the MIT license: # # Copyright (c) 2011 Sebastian Wiesner # Modifications by Charl Botha # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. if PYSIDE6: from PySide6.QtCore import QMetaObject from PySide6.QtUiTools import QUiLoader, loadUiType elif PYSIDE2: from PySide2.QtCore import QMetaObject from PySide2.QtUiTools import QUiLoader try: from xml.etree.ElementTree import Element from pyside2uic import compileUi # Patch UIParser as xml.etree.Elementree.Element.getiterator # was deprecated since Python 3.2 and removed in Python 3.9 # https://docs.python.org/3.9/whatsnew/3.9.html#removed from pyside2uic.uiparser import UIParser class ElemPatched(Element): def getiterator(self, *args, **kwargs): return self.iter(*args, **kwargs) def readResources(self, elem): return self._readResources(ElemPatched(elem)) UIParser._readResources = UIParser.readResources UIParser.readResources = readResources except ImportError: pass class UiLoader(QUiLoader): """ Subclass of :class:`~PySide.QtUiTools.QUiLoader` to create the user interface in a base instance. Unlike :class:`~PySide.QtUiTools.QUiLoader` itself this class does not create a new instance of the top-level widget, but creates the user interface in an existing instance of the top-level class if needed. This mimics the behaviour of :func:`PyQt4.uic.loadUi`. """ def __init__(self, baseinstance, customWidgets=None): """ Create a loader for the given ``baseinstance``. The user interface is created in ``baseinstance``, which must be an instance of the top-level class in the user interface to load, or a subclass thereof. ``customWidgets`` is a dictionary mapping from class name to class object for custom widgets. Usually, this should be done by calling registerCustomWidget on the QUiLoader, but with PySide 1.1.2 on Ubuntu 12.04 x86_64 this causes a segfault. ``parent`` is the parent object of this loader. """ QUiLoader.__init__(self, baseinstance) self.baseinstance = baseinstance if customWidgets is None: self.customWidgets = {} else: self.customWidgets = customWidgets def createWidget(self, class_name, parent=None, name=""): """ Function that is called for each widget defined in ui file, overridden here to populate baseinstance instead. """ if parent is None and self.baseinstance: # supposed to create the top-level widget, return the base # instance instead return self.baseinstance # For some reason, Line is not in the list of available # widgets, but works fine, so we have to special case it here. if class_name in self.availableWidgets() or class_name == "Line": # create a new widget for child widgets widget = QUiLoader.createWidget( self, class_name, parent, name, ) else: # If not in the list of availableWidgets, must be a custom # widget. This will raise KeyError if the user has not # supplied the relevant class_name in the dictionary or if # customWidgets is empty. try: widget = self.customWidgets[class_name](parent) except KeyError as error: raise NoCustomWidget( f"No custom widget {class_name} " "found in customWidgets", ) from error if self.baseinstance: # set an attribute for the new child widget on the base # instance, just like PyQt4.uic.loadUi does. setattr(self.baseinstance, name, widget) return widget def _get_custom_widgets(ui_file): """ This function is used to parse a ui file and look for the section, then automatically load all the custom widget classes. """ import importlib from xml.etree.ElementTree import ElementTree # Parse the UI file etree = ElementTree() ui = etree.parse(ui_file) # Get the customwidgets section custom_widgets = ui.find("customwidgets") if custom_widgets is None: return {} custom_widget_classes = {} for custom_widget in list(custom_widgets): cw_class = custom_widget.find("class").text cw_header = custom_widget.find("header").text module = importlib.import_module(cw_header) custom_widget_classes[cw_class] = getattr(module, cw_class) return custom_widget_classes def loadUi(uifile, baseinstance=None, workingDirectory=None): """ Dynamically load a user interface from the given ``uifile``. ``uifile`` is a string containing a file name of the UI file to load. If ``baseinstance`` is ``None``, the a new instance of the top-level widget will be created. Otherwise, the user interface is created within the given ``baseinstance``. In this case ``baseinstance`` must be an instance of the top-level widget class in the UI file to load, or a subclass thereof. In other words, if you've created a ``QMainWindow`` interface in the designer, ``baseinstance`` must be a ``QMainWindow`` or a subclass thereof, too. You cannot load a ``QMainWindow`` UI file with a plain :class:`~PySide.QtGui.QWidget` as ``baseinstance``. :method:`~PySide.QtCore.QMetaObject.connectSlotsByName()` is called on the created user interface, so you can implemented your slots according to its conventions in your widget class. Return ``baseinstance``, if ``baseinstance`` is not ``None``. Otherwise return the newly created instance of the user interface. """ # We parse the UI file and import any required custom widgets customWidgets = _get_custom_widgets(uifile) loader = UiLoader(baseinstance, customWidgets) if workingDirectory is not None: loader.setWorkingDirectory(workingDirectory) widget = loader.load(uifile) QMetaObject.connectSlotsByName(widget) return widget if PYSIDE2: def loadUiType(uifile, from_imports=False): """Load a .ui file and return the generated form class and the Qt base class. The "loadUiType" command convert the ui file to py code in-memory first and then execute it in a special frame to retrieve the form_class. Credit: https://stackoverflow.com/a/14195313/15954282 """ import sys from io import StringIO from xml.etree.ElementTree import ElementTree from . import QtWidgets # Parse the UI file etree = ElementTree() ui = etree.parse(uifile) widget_class = ui.find("widget").get("class") form_class = ui.find("class").text with open(uifile, encoding="utf-8") as fd: code_stream = StringIO() frame = {} compileUi(fd, code_stream, indent=0, from_imports=from_imports) pyc = compile(code_stream.getvalue(), "", "exec") exec(pyc, frame) # Fetch the base_class and form class based on their type in the # xml from designer form_class = frame["Ui_%s" % form_class] base_class = getattr(QtWidgets, widget_class) return form_class, base_class git-cola-4.6.1/setup.cfg000066400000000000000000000033001457126473700150560ustar00rootroot00000000000000[metadata] name = git-cola long_description = Git Cola is a powerful Git GUI with a slick and intuitive user interface. url = https://gitlab.com/git-cola/git-cola platform = any [upload_sphinx] upload-dir = docs/_build/html [build_sphinx] all_files = 1 build-dir = docs/_build source-dir = docs/ [options] packages = cola cola.bin cola.i18n cola.i18n.glossary cola.icons cola.icons.dark cola.models cola.widgets include_package_data = true install_requires = importlib_metadata; python_version<"3.8" polib >= 1.0.0 qtpy >= 1.1.0 zip_safe = false [options.package_data] cola = bin/* i18n/* icons/*.svg icons/dark/*.svg [options.data_files] share/applications = share/applications/git-cola.desktop share/applications/git-cola-folder-handler.desktop share/applications/git-dag.desktop share/doc/git-cola = docs/hotkeys.html docs/hotkeys_de.html docs/hotkeys_zh_CN.html docs/hotkeys_zh_TW.html share/icons/hicolor/scalable/apps = cola/icons/git-cola.svg share/metainfo = share/metainfo/git-cola.appdata.xml share/metainfo/git-dag.appdata.xml [options.extras_require] testing = # upstream pytest >= 6 pytest-checkdocs >= 2.4 pytest-cov pytest-enabler >= 2.2 pytest-ruff >= 0.2.1 # local docs = # upstream furo sphinx rst.linker >= 1.9 # local sphinx_rtd_theme # "extras" are optional packages that enable additional features when present. extras = # Enables the "Send to Trash" feature. send2trash # Enables macOS-specific appearance themes. pyobjc; sys_platform == 'darwin' # Developer tools. dev = cercis # Build and packaging tools. build = build pynsist twine wheel # Extra packages when installing for specific platforms or Qt versions. pyqt5 = PyQt5 pyqt6 = PyQt6 git-cola-4.6.1/share/000077500000000000000000000000001457126473700143435ustar00rootroot00000000000000git-cola-4.6.1/share/applications/000077500000000000000000000000001457126473700170315ustar00rootroot00000000000000git-cola-4.6.1/share/applications/git-cola-folder-handler.desktop000066400000000000000000000003311457126473700250040ustar00rootroot00000000000000[Desktop Entry] Name=Git Cola TryExec=git-cola Exec=git-cola --repo %f Icon=git-cola NoDisplay=true Terminal=false StartupNotify=true Type=Application Categories=Development;RevisionControl; MimeType=inode/directory; git-cola-4.6.1/share/applications/git-cola.desktop000066400000000000000000000005251457126473700221250ustar00rootroot00000000000000[Desktop Entry] Name=Git Cola Comment=The highly caffeinated Git GUI Comment[cs]=Git GUI s vysokým obsahem kofeinu Comment[zh_TW]=高咖啡因含量的 Git 圖形介面 TryExec=git-cola Exec=git-cola --prompt Icon=git-cola StartupNotify=true Terminal=false Type=Application Categories=Development;RevisionControl; X-KDE-SubstituteUID=false git-cola-4.6.1/share/applications/git-dag.desktop000066400000000000000000000003211457126473700217340ustar00rootroot00000000000000[Desktop Entry] Name=Git DAG Comment=Git DAG visualizer Exec=git-dag --prompt Icon=git-cola StartupNotify=true Terminal=false Type=Application Categories=Development;RevisionControl; X-KDE-SubstituteUID=false git-cola-4.6.1/share/doc/000077500000000000000000000000001457126473700151105ustar00rootroot00000000000000git-cola-4.6.1/share/doc/git-cola000077700000000000000000000000001457126473700200262../../docsustar00rootroot00000000000000git-cola-4.6.1/share/metainfo/000077500000000000000000000000001457126473700161455ustar00rootroot00000000000000git-cola-4.6.1/share/metainfo/git-cola.appdata.xml000066400000000000000000000033231457126473700220000ustar00rootroot00000000000000 git-cola.desktop CC0-1.0 GPL-2.0 Git Cola David Aguilar Sleek and powerful Git GUI

git-cola is a simple, powerful, and feature-rich GUI for git that provides an easy way to interact with Git repositories.

git-cola.desktop https://git-cola.github.io/images/screenshot-main-linux.png Git Cola running on Linux https://git-cola.github.io/
git-cola-4.6.1/share/metainfo/git-dag.appdata.xml000066400000000000000000000025711457126473700216210ustar00rootroot00000000000000 git-dag.desktop CC0-1.0 GPL-2.0 Git DAG David Aguilar

git-dag is an advanced git DAG visualizer

git-dag.desktop https://git-cola.github.io/
git-cola-4.6.1/test/000077500000000000000000000000001457126473700142205ustar00rootroot00000000000000git-cola-4.6.1/test/__init__.py000066400000000000000000000000001457126473700163170ustar00rootroot00000000000000git-cola-4.6.1/test/app_test.py000066400000000000000000000006541457126473700164160ustar00rootroot00000000000000import argparse from cola import app def test_setup_environment(): # If the function doesn't throw an exception we are happy. assert hasattr(app, 'setup_environment') app.setup_environment() def test_add_common_arguments(): # If the function doesn't throw an exception we are happy. parser = argparse.ArgumentParser() assert hasattr(app, 'add_common_arguments') app.add_common_arguments(parser) git-cola-4.6.1/test/branch_test.py000066400000000000000000000150571457126473700170760ustar00rootroot00000000000000"""Tests related to the branches widget""" from cola.widgets import branch from .helper import Mock def test_create_tree_entries(): names = [ 'abc', 'cat/abc', 'cat/def', 'xyz/xyz', ] root = branch.create_tree_entries(names) expect = 3 actual = len(root.children) assert expect == actual # 'abc' abc = root.children[0] expect = 'abc' actual = abc.basename assert expect == actual expect = 'abc' actual = abc.refname assert expect == actual expect = [] actual = abc.children assert expect == actual # 'cat' cat = root.children[1] expect = 'cat' actual = 'cat' assert expect == actual assert cat.refname is None expect = 2 actual = len(cat.children) assert expect == actual # 'cat/abc' cat_abc = cat.children[0] expect = 'abc' actual = cat_abc.basename assert expect == actual expect = 'cat/abc' actual = cat_abc.refname assert expect == actual expect = [] actual = cat_abc.children assert expect == actual # 'cat/def' cat_def = cat.children[1] expect = 'def' actual = cat_def.basename assert expect == actual expect = 'cat/def' actual = cat_def.refname assert expect == actual expect = [] actual = cat_def.children assert expect == actual # 'xyz' xyz = root.children[2] expect = 'xyz' actual = xyz.basename assert expect == actual assert xyz.refname is None expect = 1 actual = len(xyz.children) assert expect == actual # 'xyz/xyz' xyz_xyz = xyz.children[0] expect = 'xyz' actual = xyz_xyz.basename assert expect == actual expect = 'xyz/xyz' actual = xyz_xyz.refname assert expect == actual expect = [] actual = xyz_xyz.children assert expect == actual def test_create_name_dict(): """Test transforming unix path-like names into a nested dict""" branches = [ 'top_1/child_1/child_1_1', 'top_1/child_1/child_1_2', 'top_1/child_2/child_2_1/child_2_1_1', 'top_1/child_2/child_2_1/child_2_1_2', ] inner_child = {'child_2_1_2': {}, 'child_2_1_1': {}} expect = { 'top_1': { 'child_1': {'child_1_2': {}, 'child_1_1': {}}, 'child_2': {'child_2_1': inner_child}, } } actual = branch.create_name_dict(branches) assert expect == actual def test_create_toplevel_item(): names = [ 'child_1', 'child_2/child_2_1', 'child_2/child_2_2', ] tree = branch.create_tree_entries(names) tree.basename = 'top' top = branch.create_toplevel_item(tree) expect = 'top' actual = top.name assert expect == actual expect = 2 actual = top.childCount() assert expect == actual expect = 'child_1' actual = top.child(0).name assert expect == actual expect = 'child_1' actual = top.child(0).refname assert expect == actual expect = 'child_2' actual = top.child(1).name assert expect == actual assert top.child(1).refname is None expect = 2 actual = top.child(1).childCount() assert expect == actual expect = 'child_2_1' actual = top.child(1).child(0).name assert expect == actual expect = 'child_2_2' actual = top.child(1).child(1).name assert expect == actual expect = 'child_2/child_2_1' actual = top.child(1).child(0).refname assert expect == actual expect = 'child_2/child_2_2' actual = top.child(1).child(1).refname assert expect == actual def test_get_toplevel_item(): items = _create_top_item() actual = branch.get_toplevel_item(items['child_1']) assert items['top'] is actual actual = branch.get_toplevel_item(items['sub_child_2_1']) assert items['top'] is actual def test_refname_attribute(): items = _create_top_item() actual = items['child_1'].refname expect = 'child_1' assert expect == actual actual = items['sub_child_2_2'].refname expect = 'child_2/sub_child_2_2' assert expect == actual def test_should_return_a_valid_child_on_find_child(): """Test the find_child function.""" items = _create_top_item() child = branch.find_by_refname(items['top'], 'child_1') assert child.refname == 'child_1' child = branch.find_by_refname(items['top'], 'child_2/sub_child_2_2') assert child.name == 'sub_child_2_2' def test_should_return_empty_state_on_save_state(): """Test the save_state function.""" top = _create_item('top', None, False) tree_helper = branch.BranchesTreeHelper(Mock()) actual = tree_helper.save_state(top) assert {'top': {'children': {}, 'expanded': False, 'selected': False}} == actual def test_should_return_a_valid_state_on_save_state(): """Test the save_state function.""" items = _create_top_item() tree_helper = branch.BranchesTreeHelper(Mock()) actual = tree_helper.save_state(items['top']) expect = { 'top': { 'children': { 'child_1': { 'children': {}, 'expanded': False, 'selected': False, }, 'child_2': { 'children': { 'sub_child_2_1': { 'children': {}, 'expanded': False, 'selected': False, }, 'sub_child_2_2': { 'children': {}, 'expanded': False, 'selected': False, }, }, 'expanded': True, 'selected': False, }, }, 'expanded': True, 'selected': False, } } assert expect == actual def _create_top_item(): top = _create_item('top', None, True) child_1 = _create_item('child_1', 'child_1', False) child_2 = _create_item('child_2', None, True) sub_child_2_1 = _create_item('sub_child_2_1', 'child_2/sub_child_2_1', False) sub_child_2_2 = _create_item('sub_child_2_2', 'child_2/sub_child_2_2', False) child_2.addChildren([sub_child_2_1, sub_child_2_2]) top.addChildren([child_1, child_2]) return { 'top': top, 'child_1': child_1, 'sub_child_2_1': sub_child_2_1, 'sub_child_2_2': sub_child_2_2, } def _create_item(name, refname, expanded): item = branch.BranchTreeWidgetItem(name, refname=refname) item.isExpanded = Mock(return_value=expanded) return item git-cola-4.6.1/test/browse_model_test.py000066400000000000000000000032551457126473700203170ustar00rootroot00000000000000"""Test interfaces used by the browser (git cola browse)""" from cola import core from cola import gitcmds from . import helper from .helper import app_context # Prevent unused imports lint errors. assert app_context is not None def test_stage_paths_untracked(app_context): """Test stage_paths() with an untracked file.""" model = app_context.model core.makedirs('foo/bar') helper.touch('foo/bar/baz') gitcmds.add(app_context, ['foo']) app_context.model.update_file_status() assert 'foo/bar/baz' in model.staged assert 'foo/bar/baz' not in model.modified assert 'foo/bar/baz' not in model.untracked def test_unstage_paths(app_context): """Test a simple usage of unstage_paths().""" helper.commit_files() helper.write_file('A', 'change') helper.run_git('add', 'A') model = app_context.model gitcmds.unstage_paths(app_context, ['A']) model.update_status() assert 'A' not in model.staged assert 'A' in model.modified def test_unstage_paths_init(app_context): """Test unstage_paths() on the root commit.""" model = app_context.model gitcmds.unstage_paths(app_context, ['A']) model.update_status() assert 'A' not in model.staged assert 'A' in model.untracked def test_unstage_paths_subdir(app_context): """Test unstage_paths() in a subdirectory.""" helper.run_git('commit', '-m', 'initial commit') core.makedirs('foo/bar') helper.touch('foo/bar/baz') helper.run_git('add', 'foo/bar/baz') model = app_context.model gitcmds.unstage_paths(app_context, ['foo']) model.update_status() assert 'foo/bar/baz' in model.untracked assert 'foo/bar/baz' not in model.staged git-cola-4.6.1/test/cmds_test.py000066400000000000000000000156061457126473700165670ustar00rootroot00000000000000"""Test the cmds module""" from cola import cmds from cola.compat import uchr from .helper import Mock, patch def test_Commit_strip_comments(): """Ensure that commit messages are stripped of comments""" msg = 'subject\n\n#comment\nbody' expect = 'subject\n\nbody\n' actual = cmds.Commit.strip_comments(msg) assert expect == actual def test_commit_strip_comments_unicode(): """Ensure that unicode is preserved in stripped commit messages""" msg = uchr(0x1234) + '\n\n#comment\nbody' expect = uchr(0x1234) + '\n\nbody\n' actual = cmds.Commit.strip_comments(msg) assert expect == actual def test_unix_path_win32(): path = r'Z:\Program Files\git-cola\bin\git-dag' expect = '/Z/Program Files/git-cola/bin/git-dag' actual = cmds.unix_path(path, is_win32=lambda: True) assert expect == actual def test_unix_path_network_win32(): path = r'\\Z\Program Files\git-cola\bin\git-dag' expect = '//Z/Program Files/git-cola/bin/git-dag' actual = cmds.unix_path(path, is_win32=lambda: True) assert expect == actual def test_unix_path_is_a_noop_on_sane_platforms(): path = r'/:we/don\t/need/no/stinking/badgers!' expect = path actual = cmds.unix_path(path, is_win32=lambda: False) assert expect == actual def test_context_edit_command(): context = Mock() model = context.model cmd = cmds.EditModel(context) cmd.new_diff_text = 'test_diff_text' cmd.new_diff_type = 'test_diff_type' cmd.new_mode = 'test_mode' cmd.new_filename = 'test_filename' cmd.do() model.set_diff_text.assert_called_once_with('test_diff_text') model.set_diff_type.assert_called_once_with('test_diff_type') model.set_mode.assert_called_once_with('test_mode') assert model.filename == 'test_filename' @patch('cola.interaction.Interaction.confirm') def test_submodule_add(confirm): # "git submodule" should not be called if the answer is "no" context = Mock() url = 'url' path = '' reference = '' branch = '' depth = 0 cmd = cmds.SubmoduleAdd(context, url, path, branch, depth, reference) confirm.return_value = False cmd.do() assert not context.git.submodule.called expect = ['--', 'url'] actual = cmd.get_args() assert expect == actual cmd.path = 'path' expect = ['--', 'url', 'path'] actual = cmd.get_args() assert expect == actual cmd.reference = 'ref' expect = ['--reference', 'ref', '--', 'url', 'path'] actual = cmd.get_args() assert expect == actual cmd.branch = 'branch' expect = ['--branch', 'branch', '--reference', 'ref', '--', 'url', 'path'] actual = cmd.get_args() assert expect == actual cmd.reference = '' cmd.branch = '' cmd.depth = 1 expect = ['--depth', '1', '--', 'url', 'path'] actual = cmd.get_args() assert expect == actual # Run the command and assert that "git submodule" was called. confirm.return_value = True context.git.submodule.return_value = (0, '', '') cmd.do() context.git.submodule.assert_called_once_with('add', *expect) assert context.model.update_file_status.called assert context.model.update_submodules_list.called @patch('cola.version.check_git') @patch('cola.interaction.Interaction.confirm') def test_submodule_update(confirm, check_git): context = Mock() path = 'sub/path' update_path_cmd = cmds.SubmoduleUpdate(context, path) update_all_cmd = cmds.SubmodulesUpdate(context) # Nothing is called when confirm() returns False. confirm.return_value = False update_path_cmd.do() assert not context.git.submodule.called update_all_cmd.do() assert not context.git.submodule.called # Confirm command execution. confirm.return_value = True # Test the old command-line arguments first check_git.return_value = False expect = ['update', '--', 'sub/path'] actual = update_path_cmd.get_args() assert expect == actual context.model.update_file_status = Mock() context.git.submodule = Mock(return_value=(0, '', '')) update_path_cmd.do() context.git.submodule.assert_called_once_with(*expect) assert context.model.update_file_status.called expect = ['update'] actual = update_all_cmd.get_args() assert expect == actual context.model.update_file_status = Mock() context.git.submodule = Mock(return_value=(0, '', '')) update_all_cmd.do() context.git.submodule.assert_called_once_with(*expect) assert context.model.update_file_status.called # Test the new command-line arguments (git v1.6.5+) check_git.return_value = True expect = ['update', '--recursive', '--', 'sub/path'] actual = update_path_cmd.get_args() assert expect == actual context.model.update_file_status = Mock() context.git.submodule = Mock(return_value=(0, '', '')) update_path_cmd.do() context.git.submodule.assert_called_once_with(*expect) assert context.model.update_file_status.called expect = ['update', '--recursive'] actual = update_all_cmd.get_args() assert expect == actual context.model.update_file_status = Mock() context.git.submodule = Mock(return_value=(0, '', '')) update_all_cmd.do() context.git.submodule.assert_called_once_with(*expect) assert context.model.update_file_status.called @patch('cola.cmds.Interaction') @patch('cola.cmds.prefs') def test_undo_last_commit_confirms_action(prefs, interaction): """Test the behavior around confirmation of UndoLastCommit actions""" context = Mock() context.model = Mock() # First, test what happens when the commit is published and we say "yes". prefs.check_published_commits = Mock(return_value=True) context.model.is_commit_published = Mock(return_value=True) interaction.confirm = Mock(return_value=True) cmd = cmds.UndoLastCommit(context) assert cmd.confirm() context.model.is_commit_published.assert_called_once() interaction.confirm.assert_called_once() # Now, test what happens when we say "no". interaction.confirm = Mock(return_value=False) assert not cmd.confirm() interaction.confirm.assert_called_once() # Now check what happens when the commit is published but our preferences # say to not check for published commits. prefs.check_published_commits = Mock(return_value=False) context.model.is_commit_published = Mock(return_value=True) interaction.confirm = Mock(return_value=True) assert cmd.confirm() context.model.is_commit_published.assert_not_called() interaction.confirm.assert_called_once() # Lastly, check what when the commit is not published and we do check # for published commits. prefs.check_published_commits = Mock(return_value=True) context.model.is_commit_published = Mock(return_value=False) interaction.confirm = Mock(return_value=True) assert cmd.confirm() context.model.is_commit_published.assert_called_once() interaction.confirm.assert_called_once() git-cola-4.6.1/test/compat_test.py000066400000000000000000000005371457126473700171210ustar00rootroot00000000000000"""Tests the compat module""" import os from cola import compat def test_setenv(): """Test the core.decode function""" key = 'COLA_UNICODE_TEST' value = '字龍' compat.setenv(key, value) assert key in os.environ assert os.getenv(key) compat.unsetenv(key) assert key not in os.environ assert not os.getenv(key) git-cola-4.6.1/test/core_test.py000066400000000000000000000027701457126473700165670ustar00rootroot00000000000000"""Tests the cola.core module's unicode handling""" from cola import core from . import helper def test_core_decode(): """Test the core.decode function""" filename = helper.fixture('unicode.txt') expect = core.decode(core.encode('unicøde')) actual = core.read(filename).strip() assert expect == actual def test_core_encode(): """Test the core.encode function""" filename = helper.fixture('unicode.txt') expect = core.encode('unicøde') actual = core.encode(core.read(filename).strip()) assert expect == actual def test_decode_None(): """Ensure that decode(None) returns None""" expect = None actual = core.decode(None) assert expect == actual def test_decode_utf8(): filename = helper.fixture('cyrillic-utf-8.txt') actual = core.read(filename) assert actual.encoding == 'utf-8' def test_decode_non_utf8(): filename = helper.fixture('cyrillic-cp1251.txt') actual = core.read(filename) assert actual.encoding == 'iso-8859-15' def test_decode_non_utf8_string(): filename = helper.fixture('cyrillic-cp1251.txt') with open(filename, 'rb') as f: content = f.read() actual = core.decode(content) assert actual.encoding == 'iso-8859-15' def test_guess_mimetype(): value = '字龍.txt' expect = 'text/plain' actual = core.guess_mimetype(value) assert expect == actual # This function is robust to bytes vs. unicode actual = core.guess_mimetype(core.encode(value)) assert expect == actual git-cola-4.6.1/test/dag_test.py000066400000000000000000000077551457126473700164020ustar00rootroot00000000000000"""Tests DAG functionality""" import pytest from cola.models import dag from .helper import app_context from .helper import patch # Prevent unused imports lint errors. assert app_context is not None LOG_LINES = """ ad454b189fe5785af397fd6067cf103268b6626e^A^A (tag: refs/tags/v0.0)^ADavid Aguilar^AFri Nov 30 00:03:28 2007 -0800^Adavvid@gmail.com^Afirst cut of ugit 1ba04ad185cf9f04c56c8482e9a73ef1bd35c695^Aad454b189fe5785af397fd6067cf103268b6626e^A^ADavid Aguilar^AFri Nov 30 05:07:47 2007 -0800^Adavvid@gmail.com^Aupdated model/view/controller api fa5ad6c38be603e2ffd1f9b722a3a5c675f63de2^A1ba04ad185cf9f04c56c8482e9a73ef1bd35c695^A^ADavid Aguilar^AFri Nov 30 05:19:05 2007 -0800^Adavvid@gmail.com^AAvoid multiple signoffs 103766573cd4e6799d3ee792bcd632b92cf7c6c0^Afa5ad6c38be603e2ffd1f9b722a3a5c675f63de2^A^ADavid Aguilar^ATue Dec 11 05:13:21 2007 -0800^Adavvid@gmail.com^AAdded TODO e3f5a2d0248de6197d6e0e63c901810b8a9af2f8^Afa5ad6c38be603e2ffd1f9b722a3a5c675f63de2^A^ADavid Aguilar^AMon Dec 3 02:36:06 2007 -0800^Adavvid@gmail.com^AMerged qlistwidgets into main. f4fb8fd5baaa55d9b41faca79be289bb4407281e^Ae3f5a2d0248de6197d6e0e63c901810b8a9af2f8^A^ADavid Aguilar^ATue Dec 4 03:14:56 2007 -0800^Adavvid@gmail.com^ASquashed commit of the following: 23e7eab4ba2c94e3155f5d261c693ccac1342eb9^Af4fb8fd5baaa55d9b41faca79be289bb4407281e^A^ADavid Aguilar^AThu Dec 6 18:59:20 2007 -0800^Adavvid@gmail.com^AMerged diffdisplay into main """.strip().replace( # noqa '^A', chr(0x01) ).split( '\n' ) + [ '' ] # noqa class DAGTestData: """Test data provided by the dag_context fixture""" def __init__(self, app_context, head='HEAD', count=1000): self.context = app_context self.params = dag.DAG(head, count) self.reader = dag.RepoReader(app_context, self.params) @pytest.fixture def dag_context(app_context): """Provide DAGTestData for use by tests""" return DAGTestData(app_context) @patch('cola.models.dag.core') def test_repo_reader(core, dag_context): expect = len(LOG_LINES) - 1 actual = 0 core.readline.return_value = LOG_LINES[0] for idx, _ in enumerate(dag_context.reader.get()): core.readline.return_value = LOG_LINES[idx + 1] actual += 1 assert expect == actual @patch('cola.models.dag.core') def test_repo_reader_order(core, dag_context): commits = [ 'ad454b189fe5785af397fd6067cf103268b6626e', '1ba04ad185cf9f04c56c8482e9a73ef1bd35c695', 'fa5ad6c38be603e2ffd1f9b722a3a5c675f63de2', '103766573cd4e6799d3ee792bcd632b92cf7c6c0', 'e3f5a2d0248de6197d6e0e63c901810b8a9af2f8', 'f4fb8fd5baaa55d9b41faca79be289bb4407281e', '23e7eab4ba2c94e3155f5d261c693ccac1342eb9', ] core.readline.return_value = LOG_LINES[0] for idx, commit in enumerate(dag_context.reader.get()): assert commits[idx] == commit.oid core.readline.return_value = LOG_LINES[idx + 1] @patch('cola.models.dag.core') def test_repo_reader_parents(core, dag_context): parents = [ [], ['ad454b189fe5785af397fd6067cf103268b6626e'], ['1ba04ad185cf9f04c56c8482e9a73ef1bd35c695'], ['fa5ad6c38be603e2ffd1f9b722a3a5c675f63de2'], ['fa5ad6c38be603e2ffd1f9b722a3a5c675f63de2'], ['e3f5a2d0248de6197d6e0e63c901810b8a9af2f8'], ['f4fb8fd5baaa55d9b41faca79be289bb4407281e'], ] core.readline.return_value = LOG_LINES[0] for idx, commit in enumerate(dag_context.reader.get()): assert parents[idx] == [p.oid for p in commit.parents] core.readline.return_value = LOG_LINES[idx + 1] @patch('cola.models.dag.core') def test_repo_reader_contract(core, dag_context): core.exists.return_value = True core.readline.return_value = LOG_LINES[0] for idx, _ in enumerate(dag_context.reader.get()): core.readline.return_value = LOG_LINES[idx + 1] core.start_command.assert_called() call_args = core.start_command.call_args assert 'log.abbrevCommit=false' in call_args[0][0] assert 'log.showSignature=false' in call_args[0][0] git-cola-4.6.1/test/diffparse_test.py000066400000000000000000000235051457126473700176010ustar00rootroot00000000000000"""Tests for the diffparse module""" import pytest from cola import core from cola import diffparse from . import helper class DiffLinesTestData: """Test data used by DiffLines tests""" def __init__(self): self.parser = diffparse.DiffLines() fixture_path = helper.fixture('diff.txt') self.text = core.read(fixture_path) @pytest.fixture def difflines_data(): """Return test data for diffparse.DiffLines tests""" return DiffLinesTestData() def test_diff(): fixture_path = helper.fixture('diff.txt') patch = diffparse.Patch.parse('cola/diffparse.py', core.read(fixture_path)) hunks = patch.hunks assert len(hunks) == 3 assert len(hunks[0].lines) == 23 assert hunks[0].lines[0] == '@@ -6,10 +6,21 @@ from cola import gitcmds\n' assert hunks[0].lines[1] == ' from cola import gitcfg\n' assert hunks[0].lines[2] == ' \n' assert hunks[0].lines[3] == ' \n' assert hunks[0].lines[4] == '+class DiffSource(object):\n' assert hunks[0].lines[-1] == ( r" self._header_start_re = re.compile('^@@ -(\d+)" r" \+(\d+),(\d+) @@.*')" '\n' ) assert len(hunks[1].lines) == 18 assert hunks[1].lines[0] == '@@ -29,13 +40,11 @@ class DiffParser(object):\n' assert hunks[1].lines[1] == ' self.diff_sel = []\n' assert hunks[1].lines[2] == ' self.selected = []\n' assert hunks[1].lines[3] == ' self.filename = filename\n' assert hunks[1].lines[4] == ( '+ self.diff_source = diff_source or DiffSource()\n' ) assert hunks[1].lines[-1] == ' self.header = header\n' assert len(hunks[2].lines) == 16 assert hunks[2].lines[0] == '@@ -43,11 +52,10 @@ class DiffParser(object):\n' assert hunks[2].lines[-1] == ( ' """Writes a new diff corresponding to the user\'s' ' selection."""\n' ) def test_diff_at_start(): fixture_path = helper.fixture('diff-start.txt') patch = diffparse.Patch.parse('foo bar/a', core.read(fixture_path)) hunks = patch.hunks assert hunks[0].lines[0] == '@@ -1 +1,4 @@\n' assert hunks[-1].lines[-1] == '+c\n' assert hunks[0].old_start == 1 assert hunks[0].old_count == 1 assert hunks[0].new_start == 1 assert hunks[0].new_count == 4 assert patch.extract_subset(1, 3).as_text() == ( '--- a/foo bar/a\n' '+++ b/foo bar/a\n' '@@ -1 +1,3 @@\n' ' bar\n' '+a\n' '+b\n' ) assert patch.extract_subset(0, 4).as_text() == ( '--- a/foo bar/a\n' '+++ b/foo bar/a\n' '@@ -1 +1,4 @@\n' ' bar\n' '+a\n' '+b\n' '+c\n' ) def test_diff_at_end(): fixture_path = helper.fixture('diff-end.txt') patch = diffparse.Patch.parse('rijndael.js', core.read(fixture_path)) hunks = patch.hunks assert hunks[0].lines[0] == '@@ -1,39 +1 @@\n' assert hunks[-1].lines[-1] == ( "+module.exports = require('./build/Release/rijndael');\n" ) assert hunks[0].old_start == 1 assert hunks[0].old_count == 39 assert hunks[0].new_start == 1 assert hunks[0].new_count == 1 def test_diff_that_empties_file(): fixture_path = helper.fixture('diff-empty.txt') patch = diffparse.Patch.parse('filename', core.read(fixture_path)) hunks = patch.hunks assert hunks[0].lines[0] == '@@ -1,2 +0,0 @@\n' assert hunks[-1].lines[-1] == '-second\n' assert hunks[0].old_start == 1 assert hunks[0].old_count == 2 assert hunks[0].new_start == 0 assert hunks[0].new_count == 0 assert patch.extract_subset(1, 1).as_text() == ( '--- a/filename\n' '+++ b/filename\n' '@@ -1,2 +1 @@\n' '-first\n' ' second\n' ) assert patch.extract_subset(0, 2).as_text() == ( '--- a/filename\n' '+++ b/filename\n' '@@ -1,2 +0,0 @@\n' '-first\n' '-second\n' ) def test_diff_file_removal(): diff_text = """\ deleted file mode 100755 @@ -1,1 +0,0 @@ -#!/bin/sh """ patch = diffparse.Patch.parse('deleted.txt', diff_text) expect = 1 actual = len(patch.hunks) assert expect == actual # Selecting the first two lines generate no diff expect = '' actual = patch.extract_subset(0, 1).as_text() assert expect == actual # Selecting the last line should generate a line removal expect = """\ --- a/deleted.txt +++ b/deleted.txt @@ -1 +0,0 @@ -#!/bin/sh """ actual = patch.extract_subset(1, 2).as_text() assert expect == actual # All three lines should map to the same hunk diff actual = patch.extract_hunk(0).as_text() assert expect == actual actual = patch.extract_hunk(1).as_text() assert expect == actual actual = patch.extract_hunk(2).as_text() assert expect == actual def test_basic_diff_line_count(difflines_data): """Verify the basic line counts""" lines = difflines_data.parser.parse(difflines_data.text) expect = len(difflines_data.text.splitlines()) actual = len(lines) assert expect == actual def test_diff_line_count_ranges(difflines_data): parser = difflines_data.parser lines = parser.parse(difflines_data.text) # Diff header line = 0 count = 1 assert lines[line][0] == parser.DASH assert lines[line][1] == parser.DASH line += count # 3 lines of context count = 3 current_old = 6 current_new = 6 for i in range(count): assert lines[line + i][0] == current_old + i assert lines[line + i][1] == current_new + i line += count current_old += count current_new += count # 10 lines of new text count = 10 for i in range(count): assert lines[line + i][0] == parser.EMPTY assert lines[line + i][1] == current_new + i line += count current_new += count # 3 more lines of context count = 3 for i in range(count): assert lines[line + i][0] == current_old + i assert lines[line + i][1] == current_new + i line += count current_new += count current_old += count # 1 line of removal count = 1 for i in range(count): assert lines[line + i][0] == current_old + i assert lines[line + i][1] == parser.EMPTY line += count current_old += count # 2 lines of addition count = 2 for i in range(count): assert lines[line + i][0] == parser.EMPTY assert lines[line + i][1] == current_new + i line += count current_new += count # 3 more lines of context count = 3 for i in range(count): assert lines[line + i][0] == current_old + i assert lines[line + i][1] == current_new + i line += count current_new += count current_old += count # 1 line of header count = 1 for i in range(count): assert lines[line + i][0] == parser.DASH assert lines[line + i][1] == parser.DASH line += count # 3 more lines of context current_old = 29 current_new = 40 count = 3 for i in range(count): assert lines[line + i][0] == current_old + i assert lines[line + i][1] == current_new + i line += count current_new += count current_old += count expect_max_old = 53 assert expect_max_old == parser.old.max_value expect_max_new = 61 assert expect_max_new == parser.new.max_value assert parser.digits() == 2 def test_diff_line_for_merge(difflines_data): """Verify the basic line counts""" text = """@@@ -1,23 -1,33 +1,75 @@@ ++<<<<<<< upstream + +Ok """ parser = difflines_data.parser lines = parser.parse(text) assert len(lines) == 4 assert len(lines[0]) == 3 assert len(lines[1]) == 3 assert len(lines[2]) == 3 assert len(lines[3]) == 3 assert lines[0][0] == parser.DASH assert lines[0][1] == parser.DASH assert lines[0][2] == parser.DASH assert lines[1][0] == parser.EMPTY assert lines[1][1] == parser.EMPTY assert lines[1][2] == 1 assert lines[2][0] == 1 assert lines[2][1] == parser.EMPTY assert lines[2][2] == 2 assert lines[3][0] == 2 assert lines[3][1] == parser.EMPTY assert lines[3][2] == 3 def test_diff_line_digits(difflines_data): parser = difflines_data.parser text = """@@ -1,99 +1,99 @@""" parser.parse(text) assert parser.digits() == 2 text = """@@ -2,99 +2,99 @@""" parser.parse(text) assert parser.digits() == 3 def test_format_basic(): fmt = diffparse.FormatDigits() fmt.set_digits(2) expect = '01 99' actual = fmt.value(1, 99) assert expect == actual def test_format_reuse(): fmt = diffparse.FormatDigits() fmt.set_digits(3) expect = '001 099' actual = fmt.value(1, 99) assert expect == actual fmt.set_digits(4) expect = '0001 0099' actual = fmt.value(1, 99) assert expect == actual def test_format_special_values(): fmt = diffparse.FormatDigits(dash='-') fmt.set_digits(3) expect = ' 099' actual = fmt.value(fmt.EMPTY, 99) assert expect == actual expect = '001 ' actual = fmt.value(1, fmt.EMPTY) assert expect == actual expect = ' ' actual = fmt.value(fmt.EMPTY, fmt.EMPTY) assert expect == actual expect = '--- 001' actual = fmt.value(fmt.DASH, 1) assert expect == actual expect = '099 ---' actual = fmt.value(99, fmt.DASH) assert expect == actual expect = '--- ---' actual = fmt.value(fmt.DASH, fmt.DASH) assert expect == actual expect = ' ---' actual = fmt.value(fmt.EMPTY, fmt.DASH) assert expect == actual expect = '--- ' actual = fmt.value(fmt.DASH, fmt.EMPTY) assert expect == actual def test_parse_range_str(): start, count = diffparse.parse_range_str('1,2') assert start == 1 assert count == 2 def test_parse_range_str_single_line(): start, count = diffparse.parse_range_str('2') assert start == 2 assert count == 1 def test_parse_range_str_empty(): start, count = diffparse.parse_range_str('0,0') assert start == 0 assert count == 0 git-cola-4.6.1/test/display_test.py000066400000000000000000000013501457126473700172750ustar00rootroot00000000000000from cola import display def test_shorten_paths(): paths = ( '/usr/src/git-cola/src', '/usr/src/example/src', '/usr/src/super/lib/src', '/usr/src/super/tools/src', '/usr/src/super/example/src', '/lib/src', ) actual = display.shorten_paths(paths) assert actual[paths[0]] == 'git-cola/src' assert actual[paths[1]] == 'src/example/src' assert actual[paths[2]] == 'super/lib/src' assert actual[paths[3]] == 'tools/src' assert actual[paths[4]] == 'super/example/src' assert actual[paths[5]] == '/lib/src' def test_normalize_path(): path = r'C:\games\doom2' expect = 'C:/games/doom2' actual = display.normalize_path(path) assert expect == actual git-cola-4.6.1/test/fixtures/000077500000000000000000000000001457126473700160715ustar00rootroot00000000000000git-cola-4.6.1/test/fixtures/.gitattributes000066400000000000000000000002401457126473700207600ustar00rootroot00000000000000# The fixtures must be treated as binary to make sure we don't ever mess with # their line endings during checkout. Otherwise the tests may break. *.txt -text git-cola-4.6.1/test/fixtures/bin/000077500000000000000000000000001457126473700166415ustar00rootroot00000000000000git-cola-4.6.1/test/fixtures/bin/exe-cmd.exe000066400000000000000000000000001457126473700206540ustar00rootroot00000000000000git-cola-4.6.1/test/fixtures/cyrillic-cp1251.txt000066400000000000000000000010051457126473700213510ustar00rootroot00000000000000 Git Git ? , , Git, , . Git, , , Subversion Perforce. Git' , . Git'. git-cola-4.6.1/test/fixtures/cyrillic-utf-8.txt000066400000000000000000000015751457126473700214150ustar00rootroot00000000000000Основы Git Так что же такое Git в двух словах? Эту часть важно усвоить, поскольку если вы поймёте, что такое Git, и каковы принципы его работы, вам будет гораздо проще пользоваться им эффективно. Изучая Git, постарайтесь освободиться от всего, что вы знали о других СКВ, таких как Subversion или Perforce. В Git'е совсем не такие понятия об информации и работе с ней как в других системах, хотя пользовательский интерфейс очень похож. Знание этих различий защитит вас от путаницы при использовании Git'а. git-cola-4.6.1/test/fixtures/diff-empty.txt000066400000000000000000000000371457126473700206760ustar00rootroot00000000000000@@ -1,2 +0,0 @@ -first -second git-cola-4.6.1/test/fixtures/diff-end.txt000066400000000000000000000021301457126473700203020ustar00rootroot00000000000000@@ -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-4.6.1/test/fixtures/diff-start.txt000066400000000000000000000000341457126473700206720ustar00rootroot00000000000000@@ -1 +1,4 @@ bar +a +b +c git-cola-4.6.1/test/fixtures/diff.txt000066400000000000000000000047641457126473700175550ustar00rootroot00000000000000@@ -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-4.6.1/test/fixtures/unicode.txt000066400000000000000000000000111457126473700202500ustar00rootroot00000000000000unicøde git-cola-4.6.1/test/git_test.py000066400000000000000000000273631457126473700164270ustar00rootroot00000000000000"""Test the cola.git module""" import os import pathlib from cola import git from cola.git import STDOUT from .helper import patch # 16k+1 bytes to exhaust any output buffers. BUFFER_SIZE = (16 * 1024) + 1 @patch('cola.git.is_git_dir') def test_find_git_dir_None(is_git_dir): paths = git.find_git_directory(None) assert not is_git_dir.called assert paths.git_dir is None assert paths.git_file is None assert paths.worktree is None @patch('cola.git.is_git_dir') def test_find_git_dir_empty_string(is_git_dir): paths = git.find_git_directory('') assert not is_git_dir.called assert paths.git_dir is None assert paths.git_file is None assert paths.worktree is None @patch('cola.git.is_git_dir') def test_find_git_dir_never_found(is_git_dir): is_git_dir.return_value = False paths = git.find_git_directory(str(pathlib.Path('/does/not/exist').resolve())) assert is_git_dir.called assert paths.git_dir is None assert paths.git_file is None assert paths.worktree is None expect = 8 actual = is_git_dir.call_count assert expect == actual is_git_dir.assert_has_calls([ ((str(pathlib.Path('/does/not/exist').resolve()),), {}), ((str(pathlib.Path('/does/not/exist/.git').resolve()),), {}), ((str(pathlib.Path('/does/not').resolve()),), {}), ((str(pathlib.Path('/does/not/.git').resolve()),), {}), ((str(pathlib.Path('/does').resolve()),), {}), ((str(pathlib.Path('/does/.git').resolve()),), {}), ((str(pathlib.Path('/').resolve()),), {}), ((str(pathlib.Path('/.git').resolve()),), {}), ]) @patch('cola.git.is_git_dir') def test_find_git_dir_found_right_away(is_git_dir): git_dir = str(pathlib.Path('/seems/to/exist/.git').resolve()) worktree = str(pathlib.Path('/seems/to/exist').resolve()) is_git_dir.return_value = True paths = git.find_git_directory(git_dir) assert is_git_dir.called assert git_dir == paths.git_dir assert paths.git_file is None assert worktree == paths.worktree @patch('cola.git.is_git_dir') def test_find_git_does_discovery(is_git_dir): git_dir = str(pathlib.Path('/the/root/.git').resolve()) worktree = str(pathlib.Path('/the/root').resolve()) is_git_dir.side_effect = lambda x: x == git_dir paths = git.find_git_directory('/the/root/sub/dir') assert git_dir == paths.git_dir assert paths.git_file is None assert worktree == paths.worktree @patch('cola.git.read_git_file') @patch('cola.git.is_git_file') @patch('cola.git.is_git_dir') def test_find_git_honors_git_files(is_git_dir, is_git_file, read_git_file): git_file = str(pathlib.Path('/the/root/.git').resolve()) worktree = str(pathlib.Path('/the/root').resolve()) git_dir = str(pathlib.Path('/super/module/.git/modules/root').resolve()) is_git_dir.side_effect = lambda x: x == git_file is_git_file.side_effect = lambda x: x == git_file read_git_file.return_value = git_dir paths = git.find_git_directory(str(pathlib.Path('/the/root/sub/dir').resolve())) assert git_dir == paths.git_dir assert git_file == paths.git_file assert worktree == paths.worktree expect = 6 actual = is_git_dir.call_count assert expect == actual is_git_dir.assert_has_calls([ ((str(pathlib.Path('/the/root/sub/dir').resolve()),), {}), ((str(pathlib.Path('/the/root/sub/dir/.git').resolve()),), {}), ((str(pathlib.Path('/the/root/sub').resolve()),), {}), ((str(pathlib.Path('/the/root/sub/.git').resolve()),), {}), ((str(pathlib.Path('/the/root').resolve()),), {}), ((str(pathlib.Path('/the/root/.git').resolve()),), {}), ]) read_git_file.assert_called_once_with(git_file) @patch('cola.core.getenv') @patch('cola.git.is_git_dir') def test_find_git_honors_ceiling_dirs(is_git_dir, getenv): git_dir = str(pathlib.Path('/ceiling/.git').resolve()) ceiling = os.pathsep.join( str(pathlib.Path(path).resolve()) for path in ('/tmp', '/ceiling', '/other/ceiling') ) is_git_dir.side_effect = lambda x: x == git_dir def mock_getenv(k, v=None): if k == 'GIT_CEILING_DIRECTORIES': return ceiling return v getenv.side_effect = mock_getenv paths = git.find_git_directory(str(pathlib.Path('/ceiling/sub/dir').resolve())) assert paths.git_dir is None assert paths.git_file is None assert paths.worktree is None assert is_git_dir.call_count == 4 is_git_dir.assert_has_calls([ ((str(pathlib.Path('/ceiling/sub/dir').resolve()),), {}), ((str(pathlib.Path('/ceiling/sub/dir/.git').resolve()),), {}), ((str(pathlib.Path('/ceiling/sub').resolve()),), {}), ((str(pathlib.Path('/ceiling/sub/.git').resolve()),), {}), ]) @patch('cola.core.islink') @patch('cola.core.isdir') @patch('cola.core.isfile') def test_is_git_dir_finds_linked_repository(isfile, isdir, islink): dirs = { str(pathlib.Path(directory).resolve()) for directory in [ '/foo', '/foo/.git', '/foo/.git/refs', '/foo/.git/objects', '/foo/.git/worktrees', '/foo/.git/worktrees/foo', ] } files = { str(pathlib.Path(file).resolve()) for file in [ '/foo/.git/HEAD', '/foo/.git/worktrees/foo/HEAD', '/foo/.git/worktrees/foo/index', '/foo/.git/worktrees/foo/commondir', '/foo/.git/worktrees/foo/gitdir', ] } islink.return_value = False isfile.side_effect = lambda x: x in files isdir.side_effect = lambda x: x in dirs assert git.is_git_dir(str(pathlib.Path('/foo/.git/worktrees/foo').resolve())) assert git.is_git_dir(str(pathlib.Path('/foo/.git').resolve())) @patch('cola.core.getenv') @patch('cola.git.is_git_dir') def test_find_git_worktree_from_GIT_DIR(is_git_dir, getenv): git_dir = str(pathlib.Path('/repo/.git').resolve()) worktree = str(pathlib.Path('/repo').resolve()) is_git_dir.return_value = True getenv.side_effect = lambda x: x == 'GIT_DIR' and git_dir or None paths = git.find_git_directory(git_dir) assert is_git_dir.called assert git_dir == paths.git_dir assert paths.git_file is None assert worktree == paths.worktree @patch('cola.git.is_git_dir') def test_finds_no_worktree_from_bare_repo(is_git_dir): git_dir = str(pathlib.Path('/repos/bare.git').resolve()) worktree = None is_git_dir.return_value = True paths = git.find_git_directory(git_dir) assert is_git_dir.called assert git_dir == paths.git_dir assert paths.git_file is None assert worktree == paths.worktree @patch('cola.core.getenv') @patch('cola.git.is_git_dir') def test_find_git_directory_uses_GIT_WORK_TREE(is_git_dir, getenv): git_dir = str(pathlib.Path('/repo/worktree/.git').resolve()) worktree = str(pathlib.Path('/repo/worktree').resolve()) def is_git_dir_func(path): return path == git_dir is_git_dir.side_effect = is_git_dir_func def getenv_func(name): if name == 'GIT_WORK_TREE': return worktree return None getenv.side_effect = getenv_func paths = git.find_git_directory(worktree) assert is_git_dir.called assert git_dir == paths.git_dir assert paths.git_file is None assert worktree == paths.worktree @patch('cola.core.getenv') @patch('cola.git.is_git_dir') def test_uses_cwd_for_worktree_with_GIT_DIR(is_git_dir, getenv): git_dir = str(pathlib.Path('/repo/.yadm/repo.git').resolve()) worktree = str(pathlib.Path('/repo').resolve()) def getenv_func(name): if name == 'GIT_DIR': return git_dir return None getenv.side_effect = getenv_func def is_git_dir_func(path): return path == git_dir is_git_dir.side_effect = is_git_dir_func paths = git.find_git_directory(worktree) assert is_git_dir.called assert getenv.called assert git_dir == paths.git_dir assert paths.git_file is None assert worktree == paths.worktree def test_transform_kwargs_empty(): expect = [] actual = git.transform_kwargs(foo=None, bar=False) assert expect == actual def test_transform_kwargs_single_dash_from_True(): """Single dash for one-character True""" expect = ['-a'] actual = git.transform_kwargs(a=True) assert expect == actual def test_transform_kwargs_no_single_dash_from_False(): """No single-dash for False""" expect = [] actual = git.transform_kwargs(a=False) assert expect == actual def test_transform_kwargs_double_dash_from_True(): """Double-dash for longer True""" expect = ['--abc'] actual = git.transform_kwargs(abc=True) assert expect == actual def test_transform_kwargs_no_double_dash_from_True(): """No double-dash for False""" expect = [] actual = git.transform_kwargs(abc=False) assert expect == actual def test_transform_kwargs_single_dash_int(): expect = ['-a1'] actual = git.transform_kwargs(a=1) assert expect == actual def test_transform_kwargs_double_dash_int(): expect = ['--abc=1'] actual = git.transform_kwargs(abc=1) assert expect == actual def test_transform_kwargs_single_dash_float(): expect = ['-a1.5'] actual = git.transform_kwargs(a=1.5) assert expect == actual def test_transform_kwargs_double_dash_float(): expect = ['--abc=1.5'] actual = git.transform_kwargs(abc=1.5) assert expect == actual def test_transform_kwargs_single_dash_string(): expect = ['-abc'] actual = git.transform_kwargs(a='bc') assert expect == actual def test_transform_double_single_dash_string(): expect = ['--abc=def'] actual = git.transform_kwargs(abc='def') assert expect == actual def test_version(): """Test running 'git version'""" gitcmd = git.Git() version = gitcmd.version()[STDOUT] assert version.startswith('git version') def test_stdout(): """Test overflowing the stdout buffer""" # Write to stdout only code = r'import sys; value = "\0" * %d; sys.stdout.write(value);' % BUFFER_SIZE status, out, err = git.Git.execute(['python', '-c', code], _raw=True) assert status == 0 expect = BUFFER_SIZE actual = len(out) assert expect == actual expect = 0 actual = len(err) assert expect == actual def test_stderr(): """Test that stderr is seen""" # Write to stderr and capture it code = ( r'import sys;' r'value = "\0" * %d;' r'sys.stderr.write(value);' ) % BUFFER_SIZE status, out, err = git.Git.execute(['python', '-c', code], _raw=True) expect = 0 actual = status assert expect == actual expect = 0 actual = len(out) assert expect == actual expect = BUFFER_SIZE actual = len(err) assert expect == actual def test_stdout_and_stderr(): """Test ignoring stderr when stdout+stderr are provided (v2)""" # Write to stdout and stderr but only capture stdout code = ( r'import sys;' r'value = "\0" * %d;' r'sys.stdout.write(value);' r'sys.stderr.write(value);' ) % BUFFER_SIZE status, out, err = git.Git.execute(['python', '-c', code], _raw=True) expect = 0 actual = status assert expect == actual expect = BUFFER_SIZE actual = len(out) assert expect == actual actual = len(err) assert expect == actual def test_it_doesnt_deadlock(): """Test that we don't deadlock with both stderr and stdout""" code = ( r'import sys;' r'value = "\0" * %d;' r'sys.stderr.write(value);' r'sys.stdout.write(value);' ) % BUFFER_SIZE status, out, err = git.Git.execute(['python', '-c', code], _raw=True) expect = 0 actual = status assert expect == actual expect = '\0' * BUFFER_SIZE actual = out assert expect == actual actual = err assert expect == actual git-cola-4.6.1/test/gitcfg_test.py000066400000000000000000000107531457126473700171020ustar00rootroot00000000000000"""Test the cola.gitcfg module.""" import pathlib from . import helper from .helper import app_context # Prevent unused imports lint errors. assert app_context is not None def assert_color(context, expect, git_value, key='test', default=None): """Helper function for testing color values""" helper.run_git('config', 'cola.color.%s' % key, git_value) context.cfg.reset() actual = context.cfg.color(key, default) assert expect == actual def test_string(app_context): """Test string values in get().""" helper.run_git('config', 'test.value', 'test') assert app_context.cfg.get('test.value') == 'test' def test_int(app_context): """Test int values in get().""" helper.run_git('config', 'test.int', '42') expect = 42 actual = app_context.cfg.get('test.int') assert expect == actual def test_true(app_context): """Test bool values in get().""" helper.run_git('config', 'test.bool', 'true') assert app_context.cfg.get('test.bool') is True def test_false(app_context): helper.run_git('config', 'test.bool', 'false') assert app_context.cfg.get('test.bool') is False def test_yes(app_context): helper.run_git('config', 'test.bool', 'yes') assert app_context.cfg.get('test.bool') is True def test_no(app_context): helper.run_git('config', 'test.bool', 'no') assert app_context.cfg.get('test.bool') is False def test_bool_no_value(app_context): helper.append_file('.git/config', '[test]\n') helper.append_file('.git/config', '\tbool\n') assert app_context.cfg.get('test.bool') is True def test_empty_value(app_context): helper.append_file('.git/config', '[test]\n') helper.append_file('.git/config', '\tvalue = \n') assert app_context.cfg.get('test.value') == '' def test_default(app_context): """Test default values in get().""" assert app_context.cfg.get('does.not.exist') is None assert app_context.cfg.get('does.not.exist', default=42) == 42 def test_get_all(app_context): """Test getting multiple values in get_all()""" helper.run_git('config', '--add', 'test.value', 'abc') helper.run_git('config', '--add', 'test.value', 'def') expect = ['abc', 'def'] assert expect == app_context.cfg.get_all('test.value') def test_color_rrggbb(app_context): assert_color(app_context, (0xAA, 0xBB, 0xCC), 'aabbcc') assert_color(app_context, (0xAA, 0xBB, 0xCC), '#aabbcc') def test_color_int(app_context): assert_color(app_context, (0x10, 0x20, 0x30), '102030') assert_color(app_context, (0x10, 0x20, 0x30), '#102030') def test_guitool_opts(app_context): helper.run_git('config', 'guitool.hello world.cmd', 'hello world') opts = app_context.cfg.get_guitool_opts('hello world') expect = 'hello world' actual = opts['cmd'] assert expect == actual def test_guitool_names(app_context): helper.run_git('config', 'guitool.hello meow.cmd', 'hello meow') names = app_context.cfg.get_guitool_names() assert 'hello meow' in names def test_guitool_names_mixed_case(app_context): helper.run_git('config', 'guitool.Meow Cat.cmd', 'cat hello') names = app_context.cfg.get_guitool_names() assert 'Meow Cat' in names def test_find_mixed_case(app_context): helper.run_git('config', 'guitool.Meow Cat.cmd', 'cat hello') opts = app_context.cfg.find('guitool.Meow Cat.*') assert opts['guitool.Meow Cat.cmd'] == 'cat hello' def test_guitool_opts_mixed_case(app_context): helper.run_git('config', 'guitool.Meow Cat.cmd', 'cat hello') opts = app_context.cfg.get_guitool_opts('Meow Cat') assert opts['cmd'] == 'cat hello' def test_hooks(app_context): helper.run_git('config', 'core.hooksPath', '/test/hooks') expect = '/test/hooks' actual = app_context.cfg.hooks() assert expect == actual def test_hooks_lowercase(app_context): helper.run_git('config', 'core.hookspath', '/test/hooks-lowercase') expect = '/test/hooks-lowercase' actual = app_context.cfg.hooks() assert expect == actual def test_hooks_path(app_context): helper.run_git('config', 'core.hooksPath', str(pathlib.Path('/test/hooks'))) expect = str(pathlib.Path('/test/hooks/example')) actual = app_context.cfg.hooks_path('example') assert expect == actual def test_hooks_path_lowercase(app_context): helper.run_git( 'config', 'core.hookspath', str(pathlib.Path('/test/hooks-lowercase')) ) expect = str(pathlib.Path('/test/hooks-lowercase/example')) actual = app_context.cfg.hooks_path('example') assert expect == actual git-cola-4.6.1/test/gitcmds_test.py000066400000000000000000000161401457126473700172650ustar00rootroot00000000000000"""Test the cola.gitcmds module""" import os from cola import core from cola import gitcmds from cola.widgets.remote import get_default_remote from . import helper from .helper import app_context # Prevent unused imports lint errors. assert app_context is not None def test_currentbranch(app_context): """Test current_branch().""" assert gitcmds.current_branch(app_context) == 'main' def test_branch_list_local(app_context): """Test branch_list(remote=False).""" helper.commit_files() expect = ['main'] actual = gitcmds.branch_list(app_context, remote=False) assert expect == actual def test_branch_list_remote(app_context): """Test branch_list(remote=False).""" expect = [] actual = gitcmds.branch_list(app_context, remote=True) assert expect == actual helper.commit_files() helper.run_git('remote', 'add', 'origin', '.') helper.run_git('fetch', 'origin') expect = ['origin/main'] actual = gitcmds.branch_list(app_context, remote=True) assert expect == actual helper.run_git('remote', 'rm', 'origin') expect = [] actual = gitcmds.branch_list(app_context, remote=True) assert expect == actual def test_upstream_remote(app_context): """Test getting the configured upstream remote""" assert gitcmds.upstream_remote(app_context) is None helper.run_git('config', 'branch.main.remote', 'test') app_context.cfg.reset() assert gitcmds.upstream_remote(app_context) == 'test' def test_default_push(app_context): """Test getting what default branch to push to""" # no default push, no remote branch configured assert get_default_remote(app_context) == 'origin' # default push set, no remote branch configured helper.run_git('config', 'remote.pushDefault', 'test') app_context.cfg.reset() assert get_default_remote(app_context) == 'test' # default push set, default remote branch configured helper.run_git('config', 'branch.main.remote', 'test2') app_context.cfg.reset() assert get_default_remote(app_context) == 'test2' # default push set, default remote branch configured, on different branch helper.run_git('checkout', '-b', 'other-branch') assert get_default_remote(app_context) == 'test' def test_tracked_branch(app_context): """Test tracked_branch().""" assert gitcmds.tracked_branch(app_context) is None helper.run_git('config', 'branch.main.remote', 'test') helper.run_git('config', 'branch.main.merge', 'refs/heads/main') app_context.cfg.reset() assert gitcmds.tracked_branch(app_context) == 'test/main' def test_tracked_branch_other(app_context): """Test tracked_branch('other')""" assert gitcmds.tracked_branch(app_context, 'other') is None helper.run_git('config', 'branch.other.remote', 'test') helper.run_git('config', 'branch.other.merge', 'refs/heads/other/branch') app_context.cfg.reset() assert gitcmds.tracked_branch(app_context, 'other') == 'test/other/branch' def test_untracked_files(app_context): """Test untracked_files().""" helper.touch('C', 'D', 'E') assert gitcmds.untracked_files(app_context) == ['C', 'D', 'E'] def test_all_files(app_context): helper.touch('other-file') all_files = gitcmds.all_files(app_context) assert 'A' in all_files assert 'B' in all_files assert 'other-file' in all_files def test_tag_list(app_context): """Test tag_list()""" helper.commit_files() helper.run_git('tag', 'a') helper.run_git('tag', 'b') helper.run_git('tag', 'c') assert gitcmds.tag_list(app_context) == ['c', 'b', 'a'] def test_merge_message_path(app_context): """Test merge_message_path().""" helper.touch('.git/SQUASH_MSG') assert gitcmds.merge_message_path(app_context) == os.path.abspath('.git/SQUASH_MSG') helper.touch('.git/MERGE_MSG') assert gitcmds.merge_message_path(app_context) == os.path.abspath('.git/MERGE_MSG') os.unlink(gitcmds.merge_message_path(app_context)) assert gitcmds.merge_message_path(app_context) == os.path.abspath('.git/SQUASH_MSG') os.unlink(gitcmds.merge_message_path(app_context)) assert gitcmds.merge_message_path(app_context) is None def test_all_refs(app_context): helper.commit_files() helper.run_git('branch', 'a') helper.run_git('branch', 'b') helper.run_git('branch', 'c') helper.run_git('tag', 'd') helper.run_git('tag', 'e') helper.run_git('tag', 'f') helper.run_git('remote', 'add', 'origin', '.') helper.run_git('fetch', 'origin') refs = gitcmds.all_refs(app_context) assert refs == [ 'a', 'b', 'c', 'main', 'origin/a', 'origin/b', 'origin/c', 'origin/main', 'f', 'e', 'd', ] def test_all_refs_split(app_context): helper.commit_files() helper.run_git('branch', 'a') helper.run_git('branch', 'b') helper.run_git('branch', 'c') helper.run_git('tag', 'd') helper.run_git('tag', 'e') helper.run_git('tag', 'f') helper.run_git('remote', 'add', 'origin', '.') helper.run_git('fetch', 'origin') local, remote, tags = gitcmds.all_refs(app_context, split=True) assert local == ['a', 'b', 'c', 'main'] assert remote == ['origin/a', 'origin/b', 'origin/c', 'origin/main'] assert tags == ['f', 'e', 'd'] def test_binary_files(app_context): # Create a binary file and ensure that it's detected as binary. with core.xopen('binary-file.txt', 'wb') as f: f.write(b'hello\0world\n') assert gitcmds.is_binary(app_context, 'binary-file.txt') # Create a text file and ensure that it's not detected as binary. with core.open_write('text-file.txt') as f: f.write('hello world\n') assert not gitcmds.is_binary(app_context, 'text-file.txt') # Create a .gitattributes file and mark text-file.txt as binary. app_context.cfg.reset() with core.open_write('.gitattributes') as f: f.write('text-file.txt binary\n') assert gitcmds.is_binary(app_context, 'text-file.txt') # Remove the "binary" attribute using "-binary" from binary-file.txt. # Ensure that we do not flag this file as binary. with core.open_write('.gitattributes') as f: f.write('binary-file.txt -binary\n') assert not gitcmds.is_binary(app_context, 'binary-file.txt') def test_is_valid_ref(app_context): """Verify the behavior of is_valid_ref()""" # We are initially in a "git init" state. HEAD must be invalid. assert not gitcmds.is_valid_ref(app_context, 'HEAD') # Create the first commit onto the "test" branch. app_context.git.symbolic_ref('HEAD', 'refs/heads/test') app_context.git.commit(m='initial commit') assert gitcmds.is_valid_ref(app_context, 'HEAD') assert gitcmds.is_valid_ref(app_context, 'test') assert gitcmds.is_valid_ref(app_context, 'refs/heads/test') def test_diff_helper(app_context): helper.commit_files() with core.open_write('A') as f: f.write('A change\n') helper.run_git('add', 'A') expect_n = '+A change\n' expect_rn = '+A change\r\n' actual = gitcmds.diff_helper(app_context, ref='HEAD', cached=True) assert expect_n in actual or expect_rn in actual git-cola-4.6.1/test/gitops_test.py000066400000000000000000000014601457126473700171370ustar00rootroot00000000000000"""Tests basic git operations: commit, log, config""" from . import helper from .helper import app_context # Prevent unused imports lint errors. assert app_context is not None def test_git_commit(app_context): """Test running 'git commit' via cola.git""" helper.write_file('A', 'A') helper.write_file('B', 'B') helper.run_git('add', 'A', 'B') app_context.git.commit(m='initial commit') log = helper.run_git('-c', 'log.showsignature=false', 'log', '--pretty=oneline') expect = 1 actual = len(log.splitlines()) assert expect == actual def test_git_config(app_context): """Test cola.git.config()""" helper.run_git('config', 'section.key', 'value') expect = (0, 'value', '') actual = app_context.git.config('section.key', get=True) assert expect == actual git-cola-4.6.1/test/gravatar_test.py000066400000000000000000000006271457126473700174450ustar00rootroot00000000000000from cola import gravatar from cola.compat import ustr def test_url_for_email_(): email = 'email@example.com' expect = ( 'https://gravatar.com/avatar/5658ffccee7f0ebfda2b226238b1eb6e?s=64' + r'&d=https%3A%2F%2Fgit-cola.github.io%2Fimages%2Fgit-64x64.jpg' ) actual = gravatar.Gravatar.url_for_email(email, 64) assert expect == actual assert isinstance(actual, ustr) git-cola-4.6.1/test/helper.py000066400000000000000000000054421457126473700160560ustar00rootroot00000000000000import os import shutil import stat import tempfile from unittest.mock import Mock, patch import pytest from cola import core from cola import git from cola import gitcfg from cola import gitcmds from cola.models import main # prevent unused imports lint errors. assert patch is not None def tmp_path(*paths): """Returns a path relative to the test/tmp directory""" dirname = core.decode(os.path.dirname(__file__)) return os.path.join(dirname, 'tmp', *paths) def fixture(*paths): dirname = core.decode(os.path.dirname(__file__)) return os.path.join(dirname, 'fixtures', *paths) # shutil.rmtree() can't remove read-only files on Windows. This onerror # handler, adapted from , works # around this by changing such files to be writable and then re-trying. def remove_readonly(func, path, _exc_info): if func is os.unlink and not os.access(path, os.W_OK): os.chmod(path, stat.S_IWRITE) func(path) else: raise AssertionError('Should not happen') def touch(*paths): """Open and close a file to either create it or update its mtime""" for path in paths: core.open_append(path).close() def write_file(path, content): """Write content to the specified file path""" with core.open_write(path) as f: f.write(content) def append_file(path, content): """Open a file in append mode and write content to it""" with core.open_append(path) as f: f.write(content) def run_git(*args): """Run git with the specified arguments""" status, out, _ = core.run_command(['git'] + list(args)) assert status == 0 return out def commit_files(): """Commit the current state as the initial commit""" run_git('commit', '-m', 'initial commit') def initialize_repo(): """Initialize a git repository in the current directory""" run_git('init') run_git('symbolic-ref', 'HEAD', 'refs/heads/main') run_git('config', '--local', 'user.name', 'Your Name') run_git('config', '--local', 'user.email', 'you@example.com') run_git('config', '--local', 'commit.gpgsign', 'false') run_git('config', '--local', 'tag.gpgsign', 'false') touch('A', 'B') run_git('add', 'A', 'B') @pytest.fixture def app_context(): """Create a repository in a temporary directory and return its ApplicationContext""" tmp_directory = tempfile.mkdtemp('-cola-test') current_directory = os.getcwd() os.chdir(tmp_directory) initialize_repo() context = Mock() context.git = git.create() context.git.set_worktree(core.getcwd()) context.cfg = gitcfg.create(context) context.model = main.create(context) context.cfg.reset() gitcmds.reset() yield context os.chdir(current_directory) shutil.rmtree(tmp_directory, onerror=remove_readonly) git-cola-4.6.1/test/i18n_test.py000066400000000000000000000037011457126473700164110ustar00rootroot00000000000000"""Tests for the i18n translation module""" import os import pytest from cola import i18n from cola.i18n import N_ from cola.compat import uchr @pytest.fixture(autouse=True) def i18n_context(): """Perform cleanup/teardown of the i18n module""" yield i18n.uninstall() def test_translates_noun(): """Test that strings with @@noun are translated""" i18n.install('ja_JP') expect = uchr(0x30B3) + uchr(0x30DF) + uchr(0x30C3) + uchr(0x30C8) actual = N_('Commit@@verb') assert expect == actual def test_translates_verb(): """Test that strings with @@verb are translated""" i18n.install('de_DE') expect = 'Commit aufnehmen' actual = N_('Commit@@verb') assert expect == actual def test_translates_english_noun(): """Test that English strings with @@noun are properly handled""" i18n.install('en_US.UTF-8') expect = 'Commit' actual = N_('Commit@@noun') assert expect == actual def test_translates_english_verb(): """Test that English strings with @@verb are properly handled""" i18n.install('en_US.UTF-8') expect = 'Commit' actual = N_('Commit@@verb') assert expect == actual def test_translates_random_english(): """Test that random English strings are passed through as-is""" i18n.install('en_US.UTF-8') expect = 'Random' actual = N_('Random') assert expect == actual def test_translate_push_pull_french(): i18n.install('fr_FR') expect = 'Tirer' actual = N_('Pull') assert expect == actual expect = 'Pousser' actual = N_('Push') assert expect == actual def test_get_filename_for_locale(): """Ensure that the appropriate .po files are found""" actual = i18n.get_filename_for_locale('does_not_exist') assert actual is None actual = i18n.get_filename_for_locale('id_ID') assert os.path.basename(actual) == 'id_ID.po' actual = i18n.get_filename_for_locale('ja_JP') assert os.path.basename(actual) == 'ja.po' git-cola-4.6.1/test/icons_test.py000066400000000000000000000005361457126473700167500ustar00rootroot00000000000000from cola import compat from cola import core from cola import icons def test_from_filename_unicode(): filename = compat.uchr(0x400) + '.py' expect = 'file-code.svg' actual = icons.basename_from_filename(filename) assert expect == actual actual = icons.basename_from_filename(core.encode(filename)) assert expect == actual git-cola-4.6.1/test/main_model_test.py000066400000000000000000000143561457126473700177460ustar00rootroot00000000000000import os import pytest from cola import core from cola import git from cola.models import main from . import helper from .helper import app_context from .helper import Mock # prevent unused imports lint errors. assert app_context is not None REMOTE = 'server' LOCAL_BRANCH = 'local' REMOTE_BRANCH = 'remote' @pytest.fixture def mock_context(): """Return a Mock context for testing""" context = Mock() context.git = git.create() return context def test_project(app_context): """Test the 'project' attribute.""" project = os.path.basename(core.getcwd()) app_context.model.set_worktree(core.getcwd()) assert app_context.model.project == project def test_local_branches(app_context): """Test the 'local_branches' attribute.""" helper.commit_files() app_context.model.update_status() assert app_context.model.local_branches == ['main'] def test_remote_branches(app_context): """Test the 'remote_branches' attribute.""" app_context.model.update_status() assert app_context.model.remote_branches == [] helper.commit_files() helper.run_git('remote', 'add', 'origin', '.') helper.run_git('fetch', 'origin') app_context.model.update_status() assert app_context.model.remote_branches == ['origin/main'] def test_modified(app_context): """Test the 'modified' attribute.""" helper.write_file('A', 'change') app_context.model.update_status() assert app_context.model.modified == ['A'] def test_unstaged(app_context): """Test the 'unstaged' attribute.""" helper.write_file('A', 'change') helper.write_file('C', 'C') app_context.model.update_status() assert app_context.model.unstaged == ['A', 'C'] def test_untracked(app_context): """Test the 'untracked' attribute.""" helper.write_file('C', 'C') app_context.model.update_status() assert app_context.model.untracked == ['C'] def test_stageable(app_context): """Test the 'stageable' attribute.""" assert not app_context.model.is_stageable() def test_remotes(app_context): """Test the 'remote' attribute.""" helper.run_git('remote', 'add', 'origin', '.') app_context.model.update_status() assert app_context.model.remotes == ['origin'] def test_currentbranch(app_context): """Test the 'currentbranch' attribute.""" helper.run_git('checkout', '-b', 'test') app_context.model.update_status() assert app_context.model.currentbranch == 'test' def test_tags(app_context): """Test the 'tags' attribute.""" helper.commit_files() helper.run_git('tag', 'test') app_context.model.update_status() assert app_context.model.tags == ['test'] def test_remote_args_fetch(mock_context): # Fetch (args, kwargs) = main.remote_args( mock_context, REMOTE, local_branch=LOCAL_BRANCH, remote_branch=REMOTE_BRANCH, ) assert args == [REMOTE, 'remote:local'] assert kwargs['verbose'] assert 'tags' not in kwargs assert 'rebase' not in kwargs def test_remote_args_fetch_tags(mock_context): # Fetch tags (args, kwargs) = main.remote_args( mock_context, REMOTE, tags=True, local_branch=LOCAL_BRANCH, remote_branch=REMOTE_BRANCH, ) assert args == [REMOTE, 'remote:local'] assert kwargs['verbose'] assert kwargs['tags'] assert 'rebase' not in kwargs def test_remote_args_pull(mock_context): # Pull (args, kwargs) = main.remote_args( mock_context, REMOTE, pull=True, local_branch='', remote_branch=REMOTE_BRANCH, ) assert args == [REMOTE, 'remote'] assert kwargs['verbose'] assert 'rebase' not in kwargs assert 'tags' not in kwargs def test_remote_args_pull_rebase(mock_context): # Rebasing pull (args, kwargs) = main.remote_args( mock_context, REMOTE, pull=True, rebase=True, local_branch='', remote_branch=REMOTE_BRANCH, ) assert args == [REMOTE, 'remote'] assert kwargs['verbose'] assert kwargs['rebase'] assert 'tags' not in kwargs def test_remote_args_push(mock_context): # Push, swap local and remote (args, kwargs) = main.remote_args( mock_context, REMOTE, local_branch=REMOTE_BRANCH, remote_branch=LOCAL_BRANCH, ) assert args == [REMOTE, 'local:remote'] assert kwargs['verbose'] assert 'tags' not in kwargs assert 'rebase' not in kwargs def test_remote_args_push_tags(mock_context): # Push, swap local and remote (args, kwargs) = main.remote_args( mock_context, REMOTE, tags=True, local_branch=REMOTE_BRANCH, remote_branch=LOCAL_BRANCH, ) assert args == [REMOTE, 'local:remote'] assert kwargs['verbose'] assert kwargs['tags'] assert 'rebase' not in kwargs def test_remote_args_push_same_remote_and_local(mock_context): (args, kwargs) = main.remote_args( mock_context, REMOTE, tags=True, local_branch=LOCAL_BRANCH, remote_branch=LOCAL_BRANCH, push=True, ) assert args == [REMOTE, 'local'] assert kwargs['verbose'] assert kwargs['tags'] assert 'rebase' not in kwargs def test_remote_args_push_set_upstream(mock_context): (args, kwargs) = main.remote_args( mock_context, REMOTE, tags=True, local_branch=LOCAL_BRANCH, remote_branch=LOCAL_BRANCH, push=True, set_upstream=True, ) assert args == [REMOTE, 'local'] assert kwargs['verbose'] assert kwargs['tags'] assert kwargs['set_upstream'] assert 'rebase' not in kwargs def test_remote_args_rebase_only(mock_context): (_, kwargs) = main.remote_args( mock_context, REMOTE, pull=True, rebase=True, ff_only=True ) assert kwargs['rebase'] assert 'ff_only' not in kwargs def test_run_remote_action(mock_context): def passthrough(*args, **kwargs): return (args, kwargs) (args, kwargs) = main.run_remote_action( mock_context, passthrough, REMOTE, local_branch=LOCAL_BRANCH, remote_branch=REMOTE_BRANCH, ) assert args == (REMOTE, 'remote:local') assert kwargs['verbose'] assert 'tags' not in kwargs assert 'rebase' not in kwargs git-cola-4.6.1/test/models_selection_test.py000066400000000000000000000004501457126473700211600ustar00rootroot00000000000000from cola.models import selection from .helper import Mock def test_union(): t = Mock() t.staged = ['a'] t.unmerged = ['a', 'b'] t.modified = ['b', 'a', 'c'] t.untracked = ['d'] expect = ['a', 'b', 'c', 'd'] actual = selection.union(t) assert expect == actual git-cola-4.6.1/test/resources_test.py000066400000000000000000000021721457126473700176450ustar00rootroot00000000000000from cola import resources from . import helper from .helper import patch @patch('cola.resources.compat') @patch('cola.resources.get_prefix') def test_command_unix(mock_prefix, mock_compat): """Test the behavior of resources.command() on unix platforms""" mock_compat.WIN32 = False mock_prefix.return_value = helper.fixture() expect = helper.fixture('bin', 'bare-cmd') actual = resources.command('bare-cmd') assert expect == actual expect = helper.fixture('bin', 'exe-cmd') actual = resources.command('exe-cmd') assert expect == actual @patch('cola.resources.compat') @patch('cola.resources.get_prefix') def test_command_win32(mock_prefix, mock_compat): """Test the behavior of resources.command() on unix platforms""" mock_compat.WIN32 = True mock_prefix.return_value = helper.fixture() expect = helper.fixture('bin', 'bare-cmd') actual = resources.command('bare-cmd') assert expect == actual # Windows will return exe-cmd.exe because the path exists. expect = helper.fixture('bin', 'exe-cmd.exe') actual = resources.command('exe-cmd') assert expect == actual git-cola-4.6.1/test/settings_test.py000066400000000000000000000047371457126473700175040ustar00rootroot00000000000000"""Test the cola.settings module""" import os import pytest from cola.settings import Settings from . import helper @pytest.fixture(autouse=True) def settings_fixture(): """Provide Settings that save into a temporary location to all tests""" filename = helper.tmp_path('settings') Settings.config_path = filename yield Settings.read() if os.path.exists(filename): os.remove(filename) def test_gui_save_restore(settings_fixture): """Test saving and restoring gui state""" settings = settings_fixture settings.gui_state['test-gui'] = {'foo': 'bar'} settings.save() settings = Settings.read() state = settings.gui_state.get('test-gui', {}) assert 'foo' in state assert state['foo'] == 'bar' def test_bookmarks_save_restore(): """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 = {'path': '/tmp/python/thinks/this/exists', 'name': 'exists'} def mock_verify(path): return path == bookmark['path'] settings = Settings.read() settings.add_bookmark(bookmark['path'], bookmark['name']) settings.save() settings = Settings.read(verify=mock_verify) bookmarks = settings.bookmarks assert len(settings.bookmarks) == 1 assert bookmark in bookmarks settings.remove_bookmark(bookmark['path'], bookmark['name']) bookmarks = settings.bookmarks expect = 0 actual = len(bookmarks) assert expect == actual assert bookmark not in bookmarks def test_bookmarks_removes_missing_entries(): """Test that missing entries are removed after a reload""" # verify returns False so all entries will be removed. bookmark = {'path': '.', 'name': 'does-not-exist'} settings = Settings.read(verify=lambda x: False) settings.add_bookmark(bookmark['path'], bookmark['name']) settings.remove_missing_bookmarks() settings.save() settings = Settings.read() bookmarks = settings.bookmarks expect = 0 actual = len(bookmarks) assert expect == actual assert bookmark not in bookmarks def test_rename_bookmark(): settings = Settings.read() settings.add_bookmark('/tmp/repo', 'a') settings.add_bookmark('/tmp/repo', 'b') settings.add_bookmark('/tmp/repo', 'c') settings.rename_bookmark('/tmp/repo', 'b', 'test') expect = ['a', 'test', 'c'] actual = [i['name'] for i in settings.bookmarks] assert expect == actual git-cola-4.6.1/test/short_branch_overlapping.sh000077500000000000000000000037231457126473700216460ustar00rootroot00000000000000#!/bin/bash folder=tmp/a_repo nodeI=0 function node() { n=$nodeI nodeI=$((nodeI+1)) touch $n >> /dev/null git add $n >> /dev/null if ! [ "$1" == "" ] ; then n=$1 fi git commit -m node-$n- >> /dev/null if ! [ "$1" == "" ] ; then git tag -m "" $n >> /dev/null fi } function get_SHA1() { git log --all --grep node-$1- | grep commit | sed -e 's/commit //' } function goto() { SHA1=$(get_SHA1 $1) git checkout $SHA1 -b $2 >> /dev/null } function merge() { n=$nodeI nodeI=$((nodeI+1)) SHA1=$(get_SHA1 $1) git merge --no-ff $SHA1 -m node-$n- >> /dev/null } function range() { i=$1 I=$2 res=$i while [[ i -lt I ]] ; do i=$((i+1)) res="$res $i" done echo $res } function nodes() { I=$(($1-1)) for i in $(range 0 $I) ; do node done } rm -rf "$folder" mkdir "$folder" cd "$folder" git init git symbolic-ref HEAD refs/heads/main # Tags are used to get difference between row and generation values. # Branches main & b2 occupied 2 rows per generation because of tags. # Branches b0 is at the left of tags. Therefore, b0 uses 1 row per generation. # The same is for b1 too. The b1 is short but tag 'b1' cannot be placed # right at the row the branch ends, because the tags at the right were already # placed (they have less generation value). Hence, a gap between last two # commits of b1 is big. Let b0 forks at a row inside the gap. The fork commit # have greater generation than last commit of b1. Hence, it is placed after. # Because of the bug, making many enough branches starting from the fork will # manage to overlapping of last commit of b1 and a commit of a branch. node tag0 node tag1 node tag2 node tag3 node tag4 nodes 1 goto tag0 b0 nodes 8 b0_head=$n goto tag0 b1 nodes 5 goto tag0 b2 nodes 10 git checkout b0 nodes 5 goto $b0_head b5 nodes 5 goto $b0_head b6 nodes 5 goto $b0_head b7 nodes 5 git checkout b2 ../../../bin/git-dag --all & git-cola-4.6.1/test/spellcheck_test.py000066400000000000000000000007321457126473700177500ustar00rootroot00000000000000from cola import compat from cola import spellcheck from . import helper def test_spellcheck_generator(): check = spellcheck.NorvigSpellCheck() assert_spellcheck(check) def test_spellcheck_unicode(): path = helper.fixture('unicode.txt') check = spellcheck.NorvigSpellCheck(words=path) assert_spellcheck(check) def assert_spellcheck(check): for word in check.read(): assert word is not None assert isinstance(word, compat.ustr) git-cola-4.6.1/test/startup_test.py000066400000000000000000000047731457126473700173460ustar00rootroot00000000000000"""Test Startup Dialog (git cola --prompt) Context Menu and related classes""" from cola.widgets import startup from .helper import app_context # Prevent unused imports lint errors. assert app_context is not None def test_get_with_default_repo(app_context): """Test BuildItem::get for default repo""" path = '/home/foo/git-cola' name = 'git-cola' mode = startup.ICON_MODE is_bookmark = True app_context.cfg.set_repo('cola.defaultrepo', path) builder = startup.BuildItem(app_context) actual = builder.get(path, name, mode, is_bookmark) assert actual.path == path assert actual.name == name assert actual.mode == startup.ICON_MODE assert actual.is_default assert actual.is_bookmark assert actual.text() == name assert actual.isEditable() def test_get_with_non_default_repo(app_context): """Test BuildItem::get for non-default repo""" default_repo_path = '/home/foo/default_repo' path = '/home/foo/git-cola' name = 'git-cola' mode = startup.ICON_MODE is_bookmark = True app_context.cfg.set_repo('cola.defaultrepo', default_repo_path) builder = startup.BuildItem(app_context) actual = builder.get(path, name, mode, is_bookmark) assert actual.path == path assert actual.name == name assert not actual.is_default assert actual.is_bookmark == is_bookmark assert actual.text() == name assert actual.isEditable() def test_get_with_item_from_recent(app_context): """Test BuildItem::get for repository from recent list""" path = '/home/foo/git-cola' name = 'git-cola' mode = startup.ICON_MODE is_bookmark = False app_context.cfg.set_repo('cola.defaultrepo', path) builder = startup.BuildItem(app_context) actual = builder.get(path, name, mode, is_bookmark) assert actual.path == path assert actual.name == name assert actual.is_default assert not actual.is_bookmark assert actual.text() == name assert actual.isEditable() def test_get_with_list_mode(app_context): """Test BuildItem::get for list mode building""" path = '/home/foo/git-cola' name = 'git-cola' mode = startup.LIST_MODE is_bookmark = True app_context.cfg.set_repo('cola.defaultrepo', path) builder = startup.BuildItem(app_context) actual = builder.get(path, name, mode, is_bookmark) assert actual.path == path assert actual.name == name assert actual.is_default assert actual.is_bookmark assert actual.text() == path assert not actual.isEditable() git-cola-4.6.1/test/stash_model_test.py000066400000000000000000000027651457126473700201450ustar00rootroot00000000000000from cola.models.stash import StashModel from . import helper from .helper import app_context # Prevent unused imports lint errors. assert app_context is not None def test_stash_info_for_message_without_slash(app_context): helper.commit_files() helper.write_file('A', 'change') helper.run_git('stash', 'save', 'some message') assert StashModel(app_context).stash_info()[0] == [ r'stash@{0}: On main: some message' ] def test_stash_info_for_message_with_slash(app_context): helper.commit_files() helper.write_file('A', 'change') helper.run_git('stash', 'save', 'some message/something') model = StashModel(app_context) stash_details = model.stash_info()[0] assert stash_details == [r'stash@{0}: On main: some message/something'] def test_stash_info_on_branch_with_slash(app_context): helper.commit_files() helper.run_git('checkout', '-b', 'feature/a') helper.write_file('A', 'change') helper.run_git('stash', 'save', 'some message') model = StashModel(app_context) stash_info = model.stash_info() stash_details = stash_info[0][0] assert stash_details in ( 'stash@{0}: On feature/a: some message', # Some versions of Git do not report the full branch name 'stash@{0}: On a: some message', ) stash_rev = stash_info[1][0] assert stash_rev == r'stash@{0}' stash_message = stash_info[3][0] assert stash_message in ( 'On feature/a: some message', 'On a: some message', ) git-cola-4.6.1/test/switcher_test.py000066400000000000000000000011471457126473700174640ustar00rootroot00000000000000"""Test Quick Switcher""" from cola import icons from cola.widgets import switcher def test_switcher_item_with_only_key(): """item text would be key by building item without name""" key = 'item-key' actual = switcher.switcher_item(key) assert actual.key == key assert actual.text() == key def test_switcher_item_with_key_name_icon(): """item text would be name by building item with key and name""" key = 'item-key' name = 'item-name' icon = icons.folder() actual = switcher.switcher_item(key, icon, name) assert actual.key == key assert actual.text() == name git-cola-4.6.1/test/textwrap_test.py000066400000000000000000000114151457126473700175110ustar00rootroot00000000000000"""Test the textwrap module""" import pytest from cola import textwrap class WordWrapDefaults: def __init__(self): self.tabwidth = 8 self.limit = None def wrap(self, text, break_on_hyphens=True): return textwrap.word_wrap( text, self.tabwidth, self.limit, break_on_hyphens=break_on_hyphens ) @pytest.fixture def wordwrap(): """Provide default word wrap options for tests""" return WordWrapDefaults() def test_word_wrap(wordwrap): wordwrap.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""" assert expect == wordwrap.wrap(text) def test_word_wrap_dashes(wordwrap): wordwrap.limit = 4 text = '123-5' expect = '123-5' assert expect == wordwrap.wrap(text) def test_word_wrap_leading_spaces(wordwrap): wordwrap.limit = 4 expect = '1234\n5' assert expect == wordwrap.wrap('1234 5') assert expect == wordwrap.wrap('1234 5') assert expect == wordwrap.wrap('1234 5') assert expect == wordwrap.wrap('1234 5') assert expect == wordwrap.wrap('1234 5') expect = '123\n4' assert expect == wordwrap.wrap('123 4') assert expect == wordwrap.wrap('123 4') assert expect == wordwrap.wrap('123 4') assert expect == wordwrap.wrap('123 4') assert expect == wordwrap.wrap('123 4') def test_word_wrap_double_dashes(wordwrap): wordwrap.limit = 4 text = '12--5' expect = '12--\n5' actual = wordwrap.wrap(text, break_on_hyphens=True) assert expect == actual expect = '12--5' actual = wordwrap.wrap(text, break_on_hyphens=False) assert expect == actual def test_word_wrap_many_lines(wordwrap): wordwrap.limit = 2 text = """ aa bb cc dd""" expect = """ aa bb cc dd""" actual = wordwrap.wrap(text) assert expect == actual def test_word_python_code(wordwrap): wordwrap.limit = 78 text = """ if True: print "hello world" else: print "hello world" """ expect = text actual = wordwrap.wrap(text) assert expect == actual def test_word_wrap_spaces(wordwrap): wordwrap.limit = 2 text = ' ' * 6 expect = '' actual = wordwrap.wrap(text) assert expect == actual def test_word_wrap_special_tag(wordwrap): wordwrap.limit = 2 text = """ This test is so meta, even this sentence Cheered-on-by: Avoids word-wrap C.f. This also avoids word-wrap References: This also avoids word-wrap See-also: This also avoids word-wrap Related-to: This also avoids word-wrap Link: This also avoids word-wrap """ expect = """ This test is so meta, even this sentence Cheered-on-by: Avoids word-wrap C.f. This also avoids word-wrap References: This also avoids word-wrap See-also: This also avoids word-wrap Related-to: This also avoids word-wrap Link: This also avoids word-wrap """ actual = wordwrap.wrap(text) assert expect == actual def test_word_wrap_space_at_start_of_wrap(wordwrap): 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""" wordwrap.limit = 20 actual = wordwrap.wrap(inputs) assert expect == actual def test_word_wrap_keeps_tabs_at_start(wordwrap): inputs = """\tfirst line\n\n\tsecond line""" expect = """\tfirst line\n\n\tsecond line""" wordwrap.limit = 20 actual = wordwrap.wrap(inputs) assert expect == actual def test_word_wrap_keeps_twospace_indents(wordwrap): inputs = """first line\n\n* branch:\n line1\n line2\n""" expect = """first line\n\n* branch:\n line1\n line2\n""" wordwrap.limit = 20 actual = wordwrap.wrap(inputs) assert expect == actual def test_word_wrap_ranges(): text = 'a bb ccc dddd\neeeee' expect = 'a\nbb\nccc\ndddd\neeeee' actual = textwrap.word_wrap(text, 8, 2) assert expect == actual expect = 'a bb\nccc\ndddd\neeeee' actual = textwrap.word_wrap(text, 8, 4) assert expect == actual text = 'a bb ccc dddd\n\teeeee' expect = 'a bb\nccc\ndddd\n\t\neeeee' actual = textwrap.word_wrap(text, 8, 4) assert expect == actual def test_triplets(): text = 'xx0 xx1 xx2 xx3 xx4 xx5 xx6 xx7 xx8 xx9 xxa xxb' expect = 'xx0 xx1 xx2 xx3 xx4 xx5 xx6\nxx7 xx8 xx9 xxa xxb' actual = textwrap.word_wrap(text, 8, 27) assert expect == actual expect = 'xx0 xx1 xx2 xx3 xx4 xx5\nxx6 xx7 xx8 xx9 xxa xxb' actual = textwrap.word_wrap(text, 8, 26) assert expect == actual actual = textwrap.word_wrap(text, 8, 25) assert expect == actual actual = textwrap.word_wrap(text, 8, 24) assert expect == actual actual = textwrap.word_wrap(text, 8, 23) assert expect == actual expect = 'xx0 xx1 xx2 xx3 xx4\nxx5 xx6 xx7 xx8 xx9\nxxa xxb' actual = textwrap.word_wrap(text, 8, 22) assert expect == actual git-cola-4.6.1/test/tmp/000077500000000000000000000000001457126473700150205ustar00rootroot00000000000000git-cola-4.6.1/test/tmp/.gitignore000066400000000000000000000000001457126473700167760ustar00rootroot00000000000000git-cola-4.6.1/test/utils_test.py000066400000000000000000000057021457126473700167750ustar00rootroot00000000000000"""Tests the cola.utils module.""" import os from cola import core from cola import utils def test_basename(): """Test the utils.basename function.""" assert utils.basename('bar') == 'bar' assert utils.basename('/bar') == 'bar' assert utils.basename('/bar ') == 'bar ' assert utils.basename('foo/bar') == 'bar' assert utils.basename('/foo/bar') == 'bar' assert utils.basename('foo/foo/bar') == 'bar' assert utils.basename('/foo/foo/bar') == 'bar' assert utils.basename('/foo/foo//bar') == 'bar' assert utils.basename('////foo //foo//bar') == 'bar' def test_dirname(): """Test the utils.dirname function.""" assert utils.dirname('bar') == '' assert utils.dirname('/bar') == '' assert utils.dirname('//bar') == '' assert utils.dirname('///bar') == '' assert utils.dirname('foo/bar') == 'foo' assert utils.dirname('foo//bar') == 'foo' assert utils.dirname('foo /bar') == 'foo ' assert utils.dirname('/foo//bar') == '/foo' assert utils.dirname('/foo /bar') == '/foo ' assert utils.dirname('//foo//bar') == '/foo' assert utils.dirname('///foo///bar') == '/foo' def test_add_parents(): """Test the utils.add_parents() function.""" paths = {'foo///bar///baz'} path_set = utils.add_parents(paths) assert 'foo/bar/baz' in path_set assert 'foo/bar' in path_set assert 'foo' in path_set assert 'foo///bar///baz' not in path_set # Ensure that the original set is unchanged expect = {'foo///bar///baz'} assert expect == paths def test_tmp_filename_gives_good_file(): try: first = utils.tmp_filename('test') assert core.exists(first) assert os.path.basename(first).startswith('git-cola-test') finally: os.remove(first) try: second = utils.tmp_filename('test') assert core.exists(second) assert os.path.basename(second).startswith('git-cola-test') finally: os.remove(second) assert first != second def test_strip_one_abspath(): expect = 'bin/git' actual = utils.strip_one('/usr/bin/git') assert expect == actual def test_strip_one_relpath(): expect = 'git' actual = utils.strip_one('bin/git') assert expect == actual def test_strip_one_nested_relpath(): expect = 'bin/git' actual = utils.strip_one('local/bin/git') assert expect == actual def test_strip_one_basename(): expect = 'git' actual = utils.strip_one('git') assert expect == actual def test_select_directory(): filename = utils.tmp_filename('test') try: expect = os.path.dirname(filename) actual = utils.select_directory([filename]) assert expect == actual finally: os.remove(filename) def test_select_directory_prefers_directories(): filename = utils.tmp_filename('test') try: expect = '.' actual = utils.select_directory([filename, '.']) assert expect == actual finally: os.remove(filename) git-cola-4.6.1/tox.ini000066400000000000000000000015551457126473700145620ustar00rootroot00000000000000[tox] minversion = 4.0 envlist = clean,py36,py37,py38,py39,py310,py311,py312,report skip_missing_interpreters = true [testenv] allowlist_externals = garden passenv = FORCE_COLOR commands = garden test -- --cov --cov-append --cov-report=term-missing depends = {py36,py37,py38,py39,py310,py311,py312}: clean report: py36,py37,py38,py39,py310,py311,py312 extras = testing sitepackages = true usedevelop = true [testenv:check] allowlist_externals = garden commands = garden check {posargs} extras = docs dev testing sitepackages = true skip_install = true [testenv:clean] deps = coverage skip_install = true commands = python3 -m coverage erase [testenv:docs] extras = docs testing changedir = docs commands = python3 -m sphinx -v docs html [testenv:report] deps = coverage skip_install = true commands = python3 -m coverage report python3 -m coverage html